armci-mpi/0000755000175000017500000000000012663426407012216 5ustar mbanckmbanckarmci-mpi/VERSION0000644000175000017500000000115512663426407013270 0ustar mbanckmbanck# For libtool ABI versioning rules see: # http://www.nondot.org/sabre/Mirrored/libtool-2.1a/libtool_6.html#SEC36 # 1. If the library source code has changed at all since the last # update, then increment revision (`c:r:a' becomes `c:r+1:a'). # # 2. If any interfaces have been added, removed, or changed since # the last update, increment current, and set revision to 0. # # 3. If any interfaces have been added since the last public # release, then increment age. # # 4. If any interfaces have been removed since the last public # release, then set age to 0. libarmci_abi_version=1:0:0 armci-mpi/travis/0000755000175000017500000000000012663426407013526 5ustar mbanckmbanckarmci-mpi/travis/install-mpi.sh0000755000175000017500000000601012663426407016313 0ustar mbanckmbanck#!/bin/sh # This configuration file was taken originally from the mpi4py project # , and then modified for Julia set -e set -x os=`uname` TRAVIS_ROOT="$1" MPI_IMPL="$2" # this is where updated Autotools will be for Linux export PATH=$TRAVIS_ROOT/bin:$PATH case "$os" in Darwin) echo "Mac" brew update case "$MPI_IMPL" in mpich) brew install mpich ;; openmpi) # Homebrew is still at 1.10.1, which is broken for STRIDED/IOV=DIRECT. brew install openmpi ;; *) echo "Unknown MPI implementation: $MPI_IMPL" exit 10 ;; esac ;; Linux) echo "Linux" case "$MPI_IMPL" in mpich) if [ ! -d "$TRAVIS_ROOT/mpich" ]; then wget -q --no-check-certificate http://www.mpich.org/static/downloads/3.2/mpich-3.2.tar.gz tar -xzf mpich-3.2.tar.gz cd mpich-3.2 mkdir build && cd build ../configure CFLAGS="-w" --prefix=$TRAVIS_ROOT/mpich --disable-fortran --disable-static make -j4 make install else echo "MPICH already installed" fi ;; openmpi) if [ ! -d "$TRAVIS_ROOT/open-mpi" ]; then wget -q --no-check-certificate http://www.open-mpi.org/software/ompi/v1.10/downloads/openmpi-1.10.2rc3.tar.bz2 tar -xjf openmpi-1.10.2rc3.tar.bz2 cd openmpi-1.10.2rc3 mkdir build && cd build ../configure CFLAGS="-w" --prefix=$TRAVIS_ROOT/open-mpi \ --without-verbs --without-fca --without-mxm --without-ucx \ --without-portals4 --without-psm --without-psm2 \ --without-libfabric --without-usnic \ --without-udreg --without-ugni --without-xpmem \ --without-alps --without-munge \ --without-sge --without-loadleveler --without-tm \ --without-lsf --without-slurm \ --without-pvfs2 --without-plfs \ --without-cuda --disable-oshmem \ --disable-mpi-fortran --disable-oshmem-fortran \ --disable-libompitrace \ --disable-mpi-io --disable-io-romio \ --disable-static make -j4 make install else echo "Open-MPI already installed" fi ;; *) echo "Unknown MPI implementation: $MPI_IMPL" exit 20 ;; esac ;; esac armci-mpi/travis/install-autotools.sh0000755000175000017500000000743212663426407017570 0ustar mbanckmbanck#!/bin/sh set -e set -x os=`uname` TOP="$1" case "$os" in Darwin) brew update brew info autoconf automake libtool #brew install autoconf automake libtool brew upgrade autoconf automake libtool which glibtool which glibtoolize glibtool --version mkdir -p ${TOP}/bin ln -s `which glibtool` ${TOP}/bin/libtool ln -s `which glibtoolize` ${TOP}/bin/libtoolize ;; Linux) MAKE_JNUM=2 M4_VERSION=1.4.17 LIBTOOL_VERSION=2.4.4 AUTOCONF_VERSION=2.69 AUTOMAKE_VERSION=1.15 cd ${TOP} TOOL=m4 TDIR=${TOOL}-${M4_VERSION} FILE=${TDIR}.tar.gz BIN=${TOP}/bin/${TOOL} if [ -f ${FILE} ] ; then echo ${FILE} already exists! Using existing copy. else wget http://ftp.gnu.org/gnu/${TOOL}/${FILE} fi if [ -d ${TDIR} ] ; then echo ${TDIR} already exists! Using existing copy. else echo Unpacking ${FILE} tar -xzf ${FILE} fi if [ -f ${BIN} ] ; then echo ${BIN} already exists! Skipping build. else cd ${TOP}/${TDIR} ./configure --prefix=${TOP} && make -j ${MAKE_JNUM} && make install if [ "x$?" != "x0" ] ; then echo FAILURE 1 exit fi fi cd ${TOP} TOOL=libtool TDIR=${TOOL}-${LIBTOOL_VERSION} FILE=${TDIR}.tar.gz BIN=${TOP}/bin/${TOOL} if [ ! -f ${FILE} ] ; then wget http://ftp.gnu.org/gnu/${TOOL}/${FILE} else echo ${FILE} already exists! Using existing copy. fi if [ ! -d ${TDIR} ] ; then echo Unpacking ${FILE} tar -xzf ${FILE} else echo ${TDIR} already exists! Using existing copy. fi if [ -f ${BIN} ] ; then echo ${BIN} already exists! Skipping build. else cd ${TOP}/${TDIR} ./configure --prefix=${TOP} M4=${TOP}/bin/m4 && make -j ${MAKE_JNUM} && make install if [ "x$?" != "x0" ] ; then echo FAILURE 2 exit fi fi cd ${TOP} TOOL=autoconf TDIR=${TOOL}-${AUTOCONF_VERSION} FILE=${TDIR}.tar.gz BIN=${TOP}/bin/${TOOL} if [ ! -f ${FILE} ] ; then wget http://ftp.gnu.org/gnu/${TOOL}/${FILE} else echo ${FILE} already exists! Using existing copy. fi if [ ! -d ${TDIR} ] ; then echo Unpacking ${FILE} tar -xzf ${FILE} else echo ${TDIR} already exists! Using existing copy. fi if [ -f ${BIN} ] ; then echo ${BIN} already exists! Skipping build. else cd ${TOP}/${TDIR} ./configure --prefix=${TOP} M4=${TOP}/bin/m4 && make -j ${MAKE_JNUM} && make install if [ "x$?" != "x0" ] ; then echo FAILURE 3 exit fi fi cd ${TOP} TOOL=automake TDIR=${TOOL}-${AUTOMAKE_VERSION} FILE=${TDIR}.tar.gz BIN=${TOP}/bin/${TOOL} if [ ! -f ${FILE} ] ; then wget http://ftp.gnu.org/gnu/${TOOL}/${FILE} else echo ${FILE} already exists! Using existing copy. fi if [ ! -d ${TDIR} ] ; then echo Unpacking ${FILE} tar -xzf ${FILE} else echo ${TDIR} already exists! Using existing copy. fi if [ -f ${BIN} ] ; then echo ${BIN} already exists! Skipping build. else cd ${TOP}/${TDIR} ./configure --prefix=${TOP} M4=${TOP}/bin/m4 && make -j ${MAKE_JNUM} && make install if [ "x$?" != "x0" ] ; then echo FAILURE 4 exit fi fi ;; esac armci-mpi/travis/build-run.sh0000755000175000017500000000132712663426407015771 0ustar mbanckmbanck#! /bin/sh # Exit on error set -ev os=`uname` TRAVIS_ROOT="$1" MPI_IMPL="$2" # Environment variables export CFLAGS="-std=c99" #export MPICH_CC=$CC export MPICC=mpicc case "$os" in Darwin) ;; Linux) export PATH=$TRAVIS_ROOT/mpich/bin:$PATH export PATH=$TRAVIS_ROOT/open-mpi/bin:$PATH ;; esac # Capture details of build case "$MPI_IMPL" in mpich) mpichversion mpicc -show ;; openmpi) # this is missing with Mac build it seems #ompi_info --arch --config mpicc --showme:command ;; esac # Configure and build ./autogen.sh ./configure --disable-static --enable-win-allocate # Run unit tests export ARMCI_VERBOSE=1 make check armci-mpi/benchmarks/0000755000175000017500000000000012662706250014327 5ustar mbanckmbanckarmci-mpi/benchmarks/bench_groups.c0000644000175000017500000000403412662706250017152 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define PART_SIZE 1 int main(int argc, char **argv) { int me, nproc; int i, *procs; ARMCI_Group g_world, g_odd, g_even; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); procs = malloc(sizeof(int) * ( nproc/2 + (nproc % 2 ? 1 : 0 ))); if (me == 0) printf("ARMCI Group test starting on %d procs\n", nproc); ARMCI_Group_get_world(&g_world); if (me == 0) printf(" + Creating odd group\n"); for (i = 1; i < nproc; i += 2) { procs[i/2] = i; } ARMCI_Group_create_child(i/2, procs, &g_odd, &g_world); if (me == 0) printf(" + Creating even group\n"); for (i = 0; i < nproc; i += 2) { procs[i/2] = i; } ARMCI_Group_create_child(i/2, procs, &g_even, &g_world); /***********************************************************************/ { int grp_me, grp_nproc; double t_abs_to_grp, t_grp_to_abs; const int iter = 1000000; if (me == 0) { ARMCI_Group_rank(&g_even, &grp_me); ARMCI_Group_size(&g_even, &grp_nproc); t_abs_to_grp = MPI_Wtime(); for (i = 0; i < iter; i++) ARMCII_Translate_absolute_to_group(&g_even, (grp_me+1) % grp_nproc); t_abs_to_grp = MPI_Wtime() - t_abs_to_grp; t_grp_to_abs = MPI_Wtime(); for (i = 0; i < iter; i++) ARMCI_Absolute_id(&g_even, (grp_me+1) % grp_nproc); t_grp_to_abs = MPI_Wtime() - t_grp_to_abs; printf("t_abs_to_grp = %f us, t_grp_to_abs = %f us\n", t_abs_to_grp/iter * 1.0e6, t_grp_to_abs/iter * 1.0e6); } ARMCI_Barrier(); } /***********************************************************************/ if (me == 0) printf(" + Freeing groups\n"); if (me % 2 > 0) ARMCI_Group_free(&g_odd); else ARMCI_Group_free(&g_even); free(procs); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/benchmarks/ring-flood.c0000644000175000017500000000412512662706250016535 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #define MAX_XFER_SIZE 8192 #define NUM_XFERS 1024 int main(int argc, char **argv) { int me, nproc; int msg_length, i; double t_start, t_stop; armci_hdl_t *handles; // Non-blocking handles (NUM_XFERS) uint8_t *snd_buf; // Send buffer (MAX_XFER_SIZE) uint8_t **rcv_buf; // Receive buffer (MAX_XFER_SIZE * NUM_XFERS) MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (nproc < 2) ARMCI_Error("This benchmark should be run on at least two processes", 1); if (me == 0) printf("ARMCI flood bandwidth test, performing %d non-blocking xfers at each size.\n\n", NUM_XFERS); handles = malloc(NUM_XFERS*sizeof(armci_hdl_t)); rcv_buf = malloc(nproc*sizeof(void*)); ARMCI_Malloc((void*)rcv_buf, MAX_XFER_SIZE*NUM_XFERS); snd_buf = ARMCI_Malloc_local(MAX_XFER_SIZE); for (i = 0; i < MAX_XFER_SIZE; i++) { snd_buf[i] = (uint8_t) me; } for (msg_length = 1; msg_length <= MAX_XFER_SIZE; msg_length *= 2) { int xfer; for (xfer = 0; xfer < NUM_XFERS; xfer++) ARMCI_INIT_HANDLE(&handles[xfer]); ARMCI_Barrier(); t_start = MPI_Wtime(); // Initiate puts, perform NUM_XFERS NB puts to my right neighbor for (xfer = 0; xfer < NUM_XFERS; xfer++) { ARMCI_NbPut(snd_buf, ((uint8_t*)rcv_buf[(me+1)%nproc])+msg_length*xfer, msg_length, (me+1)%nproc, &handles[xfer]); } // Wait for completion for (xfer = 0; xfer < NUM_XFERS; xfer++) ARMCI_Wait(&handles[xfer]); ARMCI_Barrier(); t_stop = MPI_Wtime(); if (me == 0) printf("%8d bytes \t %12.8f sec \t %12.8f GB/s\n", msg_length*NUM_XFERS, (t_stop-t_start), (msg_length*NUM_XFERS)/(t_stop-t_start)/1.0e9); } ARMCI_Free(rcv_buf[me]); free(rcv_buf); free(handles); ARMCI_Free_local(snd_buf); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/benchmarks/ping-pong.c0000644000175000017500000000576512662706250016406 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #define MAX_SIZE 262144 #define NUM_ROUNDS 1000 int main(int argc, char **argv) { int me, nproc, zero, target; int msg_length, round, i; double t_start, t_stop; uint8_t *snd_buf; // Send buffer (byte array) uint8_t **rcv_buf; // Receive buffer (byte array) MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (nproc < 2) ARMCI_Error("This benchmark should be run on at least two processes", 1); if (me == 0) printf("ARMCI ping-pong latency test, performing %d rounds at each xfer size.\n", NUM_ROUNDS); rcv_buf = malloc(nproc*sizeof(void*)); ARMCI_Malloc((void*)rcv_buf, MAX_SIZE); snd_buf = ARMCI_Malloc_local(MAX_SIZE); zero = 0; for (i = 0; i < MAX_SIZE; i++) { snd_buf[i] = 1; } for (target = 1; target < nproc; target++) { if (me == 0) printf("\n========== Process pair: %d and %d ==========\n\n", 0, target); for (msg_length = 1; msg_length <= MAX_SIZE; msg_length *= 2) { ARMCI_Barrier(); t_start = MPI_Wtime(); if (me == 0 || me == target) { // Perform NUM_ROUNDS ping-pongs for (round = 0; round < NUM_ROUNDS*2; round++) { int my_target = me == 0 ? target : 0; // I am the sender if (round % 2 == me) { if ((round % 2 == 0 && me == 0) || (round % 2 != 0 && me != 0)) { // Clear start and end markers for next round #ifdef DIRECT_ACCESS ((uint8_t*)rcv_buf[me])[0] = 0; ((uint8_t*)rcv_buf[me])[msg_length-1] = 0; #else ARMCI_Put(&zero, &(((uint8_t*)rcv_buf[me])[0]), 1, me); ARMCI_Put(&zero, &(((uint8_t*)rcv_buf[me])[msg_length-1]), 1, me); #endif ARMCI_Put(snd_buf, rcv_buf[my_target], msg_length, my_target); ARMCI_Fence(my_target); // This is optional, we don't need notification } // I am the receiver else { #ifdef DIRECT_ACCESS while (((volatile uint8_t*)rcv_buf[me])[0] == 0) ; while (((volatile uint8_t*)rcv_buf[me])[msg_length-1] == 0) ; #else uint8_t val; do { ARMCI_Get(&(((uint8_t*)rcv_buf[me])[0]), &val, 1, me); } while (val == 0); do { ARMCI_Get(&(((uint8_t*)rcv_buf[me])[msg_length-1]), &val, 1, me); } while (val == 0); #endif } } } } ARMCI_Barrier(); // FIXME: Time here increases with nproc :( t_stop = MPI_Wtime(); if (me == 0) printf("%8d bytes \t %12.8f us\n", msg_length, (t_stop-t_start)/NUM_ROUNDS*1.0e6); } ARMCI_Barrier(); } ARMCI_Free(rcv_buf[me]); free(rcv_buf); ARMCI_Free_local(snd_buf); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/benchmarks/Makefile.mk0000644000175000017500000000165112662706250016400 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # check_PROGRAMS += benchmarks/ping-pong \ benchmarks/ring-flood \ benchmarks/contiguous-bench \ benchmarks/strided-bench \ benchmarks/bench_groups \ benchmarks/rmw_perf \ # end TESTS += benchmarks/ping-pong \ benchmarks/ring-flood \ benchmarks/contiguous-bench \ benchmarks/strided-bench \ benchmarks/rmw_perf \ # end benchmarks_ping_pong_LDADD = libarmci.la benchmarks_ring_flood_LDADD = libarmci.la benchmarks_contiguous_bench_LDADD = libarmci.la -lm benchmarks_strided_bench_LDADD = libarmci.la -lm benchmarks_bench_groups_LDADD = libarmci.la -lm benchmarks_rmw_perf_LDADD = libarmci.la armci-mpi/benchmarks/rmw_perf.c0000644000175000017500000000542512662706250016322 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #ifdef USE_ARMCI_LONG # define INC_TYPE long # define ARMCI_OP ARMCI_FETCH_AND_ADD_LONG #else # define INC_TYPE int # define ARMCI_OP ARMCI_FETCH_AND_ADD #endif int main(int argc, char* argv[]) { int provided; #ifdef __bgp__ MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); assert(provided==MPI_THREAD_MULTIPLE); #else MPI_Init_thread(&argc, &argv, MPI_THREAD_SINGLE, &provided); #endif int rank, nproc; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (nproc<2) { printf("This benchmark requires >1 MPI processes\n"); MPI_Finalize(); return 1; } ARMCI_Init(); int count = ( argc > 1 ? atoi(argv[1]) : 1000000 ); char * cfair = getenv ("CHECK_FAIRNESS"); int check_fairness = (cfair!=NULL) ? 1 : 0; int * complete = (int *) malloc(sizeof(int) * count); for(int i=0; i0) { int target = 0; INC_TYPE val = -1; double t0 = MPI_Wtime(); while(val < count) { ARMCI_Rmw(ARMCI_OP, &val, base_ptrs[target], 1, target); if (val < count) { complete[val] = rank; nrecv++; } } double t1 = MPI_Wtime(); tt = (t1-t0); } MPI_Allreduce(MPI_IN_PLACE, complete, count, MPI_INT, MPI_SUM, MPI_COMM_WORLD); double dt = 1.e6*(double)tt/(double)nrecv; if(nrecv>0) printf("process %d received %d counters in %lf seconds (%lf microseconds per call)\n", rank, nrecv, tt, dt); fflush(stdout); MPI_Barrier(MPI_COMM_WORLD); if (0==rank && check_fairness==1) { printf("Checking for fairness...\n"); fflush(stdout); for(int i=0; i #include #include #include #include #include #ifdef MODE_SET #include #endif #define MAX_XDIM 1024 #define MAX_YDIM 1024 #define MAX_DATA_SIZE (MAX_XDIM*MAX_YDIM*sizeof(double)) #define NUM_ITERATIONS ((xdim*ydim <= 1024) ? 64 : 16) #define NUM_WARMUP_ITER 1 int main(int argc, char ** argv) { int rank, nproc; #ifdef MULTIPLE int thread_level; #endif int target_rank, xdim, ydim, test_iter; int stride[1], count[2], levels; double scale; int *buf; void **base_ptrs; #ifdef MODE_SET ARMCI_Group grp_world; #endif #ifdef MULTIPLE MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &thread_level); #else MPI_Init(&argc, &argv); #endif ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting one-sided strided performance test with %d processes\n", nproc); buf = ARMCI_Malloc_local(MAX_DATA_SIZE); base_ptrs = malloc(sizeof(void*)*nproc); ARMCI_Malloc(base_ptrs, MAX_DATA_SIZE); memset(buf, rank+1, MAX_DATA_SIZE); #ifdef MODE_SET ARMCI_Group_get_default(&grp_world); if (getenv("ARMCIX_MODE_SET")) ARMCIX_Mode_set(ARMCIX_MODE_CONFLICT_FREE | ARMCIX_MODE_NO_LOAD_STORE, base_ptrs[rank], &grp_world); else if (rank == 0) printf("Warning: ARMCIX_MODE_SET not enabled\n"); #endif if (rank == 0) printf("%12s %12s %12s %12s %12s %12s %12s %12s\n", "Trg. Rank", "Xdim Ydim", "Get (usec)", "Put (usec)", "Acc (usec)", "Get (MiB/s)", "Put (MiB/s)", "Acc (MiB/s)"); stride[0] = MAX_XDIM*sizeof(double); levels = 1; scale = 1.0; for (target_rank = 1; rank == 0 && target_rank < nproc; target_rank++) { for (xdim = 1; xdim <= MAX_XDIM; xdim *= 2) { count[0] = xdim*sizeof(double); for (ydim = 1; ydim <= MAX_YDIM; ydim *= 2) { const int data_size = xdim*ydim*sizeof(double); double t_get=0.0, t_put=0.0, t_acc=0.0; count[1] = ydim; for (test_iter = 0; test_iter < NUM_ITERATIONS + NUM_WARMUP_ITER; test_iter++) { if (test_iter == NUM_WARMUP_ITER) t_put = MPI_Wtime(); ARMCI_PutS(buf, stride, base_ptrs[target_rank], stride, count, levels, target_rank); } ARMCI_Fence(target_rank); t_put = (MPI_Wtime() - t_put)/NUM_ITERATIONS; for (test_iter = 0; test_iter < NUM_ITERATIONS + NUM_WARMUP_ITER; test_iter++) { if (test_iter == NUM_WARMUP_ITER) t_acc = MPI_Wtime(); ARMCI_AccS(ARMCI_ACC_DBL, (void*) &scale, buf, stride, base_ptrs[target_rank], stride, count, levels, target_rank); } ARMCI_Fence(target_rank); t_acc = (MPI_Wtime() - t_acc)/NUM_ITERATIONS; for (test_iter = 0; test_iter < NUM_ITERATIONS + NUM_WARMUP_ITER; test_iter++) { if (test_iter == NUM_WARMUP_ITER) t_get = MPI_Wtime(); ARMCI_GetS(base_ptrs[target_rank], stride, buf, stride, count, levels, target_rank); } t_get = (MPI_Wtime() - t_get)/NUM_ITERATIONS; printf("%12d %6d%6d %12.3f %12.3f %12.3f %12.3f %12.3f %12.3f\n", target_rank, xdim, ydim, t_get*1.0e6, t_put*1.0e6, t_acc*1.0e6, data_size/(1024.0*1024.0)/t_get, data_size/(1024.0*1024.0)/t_put, data_size/(1024.0*1024.0)/t_acc); } } } ARMCI_Barrier(); ARMCI_Free(base_ptrs[rank]); ARMCI_Free_local(buf); free(base_ptrs); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/benchmarks/contiguous-bench.c0000644000175000017500000000642512662706250017756 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #ifdef MODE_SET #include #endif #define MAX_DATA_SIZE (1024*128*16) #define NUM_ITERATIONS ((data_size <= 2048) ? 4096 : ((data_size <= 16384) ? 1024 : 512)) #define NUM_WARMUP_ITER 1 int main(int argc, char ** argv) { int rank, nproc, test_iter, target_rank, data_size; #ifdef MULTIPLE inr thread_level; #endif int *buf; void **base_ptrs; #ifdef MODE_SET ARMCI_Group grp_world; #endif #ifdef MULTIPLE MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &thread_level); #else MPI_Init(&argc, &argv); #endif ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting one-sided contiguous performance test with %d processes\n", nproc); buf = ARMCI_Malloc_local(MAX_DATA_SIZE); base_ptrs = malloc(sizeof(void*)*nproc); ARMCI_Malloc(base_ptrs, MAX_DATA_SIZE); memset(buf, rank, MAX_DATA_SIZE); #ifdef MODE_SET ARMCI_Group_get_default(&grp_world); if (getenv("ARMCIX_MODE_SET")) ARMCIX_Mode_set(ARMCIX_MODE_CONFLICT_FREE | ARMCIX_MODE_NO_LOAD_STORE, base_ptrs[rank], &grp_world); else if (rank == 0) printf("Warning: ARMCIX_MODE_SET not enabled\n"); #endif if (rank == 0) printf("%12s %12s %12s %12s %12s %12s %12s %12s\n", "Trg. Rank", "Xfer Size", "Get (usec)", "Put (usec)", "Acc (usec)", "Get (MiB/s)", "Put (MiB/s)", "Acc (MiB/s)"); for (target_rank = 1; rank == 0 && target_rank < nproc; target_rank++) { for (data_size = sizeof(double); data_size <= MAX_DATA_SIZE; data_size *= 2) { double t_get=0, t_put=0, t_acc=0; for (test_iter = 0; test_iter < NUM_ITERATIONS + NUM_WARMUP_ITER; test_iter++) { if (test_iter == NUM_WARMUP_ITER) t_get = MPI_Wtime(); ARMCI_Get(base_ptrs[target_rank], buf, data_size, target_rank); } t_get = (MPI_Wtime() - t_get)/NUM_ITERATIONS; for (test_iter = 0; test_iter < NUM_ITERATIONS + NUM_WARMUP_ITER; test_iter++) { if (test_iter == NUM_WARMUP_ITER) t_put = MPI_Wtime(); ARMCI_Put(buf, base_ptrs[target_rank], data_size, target_rank); } ARMCI_Fence(target_rank); t_put = (MPI_Wtime() - t_put)/NUM_ITERATIONS; for (test_iter = 0; test_iter < NUM_ITERATIONS + NUM_WARMUP_ITER; test_iter++) { double scale = 1.0; if (test_iter == NUM_WARMUP_ITER) t_acc = MPI_Wtime(); #ifdef NO_ACC int stride = 0; ARMCI_AccS(ARMCI_ACC_DBL, &scale, buf, &stride, base_ptrs[target_rank], &stride, &data_size, 0, target_rank); #else ARMCI_Acc(ARMCI_ACC_DBL, &scale, buf, base_ptrs[target_rank], data_size, target_rank); #endif } ARMCI_Fence(target_rank); t_acc = (MPI_Wtime() - t_acc)/NUM_ITERATIONS; printf("%12d %12d %12.3f %12.3f %12.3f %12.3f %12.3f %12.3f\n", target_rank, data_size, t_get*1.0e6, t_put*1.0e6, t_acc*1.0e6, data_size/(1024.0*1024.0)/t_get, data_size/(1024.0*1024.0)/t_put, data_size/(1024.0*1024.0)/t_acc); } } ARMCI_Barrier(); ARMCI_Free(base_ptrs[rank]); ARMCI_Free_local(buf); free(base_ptrs); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/CHANGES0000644000175000017500000000013612662706250013205 0ustar mbanckmbanck * r506: Added support for the ARMCI profiling interface. * r498: Fixed a few memory leaks. armci-mpi/m4/0000755000175000017500000000000012663426407012536 5ustar mbanckmbanckarmci-mpi/m4/aclocal_cxx.m40000644000175000017500000001305612662706250015261 0ustar mbanckmbanckdnl PAC_PROG_CXX - reprioritize the C++ compiler search order AC_DEFUN([PAC_PROG_CXX],[ PAC_PUSH_FLAG([CXXFLAGS]) AC_PROG_CXX([g++ icpc pgCC xlC pathCC cl]) PAC_POP_FLAG([CXXFLAGS]) ]) dnl This is from crypt.to/autoconf-archive, slightly modified. dnl It defines bool as int if it is not availalbe dnl AC_DEFUN([AC_CXX_BOOL], [AC_CACHE_CHECK(whether the compiler recognizes bool as a built-in type, ac_cv_cxx_bool, [AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_TRY_COMPILE([ int f(int x){return 1;} int f(char x){return 1;} int f(bool x){return 1;} ],[bool b = true; return f(b);], ac_cv_cxx_bool=yes, ac_cv_cxx_bool=no) AC_LANG_RESTORE ]) if test "$ac_cv_cxx_bool" != yes; then AC_DEFINE(bool,int,[define if bool is a built-in type]) fi ]) dnl This is from crypt.to/autoconf-archive, slightly modified (name defined) dnl AC_DEFUN([AC_CXX_EXCEPTIONS], [AC_CACHE_CHECK(whether the compiler supports exceptions, ac_cv_cxx_exceptions, [AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_TRY_COMPILE(,[try { throw 1; } catch (int i) { return i; }], ac_cv_cxx_exceptions=yes, ac_cv_cxx_exceptions=no) AC_LANG_RESTORE ]) if test "$ac_cv_cxx_exceptions" = yes; then AC_DEFINE(HAVE_CXX_EXCEPTIONS,,[define if the compiler supports exceptions]) fi ]) dnl This is from crypt.to/autoconf-archive dnl AC_DEFUN([AC_CXX_NAMESPACES], [AC_CACHE_CHECK(whether the compiler implements namespaces, ac_cv_cxx_namespaces, [AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_TRY_COMPILE([namespace Outer { namespace Inner { int i = 0; }}], [using namespace Outer::Inner; return i;], ac_cv_cxx_namespaces=yes, ac_cv_cxx_namespaces=no) AC_LANG_RESTORE ]) if test "$ac_cv_cxx_namespaces" = yes; then AC_DEFINE(HAVE_NAMESPACES,,[define if the compiler implements namespaces]) fi ]) dnl Some compilers support namespaces but don't know about std dnl AC_DEFUN([AC_CXX_NAMESPACE_STD], [AC_REQUIRE([AC_CXX_NAMESPACES]) AC_CACHE_CHECK(whether the compiler implements the namespace std, ac_cv_cxx_namespace_std, [ac_cv_cxx_namespace_std=no if test "$ac_cv_cxx_namespaces" = yes ; then AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_TRY_COMPILE([ #include using namespace std;], [cout << "message\n";], ac_cv_cxx_namespace_std=yes, ac_cv_cxx_namespace_std=no) AC_LANG_RESTORE fi ]) if test "$ac_cv_cxx_namespace_std" = yes; then AC_DEFINE(HAVE_NAMESPACE_STD,,[define if the compiler implements namespace std]) fi ]) dnl/*D dnl PAC_CXX_CHECK_COMPILER_OPTION - Check that a C++ compiler option is dnl accepted without warning messages dnl dnl Synopsis: dnl PAC_CXX_CHECK_COMPILER_OPTION(optionname,action-if-ok,action-if-fail) dnl dnl Output Effects: dnl dnl If no actions are specified, a working value is added to 'CXXOPTIONS' dnl dnl Notes: dnl This is now careful to check that the output is different, since dnl some compilers are noisy. dnl dnl We are extra careful to prototype the functions in case compiler options dnl that complain about poor code are in effect. dnl dnl Because this is a long script, we have ensured that you can pass a dnl variable containing the option name as the first argument. dnl D*/ AC_DEFUN([PAC_CXX_CHECK_COMPILER_OPTION],[ AC_MSG_CHECKING([whether C++ compiler accepts option $1]) save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$1 $CXXFLAGS" rm -f conftest.out echo 'int foo(void);int foo(void){return 0;}' > conftest2.cpp echo 'int main(void);int main(void){return 0;}' > conftest.cpp if ${CXX-g++} $save_CXXFLAGS $CPPFLAGS -o conftest conftest.cpp $LDFLAGS >conftest.bas 2>&1 ; then if ${CXX-g++} $CXXFLAGS $CPPFLAGS -o conftest conftest.cpp $LDFLAGS >conftest.out 2>&1 ; then if diff -b conftest.out conftest.bas >/dev/null 2>&1 ; then AC_MSG_RESULT(yes) AC_MSG_CHECKING([whether routines compiled with $1 can be linked with ones compiled without $1]) rm -f conftest.out rm -f conftest.bas if ${CXX-g++} -c $save_CXXFLAGS $CPPFLAGS conftest2.cpp >conftest2.out 2>&1 ; then if ${CXX-g++} $CXXFLAGS $CPPFLAGS -o conftest conftest2.o conftest.cpp $LDFLAGS >conftest.bas 2>&1 ; then if ${CXX-g++} $CXXFLAGS $CPPFLAGS -o conftest conftest2.o conftest.cpp $LDFLAGS >conftest.out 2>&1 ; then if diff -b conftest.out conftest.bas >/dev/null 2>&1 ; then AC_MSG_RESULT(yes) CXXFLAGS="$save_CXXFLAGS" ifelse($2,,CXXOPTIONS="$CXXOPTIONS $1",$2) elif test -s conftest.out ; then cat conftest.out >&AC_FD_CC AC_MSG_RESULT(no) CXXFLAGS="$save_CXXFLAGS" $3 else AC_MSG_RESULT(no) CXXFLAGS="$save_CXXFLAGS" $3 fi else if test -s conftest.out ; then cat conftest.out >&AC_FD_CC fi AC_MSG_RESULT(no) CXXFLAGS="$save_CXXFLAGS" $3 fi else # Could not link with the option! AC_MSG_RESULT(no) fi else if test -s conftest2.out ; then cat conftest2.out >&AC_FD_CC fi AC_MSG_RESULT(no) CXXFLAGS="$save_CXXFLAGS" $3 fi else cat conftest.out >&AC_FD_CC AC_MSG_RESULT(no) $3 CXXFLAGS="$save_CXXFLAGS" fi else AC_MSG_RESULT(no) $3 if test -s conftest.out ; then cat conftest.out >&AC_FD_CC ; fi CXXFLAGS="$save_CXXFLAGS" fi else # Could not compile without the option! AC_MSG_RESULT(no) fi rm -f conftest* ]) armci-mpi/m4/aclocal_attr_alias.m40000644000175000017500000004512112662706250016600 0ustar mbanckmbanckdnl dnl Check for BSD or POSIZ style global symbol lister, nm. dnl If found, pac_path_NM_G contains the absolute athname of nm + options dnl pac_path_NM_G_type will be either POSIX or BSD. NM_G will be dnl pac_path_NM_G without the absolute path. Preference is BSD style. dnl dnl The test checks if nm accepts the known options and also if nm produces dnl the expected BSD or POSIX output format. dnl AC_DEFUN([PAC_PATH_NM_G],[ AC_MSG_CHECKING([for BSD/POSIX style global symbol lister]) AC_LANG_PUSH(C) AC_PATH_PROGS_FEATURE_CHECK(NM_G, nm, [ # Check if nm accepts -g and BSD or POSIX compatible flag. # Use the `sed 1q' to avoid HP-UX's unknown option message: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # # AIX's sed does not accept \+, 1) instead of doing 's|a\+||', do 's|aa*||' # or 2) instead of 's|A \+B|AB|g', do 's|A *B|AB|g' # Check if nm accepts -g case `${ac_path_NM_G} -g /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) ac_path_NM_G="${ac_path_NM_G} -g" # Check if nm accepts -B case `${ac_path_NM_G} -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([int iglobal;]) ],[ changequote(,) case `${ac_path_NM_G} -B conftest.$OBJEXT | sed -e 's|[0-9][0-9]* *[A-Z] *iglobal|XXXX|g'` in *XXXX*) pac_path_NM_G="${ac_path_NM_G} -B" pac_path_NM_G_type="BSD" ;; esac changequote([,]) ]) ;; *) # Check if nm accepts -P case `${ac_path_NM_G} -P /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([int iglobal;]) ],[ changequote(,) case `${ac_path_NM_G} -P conftest.$OBJEXT | sed -e 's|iglobal *[A-Z] *[0-9][0-9]*|XXXX|g'` in *XXXX*) pac_path_NM_G="${ac_path_NM_G} -P" pac_path_NM_G_type="POSIX" ;; esac changequote([,]) ]) ;; esac # Endof case `${ac_path_NM_G} -P ;; esac # Endof case `${ac_path_NM_G} -B ;; esac # Endof case `${ac_path_NM_G} -g if test "X$pac_path_NM_G" != "X" ; then AC_MSG_RESULT([$pac_path_NM_G_type style,$pac_path_NM_G]) NM_G="`echo $pac_path_NM_G | sed -e 's|^.*nm |nm |g'`" else AC_MSG_RESULT(no) fi ac_cv_path_NM_G=${ac_path_NM_G} ac_path_NM_G_found=: ], [AC_MSG_RESULT(no)], [$PATH$PATH_SEPARATOR/usr/ccs/bin/elf$PATH_SEPARATOR/usr/ccs/bin$PATH_SEPARATOR/usr/ucb$PATH_SEPARATOR/bin]) AC_LANG_POP(C) ]) dnl Endof AC_DEFUN([PAC_PATH_NM_G] dnl dnl PAC_C_MULTI_ATTR_ALIAS() dnl dnl The checks if multiple __attribute__((alias)) is available dnl If the multiple __attribute((alias)) support is found, dnl pac_c_multi_attr_alias=yes is set. dnl dnl The default is to do a runtime test. When cross_compiling=yes, dnl pac_path_NM_G will be used to determine the test result. dnl If CFLAGS(or CPPFLAGS) contains ATTR_ALIAS_DEBUG, the runtime will print dnl out addresses of struct(s) for debugging purpose. dnl dnl AC_DEFUN([PAC_C_MULTI_ATTR_ALIAS],[ AC_REQUIRE([PAC_PATH_NM_G]) AC_LANG_PUSH(C) AC_CHECK_HEADERS([stdio.h]) AC_MSG_CHECKING([for multiple __attribute__((alias)) support]) #Compile the "other" __attribute__ object file. AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ #if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) #include #endif struct mpif_cmblk_t_ { int imember; }; typedef struct mpif_cmblk_t_ mpif_cmblk_t; /* NOT initialize these structure so it appears in BSS or as COMMON symbols */ mpif_cmblk_t mpifcmb; mpif_cmblk_t MPIFCMB; /* Do the test in this file instead in the file where __attribute__((alias)) is used. This is needed for pgcc since pgcc seems to define aliased symbols if they are in the same file. */ /* We can't do the following comparision in one test: ilogical = (( &mpifcmb == ptr && &MPIFCMB == ptr ) ? TRUE : FALSE) ; because some compiler, like gcc 4.4.2's -O* optimizes the code such that the ilogical expression is FALSE. The likely reason is that mpifcmb and MPIFCMB are defined in the same scope in which C optimizer may have treated them as different objects (with different addresses), &mpifcmb != &MPIFCMB, before actually running the test and hence the illogical expression is assumed to be always FALSE. The solution taken here is to prevent the optimizer the opportunity to equate &mpifcmb and &MPIFCMB (in same scope), e.g. using 2 separate tests and combine the test results in a different scope. */ int same_addrs1( void *ptr ); int same_addrs1( void *ptr ) { #if defined(ATTR_ALIAS_DEBUG) printf( "others: addr(mpifcmb)=%p, addr(input ptr)=%p\n", &mpifcmb, ptr ); #endif return ( &mpifcmb == ptr ? 1 : 0 ); } int same_addrs2( void *ptr ); int same_addrs2( void *ptr ) { #if defined(ATTR_ALIAS_DEBUG) printf( "others: addr(MPIFCMB)=%p, addr(input ptr)=%p\n", &MPIFCMB, ptr ); #endif return ( &MPIFCMB == ptr ? 1 : 0 ); } ]) ],[ rm -f pac_conftest_other.$OBJEXT PAC_RUNLOG([cp conftest.$OBJEXT pac_conftest_other.$OBJEXT]) test -s pac_conftest_other.$OBJEXT && pac_c_attr_alias_other=yes dnl cp conftest.$ac_ext pac_conftest_other.$ac_ext dnl echo dnl echo "pac_conftest_other.$OBJEXT" dnl nm -P -g pac_conftest_other.$OBJEXT | grep -i "mpifcmb" ],[ pac_c_attr_alias_other=no ]) dnl Endof AC_COMPILE_IFELSE pac_c_attr_alias_main=no if test "$pac_c_attr_alias_other" = "yes" ; then # Save LIBS for later restoration. saved_LIBS="$LIBS" LIBS="pac_conftest_other.$OBJEXT $LIBS" # Link the "other" __attribute__ object file. AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) #include #endif struct mpif_cmblk_t_ { int imember; }; typedef struct mpif_cmblk_t_ mpif_cmblk_t; mpif_cmblk_t mpifcmbr = {0}; extern mpif_cmblk_t MPIFCMB __attribute__ ((alias("mpifcmbr"))); extern mpif_cmblk_t mpifcmb __attribute__ ((alias("mpifcmbr"))); extern int same_addrs1( void *ptr ); extern int same_addrs2( void *ptr ); ],[ int iaddr = 0; #if defined(ATTR_ALIAS_DEBUG) printf( "main: addr(mpifcmbr) = %p\n", &mpifcmbr ); printf( "main: addr(mpifcmb) = %p\n", &mpifcmb ); printf( "main: addr(MPIFCMB) = %p\n", &MPIFCMB ); #endif iaddr = same_addrs1( &mpifcmbr ) && same_addrs2( &mpifcmbr ); FILE *file = fopen( "pac_conftestval", "w" ); if (!file) return 1; fprintf( file, "%d\n", iaddr ); ]) ],[ rm -f pac_conftest_main$EXEEXT PAC_RUNLOG([cp conftest$EXEEXT pac_conftest_main$EXEEXT]) test -x pac_conftest_main$EXEEXT && pac_c_attr_alias_main=yes dnl cp conftest.$ac_ext pac_conftest_main.$ac_ext dnl echo dnl echo "pac_conftest_main$EXEEXT" dnl nm -P -g pac_conftest_main$EXEEXT | grep -i "mpifcmb" ],[ pac_c_attr_alias_main=no dnl cp conftest.$ac_ext pac_conftest_main.$ac_ext ]) dnl Endof AC_LINK_IFELSE # Restore the previously saved LIBS LIBS="$saved_LIBS" rm -f pac_conftest_other.$OBJEXT fi dnl Endof if test "$pac_c_attr_alias_other" = "yes" if test "$pac_c_attr_alias_main" = "yes" ; then if test "$cross_compiling" = "yes" ; then changequote(,) # echo "PAC CROSS-COMPILING" dnl # POSIX NM = nm -P format dnl if test "$pac_path_NM_G_type" = "POSIX" ; then addrs=`${pac_path_NM_G} ./pac_conftest_main$EXEEXT | grep -i mpifcmb | sed -e 's% *[a-zA-Z][a-zA-Z]* *[a-zA-Z] *\([0-9abcdef][0-9abcdef]*\).*%\1%g'` fi # BSD NM = nm -B format dnl if test "$pac_path_NM_G_type" = "BSD" ; then addrs=`${pac_path_NM_G} -g ./pac_conftest_main$EXEEXT | grep -i mpifcmb | sed -e "s% *\([0-9abcdef][0-9abcdef]*\) *[a-zA-Z] *[a-zA-Z][a-zA-A]*.*%\1%g"` fi changequote([,]) cmp_addr="" diff_addrs=no for addr in ${addrs} ; do if test "X${cmp_addr}" != "X" ; then if test "${cmp_addr}" != "${addr}" ; then diff_addrs=yes break fi else cmp_addr=${addr} fi done if test "$diff_addrs" != "yes" ; then dnl echo "Same addresses. Multiple aliases support" AC_MSG_RESULT([${NM_G} says yes]) pac_c_multi_attr_alias=yes else dnl echo "Different addresses. No multiple aliases support." AC_MSG_RESULT([${NM_G} says no]) pac_c_multi_attr_alias=no fi else # if test "$cross_compiling" != "yes" rm -f pac_conftestval ac_try="./pac_conftest_main$EXEEXT" if AC_TRY_EVAL(ac_try) ; then pac_c_attr_alias_val=0 if test -s pac_conftestval ; then eval pac_c_attr_alias_val=`cat pac_conftestval` fi if test "$pac_c_attr_alias_val" -eq 1 ; then AC_MSG_RESULT(yes) pac_c_multi_attr_alias=yes else AC_MSG_RESULT(no) pac_c_multi_attr_alias=no fi rm -f pac_conftestval fi fi dnl Endof if test "$cross_compiling" = "yes" rm -f pac_conftest_main$EXEEXT else AC_MSG_RESULT(no! link failure) pac_c_multi_attr_alias=no fi dnl Endof if test "$pac_c_attr_alias_main" = "yes" AC_LANG_POP(C) ]) dnl Endof AC_DEFUN([PAC_C_MULTI_ATTR_ALIAS] dnl dnl PAC_C_ATTR_ALIGNED() dnl dnl Check if __attribute__((aligned)) support is there. dnl If so, set pac_c_attr_aligned=yes. dnl dnl Do a link test instead of compile test to check if the linker dnl would emit an error. dnl AC_DEFUN([PAC_C_ATTR_ALIGNED],[ AC_LANG_PUSH(C) AC_MSG_CHECKING([for __attribute__((aligned)) support]) #Link the __attribute__ object file. AC_LINK_IFELSE([ AC_LANG_PROGRAM([ struct mpif_cmblk_t_ { int imembers[5]; }; typedef struct mpif_cmblk_t_ mpif_cmblk_t; mpif_cmblk_t mpifcmbr __attribute__((aligned)) = {0}; ],[]) ],[pac_c_attr_aligned=yes], [pac_c_attr_aligned=no]) AC_MSG_RESULT([$pac_c_attr_aligned]) AC_LANG_POP(C) ]) dnl dnl PAC_F2C_ATTR_ALIGNED_SIZE(ARRAY_SIZE, [OUTPUT_VAR], [MIN_ALIGNMENT]) dnl dnl ARRAY_SIZE : Size of the integer array within the fortran commmon block. dnl OUTPUT_VAR : Optional variable to be set. dnl if test succeeds, set OUTPUT_VAR=$pac_f2c_attr_aligned_str. dnl if test fails, set OUTPUT_VAR="unknown". dnl MIN_ALIGNMENT : Optional value. dnl Minimum alignment size to be used in OUTPUT_VAR. dnl pac_f2c_attr_aligned_str won't be modified. dnl dnl "pac_f2c_attr_aligned_str" will be set with dnl 1) __attribute__((aligned(ALIGNMENT_SIZE))), dnl 2) __attribute__((aligned)). dnl 3) "", i.e. empty string. dnl dnl 2) means the test can't find a good alignment value, but both the Fortran dnl and C compilers are OK with "aligned" which in principle means the C dnl compiler will pick the maximum useful alignment supported by the dnl architecture. dnl 3) means that the test has failed to find the alignment. dnl AC_DEFUN([PAC_F2C_ATTR_ALIGNED_SIZE],[ cmblksize=$1 AC_MSG_CHECKING([the minimum alignment of Fortran common block of $cmblksize integers]) dnl To find the minmium alignment of Fortran common block (of integer array) dnl as seen by C object file, C object files of various (typical) alignments dnl are linked to the Fortran code using the common block of integer array. # dnl Since the incorrect alignment results only a warning messages from the dnl fortran compiler(or linker), so we use "diff" to compare the fortran dnl compiler/linker output. We cannot use AC_LANG_WERROR, dnl i.e. ac_fc_werror_flag=yes, because compiler like pgf77 at version 10.x) dnl has non-zero stderr output if a fortran program is used in the linking. dnl The stderr contains the name of fortran program even if the linking is dnl successful. We could avoid the non-zero stderr output in pgf77 by dnl compiling everthing into object files and linking all the object files dnl with pgf77. Doing that would need us to use AC_TRY_EVAL instead of dnl AC_LINK_IFELSE, so "diff" approach is used instead. # dnl Using diff of compiler(linker) output requires a reference output file dnl as the base of diff. The process of creating this reference output file dnl has to be exactly the same as the testing process, because pgf77 has dnl the following weird behavour dnl pgf77 -o ftest ftest.f => when $?=0 with zero stderr output dnl pgf77 -o ftest ftest.f dummy.o => when $?=0 with non-zero stderr output. dnl stderr has "ftest.f:". dnl # First create a fortran CONFTEST which will be used repeatedly. AC_LANG_PUSH([Fortran]) dnl AC_LANG_PUSH([Fortran 77]) AC_LANG_CONFTEST([ AC_LANG_SOURCE([ program fconftest integer isize parameter (isize=$cmblksize) integer status_array(isize) common /mpifcmb/ status_array save /mpifcmb/ end ]) ]) AC_LANG_POP([Fortran]) dnl AC_LANG_POP([Fortran 77]) dnl dnl dnl # Compile a C dummy.$OBJEXT and link with Fortran test program to create # a reference linker output file, pac_align0.log, as the base of "diff". AC_LANG_PUSH([C]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],[ cp conftest.$ac_ext pac_conftest.c PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) saved_LIBS="$LIBS" LIBS="pac_conftest.$OBJEXT $LIBS" AC_LANG_PUSH([Fortran]) dnl AC_LANG_PUSH([Fortran 77]) saved_ac_link="$ac_link" ac_link="`echo $saved_ac_link | sed -e 's|>.*$|> $pac_logfile 2>\&1|g'`" pac_logfile="pac_align0.log" rm -f $pac_logfile AC_LINK_IFELSE([],[ pac_f2c_alignedn_diffbase=yes ],[ pac_f2c_alignedn_diffbase=no ]) # Be sure NOT to remove the conftest.f which is still needed for later use. # rm -f conftest.$ac_ext # Restore everything in autoconf that has been overwritten ac_link="$saved_ac_link" # restore previously saved LIBS LIBS="$saved_LIBS" AC_LANG_POP([Fortran]) dnl AC_LANG_POP([Fortran 77]) ],[ pac_f2c_alignedn_diffbase=no ]) AC_LANG_POP([C]) dnl dnl if test "$pac_f2c_alignedn_diffbase" = "yes" ; then # Initialize pac_result_str to empty string since part of the test # depends on pac_result_str is empty or non-empty string. pac_result_str="" # Initialize pac_f2c_attr_aligned_str to empty string and # it will remain as empty string if the following test fails. pac_f2c_attr_aligned_str="" for asize in 4 8 16 32 64 128 max ; do if test "$asize" != "max" ; then pac_attr_aligned_str="__attribute__((aligned($asize)))" else pac_attr_aligned_str="__attribute__((aligned))" fi AC_LANG_PUSH([C]) #Compile the __attribute__ object file. AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ changequote(,) struct mpif_cmblk_t_ { $MPI_FINT imembers[$cmblksize]; }; changequote([,]) typedef struct mpif_cmblk_t_ mpif_cmblk_t; mpif_cmblk_t mpifcmbr $pac_attr_aligned_str = {0}; extern mpif_cmblk_t _CMPIFCMB __attribute__ ((alias("mpifcmbr"))); extern mpif_cmblk_t MPIFCMB __attribute__ ((alias("mpifcmbr"))); extern mpif_cmblk_t MPIFCMB_ __attribute__ ((alias("mpifcmbr"))); extern mpif_cmblk_t _Cmpifcmb __attribute__ ((alias("mpifcmbr"))); extern mpif_cmblk_t mpifcmb __attribute__ ((alias("mpifcmbr"))); extern mpif_cmblk_t mpifcmb_ __attribute__ ((alias("mpifcmbr"))); ]) ],[ cp conftest.$ac_ext pac_conftest.c PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) saved_LIBS="$LIBS" LIBS="pac_conftest.$OBJEXT $LIBS" AC_LANG_PUSH([Fortran]) dnl AC_LANG_PUSH([Fortran 77]) saved_ac_link="$ac_link" ac_link="`echo $saved_ac_link | sed -e 's|>.*$|> $pac_logfile 2>\&1|g'`" pac_logfile="pac_align1.log" rm -f $pac_logfile # Use conftest.f created in CONFTEST. AC_LINK_IFELSE([],[ PAC_RUNLOG_IFELSE([diff -b pac_align0.log pac_align1.log],[ pac_attr_alignedn=yes ],[ pac_attr_alignedn=no cat $pac_logfile >&AS_MESSAGE_LOG_FD echo "failed C program was:" >&AS_MESSAGE_LOG_FD cat pac_conftest.c >&AS_MESSAGE_LOG_FD echo "failed Fortran program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&AS_MESSAGE_LOG_FD ]) ],[ pac_attr_alignedn=no ]) # Restore everything in autoconf that has been overwritten ac_link="$saved_ac_link" # restore previously saved LIBS LIBS="$saved_LIBS" AC_LANG_POP([Fortran]) dnl AC_LANG_POP([Fortran 77]) # remove previously generated object file and C file. rm -f pac_conftest.$OBJEXT pac_conftest.c rm -f $pac_logfile if test "$pac_attr_alignedn" = yes ; then ifelse([$3],[],[ pac_result_str="$asize" pac_f2c_attr_aligned_str="$pac_attr_aligned_str" break ],[ if test "$asize" != "max" -a "$asize" -lt "$3" ; then if test "X$pac_result_str" = "X" ; then pac_result_str="$asize" pac_f2c_attr_aligned_str="$pac_attr_aligned_str" fi continue else pac_f2c_attr_aligned_str="$pac_attr_aligned_str" if test "X$pac_result_str" != "X" ; then pac_result_str="$pac_result_str, too small! reset to $asize" else pac_result_str="$asize" fi break fi ]) fi ], [ pac_attr_alignedn=no ]) AC_LANG_POP([C]) done ifelse([$2],[],[],[$2="$pac_f2c_attr_aligned_str"]) else pac_result_str="" # Since the test fails, set pac_f2c_attr_aligned_str to empty string. pac_f2c_attr_aligned_str="" fi if test "X$pac_result_str" != "X" ; then AC_MSG_RESULT([$pac_result_str]) else AC_MSG_RESULT([unknown]) fi rm -f pac_align0.log ]) dnl armci-mpi/m4/ax_prefix_config_h.m40000644000175000017500000002170012662706250016615 0ustar mbanckmbanck# =========================================================================== # http://autoconf-archive.cryp.to/ax_prefix_config_h.html # =========================================================================== # # SYNOPSIS # # AX_PREFIX_CONFIG_H [(OUTPUT-HEADER [,PREFIX [,ORIG-HEADER]])] # # DESCRIPTION # # This is a new variant from ac_prefix_config_ this one will use a # lowercase-prefix if the config-define was starting with a # lowercase-char, e.g. "#define const", "#define restrict", or "#define # off_t", (and this one can live in another directory, e.g. # testpkg/config.h therefore I decided to move the output-header to be the # first arg) # # takes the usual config.h generated header file; looks for each of the # generated "#define SOMEDEF" lines, and prefixes the defined name (ie. # makes it "#define PREFIX_SOMEDEF". The result is written to the output # config.header file. The PREFIX is converted to uppercase for the # conversions. # # Defaults: # # OUTPUT-HEADER = $PACKAGE-config.h # PREFIX = $PACKAGE # ORIG-HEADER, from AM_CONFIG_HEADER(config.h) # # Your configure.ac script should contain both macros in this order, and # unlike the earlier variations of this prefix-macro it is okay to place # the AX_PREFIX_CONFIG_H call before the AC_OUTPUT invokation. # # Example: # # AC_INIT(config.h.in) # config.h.in as created by "autoheader" # AM_INIT_AUTOMAKE(testpkg, 0.1.1) # makes #undef VERSION and PACKAGE # AM_CONFIG_HEADER(config.h) # prep config.h from config.h.in # AX_PREFIX_CONFIG_H(mylib/_config.h) # prep mylib/_config.h from it.. # AC_MEMORY_H # makes "#undef NEED_MEMORY_H" # AC_C_CONST_H # makes "#undef const" # AC_OUTPUT(Makefile) # creates the "config.h" now # # and also mylib/_config.h # # if the argument to AX_PREFIX_CONFIG_H would have been omitted then the # default outputfile would have been called simply "testpkg-config.h", but # even under the name "mylib/_config.h" it contains prefix-defines like # # #ifndef TESTPKG_VERSION # #define TESTPKG_VERSION "0.1.1" # #endif # #ifndef TESTPKG_NEED_MEMORY_H # #define TESTPKG_NEED_MEMORY_H 1 # #endif # #ifndef _testpkg_const # #define _testpkg_const _const # #endif # # and this "mylib/_config.h" can be installed along with other # header-files, which is most convenient when creating a shared library # (that has some headers) where some functionality is dependent on the # OS-features detected at compile-time. No need to invent some # "mylib-confdefs.h.in" manually. :-) # # Note that some AC_DEFINEs that end up in the config.h file are actually # self-referential - e.g. AC_C_INLINE, AC_C_CONST, and the AC_TYPE_OFF_T # say that they "will define inline|const|off_t if the system does not do # it by itself". You might want to clean up about these - consider an # extra mylib/conf.h that reads something like: # # #include # #ifndef _testpkg_const # #define _testpkg_const const # #endif # # and then start using _testpkg_const in the header files. That is also a # good thing to differentiate whether some library-user has starting to # take up with a different compiler, so perhaps it could read something # like this: # # #ifdef _MSC_VER # #include # #else # #include # #endif # #ifndef _testpkg_const # #define _testpkg_const const # #endif # # LAST MODIFICATION # # 2008-04-12 # # COPYLEFT # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2008 Marten Svantesson # Copyright (c) 2008 Gerald Point # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Macro Archive. When you make and # distribute a modified version of the Autoconf Macro, you may extend this # special exception to the GPL to apply to your modified version as well. AC_DEFUN([AX_PREFIX_CONFIG_H],[dnl AC_BEFORE([AC_CONFIG_HEADERS],[$0])dnl AC_CONFIG_COMMANDS([ifelse($1,,$PACKAGE-config.h,$1)],[dnl AS_VAR_PUSHDEF([_OUT],[ac_prefix_conf_OUT])dnl AS_VAR_PUSHDEF([_DEF],[ac_prefix_conf_DEF])dnl AS_VAR_PUSHDEF([_PKG],[ac_prefix_conf_PKG])dnl AS_VAR_PUSHDEF([_LOW],[ac_prefix_conf_LOW])dnl AS_VAR_PUSHDEF([_UPP],[ac_prefix_conf_UPP])dnl AS_VAR_PUSHDEF([_INP],[ac_prefix_conf_INP])dnl m4_pushdef([_script],[conftest.prefix])dnl m4_pushdef([_symbol],[m4_cr_Letters[]m4_cr_digits[]_])dnl _OUT=`echo ifelse($1, , $PACKAGE-config.h, $1)` _DEF=`echo _$_OUT | sed -e "y:m4_cr_letters:m4_cr_LETTERS[]:" -e "s/@<:@^m4_cr_Letters@:>@/_/g"` _PKG=`echo ifelse($2, , $PACKAGE, $2)` _LOW=`echo _$_PKG | sed -e "y:m4_cr_LETTERS-:m4_cr_letters[]_:"` _UPP=`echo $_PKG | sed -e "y:m4_cr_letters-:m4_cr_LETTERS[]_:" -e "/^@<:@m4_cr_digits@:>@/s/^/_/"` _INP=`echo "ifelse($3,,,$3)" | sed -e 's/ *//'` if test ".$_INP" = "."; then for ac_file in : $CONFIG_HEADERS; do test "_$ac_file" = _: && continue case "$ac_file" in *.h) _INP=$ac_file ;; *) esac test ".$_INP" != "." && break done fi if test ".$_INP" = "."; then case "$_OUT" in */*) _INP=`basename "$_OUT"` ;; *-*) _INP=`echo "$_OUT" | sed -e "s/@<:@_symbol@:>@*-//"` ;; *) _INP=config.h ;; esac fi if test -z "$_PKG" ; then AC_MSG_ERROR([no prefix for _PREFIX_PKG_CONFIG_H]) else if test ! -f "$_INP" ; then if test -f "$srcdir/$_INP" ; then _INP="$srcdir/$_INP" fi fi AC_MSG_NOTICE(creating $_OUT - prefix $_UPP for $_INP defines) if test -f $_INP ; then echo "s/^@%:@undef *\\(@<:@m4_cr_LETTERS[]_@:>@\\)/@%:@undef $_UPP""_\\1/" > _script echo "s/^@%:@undef *\\(@<:@m4_cr_letters@:>@\\)/@%:@undef $_LOW""_\\1/" >> _script echo "s/^@%:@def[]ine *\\(@<:@m4_cr_LETTERS[]_@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_UPP""_\\1 \\" >> _script echo "@%:@def[]ine $_UPP""_\\1 \\2 \\" >> _script echo "@%:@endif/" >>_script echo "s/^@%:@def[]ine *\\(@<:@m4_cr_letters@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_LOW""_\\1 \\" >> _script echo "@%:@define $_LOW""_\\1 \\2 \\" >> _script echo "@%:@endif/" >> _script # now executing _script on _DEF input to create _OUT output file echo "@%:@ifndef $_DEF" >$tmp/pconfig.h echo "@%:@def[]ine $_DEF 1" >>$tmp/pconfig.h echo ' ' >>$tmp/pconfig.h echo /'*' $_OUT. Generated automatically at end of configure. '*'/ >>$tmp/pconfig.h sed -f _script $_INP >>$tmp/pconfig.h echo ' ' >>$tmp/pconfig.h echo '/* once:' $_DEF '*/' >>$tmp/pconfig.h echo "@%:@endif" >>$tmp/pconfig.h if cmp -s $_OUT $tmp/pconfig.h 2>/dev/null; then AC_MSG_NOTICE([$_OUT is unchanged]) else ac_dir=`AS_DIRNAME(["$_OUT"])` AS_MKDIR_P(["$ac_dir"]) rm -f "$_OUT" mv $tmp/pconfig.h "$_OUT" fi cp _script _configs.sed else AC_MSG_ERROR([input file $_INP does not exist - skip generating $_OUT]) fi rm -f conftest.* fi m4_popdef([_symbol])dnl m4_popdef([_script])dnl AS_VAR_POPDEF([_INP])dnl AS_VAR_POPDEF([_UPP])dnl AS_VAR_POPDEF([_LOW])dnl AS_VAR_POPDEF([_PKG])dnl AS_VAR_POPDEF([_DEF])dnl AS_VAR_POPDEF([_OUT])dnl ],[PACKAGE="$PACKAGE"])]) dnl implementation note: a bug report (31.5.2005) from Marten Svantesson points dnl out a problem where `echo "\1"` results in a Control-A. The unix standard dnl http://www.opengroup.org/onlinepubs/000095399/utilities/echo.html dnl defines all backslash-sequences to be inherently non-portable asking dnl for replacement mit printf. Some old systems had problems with that dnl one either. However, the latest libtool (!) release does export an $ECHO dnl (and $echo) that does the right thing - just one question is left: what dnl was the first version to have it? Is it greater 2.58 ? armci-mpi/m4/ax_tls.m40000644000175000017500000000625612662706250014277 0ustar mbanckmbanck# =========================================================================== # http://www.nongnu.org/autoconf-archive/ax_tls.html # =========================================================================== # # SYNOPSIS # # AX_TLS # # DESCRIPTION # # Provides a test for the compiler support of thread local storage (TLS) # extensions. Defines TLS if it is found. Currently only knows about GCC # and MSVC. I think SunPro uses the same as GCC, and Borland apparently # supports either. # # LICENSE # # Copyright (c) 2008 Alan Woodland # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. AC_DEFUN([AX_TLS], [ AC_MSG_CHECKING(for thread local storage specifier) AC_CACHE_VAL(ac_cv_tls, [ ax_tls_keywords="__thread __declspec(thread) none" for ax_tls_keyword in $ax_tls_keywords; do case $ax_tls_keyword in none) ac_cv_tls=none ; break ;; *) # MPICH2 modification: This was an AC_TRY_COMPILE before, but # Darwin with non-standard compilers will accept __thread at # compile time but fail to link due to an undefined # "__emutls_get_address" symbol unless -lgcc_eh is added to the # link line. AC_LINK_IFELSE( [AC_LANG_PROGRAM([$ax_tls_keyword int bar = 5;],[++bar;])], [ac_cv_tls=$ax_tls_keyword ; break], [ac_cv_tls=none]) esac done ]) if test "$ac_cv_tls" != "none"; then # MPICH2 modification: this was "TLS" before instead of # "MPIU_TLS_SPECIFIER", but TLS had a reasonably high chance of conflicting # with a system library. AC_DEFINE_UNQUOTED([MPIU_TLS_SPECIFIER], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) fi AC_MSG_RESULT($ac_cv_tls) ]) armci-mpi/m4/aclocal_am.m40000644000175000017500000000054712662706250015055 0ustar mbanckmbanckdnl AM_IGNORE is an extension that tells (a patched) automake not to dnl include the specified AC_SUBST variable in the Makefile.in that dnl automake generates. We don't use AC_DEFUN, since aclocal will dnl then complain that AM_IGNORE is a duplicate (if you are using the dnl patched automake/aclocal). m4_ifdef([AM_IGNORE],[],[m4_define([AM_IGNORE],[])]) armci-mpi/m4/aclocal_fc.m40000644000175000017500000007274312662706250015057 0ustar mbanckmbanckdnl /*D dnl PAC_PROG_FC([COMPILERS]) dnl dnl COMPILERS is a space separated list of Fortran 77 compilers to search dnl for. Fortran 95 isn't strictly backwards-compatible with Fortran 77, dnl but `f95' is worth trying. dnl dnl Compilers are ordered by dnl 1. F77, F90, F95 dnl 2. Good/tested native compilers, bad/untested native compilers dnl 3. Wrappers around f2c go last. dnl dnl `fort77' is a wrapper around `f2c'. dnl It is believed that under HP-UX `fort77' is the name of the native dnl compiler. On some Cray systems, fort77 is a native compiler. dnl frt is the Fujitsu F77 compiler. dnl pgf77 and pgf90 are the Portland Group F77 and F90 compilers. dnl xlf/xlf90/xlf95 are IBM (AIX) F77/F90/F95 compilers. dnl lf95 is the Lahey-Fujitsu compiler. dnl fl32 is the Microsoft Fortran "PowerStation" compiler. dnl af77 is the Apogee F77 compiler for Intergraph hardware running CLIX. dnl epcf90 is the "Edinburgh Portable Compiler" F90. dnl fort is the Compaq Fortran 90 (now 95) compiler for Tru64 and Linux/Alpha. dnl pathf90 is the Pathscale Fortran 90 compiler dnl ifort is another name for the Intel f90 compiler dnl efc - An older Intel compiler (?) dnl ifc - An older Intel compiler dnl fc - A compiler on some unknown system. This has been removed because dnl it may also be the name of a command for something other than dnl the Fortran compiler (e.g., fc=file system check!) dnl D*/ AC_DEFUN([PAC_PROG_FC],[ PAC_PUSH_FLAG([FCFLAGS]) AC_PROG_FC([m4_default([$1], [ifort pgf90 pathf90 pathf95 xlf90 xlf95 f90 epcf90 f95 fort lf95 \ gfortran g95 ifc efc])]) PAC_POP_FLAG([FCFLAGS]) ]) dnl dnl PAC_FC_EXT checks for the default Fortran 90 program extension, f90 then f. dnl This could be replaced by AC_FC_SRCEXT but since AC_FC_SRCEXT dnl adds FCFLAGS_ext, which is used to modify FCFLAGS or Makefile.in. dnl So will do this later. dnl AC_DEFUN([PAC_FC_EXT],[ AC_MSG_CHECKING([for extension for Fortran 90 programs]) ac_fc_srcext="f90" AC_LANG_PUSH(Fortran) AC_COMPILE_IFELSE([ AC_LANG_PROGRAM() ],[ AC_MSG_RESULT([f90]) ],[ ac_fc_srcext="f" AC_COMPILE_IFELSE([ AC_LANG_PROGRAM() ],[ AC_MSG_RESULT([f]) ],[ AC_MSG_RESULT([unknown!]) ]) ]) AC_LANG_POP(Fortran) ]) dnl dnl Internal routine for testing F90 dnl PAC_PROG_FC_WORKS() dnl AC_DEFUN([PAC_PROG_FC_WORKS],[ AC_REQUIRE([PAC_FC_EXT]) AC_LANG_PUSH(Fortran) AC_MSG_CHECKING([whether the Fortran 90 compiler ($FC $FCFLAGS $LDFLAGS) works]) AC_LINK_IFELSE([ AC_LANG_SOURCE([ program conftest integer, dimension(10) :: n end ]) ],[ pac_cv_prog_fc_works="yes" AC_MSG_RESULT([$pac_cv_prog_fc_works]) AC_MSG_CHECKING([whether the Fortran 90 compiler ($FC $FCFLAGS $LDFLAGS) is a cross-compiler]) AC_RUN_IFELSE([], [pac_cv_prog_fc_cross="no"], [pac_cv_prog_fc_cross="yes"], [pac_cv_prog_fc_cross="$cross_compiling"] ) AC_MSG_RESULT($pac_cv_prog_fc_cross) ],[ pac_cv_prog_fc_works="no" AC_MSG_WARN([installation or configuration problem: Fortran 90 compiler cannot create executables.]) ]) # The intel compiler sometimes generates these work.pc and .pcl files rm -f work.pc work.pcl AC_LANG_POP(Fortran) dnl cross_compiling no longer maintained by autoconf as part of the dnl AC_LANG changes. If we set it here, a later AC_LANG may not dnl restore it (in the case where one compiler claims to be a cross compiler dnl and another does not) dnl cross_compiling=$pac_cv_prog_f90_cross ]) dnl/*D dnl PAC_PROG_FC_INT_KIND - Determine kind parameter for an integer with dnl the specified number of bytes. dnl dnl Synopsis: dnl PAC_PROG_FC_INT_KIND(variable-to-set,number-of-bytes,[cross-size]) dnl dnl D*/ AC_DEFUN([PAC_PROG_FC_INT_KIND],[ # Set the default $1=-1 if test "$pac_cv_prog_fc_cross" = "yes" ; then $1="$3" else AC_LANG_PUSH(Fortran) AC_MSG_CHECKING([for Fortran 90 integer kind for $2-byte integers]) # Convert bytes to digits case $2 in 1) sellen=2 ;; 2) sellen=4 ;; 4) sellen=8 ;; 8) sellen=16 ;; 16) sellen=30 ;; *) sellen=8 ;; esac # Check for cached value eval testval=\$"pac_cv_prog_fc_int_kind_$sellen" if test -n "$testval" ; then AC_MSG_RESULT([$testval (cached)]) $1=$testval else KINDVAL="unavailable" eval "pac_cv_prog_fc_int_kind_$sellen"=-1 AC_RUN_IFELSE([ AC_LANG_SOURCE([ program main integer ii ii = selected_int_kind($sellen) open(8, file="conftest1.out", form="formatted") write (8,*) ii close(8) stop end ]) ],[pac_run_ok=yes],[pac_run_ok=no]) if test "$pac_run_ok" = "yes" ; then if test -s conftest1.out ; then # Because of write, there may be a leading blank. KINDVAL=`cat conftest1.out | sed 's/ //g'` eval "pac_cv_prog_fc_int_kind_$sellen"=$KINDVAL $1=$KINDVAL fi fi AC_MSG_RESULT([$KINDVAL]) fi # not cached AC_LANG_POP(Fortran) fi # is not cross compiling ])dnl dnl dnl ------------------------------------------------------------------------ dnl Special characteristics that have no autoconf counterpart but that dnl we need as part of the Fortran 90 support. To distinquish these, they dnl have a [PAC] prefix. dnl dnl dnl PAC_FC_MODULE_EXT(action if found,action if not found) dnl AC_DEFUN([PAC_FC_MODULE_EXT], [AC_CACHE_CHECK([for Fortran 90 module extension], pac_cv_fc_module_ext,[ pac_cv_fc_module_case="unknown" AC_LANG_PUSH(Fortran) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ module conftest integer n parameter (n=1) end module conftest ]) ],[ dnl Look for module name dnl First, try to find known names. This avoids confusion caused by dnl additional files (like .stb created by some versions of pgf90) dnl Early versions of the Intel compiler used "d" as the module extension; dnl we include that just to finish the test as early as possible. for name in conftest CONFTEST ; do for ext in mod MOD d ; do if test -s $name.$ext ; then if test $name = conftest ; then pac_cv_fc_module_case=lower else pac_cv_fc_module_case=upper fi pac_cv_fc_module_ext=$ext pac_MOD=$ext break fi done if test -n "$pac_cv_fc_module_ext" ; then break ; fi done if test -z "$pac_MOD" ; then pac_MOD=`ls conftest.* 2>&1 | grep -v conftest.${ac_fc_srcext} | grep -v conftest.o` pac_MOD=`echo $pac_MOD | sed -e 's/conftest\.//g'` pac_cv_fc_module_case="lower" if test "X$pac_MOD" = "X" ; then pac_MOD=`ls CONFTEST* 2>&1 | grep -v CONFTEST.f | grep -v CONFTEST.o` pac_MOD=`echo $pac_MOD | sed -e 's/CONFTEST\.//g'` if test -n "$pac_MOD" -a -s "CONFTEST.$pac_MOD" ; then testname="CONFTEST" pac_cv_fc_module_case="upper" else # Clear because we must have gotten an error message pac_MOD="" fi fi if test -z "$pac_MOD" ; then pac_cv_fc_module_ext="unknown" else pac_cv_fc_module_ext=$pac_MOD fi fi ],[ pac_cv_fc_module_ext="unknown" ]) AC_LANG_POP(Fortran) ]) dnl dnl dnl AC_SUBST(FCMODEXT) if test "$pac_cv_fc_module_ext" = "unknown" ; then ifelse($2,,:,[$2]) else ifelse($1,,FCMODEXT=$pac_MOD,[$1]) fi ]) dnl dnl dnl PAC_FC_MODULE_INCFLAG AC_DEFUN([PAC_FC_MODULE_INCFLAG],[ AC_CACHE_CHECK([for Fortran 90 module include flag], pac_cv_fc_module_incflag,[ AC_REQUIRE([PAC_FC_MODULE_EXT]) AC_LANG_PUSH(Fortran) AC_LANG_CONFTEST([ AC_LANG_SOURCE([ module conf integer n parameter (n=1) end module conf ]) ]) pac_madedir="no" if test ! -d conf ; then mkdir conftestdir ; pac_madedir="yes"; fi if test "$pac_cv_fc_module_case" = "upper" ; then pac_module="CONF.$pac_cv_fc_module_ext" else pac_module="conf.$pac_cv_fc_module_ext" fi AC_COMPILE_IFELSE([],[ if test -s "$pac_module" ; then mv $pac_module conftestdir # Remove any temporary files, and hide the work.pc file # (if the compiler generates them) if test -f work.pc ; then mv -f work.pc conftest.pc fi rm -f work.pcl else AC_MSG_WARN([Unable to build a simple Fortran 90 module]) # echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD # cat conftest.$ac_ext >&AS_MESSAGE_LOG_FD _AC_MSG_LOG_CONFTEST fi ], [] ) # Remove the conftest* after AC_LANG_CONFTEST rm -rf conftest.dSYM rm -f conftest.$ac_ext dnl Create the conftest here so the test isn't created everytime inside loop. AC_LANG_CONFTEST([AC_LANG_PROGRAM([],[use conf])]) # Save the original FCFLAGS saved_FCFLAGS="$FCFLAGS" pac_cv_fc_module_incflag="" for inchdr in '-I' '-M' '-p' ; do FCFLAGS="$saved_FCFLAGS ${inchdr}conftestdir" AC_COMPILE_IFELSE([],[pac_cv_fc_module_incflag="$inchdr" ; break]) done if test "X$pac_cv_fc_module_incflag" = "X" ; then if test -s conftest.pc ; then mv conftest.pc conftestdir/mpimod.pc echo "mpimod.pc" > conftestdir/mpimod.pcl echo "`pwd`/conftestdir/mpimod.pc" >> conftestdir/mpimod.pcl inchdr='-cl,' FCFLAGS="$save_FCFLAGS ${inchdr}conftestdir" AC_COMPILE_IFELSE([], [pac_fcompile_ok=yes], [pac_fcompile_ok=no]) if test "$pac_fcompile_ok" = "yes" ; then pac_cv_fc_module_incflag="$inchdr" # Not quite right; see the comments that follow AC_MSG_RESULT([-cl,filename where filename contains a list of files and directories]) FC_WORK_FILES_ARG="-cl,mpimod.pcl" FCMODINCSPEC="-cl,/mod.pcl" else # The version of the Intel compiler that I have refuses to let # you put the "work catalog" list anywhere but the current directory. pac_cv_fc_module_incflag="Unavailable!" fi else # Early versions of the Intel ifc compiler required a *file* # containing the names of files that contained the names of the # # -cl,filename.pcl # filename.pcl contains # fullpathname.pc # The "fullpathname.pc" is generated, I believe, when a module is # compiled. # Intel compilers use a wierd system: -cl,filename.pcl . If no file is # specified, work.pcl and work.pc are created. However, if you specify # a file, it must contain a the name of a file ending in .pc . Ugh! pac_cv_fc_module_incflag="unknown" fi fi # Restore the original FCFLAGS FCFLAGS="$saved_FCFLAGS" if test "$pac_madedir" = "yes" ; then rm -rf conftestdir ; fi # Remove the conftest* after AC_LANG_CONFTEST # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* AC_LANG_POP(Fortran) ]) AC_SUBST(FC_WORK_FILES_ARG) AC_SUBST(FCMODINCFLAG) FCMODINCFLAG=$pac_cv_fc_module_incflag ]) dnl dnl dnl AC_DEFUN([PAC_FC_MODULE],[ PAC_FC_MODULE_EXT PAC_FC_MODULE_INCFLAG ]) dnl dnl PAC_FC_AND_F77_COMPATIBLE([action-if-true],[action-if-false]) dnl dnl Determine whether object files compiled with Fortran 77 can be dnl linked to Fortran 90 main programs. dnl dnl The test uses a name that includes an underscore unless the 3rd dnl argument provides another routine name. dnl AC_DEFUN([PAC_FC_AND_F77_COMPATIBLE],[ AC_REQUIRE([PAC_PROG_FC_WORKS]) AC_CACHE_CHECK([whether Fortran 90 compiler works with Fortran 77 compiler], pac_cv_fc_and_f77,[ pacTestRoutine=foo_abc ifelse([$3],,,[eval pacTestRoutine=$3]) pac_cv_fc_and_f77="unknown" # compile the f77 program and link with the f90 program # The reverse may not work because the Fortran 90 environment may # expect to be in control (and to provide library files unknown to any other # environment, even Fortran 77!) AC_LANG_PUSH(Fortran 77) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ subroutine ${pacTestRoutine}(b) integer b b = b + 1 end ]) ],[ # pac_f77compile_ok=yes mv conftest.$OBJEXT pac_f77conftest.$OBJEXT # Save original LIBS, prepend previously generated object file to LIBS saved_LIBS="$LIBS" LIBS="pac_f77conftest.$OBJEXT $LIBS" AC_LANG_PUSH(Fortran) AC_LINK_IFELSE([ AC_LANG_SOURCE([ program main integer a a = 1 call ${pacTestRoutine}(a) end ]) ],[pac_cv_fc_and_f77=yes],[pac_cv_fc_and_f77=no]) # Some versions of the Intel compiler produce these two files rm -f work.pc work.pcl # Restore LIBS LIBS="$saved_LIBS" AC_LANG_POP(Fortran) # remove previously generated object file. rm -f pac_f77conftest.$OBJEXT ], [ # pac_f77compile_ok=no pac_cv_fc_and_f77=no ]) AC_LANG_POP(Fortran 77) # Perform the requested action based on whether the test succeeded if test "$pac_cv_fc_and_f77" = yes ; then ifelse($1,,:,[$1]) else ifelse($2,,:,[$2]) AC_MSG_WARN([See config.log for the failed test program and its output.]) fi ]) dnl ]) dnl dnl dnl /*D dnl PAC_PROG_FC_HAS_POINTER - Determine if Fortran allows pointer type dnl dnl Synopsis: dnl PAC_PROG_FC_HAS_POINTER(action-if-true,action-if-false) dnl D*/ AC_DEFUN([PAC_PROG_FC_HAS_POINTER],[ AC_CACHE_CHECK([whether Fortran 90 has Cray-style pointer declaration], pac_cv_prog_fc_has_pointer,[ AC_LANG_PUSH(Fortran) AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([],[ integer M pointer (MPTR,M) data MPTR/0/ ]) ],[ pac_cv_prog_fc_has_pointer="yes" ],[ pac_cv_prog_fc_has_pointer="no" ]) dnl Endof AC_COMPILE_IFELSE AC_LANG_POP(Fortran) ]) if test "$pac_cv_prog_fc_has_pointer" = "yes" ; then ifelse([$1],,:,[$1]) else ifelse([$2],,:,[$2]) fi ]) dnl dnl dnl AC_DEFUN([PAC_PROG_FC_AND_C_STDIO_LIBS],[ # To simply the code in the cache_check macro, chose the routine name # first, in case we need it confname=conf1_ case "$pac_cv_prog_f77_name_mangle" in "lower underscore") confname=conf1_ ;; "upper stdcall") confname=CONF1 ;; upper) confname=CONF1 ;; "lower doubleunderscore") confname=conf1_ ;; lower) confname=conf1 ;; "mixed underscore") confname=conf1_ ;; mixed) confname=conf1 ;; esac AC_CACHE_CHECK([what libraries are needed to link Fortran90 programs with C routines that use stdio],pac_cv_prog_fc_and_c_stdio_libs,[ pac_cv_prog_fc_and_c_stdio_libs=unknown AC_LANG_PUSH(C) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ #include int $confname( int a ) { printf( "The answer is %d\n", a ); fflush(stdout); return 0; } ]) ],[ pac_compile_ok=yes mv conftest.$OBJEXT pac_conftest.$OBJEXT # Save LIBS and prepend object file to LIBS saved_LIBS="$LIBS" LIBS="pac_conftest.$OBJEXT $LIBS" AC_LANG_PUSH(Fortran) AC_LINK_IFELSE([ AC_LANG_PROGRAM([],[call conf1(0)]) ],[ pac_cv_prog_fc_and_c_stdio_libs=none ],[ # Try again with -lSystemStubs LIBS="$LIBS -lSystemStubs" AC_LINK_IFELSE([],[ pac_cv_prog_fc_and_c_stdio_libs="-lSystemStubs" ],[]) ]) LIBS="$saved_LIBS" AC_LANG_POP(Fortran) rm -f pac_conftest.$OBJEXT ]) AC_LANG_POP(C) dnl if test "$pac_cv_prog_fc_and_c_stdio_libs" != none -a \ "$pac_cv_prog_fc_and_c_stdio_libs" != unknown ; then FC_OTHER_LIBS="$FC_OTHER_LIBS $pac_cv_prog_fc_and_c_stdio_libs" fi ]) dnl ]) dnl dnl/*D dnl PAC_FC_CHECK_COMPILER_OPTION - Check that a FC compiler option is dnl accepted without warning messages dnl dnl Synopsis: dnl PAC_FC_CHECK_COMPILER_OPTION(optionname,action-if-ok,action-if-fail) dnl dnl Output Effects: dnl dnl If no actions are specified, a working value is added to 'FCOPTIONS' dnl dnl Notes: dnl This is now careful to check that the output is different, since dnl some compilers are noisy. dnl dnl We are extra careful to prototype the functions in case compiler options dnl that complain about poor code are in effect. dnl dnl Because this is a long script, we have ensured that you can pass a dnl variable containing the option name as the first argument. dnl D*/ AC_DEFUN([PAC_FC_CHECK_COMPILER_OPTION],[ AC_MSG_CHECKING([whether Fortran 90 compiler accepts option $1]) pac_opt="$1" AC_LANG_PUSH(Fortran) dnl Instead of defining our own ac_link and ac_compile and do AC_TRY_EVAL dnl on these variables. We modify ac_link and ac_compile used by AC_*_IFELSE dnl by piping the output of the command to a logfile. The reason is that dnl 1) AC_TRY_EVAL is discouraged by Autoconf. 2) defining our ac_link and dnl ac_compile could mess up the usage and order of FCFLAGS, LDFLAGS dnl and LIBS in these commands, i.e. deviate from how GNU standard uses dnl these variables. dnl dnl Replace " >&AS_MESSAGE_LOG_FD" by "> file 2>&1" in ac_link and ac_compile pac_link="`echo $ac_link | sed -e 's|>.*$|> $pac_logfile 2>\&1|g'`" dnl echo "ac_link=\"$ac_link\"" dnl echo "pac_link=\"$pac_link\"" saved_ac_link="$ac_link" ac_link="$pac_link" dnl echo "ac_link=\"$ac_link\"" pac_compile="`echo $ac_compile | sed -e 's|>.*$|> $pac_logfile 2>\&1|g'`" dnl echo "ac_compile=\"$ac_compile\"" dnl echo "pac_compile=\"$pac_compile\"" saved_ac_compile="$ac_compile" ac_compile="$pac_compile" dnl echo "ac_compile=\"$ac_compile\"" FCFLAGS_orig="$FCFLAGS" FCFLAGS_opt="$pac_opt $FCFLAGS" pac_result="unknown" AC_LANG_CONFTEST([AC_LANG_PROGRAM()]) FCFLAGS="$FCFLAGS_orig" pac_logfile="pac_test1.log" rm -f $pac_logfile AC_LINK_IFELSE([], [ FCFLAGS="$FCFLAGS_opt" pac_logfile="pac_test2.log" rm -f $pac_logfile AC_LINK_IFELSE([], [ PAC_RUNLOG_IFELSE([diff -b pac_test1.log pac_test2.log], [pac_result=yes], [pac_result=no]) ],[ pac_result=no ]) ], [ pac_result=no ]) AC_MSG_RESULT([$pac_result]) dnl Delete the conftest created by AC_LANG_CONFTEST. rm -f conftest.$ac_ext # if test "$pac_result" = "yes" ; then AC_MSG_CHECKING([whether routines compiled with $pac_opt can be linked with ones compiled without $pac_opt]) pac_result=unknown FCFLAGS="$FCFLAGS_orig" pac_logfile="pac_test3.log" rm -f $pac_logfile AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ subroutine try() end ]) ],[ mv conftest.$OBJEXT pac_conftest.$OBJEXT saved_LIBS="$LIBS" LIBS="pac_conftest.$OBJEXT $LIBS" FCFLAGS="$FCFLAGS_opt" pac_logfile="pac_test4.log" rm -f $pac_logfile AC_LINK_IFELSE([AC_LANG_PROGRAM()], [ diffcmd='diff -b pac_test3.log pac_test4.log' PAC_RUNLOG_IFELSE([diff -b pac_test2.log pac_test4.log], [pac_result=yes], [pac_result=no]) ],[ pac_result=no ]) LIBS="$saved_LIBS" rm -f pac_conftest.$OBJEXT ],[ pac_result=no ]) AC_MSG_RESULT([$pac_result]) rm -f pac_test3.log pac_test4.log fi rm -f pac_test1.log pac_test2.log dnl Restore everything in AC that has been overwritten ac_link="$saved_ac_link" ac_compile="$saved_ac_compile" dnl echo "ac_link=\"$ac_link\"" dnl echo "ac_compile=\"$ac_compile\"" dnl Restore FCFLAGS before 2nd/3rd argument commands are executed, dnl as 2nd/3rd argument command could be modifying FCFLAGS. FCFLAGS="$FCFLAGS_orig" if test "$pac_result" = "yes" ; then ifelse([$2],[],[FCOPTIONS="$FCOPTIONS $1"],[$2]) else ifelse([$3],[],[:],[$3]) fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* AC_LANG_POP(Fortran) ]) dnl /*D dnl PAC_FC_WORKS_WITH_CPP dnl dnl Checks if Fortran 90 compiler works with C preprocessor dnl dnl Most systems allow the Fortran compiler to process .F and .F90 files dnl using the C preprocessor. However, some systems either do not dnl allow this or have serious bugs (OSF Fortran compilers have a bug dnl that generates an error message from cpp). The following test dnl checks to see if .F works, and if not, whether "cpp -P -C" can be used dnl D*/ AC_DEFUN([PAC_FC_WORKS_WITH_CPP],[ AC_REQUIRE([AC_PROG_CPP]) AC_MSG_CHECKING([whether Fortran 90 compiler processes .F90 files with C preprocessor]) AC_LANG_PUSH([Fortran]) saved_fc_ext=${ac_ext} ac_ext="F90" saved_FCFLAGS="$FCFLAGS" FCFLAGS="$FCFLAGS $CPPFLAGS" AC_LANG_CONFTEST([ AC_LANG_SOURCE([ program main #define ASIZE 10 integer a(ASIZE) end ]) ]) AC_COMPILE_IFELSE([],[ pac_cv_fc_accepts_F90=yes ifelse([$1],[],[],[$1=""]) ],[ pac_cv_fc_accepts_F90=no ifelse([$1],[],[:],[$1="false"]) ]) # Restore Fortran's ac_ext but not FCFLAGS ac_ext="$saved_fc_ext" if test "$pac_cv_fc_accepts_F90" != "yes" ; then pac_cpp_fc="$ac_cpp -C -P conftest.F90 > conftest.$ac_ext" PAC_RUNLOG_IFELSE([$pac_cpp_fc],[ if test -s conftest.${ac_ext} ; then AC_COMPILE_IFELSE([],[ pac_cv_fc_accepts_F90="no, use cpp" ifelse([$1],[],[],[$1="$CPP -C -P"]) ],[]) rm -f conftest.${ac_ext} fi ],[]) fi FCFLAGS="$saved_FCFLAGS" rm -f conftest.F90 AC_LANG_POP([Fortran]) AC_MSG_RESULT([$pac_cv_fc_accepts_F90]) ]) dnl dnl PAC_FC_VENDOR: dnl Try to get a version string for the F90 compiler. We may dnl need this to find likely command-line arguments for accessing dnl shared libraries dnl AC_DEFUN([PAC_FC_VENDOR],[ AC_MSG_CHECKING([for Fortran 90 compiler vendor]) # This is complicated by some compilers (such as the Intel 8.1 ifort) # that return a non-zero status even when they accept the -V option # (a zero status is returned only if there is a file). pac_cv_fc_vendor="unknown" for arg in --version -V -v ; do rm -f conftest.txt PAC_RUNLOG([$FC $arg conftest.txt 2>&1]) # Ignore the return code, because some compilers set the # return code to zero on invalid arguments and some to # non-zero on success (with no files to compile) if test -f conftest.txt ; then if grep 'Portland Group' conftest.txt >/dev/null 2>&1 ; then pac_cv_fc_vendor=pgi elif grep 'Sun Workshop' conftest.txt >/dev/null 2>&1 ; then pac_cv_fc_vendor=sun elif grep 'Sun Fortran 9' conftest.txt >/dev/null 2>&1 ; then pac_cv_fc_vendor=sun elif grep 'Absoft' conftest.txt >/dev/null 2>&1 ; then pac_cv_fc_vendor=absoft elif grep 'G95' conftest.txt >/dev/null 2>&1 ; then pac_cv_fc_vendor=gnu elif grep 'GNU Fortran' conftest.txt >/dev/null 2>&1 ; then # This is gfortran pac_cv_fc_vendor=gnu elif grep Intel conftest.txt >/dev/null 2>&1 ; then pac_cv_fc_vendor=intel fi fi if test "$pac_cv_fc_vendor" != "unknown" ; then break ; fi done if test "$pac_cv_fc_vendor" = "unknown" ; then # Try to use the compiler name if test "$FC" = "ifort" -o "$FC" = "ifc" ; then pac_cv_fc_vendor=intel elif test "$FC" = "pgf90" ; then pac_cv_fc_vendor=pgi elif test "$FC" = "xlf90" -o "$FC" = "xlf90_r" ; then pac_cv_fc_vendor=ibm elif test "$FC" = "xlf95" -o "$FC" = "xlf95_r" ; then pac_cv_fc_vendor=ibm fi fi AC_MSG_RESULT([$pac_cv_fc_vendor]) rm -f conftest.txt # End of checking for F90 compiler vendor ]) dnl dnl PAC_F77_IS_FC([ACTION_IF_TRUE],[ACTION_IF_FALSE]) dnl Check if F77 is a Fortran 90 compiler. dnl AC_DEFUN([PAC_F77_IS_FC],[ AC_MSG_CHECKING([whether $F77 is a Fortran 90 compiler]) AC_LANG_PUSH([Fortran 77]) saved_ac_ext=$ac_ext ac_ext="f90" AC_LINK_IFELSE([ AC_LANG_SOURCE([ program main integer, dimension(10) :: n integer k print *, range(k) end ]) ],[ pac_cv_prog_f77_is_fc=yes ifelse([$1],[],[],[$1]) ],[ pac_cv_prog_f77_is_fc=no ifelse([$2],[],[],[$2]) ]) AC_MSG_RESULT([$pac_cv_prog_f77_is_fc]) AC_LANG_POP([Fortran 77]) ]) dnl dnl PAC_FC_FLOAT_MODEL(float_type, [variable-set-if-successful-test]) dnl variable-set-if-successful-test is optional variable. dnl dnl This is a runtime test. dnl AC_DEFUN([PAC_FC_FLOAT_MODEL],[ type="$1" AC_MSG_CHECKING([for precision and range of $type]) AC_LANG_PUSH([Fortran]) AC_LINK_IFELSE([ AC_LANG_SOURCE([ program main $type aa print *, precision(aa), ",", range(aa) end ]) ],[ rm -f pac_conftest.out PAC_RUNLOG([./conftest$EXEEXT > pac_conftest.out]) if test -s pac_conftest.out ; then pac_fc_num_model="`cat pac_conftest.out | sed -e 's/ */ /g'`" AC_MSG_RESULT([$pac_fc_num_model]) ifelse([$2],[],[],[$2=$pac_fc_num_model]) else AC_MSG_WARN([No output from test program!]) fi rm -f pac_conftest.out ],[ AC_MSG_WARN([Failed to build program to determine the precision and range of $type]) ]) AC_LANG_POP([Fortran]) ]) dnl dnl PAC_FC_SIMPLE_NUMBER_MODEL(message,test-fc-code, dnl [variable-set-if-successful-test]) dnl message : message of what test-fc-code is checking dnl test-fc-code : Fortran 90 code to check a float or integer type's data model dnl variable-set-if-successful-test : dnl The optional variable to be set if the test-fc-code dnl is successful in returning the simple data model. dnl dnl This is a runtime test. dnl AC_DEFUN([PAC_FC_SIMPLE_NUMBER_MODEL],[ pac_msg="$1" AC_MSG_CHECKING([for $pac_msg]) AC_LANG_PUSH([Fortran]) AC_LINK_IFELSE([ AC_LANG_PROGRAM([],[ $2 ]) ],[ rm -f pac_conftest.out PAC_RUNLOG([./conftest$EXEEXT > pac_conftest.out]) if test -s pac_conftest.out ; then pac_fc_num_model="`cat pac_conftest.out | sed -e 's/ */ /g'`" AC_MSG_RESULT([$pac_fc_num_model]) ifelse([$3],[],[],[$3=$pac_fc_num_model]) else AC_MSG_WARN([No output from test program!]) fi rm -f pac_conftest.out ],[ AC_MSG_WARN([Failed to build program to determine $pac_msg]) ]) AC_LANG_POP([Fortran]) ]) dnl dnl PAC_FC_AVAIL_INTEGER_MODELS([INTEGER-MODELS-FLAG]) dnl Both INTEGER-MODELS-FLAG is an optional variable to be set if provided. dnl If it isn't provided, PAC_FC_ALL_INTEGER_MODELS will be set. dnl dnl This is a runtime test. dnl AC_DEFUN([PAC_FC_AVAIL_INTEGER_MODELS],[ AC_MSG_CHECKING([for available integer kinds]) AC_LANG_PUSH([Fortran]) AC_LINK_IFELSE([ AC_LANG_SOURCE([ program main integer r, lastkind lastkind=selected_int_kind(1) do r=2,30 k = selected_int_kind(r) if (k .ne. lastkind) then print *, r-1,",",lastkind lastkind = k endif if (k .le. 0) then exit endif enddo if (k.ne.lastkind) then print *, 31, ",", k endif end ]) ],[ rm -f pac_conftest.out PAC_RUNLOG([./conftest$EXEEXT > pac_conftest.out]) if test -s pac_conftest.out ; then pac_flag=`cat pac_conftest.out | sed -e 's/ */ /g'| tr '\012' ','` AC_MSG_RESULT([$pac_flag]) pac_validKinds="`sed -e 's/ */ /g' pac_conftest.out | tr '\012' ':'`" ifelse([$1],[],[PAC_FC_ALL_INTEGER_MODELS=$pac_flag],[$1=$pac_flag]) else AC_MSG_WARN([No output from test program!]) fi rm -f pac_conftest.out ],[ AC_MSG_WARN([Failed to build program to determine available integer models]) ]) AC_LANG_POP([Fortran]) ]) dnl dnl PAC_FC_INTEGER_MODEL_MAP([INTEGER-MODEL-MAP-FLAG]) dnl Both INTEGER-MODEL-MAP-FLAG is an optional variable to be set if provided. dnl If it isn't provided, PAC_FC_INTEGER_MODEL_MAP will be set. dnl dnl This test expect pac_validKinds set by PAC_FC_ALL_INTEGER_MODELS. dnl dnl This is a runtime test. dnl dnl Compile the C subroutine as pac_conftest.o and Link it with a Fortran main. AC_DEFUN([PAC_FC_INTEGER_MODEL_MAP],[ AC_REQUIRE([PAC_FC_AVAIL_INTEGER_MODELS]) AC_MSG_CHECKING([for available integer ranges]) AC_LANG_PUSH([C]) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ #include #include "confdefs.h" #ifdef F77_NAME_UPPER #define cisize_ CISIZE #define isize_ ISIZE #elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) #define cisize_ cisize #define isize_ isize #endif int cisize_(char *,char*); int cisize_(char *i1p, char *i2p) { int isize_val=0; isize_val = (int)(i2p - i1p); return isize_val; } ]) ],[ PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) pac_ccompile_ok=yes ],[ pac_ccompile_ok=no ]) AC_LANG_POP([C]) dnl if test "$pac_ccompile_ok" = "yes" ; then saved_LIBS="$LIBS" LIBS="pac_conftest.$OBJEXT $LIBS" saved_IFS=$IFS IFS=: AC_LANG_PUSH([Fortran]) pac_flag="" for rangekind in $pac_validKinds ; do kind="`echo $rangekind | sed -e 's/.*,//'`" range="`echo $rangekind | sed -e 's/,.*//'`" AC_LANG_CONFTEST([ AC_LANG_SOURCE([ program main integer (kind=$kind) a(2) integer cisize print *, $range, ",", $kind, ",", cisize( a(1), a(2) ) end ]) ]) IFS=$saved_IFS AC_LINK_IFELSE([],[ rm -f pac_conftest.out PAC_RUNLOG([./conftest$EXEEXT > pac_conftest.out]) if test -s pac_conftest.out ; then sizes="`cat pac_conftest.out | sed -e 's/ */ /g'`" pac_flag="$pac_flag { $sizes }," else AC_MSG_WARN([No output from test program!]) fi rm -f pac_conftest.out ],[ AC_MSG_WARN([Fortran program fails to build!]) ]) IFS=: done IFS=$saved_IFS AC_MSG_RESULT([$pac_flag]) ifelse([$1],[],[PAC_FC_INTEGER_MODEL_MAP=$pac_flag],[$1=$pac_flag]) AC_LANG_POP([Fortran]) LIBS="$saved_LIBS" rm -f pac_conftest.$OBJEXT fi ]) armci-mpi/m4/aclocal_cc.m40000644000175000017500000014352112662706250015045 0ustar mbanckmbanckdnl AC_PROG_CC_GNU ifdef([AC_PROG_CC_GNU],,[AC_DEFUN([AC_PROG_CC_GNU],)]) dnl PAC_PROG_CC - reprioritize the C compiler search order AC_DEFUN([PAC_PROG_CC],[ PAC_PUSH_FLAG([CFLAGS]) AC_PROG_CC([gcc icc pgcc xlc xlC pathcc cc]) PAC_POP_FLAG([CFLAGS]) ]) dnl dnl/*D dnl PAC_C_CHECK_COMPILER_OPTION - Check that a compiler option is accepted dnl without warning messages dnl dnl Synopsis: dnl PAC_C_CHECK_COMPILER_OPTION(optionname,action-if-ok,action-if-fail) dnl dnl Output Effects: dnl dnl If no actions are specified, a working value is added to 'COPTIONS' dnl dnl Notes: dnl This is now careful to check that the output is different, since dnl some compilers are noisy. dnl dnl We are extra careful to prototype the functions in case compiler options dnl that complain about poor code are in effect. dnl dnl Because this is a long script, we have ensured that you can pass a dnl variable containing the option name as the first argument. dnl dnl gcc 4.2.4 on 32-bit does not complain about the -Wno-type-limits option dnl even though it doesn't support it. However, when another warning is dnl triggered, it gives an error that the option is not recognized. So we dnl need to test with a conftest file that will generate warnings dnl D*/ AC_DEFUN([PAC_C_CHECK_COMPILER_OPTION],[ AC_MSG_CHECKING([whether C compiler accepts option $1]) pccco_save_CFLAGS="$CFLAGS" CFLAGS="$1 $CFLAGS" rm -f conftest.out pac_success=no # conftest3.c has an invalid prototype to ensure we generate warnings echo 'int main(){}' > conftest3.c echo 'int foo(void);int foo(void){return 0;}' > conftest2.c echo 'int main(void);int main(void){return 0;}' > conftest.c if ${CC-cc} $CFLAGS $CPPFLAGS -o conftest conftest3.c $LDFLAGS >/dev/null 2>&1 && ${CC-cc} $pccco_save_CFLAGS $CPPFLAGS -o conftest conftest.c $LDFLAGS >conftest.bas 2>&1 ; then if ${CC-cc} $CFLAGS $CPPFLAGS -o conftest conftest.c $LDFLAGS >conftest.out 2>&1 ; then if diff -b conftest.out conftest.bas >/dev/null 2>&1 ; then AC_MSG_RESULT(yes) AC_MSG_CHECKING([whether routines compiled with $1 can be linked with ones compiled without $1]) rm -f conftest.out rm -f conftest.bas if ${CC-cc} -c $pccco_save_CFLAGS $CPPFLAGS conftest2.c >conftest2.out 2>&1 ; then if ${CC-cc} $CFLAGS $CPPFLAGS -o conftest conftest2.o conftest.c $LDFLAGS >conftest.bas 2>&1 ; then if ${CC-cc} $CFLAGS $CPPFLAGS -o conftest conftest2.o conftest.c $LDFLAGS >conftest.out 2>&1 ; then if diff -b conftest.out conftest.bas >/dev/null 2>&1 ; then pac_success=yes else : fi else : fi else # Could not link with the option! : fi else if test -s conftest2.out ; then cat conftest2.out >&AC_FD_CC fi fi else : fi else : fi else # Could not compile without the option! : fi CFLAGS="$pccco_save_CFLAGS" if test "$pac_success" = yes ; then AC_MSG_RESULT(yes) ifelse($2,,COPTIONS="$COPTIONS $1",$2) else AC_MSG_RESULT(no) if test -s conftest.out ; then cat conftest.out >&AC_FD_CC ; fi $3 fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* ]) dnl dnl/*D dnl PAC_C_OPTIMIZATION - Determine C options for producing optimized code dnl dnl Synopsis dnl PAC_C_OPTIMIZATION([action if found]) dnl dnl Output Effect: dnl Adds options to 'COPTIONS' if no other action is specified dnl dnl Notes: dnl This is a temporary standin for compiler optimization. dnl It should try to match known systems to known compilers (checking, of dnl course), and then falling back to some common defaults. dnl Note that many compilers will complain about -g and aggressive dnl optimization. dnl D*/ AC_DEFUN([PAC_C_OPTIMIZATION],[ for copt in "-O4 -Ofast" "-Ofast" "-fast" "-O3" "-xO3" "-O" ; do PAC_C_CHECK_COMPILER_OPTION($copt,found_opt=yes,found_opt=no) if test "$found_opt" = "yes" ; then ifelse($1,,COPTIONS="$COPTIONS $copt",$1) break fi done if test "$ac_cv_prog_gcc" = "yes" ; then for copt in "-fomit-frame-pointer" "-finline-functions" \ "-funroll-loops" ; do PAC_C_CHECK_COMPILER_OPTION($copt,found_opt=yes,found_opt=no) if test "$found_opt" = "yes" ; then ifelse($1,,COPTIONS="$COPTIONS $copt",$1) # no break because we're trying to add them all fi done # We could also look for architecture-specific gcc options fi ]) dnl/*D dnl PAC_PROG_C_UNALIGNED_DOUBLES - Check that the C compiler allows unaligned dnl doubles dnl dnl Synopsis: dnl PAC_PROG_C_UNALIGNED_DOUBLES(action-if-true,action-if-false, dnl action-if-unknown) dnl dnl Notes: dnl 'action-if-unknown' is used in the case of cross-compilation. dnl D*/ AC_DEFUN([PAC_PROG_C_UNALIGNED_DOUBLES],[ AC_CACHE_CHECK([whether C compiler allows unaligned doubles], pac_cv_prog_c_unaligned_doubles,[ AC_TRY_RUN([ void fetch_double( v ) double *v; { *v = 1.0; } int main( argc, argv ) int argc; char **argv; { int p[4]; double *p_val; fetch_double( (double *)&(p[0]) ); p_val = (double *)&(p[0]); if (*p_val != 1.0) return 1; fetch_double( (double *)&(p[1]) ); p_val = (double *)&(p[1]); if (*p_val != 1.0) return 1; return 0; } ],pac_cv_prog_c_unaligned_doubles="yes",pac_cv_prog_c_unaligned_doubles="no", pac_cv_prog_c_unaligned_doubles="unknown")]) ifelse($1,,,if test "X$pac_cv_prog_c_unaligned_doubles" = "yes" ; then $1 fi) ifelse($2,,,if test "X$pac_cv_prog_c_unaligned_doubles" = "no" ; then $2 fi) ifelse($3,,,if test "X$pac_cv_prog_c_unaligned_doubles" = "unknown" ; then $3 fi) ]) dnl/*D dnl PAC_PROG_C_WEAK_SYMBOLS - Test whether C supports weak alias symbols. dnl dnl Synopsis dnl PAC_PROG_C_WEAK_SYMBOLS(action-if-true,action-if-false) dnl dnl Output Effect: dnl Defines one of the following if a weak symbol pragma is found: dnl.vb dnl HAVE_PRAGMA_WEAK - #pragma weak dnl HAVE_PRAGMA_HP_SEC_DEF - #pragma _HP_SECONDARY_DEF dnl HAVE_PRAGMA_CRI_DUP - #pragma _CRI duplicate x as y dnl.ve dnl May also define dnl.vb dnl HAVE_WEAK_ATTRIBUTE dnl.ve dnl if functions can be declared as 'int foo(...) __attribute__ ((weak));' dnl sets the shell variable pac_cv_attr_weak to yes. dnl Also checks for __attribute__((weak_import)) which is supported by dnl Apple in Mac OSX (at least in Darwin). Note that this provides only dnl weak symbols, not weak aliases dnl dnl D*/ AC_DEFUN([PAC_PROG_C_WEAK_SYMBOLS],[ pragma_extra_message="" AC_CACHE_CHECK([for type of weak symbol alias support], pac_cv_prog_c_weak_symbols,[ # Test for weak symbol support... # We can't put # in the message because it causes autoconf to generate # incorrect code AC_TRY_LINK([ extern int PFoo(int); #pragma weak PFoo = Foo int Foo(int a) { return a; } ],[return PFoo(1);],has_pragma_weak=yes) # # Some systems (Linux ia64 and ecc, for example), support weak symbols # only within a single object file! This tests that case. # Note that there is an extern int PFoo declaration before the # pragma. Some compilers require this in order to make the weak symbol # extenally visible. if test "$has_pragma_weak" = yes ; then # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >>conftest1.c <>conftest2.c <>conftest1.c <>conftest2.c <> config.log echo "Failed program was" >> config.log cat conftest1.c >>config.log cat conftest2.c >>config.log if test -s conftest.out ; then cat conftest.out >> config.log ; fi has_pragma_weak=0 pragma_extra_message="pragma weak accepted but does not work (probably creates two non-weak entries)" fi else echo "$ac_link2" >>config.log echo "Failed program was" >>config.log cat conftest1.c >>config.log cat conftest2.c >>config.log if test -s conftest.out ; then cat conftest.out >> config.log ; fi has_pragma_weak=0 pragma_extra_message="pragma weak does not work outside of a file" fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* fi dnl if test -z "$pac_cv_prog_c_weak_symbols" ; then AC_TRY_LINK([ extern int PFoo(int); #pragma _HP_SECONDARY_DEF Foo PFoo int Foo(int a) { return a; } ],[return PFoo(1);],pac_cv_prog_c_weak_symbols="pragma _HP_SECONDARY_DEF") fi dnl if test -z "$pac_cv_prog_c_weak_symbols" ; then AC_TRY_LINK([ extern int PFoo(int); #pragma _CRI duplicate PFoo as Foo int Foo(int a) { return a; } ],[return PFoo(1);],pac_cv_prog_c_weak_symbols="pragma _CRI duplicate x as y") fi dnl if test -z "$pac_cv_prog_c_weak_symbols" ; then pac_cv_prog_c_weak_symbols="no" fi dnl dnl If there is an extra explanatory message, echo it now so that it dnl doesn't interfere with the cache result value if test -n "$pragma_extra_message" ; then echo $pragma_extra_message fi dnl ]) if test "$pac_cv_prog_c_weak_symbols" = "no" ; then ifelse([$2],,:,[$2]) else case "$pac_cv_prog_c_weak_symbols" in "pragma weak") AC_DEFINE(HAVE_PRAGMA_WEAK,1,[Supports weak pragma]) ;; "pragma _HP") AC_DEFINE(HAVE_PRAGMA_HP_SEC_DEF,1,[HP style weak pragma]) ;; "pragma _CRI") AC_DEFINE(HAVE_PRAGMA_CRI_DUP,1,[Cray style weak pragma]) ;; esac ifelse([$1],,:,[$1]) fi AC_CACHE_CHECK([whether __attribute__ ((weak)) allowed], pac_cv_attr_weak,[ AC_TRY_COMPILE([int foo(int) __attribute__ ((weak));],[int a;], pac_cv_attr_weak=yes,pac_cv_attr_weak=no)]) # Note that being able to compile with weak_import doesn't mean that # it works. AC_CACHE_CHECK([whether __attribute__ ((weak_import)) allowed], pac_cv_attr_weak_import,[ AC_TRY_COMPILE([int foo(int) __attribute__ ((weak_import));],[int a;], pac_cv_attr_weak_import=yes,pac_cv_attr_weak_import=no)]) # Check if the alias option for weak attributes is allowed AC_CACHE_CHECK([whether __attribute__((weak,alias(...))) allowed], pac_cv_attr_weak_alias,[ AC_TRY_COMPILE([int foo(int) __attribute__((weak,alias("__foo")));],[int a;], pac_cv_attr_weak_alias=yes,pac_cv_attr_weak_alias=no)]) ]) # # This is a replacement that checks that FAILURES are signaled as well # (later configure macros look for the .o file, not just success from the # compiler, but they should not HAVE to # dnl --- insert 2.52 compatibility here --- dnl 2.52 does not have AC_PROG_CC_WORKS ifdef([AC_PROG_CC_WORKS],,[AC_DEFUN([AC_PROG_CC_WORKS],)]) dnl AC_DEFUN([PAC_PROG_CC_WORKS], [AC_PROG_CC_WORKS AC_MSG_CHECKING([whether the C compiler sets its return status correctly]) AC_LANG_SAVE AC_LANG_C AC_TRY_COMPILE(,[int a = bzzzt;],notbroken=no,notbroken=yes) AC_MSG_RESULT($notbroken) if test "$notbroken" = "no" ; then AC_MSG_ERROR([installation or configuration problem: C compiler does not correctly set error code when a fatal error occurs]) fi ]) dnl/*D dnl PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS - Test whether C and the dnl linker allow multiple weak symbols. dnl dnl Synopsis dnl PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS(action-if-true,action-if-false) dnl dnl dnl D*/ AC_DEFUN([PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS],[ AC_CACHE_CHECK([for multiple weak symbol support], pac_cv_prog_c_multiple_weak_symbols,[ # Test for multiple weak symbol support... # # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >>conftest1.c <>conftest2.c <>config.log echo "Failed program was" >>config.log cat conftest1.c >>config.log cat conftest2.c >>config.log if test -s conftest.out ; then cat conftest.out >> config.log ; fi fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* dnl ]) if test "$pac_cv_prog_c_multiple_weak_symbols" = "yes" ; then ifelse([$1],,:,[$1]) else ifelse([$2],,:,[$2]) fi ]) dnl Use the value of enable-strict to update CFLAGS dnl pac_cc_strict_flags contains the strict flags. dnl dnl -std=c89 is used to select the C89 version of the ANSI/ISO C standard. dnl As of this writing, many C compilers still accepted only this version, dnl not the later C99 version. When all compilers accept C99, this dnl should be changed to the appropriate standard level. Note that we've dnl had trouble with gcc 2.95.3 accepting -std=c89 but then trying to dnl compile program with a invalid set of options dnl (-D __STRICT_ANSI__-trigraphs) AC_DEFUN([PAC_CC_STRICT],[ export enable_strict_done if test "$enable_strict_done" != "yes" ; then # Some comments on strict warning options. # These were added to reduce warnings: # -Wno-missing-field-initializers -- We want to allow a struct to be # initialized to zero using "struct x y = {0};" and not require # each field to be initialized individually. # -Wno-unused-parameter -- For portability, some parameters go unused # when we have different implementations of functions for # different platforms # -Wno-unused-label -- We add fn_exit: and fn_fail: on all functions, # but fn_fail may not be used if the function doesn't return an # error. # -Wno-sign-compare -- read() and write() return bytes read/written # as a signed value, but we often compare this to size_t (or # msg_sz_t) variables. # -Wno-format-zero-length -- this warning is irritating and useless, since # a zero-length format string is very well defined # -Wno-type-limits -- There are places where we compare an unsigned to # a constant that happens to be zero e.g., if x is unsigned and # MIN_VAL is zero, we'd like to do "MPIU_Assert(x >= MIN_VAL);". # Note this option is not supported by gcc 4.2. This needs to be added # after most other warning flags, so that we catch a gcc bug on 32-bit # that doesn't give a warning that this is unsupported, unless another # warning is triggered, and then if gives an error. # These were removed to reduce warnings: # -Wcast-qual -- Sometimes we need to cast "volatile char*" to # "char*", e.g., for memcpy. # -Wpadded -- We catch struct padding with asserts when we need to # -Wredundant-decls -- Having redundant declarations is benign and the # code already has some. # -Waggregate-return -- This seems to be a performance-related warning # aggregate return values are legal in ANSI C, but they may be returned # in memory rather than through a register. We do use aggregate return # values, but they are structs of a single basic type (used to enforce # type checking for relative vs. absolute ptrs), and with optimization # the aggregate value is converted to a scalar. # the embedded newlines in this string are safe because we evaluate each # argument in the for-loop below and append them to the CFLAGS with a space # as the separator instead pac_common_strict_flags=" -Wall -Wextra -Wno-missing-field-initializers -Wstrict-prototypes -Wmissing-prototypes -DGCC_WALL -Wno-unused-parameter -Wno-unused-label -Wshadow -Wmissing-declarations -Wno-long-long -Wfloat-equal -Wdeclaration-after-statement -Wundef -Wno-endif-labels -Wpointer-arith -Wbad-function-cast -Wcast-align -Wwrite-strings -Wno-sign-compare -Wold-style-definition -Wno-multichar -Wno-deprecated-declarations -Wpacked -Wnested-externs -Winvalid-pch -Wno-pointer-sign -Wvariadic-macros -Wno-format-zero-length -Wno-type-limits " enable_c89=yes enable_c99=no enable_posix=yes enable_opt=yes flags="`echo $1 | sed -e 's/:/ /g' -e 's/,/ /g'`" for flag in ${flags}; do case "$flag" in c89) enable_strict_done="yes" enable_c89=yes ;; c99) enable_strict_done="yes" enable_c99=yes ;; posix) enable_strict_done="yes" enable_posix=yes ;; noposix) enable_strict_done="yes" enable_posix=no ;; opt) enable_strict_done="yes" enable_opt=yes ;; noopt) enable_strict_done="yes" enable_opt=no ;; all|yes) enable_strict_done="yes" enable_c89=yes enable_posix=yes enable_opt=yes ;; no) # Accept and ignore this value : ;; *) if test -n "$flag" ; then AC_MSG_WARN([Unrecognized value for enable-strict:$flag]) fi ;; esac done pac_cc_strict_flags="" if test "${enable_strict_done}" = "yes" ; then if test "${enable_opt}" = "yes" ; then pac_cc_strict_flags="-O2" fi pac_cc_strict_flags="$pac_cc_strict_flags $pac_common_strict_flags" if test "${enable_posix}" = "yes" ; then PAC_APPEND_FLAG([-D_POSIX_C_SOURCE=199506L],[pac_cc_strict_flags]) fi # We only allow one of strict-C99 or strict-C89 to be # enabled. If C99 is enabled, we automatically disable C89. if test "${enable_c99}" = "yes" ; then PAC_APPEND_FLAG([-std=c99],[pac_cc_strict_flags]) elif test "${enable_c89}" = "yes" ; then PAC_APPEND_FLAG([-std=c89],[pac_cc_strict_flags]) fi fi # See if the above options work with the compiler accepted_flags="" for flag in $pac_cc_strict_flags ; do PAC_PUSH_FLAG([CFLAGS]) CFLAGS="$CFLAGS $accepted_flags" PAC_C_CHECK_COMPILER_OPTION([$flag],[accepted_flags="$accepted_flags $flag"],) PAC_POP_FLAG([CFLAGS]) done pac_cc_strict_flags=$accepted_flags fi ]) dnl/*D dnl PAC_ARG_STRICT - Add --enable-strict to configure. dnl dnl Synopsis: dnl PAC_ARG_STRICT dnl dnl Output effects: dnl Adds '--enable-strict' to the command line. dnl dnl D*/ AC_DEFUN([PAC_ARG_STRICT],[ AC_ARG_ENABLE(strict, AC_HELP_STRING([--enable-strict], [Turn on strict compilation testing])) PAC_CC_STRICT($enable_strict) CFLAGS="$CFLAGS $pac_cc_strict_flags" export CFLAGS ]) dnl Return the integer structure alignment in pac_cv_c_max_integer_align dnl Possible values include dnl packed dnl two dnl four dnl eight dnl dnl In addition, a "Could not determine alignment" and a "error!" dnl return is possible. AC_DEFUN([PAC_C_MAX_INTEGER_ALIGN],[ AC_CACHE_CHECK([for max C struct integer alignment], pac_cv_c_max_integer_align,[ AC_TRY_RUN([ #include #define DBG(a,b,c) int main( int argc, char *argv[] ) { FILE *cf; int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; struct { char a; int b; } char_int; struct { char a; short b; } char_short; struct { char a; long b; } char_long; struct { char a; int b; char c; } char_int_char; struct { char a; short b; char c; } char_short_char; #ifdef HAVE_LONG_LONG_INT struct { long long int a; char b; } lli_c; struct { char a; long long int b; } c_lli; #endif int size, extent, extent2; /* assume max integer alignment isn't 8 if we don't have * an eight-byte value :) */ #ifdef HAVE_LONG_LONG_INT if (sizeof(int) < 8 && sizeof(long) < 8 && sizeof(long long int) < 8) is_eight = 0; #else if (sizeof(int) < 8 && sizeof(long) < 8) is_eight = 0; #endif size = sizeof(char) + sizeof(int); extent = sizeof(char_int); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if ( (extent % 4) != 0) is_four = 0; if (sizeof(int) == 8 && (extent % 8) != 0) is_eight = 0; DBG("char_int",size,extent); size = sizeof(char) + sizeof(short); extent = sizeof(char_short); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if (sizeof(short) == 4 && (extent % 4) != 0) is_four = 0; if (sizeof(short) == 8 && (extent % 8) != 0) is_eight = 0; DBG("char_short",size,extent); size = sizeof(char) + sizeof(long); extent = sizeof(char_long); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if ( (extent % 4) != 0) is_four = 0; if (sizeof(long) == 8 && (extent % 8) != 0) is_eight = 0; DBG("char_long",size,extent); #ifdef HAVE_LONG_LONG_INT size = sizeof(char) + sizeof(long long int); extent = sizeof(lli_c); extent2 = sizeof(c_lli); if (size != extent) is_packed = 0; if ( (extent % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(long long int) >= 8 && (extent % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; #endif size = sizeof(char) + sizeof(int) + sizeof(char); extent = sizeof(char_int_char); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if ( (extent % 4) != 0) is_four = 0; if (sizeof(int) == 8 && (extent % 8) != 0) is_eight = 0; DBG("char_int_char",size,extent); size = sizeof(char) + sizeof(short) + sizeof(char); extent = sizeof(char_short_char); if (size != extent) is_packed = 0; if ( (extent % 2) != 0) is_two = 0; if (sizeof(short) == 4 && (extent % 4) != 0) is_four = 0; if (sizeof(short) == 8 && (extent % 8) != 0) is_eight = 0; DBG("char_short_char",size,extent); /* If aligned mod 8, it will be aligned mod 4 */ if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; /* Tabulate the results */ cf = fopen( "ctest.out", "w" ); if (is_packed + is_two + is_four + is_eight == 0) { fprintf( cf, "Could not determine alignment\n" ); } else { if (is_packed + is_two + is_four + is_eight != 1) { fprintf( cf, "error!\n" ); } else { if (is_packed) fprintf( cf, "packed\n" ); if (is_two) fprintf( cf, "two\n" ); if (is_four) fprintf( cf, "four\n" ); if (is_eight) fprintf( cf, "eight\n" ); } } fclose( cf ); return 0; }], pac_cv_c_max_integer_align=`cat ctest.out`, pac_cv_c_max_integer_align="unknown", pac_cv_c_max_integer_align="$CROSS_ALIGN_STRUCT_INT") rm -f ctest.out ]) if test -z "$pac_cv_c_max_integer_align" ; then pac_cv_c_max_integer_align="unknown" fi ]) dnl Return the floating point structure alignment in dnl pac_cv_c_max_fp_align. dnl dnl Possible values include: dnl packed dnl two dnl four dnl eight dnl sixteen dnl dnl In addition, a "Could not determine alignment" and a "error!" dnl return is possible. AC_DEFUN([PAC_C_MAX_FP_ALIGN],[ AC_CACHE_CHECK([for max C struct floating point alignment], pac_cv_c_max_fp_align,[ AC_TRY_RUN([ #include #define DBG(a,b,c) int main( int argc, char *argv[] ) { FILE *cf; int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; int is_sixteen = 1; struct { char a; float b; } char_float; struct { float b; char a; } float_char; struct { char a; double b; } char_double; struct { double b; char a; } double_char; #ifdef HAVE_LONG_DOUBLE struct { char a; long double b; } char_long_double; struct { long double b; char a; } long_double_char; struct { long double a; int b; char c; } long_double_int_char; #endif int size, extent1, extent2; size = sizeof(char) + sizeof(float); extent1 = sizeof(char_float); extent2 = sizeof(float_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(float) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; DBG("char_float",size,extent1); size = sizeof(char) + sizeof(double); extent1 = sizeof(char_double); extent2 = sizeof(double_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(double) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; DBG("char_double",size,extent1); #ifdef HAVE_LONG_DOUBLE size = sizeof(char) + sizeof(long double); extent1 = sizeof(char_long_double); extent2 = sizeof(long_double_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(long double) >= 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; if (sizeof(long double) > 8 && (extent1 % 16) != 0 && (extent2 % 16) != 0) is_sixteen = 0; DBG("char_long-double",size,extent1); extent1 = sizeof(long_double_int_char); if ( (extent1 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0) is_four = 0; if (sizeof(long double) >= 8 && (extent1 % 8) != 0) is_eight = 0; if (sizeof(long double) > 8 && (extent1 % 16) != 0) is_sixteen = 0; #else is_sixteen = 0; #endif if (is_sixteen) { is_eight = 0; is_four = 0; is_two = 0; } if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; /* Tabulate the results */ cf = fopen( "ctest.out", "w" ); if (is_packed + is_two + is_four + is_eight + is_sixteen == 0) { fprintf( cf, "Could not determine alignment\n" ); } else { if (is_packed + is_two + is_four + is_eight + is_sixteen != 1) { fprintf( cf, "error!\n" ); } else { if (is_packed) fprintf( cf, "packed\n" ); if (is_two) fprintf( cf, "two\n" ); if (is_four) fprintf( cf, "four\n" ); if (is_eight) fprintf( cf, "eight\n" ); if (is_sixteen) fprintf( cf, "sixteen\n" ); } } fclose( cf ); return 0; }], pac_cv_c_max_fp_align=`cat ctest.out`, pac_cv_c_max_fp_align="unknown", pac_cv_c_max_fp_align="$CROSS_ALIGN_STRUCT_FP") rm -f ctest.out ]) if test -z "$pac_cv_c_max_fp_align" ; then pac_cv_c_max_fp_align="unknown" fi ]) dnl Return the floating point structure alignment in dnl pac_cv_c_max_double_fp_align. dnl dnl Possible values include: dnl packed dnl two dnl four dnl eight dnl dnl In addition, a "Could not determine alignment" and a "error!" dnl return is possible. AC_DEFUN([PAC_C_MAX_DOUBLE_FP_ALIGN],[ AC_CACHE_CHECK([for max C struct alignment of structs with doubles], pac_cv_c_max_double_fp_align,[ AC_TRY_RUN([ #include #define DBG(a,b,c) int main( int argc, char *argv[] ) { FILE *cf; int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; struct { char a; float b; } char_float; struct { float b; char a; } float_char; struct { char a; double b; } char_double; struct { double b; char a; } double_char; int size, extent1, extent2; size = sizeof(char) + sizeof(float); extent1 = sizeof(char_float); extent2 = sizeof(float_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(float) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; DBG("char_float",size,extent1); size = sizeof(char) + sizeof(double); extent1 = sizeof(char_double); extent2 = sizeof(double_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(double) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; DBG("char_double",size,extent1); if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; /* Tabulate the results */ cf = fopen( "ctest.out", "w" ); if (is_packed + is_two + is_four + is_eight == 0) { fprintf( cf, "Could not determine alignment\n" ); } else { if (is_packed + is_two + is_four + is_eight != 1) { fprintf( cf, "error!\n" ); } else { if (is_packed) fprintf( cf, "packed\n" ); if (is_two) fprintf( cf, "two\n" ); if (is_four) fprintf( cf, "four\n" ); if (is_eight) fprintf( cf, "eight\n" ); } } fclose( cf ); return 0; }], pac_cv_c_max_double_fp_align=`cat ctest.out`, pac_cv_c_max_double_fp_align="unknown", pac_cv_c_max_double_fp_align="$CROSS_ALIGN_STRUCT_DOUBLE_FP") rm -f ctest.out ]) if test -z "$pac_cv_c_max_double_fp_align" ; then pac_cv_c_max_double_fp_align="unknown" fi ]) AC_DEFUN([PAC_C_MAX_LONGDOUBLE_FP_ALIGN],[ AC_CACHE_CHECK([for max C struct floating point alignment with long doubles], pac_cv_c_max_longdouble_fp_align,[ AC_TRY_RUN([ #include #define DBG(a,b,c) int main( int argc, char *argv[] ) { FILE *cf; int is_packed = 1; int is_two = 1; int is_four = 1; int is_eight = 1; int is_sixteen = 1; struct { char a; long double b; } char_long_double; struct { long double b; char a; } long_double_char; struct { long double a; int b; char c; } long_double_int_char; int size, extent1, extent2; size = sizeof(char) + sizeof(long double); extent1 = sizeof(char_long_double); extent2 = sizeof(long_double_char); if (size != extent1) is_packed = 0; if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; if (sizeof(long double) >= 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) is_eight = 0; if (sizeof(long double) > 8 && (extent1 % 16) != 0 && (extent2 % 16) != 0) is_sixteen = 0; DBG("char_long-double",size,extent1); extent1 = sizeof(long_double_int_char); if ( (extent1 % 2) != 0) is_two = 0; if ( (extent1 % 4) != 0) is_four = 0; if (sizeof(long double) >= 8 && (extent1 % 8) != 0) is_eight = 0; if (sizeof(long double) > 8 && (extent1 % 16) != 0) is_sixteen = 0; if (is_sixteen) { is_eight = 0; is_four = 0; is_two = 0; } if (is_eight) { is_four = 0; is_two = 0; } if (is_four) is_two = 0; /* Tabulate the results */ cf = fopen( "ctest.out", "w" ); if (is_packed + is_two + is_four + is_eight + is_sixteen == 0) { fprintf( cf, "Could not determine alignment\n" ); } else { if (is_packed + is_two + is_four + is_eight + is_sixteen != 1) { fprintf( cf, "error!\n" ); } else { if (is_packed) fprintf( cf, "packed\n" ); if (is_two) fprintf( cf, "two\n" ); if (is_four) fprintf( cf, "four\n" ); if (is_eight) fprintf( cf, "eight\n" ); if (is_sixteen) fprintf( cf, "sixteen\n" ); } } fclose( cf ); return 0; }], pac_cv_c_max_longdouble_fp_align=`cat ctest.out`, pac_cv_c_max_longdouble_fp_align="unknown", pac_cv_c_max_longdouble_fp_align="$CROSS_ALIGN_STRUCT_LONGDOUBLE_FP") rm -f ctest.out ]) if test -z "$pac_cv_c_max_longdouble_fp_align" ; then pac_cv_c_max_longdouble_fp_align="unknown" fi ]) dnl Other tests assume that there is potentially a maximum alignment dnl and that if there is no maximum alignment, or a type is smaller than dnl that value, then we align on the size of the value, with the exception dnl of the "position-based alignment" rules we test for separately. dnl dnl It turns out that these assumptions have fallen short in at least one dnl case, on MacBook Pros, where doubles are aligned on 4-byte boundaries dnl even when long doubles are aligned on 16-byte boundaries. So this test dnl is here specifically to handle this case. dnl dnl Puts result in pac_cv_c_double_alignment_exception. dnl dnl Possible values currently include no and four. dnl AC_DEFUN([PAC_C_DOUBLE_ALIGNMENT_EXCEPTION],[ AC_CACHE_CHECK([if double alignment breaks rules, find actual alignment], pac_cv_c_double_alignment_exception,[ AC_TRY_RUN([ #include #define DBG(a,b,c) int main( int argc, char *argv[] ) { FILE *cf; struct { char a; double b; } char_double; struct { double b; char a; } double_char; int extent1, extent2, align_4 = 0; extent1 = sizeof(char_double); extent2 = sizeof(double_char); /* we're interested in the largest value, will let separate test * deal with position-based issues. */ if (extent1 < extent2) extent1 = extent2; if ((sizeof(double) == 8) && (extent1 % 8) != 0) { if (extent1 % 4 == 0) { #ifdef HAVE_MAX_FP_ALIGNMENT if (HAVE_MAX_FP_ALIGNMENT >= 8) align_4 = 1; #else align_4 = 1; #endif } } cf = fopen( "ctest.out", "w" ); if (align_4) fprintf( cf, "four\n" ); else fprintf( cf, "no\n" ); fclose( cf ); return 0; }], pac_cv_c_double_alignment_exception=`cat ctest.out`, pac_cv_c_double_alignment_exception="unknown", pac_cv_c_double_alignment_exception="$CROSS_ALIGN_DOUBLE_EXCEPTION") rm -f ctest.out ]) if test -z "$pac_cv_c_double_alignment_exception" ; then pac_cv_c_double_alignment_exception="unknown" fi ]) dnl Test for odd struct alignment rule that only applies max. dnl padding when double value is at front of type. dnl Puts result in pac_cv_c_double_pos_align. dnl dnl Search for "Power alignment mode" for more details. dnl dnl Possible values include yes, no, and unknown. dnl AC_DEFUN([PAC_C_DOUBLE_POS_ALIGN],[ AC_CACHE_CHECK([if alignment of structs with doubles is based on position], pac_cv_c_double_pos_align,[ AC_TRY_RUN([ #include #define DBG(a,b,c) int main( int argc, char *argv[] ) { FILE *cf; int padding_varies_by_pos = 0; struct { char a; double b; } char_double; struct { double b; char a; } double_char; int extent1, extent2; extent1 = sizeof(char_double); extent2 = sizeof(double_char); if (extent1 != extent2) padding_varies_by_pos = 1; cf = fopen( "ctest.out", "w" ); if (padding_varies_by_pos) fprintf( cf, "yes\n" ); else fprintf( cf, "no\n" ); fclose( cf ); return 0; }], pac_cv_c_double_pos_align=`cat ctest.out`, pac_cv_c_double_pos_align="unknown", pac_cv_c_double_pos_align="$CROSS_ALIGN_DOUBLE_POS") rm -f ctest.out ]) if test -z "$pac_cv_c_double_pos_align" ; then pac_cv_c_double_pos_align="unknown" fi ]) dnl Test for odd struct alignment rule that only applies max. dnl padding when long long int value is at front of type. dnl Puts result in pac_cv_c_llint_pos_align. dnl dnl Search for "Power alignment mode" for more details. dnl dnl Possible values include yes, no, and unknown. dnl AC_DEFUN([PAC_C_LLINT_POS_ALIGN],[ AC_CACHE_CHECK([if alignment of structs with long long ints is based on position], pac_cv_c_llint_pos_align,[ AC_TRY_RUN([ #include #define DBG(a,b,c) int main( int argc, char *argv[] ) { FILE *cf; int padding_varies_by_pos = 0; #ifdef HAVE_LONG_LONG_INT struct { char a; long long int b; } char_llint; struct { long long int b; char a; } llint_char; int extent1, extent2; extent1 = sizeof(char_llint); extent2 = sizeof(llint_char); if (extent1 != extent2) padding_varies_by_pos = 1; #endif cf = fopen( "ctest.out", "w" ); if (padding_varies_by_pos) fprintf( cf, "yes\n" ); else fprintf( cf, "no\n" ); fclose( cf ); return 0; }], pac_cv_c_llint_pos_align=`cat ctest.out`, pac_cv_c_llint_pos_align="unknown", pac_cv_c_llint_pos_align="$CROSS_ALIGN_LLINT_POS") rm -f ctest.out ]) if test -z "$pac_cv_c_llint_pos_align" ; then pac_cv_c_llint_pos_align="unknown" fi ]) dnl/*D dnl PAC_FUNC_NEEDS_DECL - Set NEEDS__DECL if a declaration is needed dnl dnl Synopsis: dnl PAC_FUNC_NEEDS_DECL(headerfiles,funcname) dnl dnl Output Effect: dnl Sets 'NEEDS__DECL' if 'funcname' is not declared by the dnl headerfiles. dnl dnl Approach: dnl Try to compile a program with the function, but passed with an incorrect dnl calling sequence. If the compilation fails, then the declaration dnl is provided within the header files. If the compilation succeeds, dnl the declaration is required. dnl dnl We use a 'double' as the first argument to try and catch varargs dnl routines that may use an int or pointer as the first argument. dnl dnl There is one difficulty - if the compiler has been instructed to dnl fail on implicitly defined functions, then this test will always dnl fail. dnl dnl D*/ AC_DEFUN([PAC_FUNC_NEEDS_DECL],[ AC_CACHE_CHECK([whether $2 needs a declaration], pac_cv_func_decl_$2,[ AC_TRY_COMPILE([$1 int $2(double, int, double, const char *);],[int a=$2(1.0,27,1.0,"foo");], pac_cv_func_decl_$2=yes,pac_cv_func_decl_$2=no)]) if test "$pac_cv_func_decl_$2" = "yes" ; then changequote(<<,>>)dnl define(<>, translit(NEEDS_$2_DECL, [a-z *], [A-Z__]))dnl changequote([, ])dnl AC_DEFINE_UNQUOTED(PAC_FUNC_NAME,1,[Define if $2 needs a declaration]) undefine([PAC_FUNC_NAME]) fi ]) dnl PAC_C_GNU_ATTRIBUTE - See if the GCC __attribute__ specifier is allow. dnl Use the following dnl #ifndef HAVE_GCC_ATTRIBUTE dnl #define __attribute__(a) dnl #endif dnl If *not*, define __attribute__(a) as null dnl dnl We start by requiring Gcc. Some other compilers accept __attribute__ dnl but generate warning messages, or have different interpretations dnl (which seems to make __attribute__ just as bad as #pragma) dnl For example, the Intel icc compiler accepts __attribute__ and dnl __attribute__((pure)) but generates warnings for __attribute__((format...)) dnl AC_DEFUN([PAC_C_GNU_ATTRIBUTE],[ AC_REQUIRE([AC_PROG_CC_GNU]) if test "$ac_cv_prog_gcc" = "yes" ; then AC_CACHE_CHECK([whether __attribute__ allowed], pac_cv_gnu_attr_pure,[ AC_TRY_COMPILE([int foo(int) __attribute__ ((pure));],[int a;], pac_cv_gnu_attr_pure=yes,pac_cv_gnu_attr_pure=no)]) AC_CACHE_CHECK([whether __attribute__((format)) allowed], pac_cv_gnu_attr_format,[ AC_TRY_COMPILE([int foo(char *,...) __attribute__ ((format(printf,1,2)));],[int a;], pac_cv_gnu_attr_format=yes,pac_cv_gnu_attr_format=no)]) if test "$pac_cv_gnu_attr_pure" = "yes" -a "$pac_cv_gnu_attr_format" = "yes" ; then AC_DEFINE(HAVE_GCC_ATTRIBUTE,1,[Define if GNU __attribute__ is supported]) fi fi ]) dnl dnl Check for a broken install (fails to preserve file modification times, dnl thus breaking libraries. dnl dnl Create a library, install it, and then try to link against it. AC_DEFUN([PAC_PROG_INSTALL_BREAKS_LIBS],[ AC_CACHE_CHECK([whether install breaks libraries], ac_cv_prog_install_breaks_libs,[ AC_REQUIRE([AC_PROG_RANLIB]) AC_REQUIRE([AC_PROG_INSTALL]) AC_REQUIRE([AC_PROG_CC]) ac_cv_prog_install_breaks_libs=yes # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f libconftest* conftest* echo 'int foo(int);int foo(int a){return a;}' > conftest1.c echo 'extern int foo(int); int main( int argc, char **argv){ return foo(0); }' > conftest2.c if ${CC-cc} $CFLAGS -c conftest1.c >conftest.out 2>&1 ; then if ${AR-ar} cr libconftest.a conftest1.o >/dev/null 2>&1 ; then if ${RANLIB-:} libconftest.a >/dev/null 2>&1 ; then # Anything less than sleep 10, and Mac OS/X (Darwin) # will claim that install works because ranlib won't complain sleep 10 libinstall="$INSTALL_DATA" eval "libinstall=\"$libinstall\"" if ${libinstall} libconftest.a libconftest1.a >/dev/null 2>&1 ; then if ${CC-cc} $CFLAGS -o conftest conftest2.c $LDFLAGS libconftest1.a >>conftest.out 2>&1 && test -x conftest ; then # Success! Install works ac_cv_prog_install_breaks_libs=no else # Failure! Does install -p work? rm -f libconftest1.a if ${libinstall} -p libconftest.a libconftest1.a >/dev/null 2>&1 ; then if ${CC-cc} $CFLAGS -o conftest conftest2.c $LDFLAGS libconftest1.a >>conftest.out 2>&1 && test -x conftest ; then # Success! Install works ac_cv_prog_install_breaks_libs="no, with -p" fi fi fi fi fi fi fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* libconftest*]) if test -z "$RANLIB_AFTER_INSTALL" ; then RANLIB_AFTER_INSTALL=no fi case "$ac_cv_prog_install_breaks_libs" in yes) RANLIB_AFTER_INSTALL=yes ;; "no, with -p") INSTALL_DATA="$INSTALL_DATA -p" ;; *) # Do nothing : ;; esac AC_SUBST(RANLIB_AFTER_INSTALL) ]) # # determine if the compiler defines a symbol containing the function name # Inspired by checks within the src/mpid/globus/configure.in file in MPICH2 # # These tests check not only that the compiler defines some symbol, such # as __FUNCTION__, but that the symbol correctly names the function. # # Defines # HAVE__FUNC__ (if __func__ defined) # HAVE_CAP__FUNC__ (if __FUNC__ defined) # HAVE__FUNCTION__ (if __FUNCTION__ defined) # AC_DEFUN([PAC_CC_FUNCTION_NAME_SYMBOL],[ AC_CACHE_CHECK([whether the compiler defines __func__], pac_cv_have__func__,[ tmp_am_cross=no AC_RUN_IFELSE([ AC_LANG_SOURCE([ #include int foo(void); int foo(void) { return (strcmp(__func__, "foo") == 0); } int main(int argc, char ** argv) { return (foo() ? 0 : 1); } ]) ], pac_cv_have__func__=yes, pac_cv_have__func__=no,tmp_am_cross=yes) if test "$tmp_am_cross" = yes ; then AC_LINK_IFELSE([ AC_LANG_SOURCE([ #include int foo(void); int foo(void) { return (strcmp(__func__, "foo") == 0); } int main(int argc, char ** argv) { return (foo() ? 0 : 1); } ]) ], pac_cv_have__func__=yes, pac_cv_have__func__=no) fi ]) if test "$pac_cv_have__func__" = "yes" ; then AC_DEFINE(HAVE__FUNC__,,[define if the compiler defines __func__]) fi AC_CACHE_CHECK([whether the compiler defines __FUNC__], pac_cv_have_cap__func__,[ tmp_am_cross=no AC_RUN_IFELSE([ AC_LANG_SOURCE([ #include int foo(void); int foo(void) { return (strcmp(__FUNC__, "foo") == 0); } int main(int argc, char ** argv) { return (foo() ? 0 : 1); } ]) ], pac_cv_have_cap__func__=yes, pac_cv_have_cap__func__=no,tmp_am_cross=yes) if test "$tmp_am_cross" = yes ; then AC_LINK_IFELSE([ AC_LANG_SOURCE([ #include int foo(void); int foo(void) { return (strcmp(__FUNC__, "foo") == 0); } int main(int argc, char ** argv) { return (foo() ? 0 : 1); } ]) ], pac_cv_have__func__=yes, pac_cv_have__func__=no) fi ]) if test "$pac_cv_have_cap__func__" = "yes" ; then AC_DEFINE(HAVE_CAP__FUNC__,,[define if the compiler defines __FUNC__]) fi AC_CACHE_CHECK([whether the compiler sets __FUNCTION__], pac_cv_have__function__,[ tmp_am_cross=no AC_RUN_IFELSE([ AC_LANG_SOURCE([ #include int foo(void); int foo(void) { return (strcmp(__FUNCTION__, "foo") == 0); } int main(int argc, char ** argv) { return (foo() ? 0 : 1); } ]) ], pac_cv_have__function__=yes, pac_cv_have__function__=no,tmp_am_cross=yes) if test "$tmp_am_cross" = yes ; then AC_LINK_IFELSE([ AC_LANG_SOURCE([ #include int foo(void); int foo(void) { return (strcmp(__FUNCTION__, "foo") == 0); } int main(int argc, char ** argv) { return (foo() ? 0 : 1); } ]) ], pac_cv_have__func__=yes, pac_cv_have__func__=no) fi ]) if test "$pac_cv_have__function__" = "yes" ; then AC_DEFINE(HAVE__FUNCTION__,,[define if the compiler defines __FUNCTION__]) fi ]) dnl Check structure alignment AC_DEFUN([PAC_STRUCT_ALIGNMENT],[ # Initialize alignment checks is_packed=1 is_two=1 is_four=1 is_eight=1 is_largest=1 # See if long double exists AC_TRY_COMPILE(,[long double a;],have_long_double=yes,have_long_double=no) # Get sizes of regular types AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(float) AC_CHECK_SIZEOF(double) AC_CHECK_SIZEOF(long double) # char_int comparison AC_CHECK_SIZEOF(char_int, 0, [typedef struct { char a; int b; } char_int; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_int` extent=$ac_cv_sizeof_char_int if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_int`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi if test "$ac_cv_sizeof_int" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi # char_short comparison AC_CHECK_SIZEOF(char_short, 0, [typedef struct { char a; short b; } char_short; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_short` extent=$ac_cv_sizeof_char_short if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_short`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "$ac_cv_sizeof_short" = "4" -a "`expr $extent % 4`" != "0" ; then is_four=0 fi if test "$ac_cv_sizeof_short" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi # char_long comparison AC_CHECK_SIZEOF(char_long, 0, [typedef struct { char a; long b; } char_long; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_long` extent=$ac_cv_sizeof_char_long if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_long`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi if test "$ac_cv_sizeof_long" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi # char_float comparison AC_CHECK_SIZEOF(char_float, 0, [typedef struct { char a; float b; } char_float; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_float` extent=$ac_cv_sizeof_char_float if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_float`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi if test "$ac_cv_sizeof_float" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi # char_double comparison AC_CHECK_SIZEOF(char_double, 0, [typedef struct { char a; double b; } char_double; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_double` extent=$ac_cv_sizeof_char_double if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_double`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi if test "$ac_cv_sizeof_double" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi # char_long_double comparison if test "$have_long_double" = "yes"; then AC_CHECK_SIZEOF(char_long_double, 0, [ typedef struct { char a; long double b; } char_long_double; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_long_double` extent=$ac_cv_sizeof_char_long_double if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_long_double`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi if test "$ac_cv_sizeof_long_double" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi fi # char_int_char comparison AC_CHECK_SIZEOF(char_int_char, 0, [ typedef struct { char a; int b; char c; } char_int_char; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_int + $ac_cv_sizeof_char` extent=$ac_cv_sizeof_char_int_char if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_int`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi if test "$ac_cv_sizeof_int" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi # char_short_char comparison AC_CHECK_SIZEOF(char_short_char, 0, [ typedef struct { char a; short b; char c; } char_short_char; ]) size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_short + $ac_cv_sizeof_char` extent=$ac_cv_sizeof_char_short_char if test "$size" != "$extent" ; then is_packed=0 ; fi if test "`expr $extent % $ac_cv_sizeof_short`" != "0" ; then is_largest=0 ; fi if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi if test "$ac_cv_sizeof_short" = "4" -a "`expr $extent % 4`" != "0" ; then is_four=0 fi if test "$ac_cv_sizeof_short" = "8" -a "`expr $extent % 8`" != "0" ; then is_eight=0 fi # If aligned mod 8, it will be aligned mod 4 if test $is_eight = 1 ; then is_four=0 ; is_two=0 ; fi if test $is_four = 1 ; then is_two=0 ; fi # Largest supersedes 8 if test $is_largest = 1 ; then is_eight=0 ; fi # Find the alignment if test "`expr $is_packed + $is_largest + $is_two + $is_four + $is_eight`" = "0" ; then pac_cv_struct_alignment="unknown" elif test "`expr $is_packed + $is_largest + $is_two + $is_four + $is_eight`" != "1" ; then pac_cv_struct_alignment="unknown" elif test $is_packed = 1 ; then pac_cv_struct_alignment="packed" elif test $is_largest = 1 ; then pac_cv_struct_alignment="largest" elif test $is_two = 1 ; then pac_cv_struct_alignment="two" elif test $is_four = 1 ; then pac_cv_struct_alignment="four" elif test $is_eight = 1 ; then pac_cv_struct_alignment="eight" fi ]) dnl dnl PAC_C_MACRO_VA_ARGS dnl dnl will AC_DEFINE([HAVE_MACRO_VA_ARGS]) if the compiler supports C99 variable dnl length argument lists in macros (#define foo(...) bar(__VA_ARGS__)) AC_DEFUN([PAC_C_MACRO_VA_ARGS],[ AC_MSG_CHECKING([for variable argument list macro functionality]) AC_LINK_IFELSE([AC_LANG_PROGRAM([ #include #define conftest_va_arg_macro(...) printf(__VA_ARGS__) ], [conftest_va_arg_macro("a test %d", 3);])], [AC_DEFINE([HAVE_MACRO_VA_ARGS],[1],[Define if C99-style variable argument list macro functionality]) AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) ])dnl armci-mpi/m4/aclocal_atomic.m40000644000175000017500000001660712662706250015740 0ustar mbanckmbanckdnl /*D PAC_C_MEMATOMIC - Try and determine how to implement memory-atomic dnl operations with the selected C compiler dnl dnl Synopsis: dnl PAC_C_MEMATOMIC dnl dnl Notes: dnl Defines names of the following form dnl + HAVE_GCC_ASM_AND_X86_{MFENCE,LFENCE,SFENCE} - gcc __asm__ will issue dnl mfence, lfence, or sfence dnl . HAVE___ASM_AND_X86_{MFENCE,LFENCE,SFENCE} - __asm _emit will issue dnl mfence, lfence, or sfence dnl . HAVE_ASM_AND_X86_{MFENCE,LFENCE,SFENCE} - asm("...") will issue dnl mfence, lfence, or sfence dnl . HAVE__INTERLOCKEDEXCHANGE - _InterlockedExchange intrinsic is available dnl (IA64) dnl . HAVE_GCC_ASM_SPARC_MEMBAR - gcc __asm__ will issue SPARC architecture dnl memory barrier instruction dnl . HAVE_SOLARIS_ASM_SPARC_MEMBAR - Solaris asm() will issue SPARC dnl architecture memory barrier instruction dnl . HAVE_GCC_ASM_SPARC_STBAR - gcc __asm__ will issue stbar dnl - HAVE_SOLARIS_ASM_SPARC_STBAR - Solaris __asm() will issue stbar dnl dnl D*/ AC_DEFUN([PAC_C_MEMATOMIC],[ AC_CACHE_CHECK([for x86 mfence instruction using __asm__], pac_cv_have_gcc_asm_and_x86_mfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { __asm__ __volatile__ ( ".byte 0x0f, 0xae, 0xf0" ::: "memory" ); exit(0); } ], pac_cv_have_gcc_asm_and_x86_mfence=yes,pac_cv_have_gcc_asm_and_x86_mfence=no)]) if test "$pac_cv_have_gcc_asm_and_x86_mfence" = "yes" ; then AC_DEFINE(HAVE_GCC_ASM_AND_X86_MFENCE, 1, [Define if using gcc on a x86 system with the mfence instruction]) fi AC_CACHE_CHECK([for x86 sfence instruction using __asm__], pac_cv_have_gcc_asm_and_x86_sfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { __asm__ __volatile__ ( ".byte 0x0f, 0xae, 0xf8" ::: "memory" ); exit(0); } ], pac_cv_have_gcc_asm_and_x86_sfence=yes,pac_cv_have_gcc_asm_and_x86_sfence=no)]) if test "$pac_cv_have_gcc_asm_and_x86_sfence" = "yes" ; then AC_DEFINE(HAVE_GCC_ASM_AND_X86_SFENCE, 1, [Define if using gcc on a x86 system with the sfence instruction]) fi AC_CACHE_CHECK([for x86 lfence instruction using __asm__], pac_cv_have_gcc_asm_and_x86_lfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { __asm__ __volatile__ ( ".byte 0x0f, 0xae, 0xe8" ::: "memory" ); exit(0); } ], pac_cv_have_gcc_asm_and_x86_lfence=yes,pac_cv_have_gcc_asm_and_x86_lfence=no)]) if test "$pac_cv_have_gcc_asm_and_x86_lfence" = "yes" ; then AC_DEFINE(HAVE_GCC_ASM_AND_X86_LFENCE, 1, [Define if using gcc on a x86 system with the lfence instruction]) fi dnl Some compilers, like icc, may want __asm _emit AC_CACHE_CHECK([for x86 mfence instruction using __asm], pac_cv_have___asm_and_x86_mfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { __asm _emit 0x0f __asm _emit 0xae __asm _emit 0xf0 ; exit(0); } ], pac_cv_have___asm_and_x86_mfence=yes,pac_cv_have___asm_and_x86_mfence=no)]) if test "$pac_cv_have___asm_and_x86_mfence" = "yes" ; then AC_DEFINE(HAVE___ASM_AND_X86_MFENCE, 1, [Define if using __asm on a x86 system with the mfence instruction]) fi AC_CACHE_CHECK([for x86 sfence instruction using __asm], pac_cv_have___asm_and_x86_sfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { __asm sfence ; exit(0); } ], pac_cv_have___asm_and_x86_sfence=yes,pac_cv_have___asm_and_x86_sfence=no)]) if test "$pac_cv_have___asm_and_x86_sfence" = "yes" ; then AC_DEFINE(HAVE___ASM_AND_X86_SFENCE, 1, [Define if using __asm on a x86 system with the sfence instruction]) fi AC_CACHE_CHECK([for x86 lfence instruction using __asm], pac_cv_have___asm_and_x86_lfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { __asm _emit 0x0f __asm _emit 0xae __asm _emit 0xe8 ; exit(0); } ], pac_cv_have___asm_and_x86_lfence=yes,pac_cv_have___asm_and_x86_lfence=no)]) if test "$lac_cv_have___asm_and_x86_lfence" = "yes" ; then AC_DEFINE(HAVE___ASM_AND_X86_LFENCE, 1, [Define if using __asm on a x86 system with the lfence instruction]) fi dnl dnl Some compilers, such as pgcc, may require additional arguments. dnl pgcc may need -Masmkeyword flag. We may want to try this with and dnl without adding -Masmkeyword to CFLAGS AC_CACHE_CHECK([for x86 mfence instruction using asm()], pac_cv_have_asm_and_x86_mfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { asm("_emit 0x0f __asm _emit 0xae __asm _emit 0xf0"); exit(0); } ], pac_cv_have_asm_and_x86_mfence=yes,pac_cv_have_asm_and_x86_mfence=no)]) if test "$pac_cv_have_asm_and_x86_mfence" = "yes" ; then AC_DEFINE(HAVE_ASM_AND_X86_MFENCE, 1, [Define if using asm() on a x86 system with the mfence instruction]) fi AC_CACHE_CHECK([for x86 sfence instruction using asm()], pac_cv_have_asm_and_x86_sfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { asm("sfence"); exit(0); } ], pac_cv_have_asm_and_x86_sfence=yes,pac_cv_have_asm_and_x86_sfence=no)]) if test "$pac_cv_have_asm_and_x86_sfence" = "yes" ; then AC_DEFINE(HAVE_ASM_AND_X86_SFENCE, 1, [Define if using asm() on a x86 system with the sfence instruction]) fi AC_CACHE_CHECK([for x86 lfence instruction using asm()], pac_cv_have_asm_and_x86_lfence,[ AC_TRY_RUN([ int main(int argc, char **argv) { asm("_emit 0x0f __asm _emit 0xae __asm _emit 0xe8"); exit(0); } ], pac_cv_have_asm_and_x86_lfence=yes,pac_cv_have_asm_and_x86_lfence=no)]) if test "$pac_cv_have_asm_and_x86_lfence" = "yes" ; then AC_DEFINE(HAVE_ASM_AND_X86_LFENCE, 1, [Define if using asm() on a x86 system with the lfence instruction]) fi AC_CACHE_CHECK([for _InterlockedExchange intrinsic], pac_cv_have__InterlockedExchange,[ AC_TRY_RUN([ int main(int argc, char **argv) { unsigned long lock, *lock_ptr; lock_ptr = &lock; _InterlockedExchange(lock_ptr, 1); exit(0); } ], pac_cv_have__InterlockedExchange=yes,pac_cv_have__InterlockedExchange=no)]) if test "$pac_cv_have__InterlockedExchange" = "yes" ; then AC_DEFINE(HAVE__INTERLOCKEDEXCHANGE, 1, [Define if _InterlockedExchange intrinsic is available]) fi AC_CACHE_CHECK([for SPARC membar instruction with gcc], pac_cv_gcc_sparc_membar,[ AC_TRY_RUN([ int main(int argc, char **argv){ __asm__ __volatile__ ( "membar #StoreLoad | #StoreStore" : : : "memory" ); exit(0); }],pac_cv_gcc_sparc_membar=yes,pac_cv_gcc_sparc_membar=no)]) if test "$pac_cv_gcc_sparc_membar" = yes ; then AC_DEFINE(HAVE_GCC_ASM_SPARC_MEMBAR,1,[Define if gcc asm membar supported]) fi AC_CACHE_CHECK([for SPARC membar instruction with Solaris C], pac_cv_solaris_sparc_membar,[ AC_TRY_RUN([ int main(int argc, char **argv){ __asm ( "membar #StoreLoad | #StoreStore"); exit(0); }],pac_cv_solaris_sparc_membar=yes,pac_cv_solaris_sparc_membar=no)]) if test "$pac_cv_solaris_sparc_membar" = yes ; then AC_DEFINE(HAVE_SOLARIS_ASM_SPARC_MEMBAR,1,[Define if solaris asm membar supported]) fi AC_CACHE_CHECK([for SPARC stbar instruction with gcc], pac_cv_gcc_sparc_stbar,[ AC_TRY_RUN([ int main(int argc, char **argv){ __asm__ __volatile__ ( "stbar" : : : "memory" ); exit(0); }],pac_cv_gcc_sparc_stbar=yes,pac_cv_gcc_sparc_stbar=no)]) if test "$pac_cv_gcc_sparc_stbar" = yes ; then AC_DEFINE(HAVE_GCC_ASM_SPARC_STBAR,1,[Define if gcc asm stbar supported]) fi AC_CACHE_CHECK([for SPARC stbar instruction with Solaris C], pac_cv_solaris_sparc_stbar,[ AC_TRY_RUN([ int main(int argc, char **argv){ __asm ( "stbar" ); exit(0); }],pac_cv_solaris_sparc_stbar=yes,pac_cv_solaris_sparc_stbar=no)]) if test "$pac_cv_solaris_sparc_stbar" = yes ; then AC_DEFINE(HAVE_SOLARIS_ASM_SPARC_STBAR,1,[Define if solaris asm stbar supported]) fi ])armci-mpi/m4/aclocal_mpi.m40000644000175000017500000003762512662706250015254 0ustar mbanckmbanckdnl dnl/*D dnl PAC_LIB_MPI - Check for MPI library dnl dnl Synopsis: dnl PAC_LIB_MPI([action if found],[action if not found]) dnl dnl Output Effect: dnl dnl Notes: dnl Currently, only checks for lib mpi and mpi.h. Later, we will add dnl MPI_Pcontrol prototype (const int or not?). dnl dnl Prerequisites: dnl autoconf version 2.13 (for AC_SEARCH_LIBS) dnl D*/ dnl Other tests to add: dnl Version of MPI dnl MPI-2 I/O? dnl MPI-2 Spawn? dnl MPI-2 RMA? dnl PAC_LIB_MPI([found text],[not found text]) AC_DEFUN([PAC_LIB_MPI],[ dnl Set the prereq to 2.50 to avoid having AC_PREREQ(2.50) if test "X$pac_lib_mpi_is_building" != "Xyes" ; then # Use CC if TESTCC is defined if test "X$pac_save_level" != "X" ; then pac_save_TESTCC="${TESTCC}" pac_save_TESTCPP="${TESTCPP}" CC="$pac_save_CC" if test "X$pac_save_CPP" != "X" ; then CPP="$pac_save_CPP" fi fi # Look for MPILIB first if it is defined AC_SEARCH_LIBS(MPI_Init,$MPILIB mpi mpich mpich2) if test "$ac_cv_search_MPI_Init" = "no" ; then ifelse($2,, AC_MSG_ERROR([Could not find MPI library]),[$2]) fi AC_CHECK_HEADER(mpi.h,pac_have_mpi_h="yes",pac_have_mpi_h="no") if test $pac_have_mpi_h = "no" ; then ifelse($2,, AC_MSG_ERROR([Could not find mpi.h include file]),[$2]) fi if test "X$pac_save_level" != "X" ; then CC="$pac_save_TESTCC" CPP="$pac_save_TESTCPP" fi fi ifelse($1,,,[$1]) ]) dnl This should also set MPIRUN. dnl dnl/*D dnl PAC_ARG_MPI_TYPES - Add command-line switches for different MPI dnl environments dnl dnl Synopsis: dnl PAC_ARG_MPI_TYPES([default]) dnl dnl Output Effects: dnl Adds the following command line options to configure dnl+ \-\-with\-mpich[=path] - MPICH. 'path' is the location of MPICH commands dnl. \-\-with\-ibmmpi - IBM MPI dnl. \-\-with\-lammpi[=path] - LAM/MPI dnl. \-\-with\-mpichnt - MPICH NT dnl- \-\-with\-sgimpi - SGI MPI dnl If no type is selected, and a default ("mpich", "ibmmpi", or "sgimpi") dnl is given, that type is used as if '--with-' was given. dnl dnl Sets 'CC', 'F77', 'TESTCC', 'TESTF77', and 'MPILIBNAME'. Does `not` dnl perform an AC_SUBST for these values. dnl Also sets 'MPIBOOT' and 'MPIUNBOOT'. These are used to specify dnl programs that may need to be run before and after running MPI programs. dnl For example, 'MPIBOOT' may start demons necessary to run MPI programs and dnl 'MPIUNBOOT' will stop those demons. dnl dnl The two forms of the compilers are to allow for tests of the compiler dnl when the MPI version of the compiler creates executables that cannot dnl be run on the local system (for example, the IBM SP, where executables dnl created with mpcc will not run locally, but executables created dnl with xlc may be used to discover properties of the compiler, such as dnl the size of data types). dnl dnl Historical note: dnl Some common autoconf tests, such as AC_CHECK_SIZEOF, used to require dnl running a program. But some MPI compilers (often really compilation dnl scripts) produced programs that could only be run with special commands, dnl such as a batch submission system. To allow these test programs to be dnl run, a separate set of compiler variables, TESTCC, TESTF77, etc., dnl were defined. However, in later versions of autoconf, it both became dnl unnecessary to run programs for tests such as AC_CHECK_SIZEOF and dnl it became necessary to define CC etc. before invoking AC_PROG_CC (and dnl the othe language compilers), because those commands now do much, much dnl more than just determining the compiler. dnl dnl To address the change, we still define the TESTCC ect. compilers where dnl possible to allow the use of AC_TRY_RUN when required, but we define dnl the CC etc variables and do not define ac_cv_prog_CC etc., as these dnl cause autoconf to skip all of the other initialization code that dnl AC_PROG_CC etc. runs. Note also that this command must occur before dnl AC_PROG_CC (or anything that might cause AC_PROG_CC to be invoked). dnl dnl See also: dnl PAC_LANG_PUSH_COMPILERS, PAC_LIB_MPI dnl D*/ AC_DEFUN([PAC_ARG_MPI_TYPES],[ PAC_ARG_MPI_KNOWN_TYPES PAC_MPI_FIND_COMPILERS PAC_MPI_CHECK_MPI_LIB ]) dnl dnl To keep autoconf from prematurely invoking the compiler check scripts, dnl we need a command that first sets the compilers and a separate one dnl that makes any necessary checks for libraries dnl AC_DEFUN([PAC_ARG_MPI_KNOWN_TYPES],[ AC_ARG_WITH(mpich, [--with-mpich=path - Assume that we are building with MPICH], ac_mpi_type=mpich) # Allow MPICH2 as well as MPICH AC_ARG_WITH(mpich2, [--with-mpich=path - Assume that we are building with MPICH], ac_mpi_type=mpich) AC_ARG_WITH(lammpi, [--with-lammpi=path - Assume that we are building with LAM/MPI], ac_mpi_type=lammpi) AC_ARG_WITH(ibmmpi, [--with-ibmmpi - Use the IBM SP implementation of MPI], ac_mpi_type=ibmmpi) AC_ARG_WITH(sgimpi, [--with-sgimpi - Use the SGI implementation of MPI], ac_mpi_type=sgimpi) AC_ARG_WITH(mpichnt, [--with-mpichnt - Use MPICH for Windows NT ], ac_mpi_type=mpichnt) AC_ARG_WITH(mpi, [--with-mpi=path - Use an MPI implementation with compile scripts mpicc and mpif77 in path/bin],ac_mpi_type=generic) if test "X$ac_mpi_type" = "X" ; then if test "X$1" != "X" ; then ac_mpi_type=$1 else ac_mpi_type=unknown fi fi if test "$ac_mpi_type" = "unknown" -a "$pac_lib_mpi_is_building" = "yes" ; then ac_mpi_type="mpich" fi ]) AC_DEFUN([PAC_MPI_FIND_COMPILERS],[ # Set defaults MPIRUN_NP="-np " MPIEXEC_N="-n " AC_SUBST(MPIRUN_NP) AC_SUBST(MPIEXEC_N) dnl AC_ARG_VAR([MPIEXEC],[Name and path of mpiexec program]) AC_ARG_VAR([MPIRUN],[Name and path of mpirun program]) AC_ARG_VAR([MPIBOOT],[Name and path of program to run before mpirun]) AC_ARG_VAR([MPIUNBOOT],[Name and path of program to run after all mpirun]) AC_ARG_VAR([MPICC],[Name and absolute path of program used to compile MPI programs in C]) AC_ARG_VAR([MPIF77],[Name and absolute path of program used to compile MPI programs in F77]) AC_ARG_VAR([MPICXX],[Name and absolute path of program used to compile MPI programs in C++]) AC_ARG_VAR([MPIF90],[Name and absolute path of program used to compile MPI programs in F90]) # # Check for things that will cause trouble. For example, # if MPICC is defined but does not contain a / or \, then PATH_PROG will # ignore the value if test -n "$MPICC" ; then case $MPICC in changequote(<<,>>) [\\/]* | ?:[\\/]*) changequote([,]) # Ok, PATH_PROG will figure it out ;; *) AC_MSG_ERROR([MPICC must be set to an absolute path if it is set]) esac fi if test -n "$MPICXX" ; then case $MPICXX in changequote(<<,>>) [\\/]* | ?:[\\/]*) changequote([,]) # Ok, PATH_PROG will figure it out ;; *) AC_MSG_ERROR([MPICXX must be set to an absolute path if it is set]) esac fi if test -n "$MPIF77" ; then case $MPIF77 in changequote(<<,>>) [\\/]* | ?:[\\/]*) changequote([,]) # Ok, PATH_PROG will figure it out ;; *) AC_MSG_ERROR([MPIF77 must be set to an absolute path if it is set]) esac fi if test -n "$MPIF90" ; then case $MPIF90 in changequote(<<,>>) [\\/]* | ?:[\\/]*) changequote([,]) # Ok, PATH_PROG will figure it out ;; *) AC_MSG_ERROR([MPIF90 must be set to an absolute path if it is set]) esac fi case $ac_mpi_type in mpich) dnl dnl This isn't correct. It should try to get the underlying compiler dnl from the mpicc and mpif77 scripts or mpireconfig if test "X$pac_lib_mpi_is_building" != "Xyes" ; then save_PATH="$PATH" if test "$with_mpich" != "yes" -a "$with_mpich" != "no" ; then # Look for commands; if not found, try adding bin to the # path if test ! -x $with_mpich/mpicc -a -x $with_mpich/bin/mpicc ; then with_mpich="$with_mpich/bin" fi PATH=$with_mpich:${PATH} fi AC_PATH_PROG(MPICC,mpicc) if test -z "$TESTCC" ; then TESTCC=${CC-cc} ; fi CC="$MPICC" # Note that autoconf may unconditionally change the value of # CC (!) in some other command. Thus, we define CCMASTER CCMASTER=$CC # to permit configure codes to recover the correct CC. This # is an ugly not-quite-correct workaround for the fact that # does not want you to change the C compiler once you have set it # (But since it does so unconditionally, it silently creates # bogus output files.) AC_PATH_PROG(MPIF77,mpif77) if test -z "$TESTF77" ; then TESTF77=${F77-f77} ; fi F77="$MPIF77" AC_PATH_PROG(MPIFC,mpif90) if test -z "$TESTFC" ; then TESTFC=${FC-f90} ; fi FC="$MPIFC" AC_PATH_PROG(MPICXX,mpiCC) if test -z "$TESTCXX" ; then TESTCXX=${CXX-CC} ; fi CXX="$MPICXX" # We may want to restrict this to the path containing mpirun AC_PATH_PROG(MPIEXEC,mpiexec) AC_PATH_PROG(MPIRUN,mpirun) AC_PATH_PROG(MPIBOOT,mpichboot) AC_PATH_PROG(MPIUNBOOT,mpichstop) PATH="$save_PATH" MPILIBNAME="mpich" else # All of the above should have been passed in the environment! : fi ;; mpichnt) ;; lammpi) dnl dnl This isn't correct. It should try to get the underlying compiler dnl from the mpicc and mpif77 scripts or mpireconfig save_PATH="$PATH" if test "$with_mpich" != "yes" -a "$with_mpich" != "no" ; then # Look for commands; if not found, try adding bin to the path if test ! -x $with_lammpi/mpicc -a -x $with_lammpi/bin/mpicc ; then with_lammpi="$with_lammpi/bin" fi PATH=$with_lammpi:${PATH} fi AC_PATH_PROG(MPICC,mpicc) if test -z "$TESTCC" ; then TESTCC=${CC-cc} ; fi CC="$MPICC" AC_PATH_PROG(MPIF77,mpif77) if test -z "$TESTCC" ; then TESTF77=${F77-f77} ; fi F77="$MPIF77" AC_PATH_PROG(MPIFC,mpif90) TESTFC=${FC-f90} if test -z "$TESTFC" ; then TESTFC=${FC-f90} ; fi FC="$MPIFC" AC_PATH_PROG(MPICXX,mpiCC) if test -z "$TESTCXX" ; then TESTCXX=${CXX-CC} ; fi CXX="$MPICXX" PATH="$save_PATH" MPILIBNAME="lammpi" MPIBOOT="lamboot" MPIUNBOOT="wipe" MPIRUN="mpirun" ;; ibmmpi) AC_CHECK_PROGS(MPCC,mpcc) AC_CHECK_PROGS(MPXLF,mpxlf) if test -z "$MPCC" -o -z "$MPXLF" ; then AC_MSG_ERROR([Could not find IBM MPI compilation scripts. Either mpcc or mpxlf is missing]) fi if test -z "$TESTCC" ; then TESTCC=${CC-xlC} ; fi if test -z "$TESTF77" ; then TESTF77=${F77-xlf}; fi CC=mpcc; F77=mpxlf # There is no mpxlf90, but the options langlvl and free can # select the Fortran 90 version of xlf if test "$enable_f90" != no ; then AC_CHECK_PROGS(MPIXLF90,mpxlf90) if test -z "$TESTFC" ; then TESTFC=${FC-xlf90}; fi if test "X$MPIXLF90" != "X" ; then FC="mpxlf90" else FC="mpxlf -qlanglvl=90ext -qfree=f90" fi fi MPILIBNAME="" cross_compiling=yes # Turn off the autoconf version 3 warning message ac_tool_warned=yes ;; sgimpi) if test -z "$TESTCC" ; then TESTCC=${CC:=cc} ; fi if test -z "$TESTF77" ; then TESTF77=${F77:=f77} ; fi if test -z "$TESTCXX" ; then TESTCXX=${CXX:=CC} ; fi if test -z "$TESTFC" ; then TESTFC=${FC:=f90} ; fi AC_CHECK_LIB(mpi,MPI_Init) if test "$ac_cv_lib_mpi_MPI_Init" = "yes" ; then MPILIBNAME="mpi" fi MPIRUN=mpirun MPIBOOT="" MPIUNBOOT="" ;; generic) # Find the compilers. Expect the compilers to be mpicc and mpif77 # in $with_mpi/bin PAC_PROG_CC # We only look for the other compilers if there is no # disable for them if test "$enable_f77" != no -a "$enable_fortran" != no ; then AC_PROG_F77 fi if test "$enable_cxx" != no ; then AC_PROG_CXX fi if test "$enable_f90" != no ; then PAC_PROG_FC fi # Set defaults for the TEST versions if not already set if test -z "$TESTCC" ; then TESTCC=${CC:=cc} fi if test -z "$TESTF77" ; then TESTF77=${F77:=f77} fi if test -z "$TESTCXX" ; then TESTCXX=${CXX:=CC} fi if test -z "$TESTFC" ; then TESTFC=${FC:=f90} fi # in $with_mpi/bin or $with_mpi if test "X$MPICC" = "X" ; then if test -x "$with_mpi/bin/mpicc" ; then MPICC=$with_mpi/bin/mpicc elif test -x "$with_mpi/mpicc" ; then MPICC=$with_mpi/mpicc fi fi if test "X$MPICXX" = "X" ; then if test -x "$with_mpi/bin/mpicxx" ; then MPICXX=$with_mpi/bin/mpicxx elif test -x "$with_mpi/mpicxx" ; then MPICXX=$with_mpi/mpicxx fi fi if test "X$MPIF77" = "X" ; then if test -x "$with_mpi/bin/mpif77" ; then MPIF77=$with_mpi/bin/mpif77 elif test -x "$with_mpi/mpif77" ; then MPIF77=$with_mpi/mpif77 fi fi if test "X$MPIF90" = "X" ; then if test -x "$with_mpi/bin/mpif90" ; then MPIF90=$with_mpi/bin/mpif90 elif test -x "$with_mpi/mpif90" ; then MPIF90=$with_mpi/mpif90 fi fi if test "X$MPIEXEC" = "X" ; then if test -x "$with_mpi/bin/mpiexec" ; then MPIEXEC=$with_mpi/bin/mpiexec elif test -x "$with_mpi/mpiexec" ; then MPIEXEC=$with_mpi/mpiexec fi fi CC=$MPICC F77=$MPIF77 if test "X$MPICXX" != "X" ; then CXX=$MPICXX ; fi if test "X$MPIF90" != "X" ; then F90=$MPIF90 ; fi ;; *) # Use the default choices for the compilers ;; esac # Tell autoconf to determine properties of the compilers (these are the # compilers for MPI programs) AC_PROG_CC if test "$enable_f77" != no -a "$enable_fortran" != no ; then AC_PROG_F77 fi if test "$enable_cxx" != no ; then AC_PROG_CXX fi if test "$enable_f90" != no ; then PAC_PROG_FC fi ]) dnl dnl This uses the selected CC etc to check for include paths and libraries AC_DEFUN([PAC_MPI_CHECK_MPI_LIB],[ case $ac_mpi_type in mpich) ;; mpichnt) dnl dnl This isn't adequate, but it helps with using MPICH-NT/SDK.gcc save_CFLAGS="$CFLAGS" CFLAGS="$save_CFLAGS -I$with_mpichnt/include" save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$save_CPPFLAGS -I$with_mpichnt/include" save_LDFLAGS="$LDFLAGS" LDFLAGS="$save_LDFLAGS -L$with_mpichnt/lib" AC_CHECK_LIB(mpich,MPI_Init,found="yes",found="no") if test "$found" = "no" ; then AC_CHECK_LIB(mpich2,MPI_Init,found="yes",found="no") fi if test "$enable_cxx" != no ; then AC_PROG_CXX fi if test "$enable_f90" != no ; then PAC_PROG_FC fi # Set defaults for the TEST versions if not already set if test -z "$TESTCC" ; then TESTCC=${CC:=cc} ; fi if test -z "$TESTF77" ; then TESTF77=${F77:=f77} ; fi if test -z "$TESTCXX" ; then TESTCXX=${CXX:=CC} ; fi if test -z "$TESTFC" ; then TESTFC=${FC:=f90} ; fi if test "$found" = "no" ; then CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS fi ;; lammpi) ;; ibmmpi) ;; sgimpi) AC_CHECK_LIB(mpi,MPI_Init) if test "$ac_cv_lib_mpi_MPI_Init" = "yes" ; then MPILIBNAME="mpi" fi ;; generic) AC_SEARCH_LIBS(MPI_Init,mpi mpich2 mpich) if test "$ac_cv_lib_mpi_MPI_Init" = "yes" ; then MPILIBNAME="mpi" fi ;; *) ;; esac ]) dnl dnl/*D dnl PAC_MPI_F2C - Determine if MPI has the MPI-2 functions MPI_xxx_f2c and dnl MPI_xxx_c2f dnl dnl Output Effect: dnl Define 'HAVE_MPI_F2C' if the routines are found. dnl dnl Notes: dnl Looks only for 'MPI_Request_c2f'. dnl D*/ AC_DEFUN([PAC_MPI_F2C],[ AC_CACHE_CHECK([for MPI F2C and C2F routines], pac_cv_mpi_f2c, [ AC_TRY_LINK([#include "mpi.h"], [MPI_Request request;MPI_Fint a;a = MPI_Request_c2f(request);], pac_cv_mpi_f2c="yes",pac_cv_mpi_f2c="no") ]) if test "$pac_cv_mpi_f2c" = "yes" ; then AC_DEFINE(HAVE_MPI_F2C,1,[Define if MPI has F2C]) fi ]) dnl dnl/*D dnl PAC_HAVE_ROMIO - make mpi.h include mpio.h if romio enabled dnl dnl Output Effect: dnl expands @HAVE_ROMIO@ in mpi.h into #include "mpio.h" dnl D*/ AC_DEFUN([PAC_HAVE_ROMIO],[ if test "$enable_romio" = "yes" ; then HAVE_ROMIO='#include "mpio.h"'; fi AC_SUBST(HAVE_ROMIO) ]) armci-mpi/m4/aclocal_libs.m40000644000175000017500000000442412662706250015407 0ustar mbanckmbanck dnl PAC_SET_HEADER_LIB_PATH(with_option) dnl This macro looks for the --with-xxx=, --with-xxx-include and --with-xxx-lib= dnl options and sets the library and include paths. AC_DEFUN([PAC_SET_HEADER_LIB_PATH],[ AC_ARG_WITH($1, AC_HELP_STRING([--with-$1=path], [specify path where $1 include directory and lib directory can be found]), if test "${with_$1}" != "yes" -a "${with_$1}" != "no" ; then # is adding lib64 by default really the right thing to do? What if # we are on a 32-bit host that happens to have both lib dirs available? LDFLAGS="$LDFLAGS -L${with_$1}/lib64 -L${with_$1}/lib" CPPFLAGS="$CPPFLAGS -I${with_$1}/include" WRAPPER_CFLAGS="$WRAPPER_CFLAGS -I${with_$1}/include" fi, ) AC_ARG_WITH($1-include, AC_HELP_STRING([--with-$1-include=path], [specify path where $1 include directory can be found]), if test "${with_$1_include}" != "yes" -a "${with_$1_include}" != "no" ; then CPPFLAGS="$CPPFLAGS -I${with_$1_include}" WRAPPER_CFLAGS="$WRAPPER_CFLAGS -I${with_$1_include}" fi, ) AC_ARG_WITH($1-lib, AC_HELP_STRING([--with-$1-lib=path], [specify path where $1 lib directory can be found]), if test "${with_$1_lib}" != "yes" -a "${with_$1_lib}" != "no" ; then LDFLAGS="$LDFLAGS -L${with_$1_lib}" fi, ) ]) dnl PAC_CHECK_HEADER_LIB(with_option, header.h, libname, function, action-if-yes, action-if-no) dnl This macro checks for a header and lib. It is assumed that the dnl user can specify a path to the includes and libs using --with-xxx=. dnl The xxx is specified in the "with_option" parameter. AC_DEFUN([PAC_CHECK_HEADER_LIB],[ failure=no AC_CHECK_HEADER([$2],,failure=yes) AC_CHECK_LIB($3,$4,,failure=yes) if test "$failure" = "no" ; then $5 else $6 fi ]) dnl PAC_CHECK_HEADER_LIB_FATAL(with_option, header.h, libname, function) dnl Similar to PAC_CHECK_HEADER_LIB, but errors out on failure AC_DEFUN([PAC_CHECK_HEADER_LIB_FATAL],[ PAC_CHECK_HEADER_LIB($1,$2,$3,$4,success=yes,success=no) if test "$success" = "no" ; then AC_MSG_ERROR(['$2 or lib$3 library not found. Did you specify --with-$1= or --with-$1-include= or --with-$1-lib=?']) fi ]) armci-mpi/m4/aclocal_runlog.m40000644000175000017500000000350712662706250015765 0ustar mbanckmbanckdnl dnl PAC_RUN_LOG mimics _AC_RUN_LOG which is autoconf internal routine. dnl We also make sure PAC_RUN_LOG can be used in AS_IF, so the last dnl test command should have terminating ]), i.e. without newline before ]). dnl AC_DEFUN([PAC_RUNLOG],[ { AS_ECHO(["$as_me:$LINENO: $1"]) >&AS_MESSAGE_LOG_FD (eval $1) 2>&AS_MESSAGE_LOG_FD ac_status=$? AS_ECHO(["$as_me:$LINENO: \$? = $ac_status"]) >&AS_MESSAGE_LOG_FD test $ac_status = 0; }]) dnl dnl PAC_COMMAND_IFELSE is written to replace AC_TRY_EVAL with added logging dnl to config.log, i.e. AC_TRY_EVAL does not log anything to config.log. dnl If autoconf provides AC_COMMAND_IFELSE or AC_EVAL_IFELSE, dnl AC_COMMAND_IFELSE dnl should be replaced by the official autoconf macros. dnl dnl PAC_COMMAND_IFELSE(COMMMAND,[ACTION-IF-RUN-OK],[ACTION-IF-RUN-FAIL]) dnl AC_DEFUN([PAC_COMMAND_IFELSE],[ dnl Should use _AC_DO_TOKENS but use AC_RUN_LOG instead dnl because _AC_XX is autoconf's undocumented macro. AS_IF([PAC_RUNLOG([$1])],[ $2 ],[ AS_ECHO(["$as_me: program exited with status $ac_status"]) >&AS_MESSAGE_LOG_FD m4_ifvaln([$3],[ (exit $ac_status) $3 ]) ]) ]) dnl dnl dnl AC_DEFUN([PAC_EVAL_IFELSE],[ dnl Should use _AC_DO_TOKENS but use AC_RUN_LOG instead dnl because _AC_XX is autoconf's undocumented macro. AS_IF([PAC_RUNLOG([$$1])],[ $2 ],[ AS_ECHO(["$as_me: program exited with status $ac_status"]) >&AS_MESSAGE_LOG_FD m4_ifvaln([$3],[ (exit $ac_status) $3 ]) ]) ]) dnl dnl dnl AC_DEFUN([PAC_RUNLOG_IFELSE],[ dnl pac_TESTLOG is the internal temporary logfile for this macro. pac_TESTLOG="pac_test.log" rm -f $pac_TESTLOG PAC_COMMAND_IFELSE([$1 > $pac_TESTLOG],[ ifelse([$2],[],[],[$2]) ],[ AS_ECHO(["*** $1 :"]) >&AS_MESSAGE_LOG_FD cat $pac_TESTLOG >&AS_MESSAGE_LOG_FD ifelse([$3],[],[],[$3]) ]) rm -f $pac_TESTLOG ]) armci-mpi/m4/CHECKOUT0000644000175000017500000000013612662706250013662 0ustar mbanckmbanckThis is a snapshot checkout of https://svn.mcs.anl.gov/repos/mpi/mpich2/trunk revision r7341. armci-mpi/m4/aclocal_util.m40000644000175000017500000001310112662706250015423 0ustar mbanckmbanckdnl Nesting safe macros for saving variables dnl Usage: PAC_PUSH_FLAG(CFLAGS) AC_DEFUN([PAC_PUSH_FLAG],[ if test -z "${pac_save_$1_nesting}" ; then pac_save_$1_nesting=0 fi eval pac_save_$1_${pac_save_$1_nesting}='"$$1"' pac_save_$1_nesting=`expr ${pac_save_$1_nesting} + 1` ]) dnl Usage: PAC_POP_FLAG(CFLAGS) AC_DEFUN([PAC_POP_FLAG],[ pac_save_$1_nesting=`expr ${pac_save_$1_nesting} - 1` eval $1="\$pac_save_$1_${pac_save_$1_nesting}" eval pac_save_$1_${pac_save_$1_nesting}="" ]) dnl Usage: PAC_PUSH_ALL_FLAGS AC_DEFUN([PAC_PUSH_ALL_FLAGS],[ PAC_PUSH_FLAG(CFLAGS) PAC_PUSH_FLAG(CPPFLAGS) PAC_PUSH_FLAG(CXXFLAGS) PAC_PUSH_FLAG(FFLAGS) PAC_PUSH_FLAG(FCFLAGS) PAC_PUSH_FLAG(LDFLAGS) PAC_PUSH_FLAG(LIBS) ]) dnl Usage: PAC_POP_ALL_FLAGS AC_DEFUN([PAC_POP_ALL_FLAGS],[ PAC_POP_FLAG(CFLAGS) PAC_POP_FLAG(CPPFLAGS) PAC_POP_FLAG(CXXFLAGS) PAC_POP_FLAG(FFLAGS) PAC_POP_FLAG(FCFLAGS) PAC_POP_FLAG(LDFLAGS) PAC_POP_FLAG(LIBS) ]) dnl PAC_PREFIX_FLAG - Save flag with a prefix dnl Usage: PAC_PREFIX_FLAG(PREFIX, FLAG) AC_DEFUN([PAC_PREFIX_FLAG],[ $1_$2=$$2 export $1_$2 AC_SUBST($1_$2) ]) dnl PAC_PREFIX_ALL_FLAGS - Save flags with a prefix dnl Usage: PAC_PREFIX_ALL_FLAGS(PREFIX) AC_DEFUN([PAC_PREFIX_ALL_FLAGS],[ PAC_PREFIX_FLAG($1, CFLAGS) PAC_PREFIX_FLAG($1, CPPFLAGS) PAC_PREFIX_FLAG($1, CXXFLAGS) PAC_PREFIX_FLAG($1, FFLAGS) PAC_PREFIX_FLAG($1, FCFLAGS) PAC_PREFIX_FLAG($1, LDFLAGS) PAC_PREFIX_FLAG($1, LIBS) ]) dnl Usage: PAC_APPEND_FLAG([-02], [CFLAGS]) dnl appends the given argument to the specified shell variable unless the dnl argument is already present in the variable AC_DEFUN([PAC_APPEND_FLAG],[ AC_REQUIRE([AC_PROG_FGREP]) AS_IF( [echo "$$2" | $FGREP -e '$1' >/dev/null 2>&1], [echo "$2(='$$2') contains '$1', not appending" >&AS_MESSAGE_LOG_FD], [echo "$2(='$$2') does not contain '$1', appending" >&AS_MESSAGE_LOG_FD $2="$$2 $1"] ) ]) dnl Usage: PAC_PREPEND_FLAG([-lpthread], [LIBS]) dnl Prepends the given argument to the specified shell variable unless the dnl argument is already present in the variable. dnl dnl This is typically used for LIBS and similar variables because libraries dnl should be added in reverse order. AC_DEFUN([PAC_PREPEND_FLAG],[ AC_REQUIRE([AC_PROG_FGREP]) AS_IF( [echo "$$2" | $FGREP -e '$1' >/dev/null 2>&1], [echo "$2(='$$2') contains '$1', not prepending" >&AS_MESSAGE_LOG_FD], [echo "$2(='$$2') does not contain '$1', prepending" >&AS_MESSAGE_LOG_FD $2="$1 $$2"] ) ]) dnl PAC_MKDIRS(path) dnl Create any missing directories in the path AC_DEFUN([PAC_MKDIRS],[ # Build any intermediate directories for dir in $1 ; do saveIFS="$IFS" IFS="/" tmp_curdir="" for tmp_subdir in $dir ; do tmp_curdir="${tmp_curdir}$tmp_subdir" if test ! -d "$tmp_curdir" ; then mkdir "$tmp_curdir" ; fi tmp_curdir="${tmp_curdir}/" done IFS="$saveIFS" done ]) # Find something to use for mkdir -p. Eventually, this will have a # script for backup. As of autoconf-2.63, AC_PROG_MKDIR_P was broken; # it was checking to see if it recognized the "version" of mkdir and # was deciding based on that. This should always be a feature test. AC_DEFUN([PAC_PROG_MKDIR_P],[ AC_CACHE_CHECK([whether mkdir -p works], pac_cv_mkdir_p,[ pac_cv_mkdir_p=no rm -rf .tmp if mkdir -p .tmp/.foo 1>/dev/null 2>&1 ; then if test -d .tmp/.foo ; then pac_cv_mkdir_p=yes fi fi rm -rf .tmp ]) if test "$pac_cv_mkdir_p" = "yes" ; then MKDIR_P="mkdir -p" export MKDIR_P else AC_MSG_WARN([mkdir -p does not work; the install step may fail]) fi AC_SUBST(MKDIR_P) ]) dnl Test for a clean VPATH directory. Provide this command with the names dnl of all of the generated files that might cause problems dnl (Makefiles won't cause problems because there's no VPATH usage for them) dnl dnl Synopsis dnl PAC_VPATH_CHECK([file-names],[directory-names]) dnl file-names should be files other than config.status and any header (e.g., dnl fooconf.h) file that should be removed. It is optional AC_DEFUN([PAC_VPATH_CHECK],[ # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* date >conftest$$ # If creating a file in the current directory does not show up in the srcdir # then we're doing a VPATH build (or something is very wrong) if test ! -s $srcdir/conftest$$ ; then pac_dirtyfiles="" pac_dirtydirs="" pac_header="" ifdef([AC_LIST_HEADER],[pac_header=AC_LIST_HEADER]) for file in config.status $pac_header $1 ; do if test -f $srcdir/$file ; then pac_dirtyfiles="$pac_dirtyfiles $file" fi done ifelse($2,,,[ for dir in $2 ; do if test -d $srcdir/$dir ; then pac_dirtydirs="$pac_dirtydirs $dir" fi done ]) if test -n "$pac_dirtyfiles" -o -n "$pac_dirtydirs" ; then # Create a nice message about what to remove rmmsg="" if test -n "$pac_dirtyfiles" ; then rmmsg="files $pac_dirtyfiles" fi if test -n "$pac_dirtydirs" ; then if test -n "$rmmsg" ; then rmmsg="$rmmsg and directories $pac_dirtydirs" else rmmsg="directories $pac_dirtydirs" fi fi if test -f $srcdir/Makefile ; then AC_MSG_ERROR([You cannot do a VPATH build if the source directory has been configured. Run "make distclean" in $srcdir first and make sure that the $rmmsg have been removed.]) else AC_MSG_ERROR([You cannot do a VPATH build if the source directory has been configured. Remove the $rmmsg in $srcdir.]) fi fi fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* ]) armci-mpi/m4/aclocal_f77.m40000644000175000017500000015267212662706250015072 0ustar mbanckmbanckdnl PAC_PROG_F77 - reprioritize the F77 compiler search order AC_DEFUN([PAC_PROG_F77],[ PAC_PUSH_FLAG([FFLAGS]) AC_PROG_F77([ifort pgf77 af77 xlf frt cf77 fort77 fl32 fort ifc efc ftn gfortran f77 g77]) PAC_POP_FLAG([FFLAGS]) ]) dnl dnl/*D dnl PAC_PROG_F77_NAME_MANGLE - Determine how the Fortran compiler mangles dnl names dnl dnl Synopsis: dnl PAC_PROG_F77_NAME_MANGLE([action]) dnl dnl Output Effect: dnl If no action is specified, one of the following names is defined: dnl.vb dnl If fortran names are mapped: dnl lower -> lower F77_NAME_LOWER dnl lower -> lower_ F77_NAME_LOWER_USCORE dnl lower -> UPPER F77_NAME_UPPER dnl lower_lower -> lower__ F77_NAME_LOWER_2USCORE dnl mixed -> mixed F77_NAME_MIXED dnl mixed -> mixed_ F77_NAME_MIXED_USCORE dnl mixed -> UPPER@STACK_SIZE F77_NAME_UPPER_STDCALL dnl.ve dnl If an action is specified, it is executed instead. dnl dnl Notes: dnl We assume that if lower -> lower (any underscore), upper -> upper with the dnl same underscore behavior. Previous versions did this by dnl compiling a Fortran program and running strings -a over it. Depending on dnl strings is a bad idea, so instead we try compiling and linking with a dnl C program, since that is why we are doing this anyway. A similar approach dnl is used by FFTW, though without some of the cases we check (specifically, dnl mixed name mangling). STD_CALL not only specifies a particular name dnl mangling convention (adding the size of the calling stack into the function dnl name, but also the stack management convention (callee cleans the stack, dnl and arguments are pushed onto the stack from right to left) dnl dnl One additional problem is that some Fortran implementations include dnl references to the runtime (like pgf90_compiled for the pgf90 compiler dnl used as the "Fortran 77" compiler). This is not yet solved. dnl dnl D*/ dnl AC_DEFUN([PAC_PROG_F77_NAME_MANGLE],[ AC_CACHE_CHECK([for Fortran 77 name mangling], pac_cv_prog_f77_name_mangle, [ # Check for strange behavior of Fortran. For example, some FreeBSD # systems use f2c to implement f77, and the version of f2c that they # use generates TWO (!!!) trailing underscores # Currently, WDEF is not used but could be... # # Eventually, we want to be able to override the choices here and # force a particular form. This is particularly useful in systems # where a Fortran compiler option is used to force a particular # external name format (rs6000 xlf, for example). # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat > conftest.f <&AC_FD_CC cat conftest.f >&AC_FD_CC fi AC_LANG_SAVE AC_LANG_C save_LIBS="$LIBS" dnl FLIBS comes from AC_F77_LIBRARY_LDFLAGS LIBS="fconftestf.o $FLIBS $LIBS" AC_TRY_LINK([extern void my_name(int);],my_name(0);,pac_cv_prog_f77_name_mangle="lower") if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then AC_TRY_LINK([extern void my_name_(int);],my_name_(0);,pac_cv_prog_f77_name_mangle="lower underscore") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then AC_TRY_LINK([void __stdcall MY_NAME(int);],MY_NAME(0);,pac_cv_prog_f77_name_mangle="upper stdcall") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then AC_TRY_LINK([extern void MY_NAME(int);],MY_NAME(0);,pac_cv_prog_f77_name_mangle="upper") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then AC_TRY_LINK([extern void my_name__(int);],my_name__(0);, pac_cv_prog_f77_name_mangle="lower doubleunderscore") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then AC_TRY_LINK([extern void MY_name(int);],MY_name(0);,pac_cv_prog_f77_name_mangle="mixed") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then AC_TRY_LINK([extern void MY_name_(int);],MY_name_(0);,pac_cv_prog_f77_name_mangle="mixed underscore") fi LIBS="$save_LIBS" AC_LANG_RESTORE # If we got to this point, it may be that the programs have to be # linked with the Fortran, not the C, compiler. Try reversing # the language used for the test dnl Note that the definition of AC_TRY_LINK and AC_LANG_PROGRAM dnl is broken in autoconf and will generate spurious warning messages dnl To fix this, we use dnl AC _LINK_IFELSE([AC _LANG_PROGRAM(,[[body]])],action-if-true) dnl instead of AC _TRY_LINK(,body,action-if-true) if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then AC_LANG_SAVE AC_LANG_FORTRAN77 save_LIBS="$LIBS" LIBS="conftestc.o $LIBS" if test "X$ac_ccompile" = "X" ; then ac_ccompile='${CC-cc} -c $CFLAGS conftest.c 1>&AC_FD_CC' fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat > conftest.c <&AC_FD_CC cat conftest.c >&AC_FD_CC fi AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[ call my_name(0)]])], pac_cv_prog_f77_name_mangle="lower") if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat > conftest.c <&AC_FD_CC cat conftest.c >&AC_FD_CC fi AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[ call my_name(0)]])], pac_cv_prog_f77_name_mangle="lower underscore") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >conftest.c <&AC_FD_CC cat conftest.c >&AC_FD_CC fi AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[ call my_name(0)]])], pac_cv_prog_f77_name_mangle="upper stdcall") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >conftest.c <&AC_FD_CC cat conftest.c >&AC_FD_CC fi AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[ call MY_NAME(0)]])], pac_cv_prog_f77_name_mangle="upper") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >conftest.c <&AC_FD_CC cat conftest.c >&AC_FD_CC fi AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[ call my_name(0)]])], pac_cv_prog_f77_name_mangle="lower doubleunderscore") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >conftest.c <&AC_FD_CC cat conftest.c >&AC_FD_CC fi AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[ call MY_name(0)]])], pac_cv_prog_f77_name_mangle="mixed") fi if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >conftest.c <&AC_FD_CC cat conftest.c >&AC_FD_CC fi AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[ call MY_name(0)]])], pac_cv_prog_f77_name_mangle="mixed underscore") fi LIBS="$save_LIBS" AC_LANG_RESTORE fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f fconftest* ]) # Make the actual definition pac_namecheck=`echo X$pac_cv_prog_f77_name_mangle | sed 's/ /-/g'` ifelse([$1],,[ pac_cv_test_stdcall="" case $pac_namecheck in X) AC_MSG_WARN([Cannot determine Fortran naming scheme]) ;; Xlower) AC_DEFINE(F77_NAME_LOWER,1,[Define if Fortran names are lowercase]) F77_NAME_MANGLE="F77_NAME_LOWER" ;; Xlower-underscore) AC_DEFINE(F77_NAME_LOWER_USCORE,1,[Define if Fortran names are lowercase with a trailing underscore]) F77_NAME_MANGLE="F77_NAME_LOWER_USCORE" ;; Xlower-doubleunderscore) AC_DEFINE(F77_NAME_LOWER_2USCORE,1,[Define if Fortran names containing an underscore have two trailing underscores]) F77_NAME_MANGLE="F77_NAME_LOWER_2USCORE" ;; Xupper) AC_DEFINE(F77_NAME_UPPER,1,[Define if Fortran names are uppercase]) F77_NAME_MANGLE="F77_NAME_UPPER" ;; Xmixed) AC_DEFINE(F77_NAME_MIXED,1,[Define if Fortran names preserve the original case]) F77_NAME_MANGLE="F77_NAME_MIXED" ;; Xmixed-underscore) AC_DEFINE(F77_NAME_MIXED_USCORE,1,[Define if Fortran names preserve the original case and add a trailing underscore]) F77_NAME_MANGLE="F77_NAME_MIXED_USCORE" ;; Xupper-stdcall) AC_DEFINE(F77_NAME_UPPER,1,[Define if Fortran names are uppercase]) F77_NAME_MANGLE="F77_NAME_UPPER_STDCALL" pac_cv_test_stdcall="__stdcall" ;; *) AC_MSG_WARN([Unknown Fortran naming scheme]) ;; esac AC_SUBST(F77_NAME_MANGLE) # Get the standard call definition # FIXME: This should use F77_STDCALL, not STDCALL (non-conforming name) if test "X$pac_cv_test_stdcall" = "X" ; then F77_STDCALL="" else F77_STDCALL="__stdcall" fi # AC_DEFINE_UNQUOTED(STDCALL,$F77_STDCALL,[Define calling convention]) ],[$1]) ]) dnl dnl/*D dnl PAC_PROG_F77_CHECK_SIZEOF - Determine the size in bytes of a Fortran dnl type dnl dnl Synopsis: dnl PAC_PROG_F77_CHECK_SIZEOF(type,[cross-size]) dnl dnl Output Effect: dnl Sets SIZEOF_F77_uctype to the size if bytes of type. dnl If type is unknown, the size is set to 0. dnl If cross-compiling, the value cross-size is used (it may be a variable) dnl For example 'PAC_PROG_F77_CHECK_SIZEOF(real)' defines dnl 'SIZEOF_F77_REAL' to 4 on most systems. The variable dnl 'pac_cv_sizeof_f77_' (e.g., 'pac_cv_sizeof_f77_real') is also set to dnl the size of the type. dnl If the corresponding variable is already set, that value is used. dnl If the name has an '*' in it (e.g., 'integer*4'), the defined name dnl replaces that with an underscore (e.g., 'SIZEOF_F77_INTEGER_4'). dnl dnl Notes: dnl If the 'cross-size' argument is not given, 'autoconf' will issue an error dnl message. You can use '0' to specify undetermined. dnl dnl D*/ AC_DEFUN([PAC_PROG_F77_CHECK_SIZEOF],[ changequote(<<, >>)dnl dnl The name to #define. dnl If the arg value contains a variable, we need to update that define(<>, translit(sizeof_f77_$1, [a-z *], [A-Z__]))dnl dnl The cache variable name. define(<>, translit(pac_cv_f77_sizeof_$1, [ *], [__]))dnl changequote([, ])dnl AC_CACHE_CHECK([for size of Fortran type $1],PAC_CV_NAME,[ AC_REQUIRE([PAC_PROG_F77_NAME_MANGLE]) # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat < conftest.f subroutine isize( ) $1 i(2) call cisize( i(1), i(2) ) end EOF if test "X$ac_fcompile" = "X" ; then ac_fcompile='${F77-f77} -c $FFLAGS conftest.f 1>&AC_FD_CC' fi if AC_TRY_EVAL(ac_fcompile) && test -s conftest.o ; then mv conftest.o conftestf.o AC_LANG_SAVE AC_LANG_C save_LIBS="$LIBS" dnl Add the Fortran linking libraries LIBS="conftestf.o $FLIBS $LIBS" AC_TRY_RUN([#include #ifdef F77_NAME_UPPER #define cisize_ CISIZE #define isize_ ISIZE #elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) #define cisize_ cisize #define isize_ isize #endif static int isize_val=0; void cisize_(char *,char*); void isize_(void); void cisize_(char *i1p, char *i2p) { isize_val = (int)(i2p - i1p); } int main(int argc, char **argv) { FILE *f = fopen("conftestval", "w"); if (!f) return 1; isize_(); fprintf(f,"%d\n", isize_val ); return 0; }], eval PAC_CV_NAME=`cat conftestval`,eval PAC_CV_NAME=0, ifelse([$2],,,eval PAC_CV_NAME=$2)) # Problem. If the process fails to run, then there won't be # a good error message. For example, with one Portland Group # installation, we had problems with finding the libpgc.so shared library # The autoconf code for TRY_RUN doesn't capture the output from # the test program (!) LIBS="$save_LIBS" AC_LANG_RESTORE else echo "configure: failed program was:" >&AC_FD_CC cat conftest.f >&AC_FD_CC ifelse([$2],,eval PAC_CV_NAME=0,eval PAC_CV_NAME=$2) fi ]) AC_DEFINE_UNQUOTED(PAC_TYPE_NAME,$PAC_CV_NAME,[Define size of PAC_TYPE_NAME]) undefine([PAC_TYPE_NAME]) undefine([PAC_CV_NAME]) ]) dnl dnl This version uses a Fortran program to link programs. dnl This is necessary because some compilers provide shared libraries dnl that are not within the default linker paths (e.g., our installation dnl of the Portland Group compilers) dnl AC_DEFUN([PAC_PROG_F77_CHECK_SIZEOF_EXT],[ changequote(<<,>>)dnl dnl The name to #define. dnl If the arg value contains a variable, we need to update that define(<>, translit(sizeof_f77_$1, [a-z *], [A-Z__]))dnl dnl The cache variable name. define(<>, translit(pac_cv_f77_sizeof_$1, [ *], [__]))dnl changequote([,])dnl AC_CACHE_CHECK([for size of Fortran type $1],PAC_CV_NAME,[ AC_REQUIRE([PAC_PROG_F77_NAME_MANGLE]) if test "$cross_compiling" = yes ; then ifelse([$2],,[AC_MSG_WARN([No value provided for size of $1 when cross-compiling])] ,eval PAC_CV_NAME=$2) else # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat < conftestc.c #include #include "confdefs.h" #ifdef F77_NAME_UPPER #define cisize_ CISIZE #define isize_ ISIZE #elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) #define cisize_ cisize #define isize_ isize #endif int cisize_(char *,char*); int cisize_(char *i1p, char *i2p) { int isize_val=0; FILE *f = fopen("conftestval", "w"); if (!f) return 1; isize_val = (int)(i2p - i1p); fprintf(f,"%d\n", isize_val ); fclose(f); return 0; } EOF pac_tmp_compile='$CC -c $CFLAGS $CPPFLAGS conftestc.c >&5' if AC_TRY_EVAL(pac_tmp_compile) && test -s conftestc.o ; then AC_LANG_SAVE AC_LANG_FORTRAN77 saveLIBS=$LIBS LIBS="conftestc.o $LIBS" dnl TRY_RUN does not work correctly for autoconf 2.13 (the dnl macro includes C-preprocessor directives that are not dnl valid in Fortran. Instead, we do this by hand cat >conftest.f <conftest2.f <conftest.f </dev/null 2>&1 ; then AC_MSG_RESULT(yes) AC_MSG_CHECKING([whether routines compiled with $1 can be linked with ones compiled without $1]) rm -f conftest2.out rm -f conftest.bas ac_fscompile3='${F77-f77} -c $save_FFLAGS conftest2.f >conftest2.out 2>&1' ac_fscompilelink4='${F77-f77} $FFLAGS -o conftest conftest2.o conftest.f $LDFLAGS >conftest.bas 2>&1' if AC_TRY_EVAL(ac_fscompile3) && test -s conftest2.o ; then if AC_TRY_EVAL(ac_fscompilelink4) && test -x conftest ; then if diff -b conftest.out conftest.bas >/dev/null 2>&1 ; then ac_result="yes" else echo "configure: Compiler output differed in two cases" >&AC_FD_CC diff -b conftest.out conftest.bas >&AC_FD_CC fi else echo "configure: failed program was:" >&AC_FD_CC cat conftest.f >&AC_FD_CC fi else echo "configure: failed program was:" >&AC_FD_CC cat conftest2.f >&AC_FD_CC fi else # diff echo "configure: Compiler output differed in two cases" >&AC_FD_CC diff -b conftest.out conftest.bas >&AC_FD_CC fi else # try_eval(fscompilelink2) echo "configure: failed program was:" >&AC_FD_CC cat conftest.f >&AC_FD_CC fi if test "$ac_result" != "yes" -a -s conftest.out ; then cat conftest.out >&AC_FD_CC fi else # Could not compile without the option! echo "configure: Could not compile program" >&AC_FD_CC cat conftest.f >&AC_FD_CC cat conftest.bas >&AC_FD_CC fi # Restore FFLAGS before 2nd/3rd argument commands are executed, # as 2nd/3rd argument command could be modifying FFLAGS. FFLAGS="$save_FFLAGS" if test "$ac_result" = "yes" ; then AC_MSG_RESULT(yes) ifelse($2,,FOPTIONS="$FOPTIONS $1",$2) else AC_MSG_RESULT(no) $3 fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* ]) dnl/*D dnl PAC_PROG_F77_CMDARGS - Determine how to access the command line from dnl Fortran 77 dnl dnl Output Effects: dnl The following variables are set: dnl.vb dnl F77_GETARG - Statement to get an argument i into string s dnl F77_IARGC - Routine to return the number of arguments dnl FXX_MODULE - Module command when using Fortran 90 compiler dnl F77_GETARGDECL - Declaration of routine used for F77_GETARG dnl F77_GETARG_FFLAGS - Flags needed when compiling/linking dnl F77_GETARG_LDFLAGS - Flags needed when linking dnl.ve dnl If 'F77_GETARG' has a value, then that value and the values for these dnl other symbols will be used instead. If no approach is found, all of these dnl variables will have empty values. dnl If no other approach works and a file 'f77argdef' is in the directory, dnl that file will be sourced for the values of the above four variables. dnl dnl In most cases, you should add F77_GETARG_FFLAGS to the FFLAGS variable dnl and F77_GETARG_LDFLAGS to the LDFLAGS variable, to ensure that tests are dnl performed on the compiler version that will be used. dnl dnl 'AC_SUBST' is called for all six variables. dnl dnl One complication is that on systems with multiple Fortran compilers, dnl some libraries used by one Fortran compiler may have been (mis)placed dnl in a common location. We have had trouble with libg2c in particular. dnl To work around this, we test whether iargc etc. work first. This dnl will catch most systems and will speed up the tests. dnl dnl Next, the libraries are only added if they are needed to complete a dnl link; they aren''t added just because they exist. dnl dnl f77argdef dnl D*/ dnl dnl Random notes dnl You can export the command line arguments from C to the g77 compiler dnl using dnl extern char **__libc_argv; dnl extern int __libc_argc; dnl f_setarg( __libc_argc, __libc_argv ); dnl AC_DEFUN([PAC_PROG_F77_CMDARGS],[ found_cached="yes" AC_MSG_CHECKING([for routines to access the command line from Fortran 77]) AC_CACHE_VAL(pac_cv_prog_f77_cmdarg, [ AC_MSG_RESULT([searching...]) found_cached="no" # First, we perform a quick check. Does iargc and getarg work? fxx_module="${FXX_MODULE:-}" f77_getargdecl="${F77_GETARGDECL:-external getarg}" f77_getarg="${F77_GETARG:-call GETARG(i,s)}" f77_iargc="${F77_IARGC:-IARGC()}" # # Grumble. The Absoft Fortran compiler computes i - i as 0 and then # 1.0 / 0 at compile time, even though the code may never be executed. # What we need is a way to generate an error, so the second usage of i # was replaced with f77_iargc. cat > conftest.f </dev/null 2>&1 ; then found_answer="yes" FXX_MODULE="$fxx_module" F77_GETARGDECL="$f77_getargdecl" F77_GETARG="$f77_getarg" F77_IARGC="$f77_iargc" AC_MSG_RESULT(yes) fi fi fi if test $found_answer = "no" ; then AC_MSG_RESULT(no) # Grumph. Here are a bunch of different approaches # We have several axes the check: # Library to link with (none, -lU77 (HPUX), -lg2c (LINUX f77)) # PEPCF90 (Intel ifc) # The first line is a dummy # (we experimented with using a , but this caused other # problems because we need in the IFS) trial_LIBS="0 -lU77 -lPEPCF90" if test "$NOG2C" != "1" ; then trial_LIBS="$trial_LIBS -lg2c" fi # Discard libs that are not availble: save_IFS="$IFS" # Make sure that IFS includes a space, or the tests that run programs # may fail IFS=" "" " save_trial_LIBS="$trial_LIBS" trial_LIBS="" cat > conftest.f <, the space is important # To make the Absoft f77 and f90 work together, we need to prefer the # upper case versions of the arguments. They also require libU77. # -YCFRL=1 causes Absoft f90 to work with g77 and similar (f2c-based) # Fortran compilers # # Problem: The Intel efc compiler hangs when presented with -N109 . # The only real fix for this is to detect this compiler and exclude # the test. We may want to reorganize these tests so that if we # can compile code without special options, we never look for them. # using_intel_efc="no" pac_test_msg=`$F77 -V 2>&1 | grep 'Intel(R) Fortran Itanium'` if test "$pac_test_msg" != "" ; then using_intel_efc="yes" fi if test "$using_intel_efc" = "yes" ; then trial_FLAGS="000" else trial_FLAGS="000 -N109 -f -YEXT_NAMES=UCS -YEXT_NAMES=LCS -YCFRL=1 +U77" fi # Discard options that are not available: # (IFS already saved above) IFS=" "" " save_trial_FLAGS="$trial_FLAGS" trial_FLAGS="" for flag in $save_trial_FLAGS ; do if test "$flag" = " " -o "$flag" = "000" ; then opt_ok="yes" else PAC_F77_CHECK_COMPILER_OPTION($flag,opt_ok=yes,opt_ok=no) fi if test "$opt_ok" = "yes" ; then if test "$flag" = " " -o "$flag" = "000" ; then fflag="" else fflag="$flag" fi # discard options that don't allow mixed-case name matching cat > conftest.f < conftest.f </dev/null 2>&1 ; then found_answer="yes" fi else found_answer="yes" fi fi IFS=" "" " if test "$found_answer" = "yes" ; then AC_MSG_RESULT([yes]) pac_cv_prog_f77_cmdarg="$MSG" pac_cv_prog_f77_cmdarg_fflags="$flags" pac_cv_prog_f77_cmdarg_ldflags="$libs" break else AC_MSG_RESULT([no]) echo "configure: failed program was:" >&AC_FD_CC cat conftest.f >&AC_FD_CC fi done done IFS="$save_IFS" rm -f conftest.* trial=`expr $trial + 1` done fi pac_cv_F77_GETARGDECL="$F77_GETARGDECL" pac_cv_F77_IARGC="$F77_IARGC" pac_cv_F77_GETARG="$F77_GETARG" pac_cv_FXX_MODULE="$FXX_MODULE" ]) if test "$found_cached" = "yes" ; then AC_MSG_RESULT([$pac_cv_prog_f77_cmdarg]) elif test -z "$pac_cv_F77_IARGC" ; then AC_MSG_WARN([Could not find a way to access the command line from Fortran 77]) fi # Set the variable values based on pac_cv_prog_xxx F77_GETARGDECL="$pac_cv_F77_GETARGDECL" F77_IARGC="$pac_cv_F77_IARGC" F77_GETARG="$pac_cv_F77_GETARG" FXX_MODULE="$pac_cv_FXX_MODULE" F77_GETARG_FFLAGS="$pac_cv_prog_f77_cmdarg_fflags" F77_GETARG_LDFLAGS="$pac_cv_prog_f77_cmdarg_ldflags" AC_SUBST(F77_GETARGDECL) AC_SUBST(F77_IARGC) AC_SUBST(F77_GETARG) AC_SUBST(FXX_MODULE) AC_SUBST(F77_GETARG_FFLAGS) AC_SUBST(F77_GETARG_LDFLAGS) ]) dnl/*D dnl PAC_PROG_F77_LIBRARY_DIR_FLAG - Determine the flag used to indicate dnl the directories to find libraries in dnl dnl Notes: dnl Many compilers accept '-Ldir' just like most C compilers. dnl Unfortunately, some (such as some HPUX Fortran compilers) do not, dnl and require instead either '-Wl,-L,dir' or something else. This dnl command attempts to determine what is accepted. The flag is dnl placed into 'F77_LIBDIR_LEADER'. dnl dnl D*/ dnl dnl An earlier version of this only tried the arguments without using dnl a library. This failed when the HP compiler complained about the dnl arguments, but produced an executable anyway. AC_DEFUN([PAC_PROG_F77_LIBRARY_DIR_FLAG],[ if test "X$F77_LIBDIR_LEADER" = "X" ; then AC_CACHE_CHECK([for Fortran 77 flag for library directories], pac_cv_prog_f77_library_dir_flag, [ rm -f conftest.* conftest1.* cat > conftest.f < conftest1.f <&AC_FD_CC cat conftest1.f >&AC_FD_CC fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* ]) AC_SUBST(F77_LIBDIR_LEADER) if test "X$pac_cv_prog_f77_library_dir_flag" != "X" ; then F77_LIBDIR_LEADER="$pac_cv_prog_f77_library_dir_flag" fi fi ]) dnl/*D dnl PAC_PROG_F77_HAS_INCDIR - Check whether Fortran accepts -Idir flag dnl dnl Syntax: dnl PAC_PROG_F77_HAS_INCDIR(directory,action-if-true,action-if-false) dnl dnl Output Effect: dnl Sets 'F77_INCDIR' to the flag used to choose the directory. dnl dnl Notes: dnl This refers to the handling of the common Fortran include extension, dnl not to the use of '#include' with the C preprocessor. dnl If directory does not exist, it will be created. In that case, the dnl directory should be a direct descendant of the current directory. dnl dnl D*/ AC_DEFUN([PAC_PROG_F77_HAS_INCDIR],[ checkdir=$1 AC_CACHE_CHECK([for include directory flag for Fortran], pac_cv_prog_f77_has_incdir,[ if test ! -d $checkdir ; then mkdir $checkdir ; fi cat >$checkdir/conftestf.h <conftest.f < conftest.$ac_ext <&AC_FD_CC cat conftest.$ac_ext >&AC_FD_CC # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -rf conftest* pac_cv_prog_f77_allows_unused_externals="no" $4 fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* # AC_LANG_RESTORE ]) if test "X$pac_cv_prog_f77_allows_unused_externals" = "Xyes" ; then ifelse([$1],,:,[$1]) else ifelse([$2],,:,[$2]) fi ]) dnl /*D dnl PAC_PROG_F77_HAS_POINTER - Determine if Fortran allows pointer type dnl dnl Synopsis: dnl PAC_PROG_F77_HAS_POINTER(action-if-true,action-if-false) dnl D*/ AC_DEFUN([PAC_PROG_F77_HAS_POINTER],[ AC_CACHE_CHECK([whether Fortran has pointer declaration], pac_cv_prog_f77_has_pointer,[ AC_LANG_SAVE AC_LANG_FORTRAN77 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ integer M pointer (MPTR,M) data MPTR/0/ ])], pac_cv_prog_f77_has_pointer="yes", pac_cv_prog_f77_has_pointer="no") AC_LANG_RESTORE ]) if test "$pac_cv_prog_f77_has_pointer" = "yes" ; then ifelse([$1],,:,[$1]) else ifelse([$2],,:,[$2]) fi ]) dnl pac_prog_f77_run_proc_from_c( c main program, fortran routine, dnl action-if-works, action-if-fails, dnl cross-action ) dnl Fortran routine MUST be named ftest unless you include code dnl to select the appropriate Fortran name. dnl AC_DEFUN([PAC_PROG_F77_RUN_PROC_FROM_C],[ # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat < conftest.f $2 EOF dnl if test "X$ac_fcompile" = "X" ; then ac_fcompile='${F77-f77} -c $FFLAGS conftest.f 1>&AC_FD_CC' fi if AC_TRY_EVAL(ac_fcompile) && test -s conftest.o ; then mv conftest.o conftestf.o AC_LANG_SAVE AC_LANG_C save_LIBS="$LIBS" LIBS="conftestf.o $FLIBS $LIBS" AC_TRY_RUN([#include #ifdef F77_NAME_UPPER #define ftest_ FTEST #elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) #define ftest_ ftest #endif $1 ], [$3], [$4], [$5] ) LIBS="$save_LIBS" AC_LANG_RESTORE else echo "configure: failed program was:" >&AC_FD_CC cat conftest.f >&AC_FD_CC fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* ]) dnl PAC_PROG_F77_IN_C_LIBS dnl dnl Find the essential libraries that are needed to use the C linker to dnl create a program that includes a trival Fortran code. dnl dnl For example, all pgf90 compiled objects include a reference to the dnl symbol pgf90_compiled, found in libpgf90 . dnl dnl There is an additional problem. To *run* programs, we may need dnl additional arguments; e.g., if shared libraries are used. Even dnl with autoconf 2.52, the autoconf macro to find the library arguments dnl doesn't handle this, either by detecting the use of -rpath or dnl by trying to *run* a trivial program. It only checks for *linking*. dnl dnl AC_DEFUN([PAC_PROG_F77_IN_C_LIBS],[ AC_MSG_CHECKING([for which Fortran libraries are needed to link C with Fortran]) F77_IN_C_LIBS="$FLIBS" # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat < conftest.f subroutine ftest end EOF dnl if test "X$ac_fcompile" = "X" ; then ac_fcompile='${F77-f77} -c $FFLAGS conftest.f 1>&AC_FD_CC' fi if AC_TRY_EVAL(ac_fcompile) && test -s conftest.o ; then mv conftest.o mconftestf.o AC_LANG_SAVE AC_LANG_C save_LIBS="$LIBS" dnl First try with no libraries LIBS="mconftestf.o $save_LIBS" AC_TRY_LINK([#include ],[ #ifdef F77_NAME_UPPER #define ftest_ FTEST #elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) #define ftest_ ftest #endif extern void ftest_(void); ftest_(); ], [link_worked=yes], [link_worked=no] ) if test "$link_worked" = "no" ; then flibdirs=`echo $FLIBS | tr ' ' '\012' | grep '\-L' | tr '\012' ' '` fliblibs=`echo $FLIBS | tr ' ' '\012' | grep -v '\-L' | tr '\012' ' '` for flibs in $fliblibs ; do LIBS="mconftestf.o $flibdirs $flibs $save_LIBS" AC_TRY_LINK([#include ],[ #ifdef F77_NAME_UPPER #define ftest_ FTEST #elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) #define ftest_ ftest #endif extern void ftest_(void); ftest_(); ], [link_worked=yes], [link_worked=no] ) if test "$link_worked" = "yes" ; then F77_IN_C_LIBS="$flibdirs $flibs" break fi done if test "$link_worked" = "no" ; then # try to add libraries until it works... flibscat="" for flibs in $fliblibs ; do flibscat="$flibscat $flibs" LIBS="mconftestf.o $flibdirs $flibscat $save_LIBS" AC_TRY_LINK([#include ],[ #ifdef F77_NAME_UPPER #define ftest_ FTEST #elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) #define ftest_ ftest #endif extern void ftest_(void); ftest_(); ], [link_worked=yes], [link_worked=no] ) if test "$link_worked" = "yes" ; then F77_IN_C_LIBS="$flibdirs $flibscat" break fi done fi else # No libraries needed F77_IN_C_LIBS="" fi LIBS="$save_LIBS" AC_LANG_RESTORE else echo "configure: failed program was:" >&AC_FD_CC cat conftest.f >&AC_FD_CC fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* mconftest* if test -z "$F77_IN_C_LIBS" ; then AC_MSG_RESULT(none) else AC_MSG_RESULT($F77_IN_C_LIBS) fi ]) dnl Test to see if we should use C or Fortran to link programs whose dnl main program is in Fortran. We may find that neither work because dnl we need special libraries in each case. dnl AC_DEFUN([PAC_PROG_F77_LINKER_WITH_C],[ AC_LANG_SAVE AC_LANG_C AC_TRY_COMPILE(, long long a;,AC_DEFINE(HAVE_LONG_LONG,1,[Define if long long allowed])) AC_MSG_CHECKING([for linker for Fortran main programs]) dnl dnl Create a program that uses multiplication and division in case dnl that requires special libraries cat > conftest.c < conftest.f <&AC_FD_CC ; then AC_MSG_RESULT([Use Fortran to link programs]) elif ${CC} ${CFLAGS} -o conftest conftest.o conftest1.o $LDFLAGS $FLIBS 2>&AC_FD_CC ; then AC_MSG_RESULT([Use C with FLIBS to link programs]) F77LINKER="$CC" F77_LDFLAGS="$F77_LDFLAGS $FLIBS" else AC_MSG_RESULT([Unable to determine how to link Fortran programs with C]) fi else AC_MSG_ERROR([Could not compile Fortran test program]) fi AC_LANG_RESTORE ]) dnl Check to see if a C program can be linked when using the libraries dnl needed by C programs dnl AC_DEFUN([PAC_PROG_F77_CHECK_FLIBS], [AC_MSG_CHECKING([whether C can link with $FLIBS]) # Try to link a C program with all of these libraries save_LIBS="$LIBS" LIBS="$LIBS $FLIBS" AC_TRY_LINK(,[int a;],runs=yes,runs=no) LIBS="$save_LIBS" AC_MSG_RESULT($runs) if test "$runs" = "no" ; then AC_MSG_CHECKING([for which libraries can be used]) pac_ldirs="" pac_libs="" pac_other="" for name in $FLIBS ; do case $name in -l*) pac_libs="$pac_libs $name" ;; -L*) pac_ldirs="$pac_ldirs $name" ;; *) pac_other="$pac_other $name" ;; esac done save_LIBS="$LIBS" keep_libs="" for name in $pac_libs ; do LIBS="$save_LIBS $pac_ldirs $pac_other $name" AC_TRY_LINK(,[int a;],runs=yes,runs=no) if test $runs = "yes" ; then keep_libs="$keep_libs $name" ; fi done AC_MSG_RESULT($keep_libs) LIBS="$save_LIBS" FLIBS="$pac_ldirs $pac_other $keep_libs" fi ]) dnl Test for extra libraries needed when linking C routines that use dnl stdio with Fortran. This test was created for OSX, which dnl sometimes requires -lSystemStubs. If another library is needed, dnl add it to F77_OTHER_LIBS AC_DEFUN([PAC_PROG_F77_AND_C_STDIO_LIBS],[ # To simply the code in the cache_check macro, chose the routine name # first, in case we need it confname=conf1_ case "$pac_cv_prog_f77_name_mangle" in "lower underscore") confname=conf1_ ;; "upper stdcall") confname=CONF1 ;; upper) confname=CONF1 ;; "lower doubleunderscore") confname=conf1_ ;; lower) confname=conf1 ;; "mixed underscore") confname=conf1_ ;; mixed) confname=conf1 ;; esac AC_CACHE_CHECK([what libraries are needed to link Fortran programs with C routines that use stdio],pac_cv_prog_f77_and_c_stdio_libs,[ pac_cv_prog_f77_and_c_stdio_libs=unknown # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat >conftest.f <conftestc.c < int $confname( int a ) { printf( "The answer is %d\n", a ); fflush(stdout); return 0; } EOF tmpcmd='${CC-cc} -c $CFLAGS conftestc.c 1>&AC_FD_CC' if AC_TRY_EVAL(tmpcmd) && test -s conftestc.o ; then : else echo "configure: failed program was:" >&AC_FD_CC cat conftestc.c >&AC_FD_CC fi tmpcmd='${F77-f77} $FFLAGS -o conftest conftest.f conftestc.o 1>&AC_FD_CC' if AC_TRY_EVAL(tmpcmd) && test -x conftest ; then pac_cv_prog_f77_and_c_stdio_libs=none else # Try again with -lSystemStubs tmpcmd='${F77-f77} $FFLAGS -o conftest conftest.f conftestc.o -lSystemStubs 1>&AC_FD_CC' if AC_TRY_EVAL(tmpcmd) && test -x conftest ; then pac_cv_prog_f77_and_c_stdio_libs="-lSystemStubs" else echo "configure: failed program was:" >&AC_FD_CC cat conftestc.c >&AC_FD_CC echo "configure: with Fortran 77 program:" >&AC_FD_CC cat conftest.f >&AC_FD_CC fi fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* ]) if test "$pac_cv_prog_f77_and_c_stdio_libs" != none -a \ "$pac_cv_prog_f77_and_c_stdio_libs" != unknown ; then F77_OTHER_LIBS="$F77_OTHER_LIBS $pac_cv_prog_f77_and_c_stdio_libs" fi ]) dnl Check that the FLIBS determined by AC_F77_LIBRARY_LDFLAGS is valid. dnl That macro (at least as of autoconf 2.59) attempted to parse the output dnl of the compiler when asked to be verbose; in the case of the Fujitsu dnl frt Fortran compiler, it included files that frt looked for and then dnl discarded because they did not exist. AC_DEFUN([PAC_PROG_F77_FLIBS_VALID],[ pac_cv_f77_flibs_valid=unknown AC_MSG_CHECKING([whether $F77 accepts the FLIBS found by autoconf]) AC_LANG_SAVE AC_LANG_FORTRAN77 dnl We can't use TRY_LINK, because it wants a routine name, not a dnl declaration. The following is the body of TRY_LINK, slightly modified. cat > conftest.$ac_ext <&AC_FD_CC cat conftest.$ac_ext >&AC_FD_CC pac_cv_f77_flibs_valid=no fi AC_MSG_RESULT($pac_cv_f77_flibs_valid) if test $pac_cv_f77_flibs_valid = no ; then # See which ones *are* valid AC_MSG_CHECKING([for valid entries in FLIBS]) goodFLIBS="" saveFLIBS=$FLIBS FLIBS="" for arg in $saveFLIBS ; do FLIBS="$goodFLIBS $arg" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then goodFLIBS=$FLIBS else echo "configure: failed program was:" >&AC_FD_CC cat conftest.$ac_ext >&AC_FD_CC fi done FLIBS=$goodFLIBS AC_MSG_RESULT($FLIBS) fi # # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* AC_LANG_RESTORE ]) AC_DEFUN([PAC_PROG_F77_OBJ_LINKS_WITH_C],[ AC_MSG_CHECKING([whether Fortran 77 and C objects are compatible]) dnl rm -rf conftestc.dSYM rm -f conftestc* dnl construct with a C function with all possible F77 name mangling schemes. cat <<_EOF > conftestc.c /* lower */ void c_subpgm( int *rc ); void c_subpgm( int *rc ) { *rc = 1; } /* lower underscore */ void c_subpgm_( int *rc ); void c_subpgm_( int *rc ) { *rc = 2; } /* upper */ void C_SUBPGM( int *rc ); void C_SUBPGM( int *rc ) { *rc = 3; } /* lower doubleunderscore */ void c_subpgm__( int *rc ); void c_subpgm__( int *rc ) { *rc = 4; } /* mixed */ void C_subpgm( int *rc ); void C_subpgm( int *rc ) { *rc = 5; } /* mixed underscore */ void C_subpgm_( int *rc ); void C_subpgm_( int *rc ) { *rc = 6; } _EOF dnl dnl Compile the C function into object file. dnl pac_Ccompile='${CC-cc} -c $CFLAGS conftestc.c 1>&AC_FD_CC' if AC_TRY_EVAL(pac_Ccompile) && test -s conftestc.${ac_objext} ; then pac_c_working=yes else pac_c_working=no echo "configure: failed C program was:" >&AC_FD_CC cat conftestc.c >&AC_FD_CC fi dnl rm -rf conftestf.dSYM rm -f conftestf* cat <<_EOF > conftestf.f program test integer rc rc = -1 call c_subpgm( rc ) write(6,*) "rc=", rc end _EOF dnl - compile the fortran program into object file pac_Fcompile='${F77-f77} -c $FFLAGS conftestf.f 1>&AC_FD_CC' if AC_TRY_EVAL(pac_Fcompile) && test -s conftestf.${ac_objext} ; then pac_f77_working=yes else pac_f77_working=no echo "configure: failed F77 program was:" >&AC_FD_CC cat conftestf.f >&AC_FD_CC fi dnl if test "$pac_c_working" = "yes" -a "$pac_f77_working" = "yes" ; then dnl Try linking with F77 compiler rm -f conftest${ac_exeext} pac_link='$F77 $FFLAGS -o conftest${ac_exeext} conftestf.${ac_objext} conftestc.${ac_objext} $LDFLAGS >&AC_FD_CC' if AC_TRY_EVAL(pac_link) && test -s conftest${ac_exeext} ; then AC_MSG_RESULT(yes) rm -fr conftestf.dSYM conftestc.dSYM conftest.dSYM rm -f conftest* else dnl Try linking with C compiler rm -f conftest${ac_exeext} pac_link='$CC $CFLAGS -o conftest${ac_exeext} conftestf.${ac_objext} conftestc.${ac_objext} $LDFLAGS $FLIBS >&AC_FD_CC' if AC_TRY_EVAL(pac_link) && test -s conftest${ac_exeext} ; then AC_MSG_RESULT(yes) rm -fr conftestf.dSYM conftestc.dSYM conftest.dSYM rm -f conftest* else AC_MSG_RESULT(no) AC_CHECK_PROG(FILE, file, file, []) if test "X$FILE" != "X" ; then fobjtype="`${FILE} conftestf.${ac_objext} | sed -e \"s|conftestf\.${ac_objext}||g\"`" cobjtype="`${FILE} conftestc.${ac_objext} | sed -e \"s|conftestc\.${ac_objext}||g\"`" if test "$fobjtype" != "$cobjtype" ; then AC_MSG_ERROR([**** Incompatible Fortran and C Object File Types! **** F77 Object File Type produced by \"${F77} ${FFLAGS}\" is : ${fobjtype}. C Object File Type produced by \"${CC} ${CFLAGS}\" is : ${cobjtype}.]) fi fi fi fi else AC_MSG_RESULT([failed compilation]) fi ]) armci-mpi/m4/aclocal.m40000644000175000017500000000252212662706250014373 0ustar mbanckmbanckdnl This version of aclocal.m4 simply includes all of the individual dnl components builtin(include,aclocal_am.m4) builtin(include,aclocal_bugfix.m4) builtin(include,aclocal_cache.m4) builtin(include,aclocal_cc.m4) builtin(include,aclocal_atomic.m4) dnl aclocal_cross.m4 uses autoconf features dated back to 2.13. dnl too old to be useful, 07/14/2010. dnl builtin(include,aclocal_cross.m4) builtin(include,aclocal_cxx.m4) builtin(include,aclocal_f77.m4) builtin(include,aclocal_f77new.m4) builtin(include,aclocal_util.m4) builtin(include,aclocal_subcfg.m4) builtin(include,aclocal_make.m4) builtin(include,aclocal_mpi.m4) builtin(include,aclocal_shl.m4) dnl fortran90.m4 defines [Fortran 90] as an AC_LANG dnl which works for autoconf 2.63 and older, 07/14/2010. dnl builtin(include,fortran90.m4) builtin(include,aclocal_runlog.m4) builtin(include,aclocal_fc.m4) builtin(include,aclocal_libs.m4) builtin(include,aclocal_attr_alias.m4) builtin(include,ax_tls.m4) builtin(include,aclocal_romio.m4) dnl Add the libtool files that libtoolize wants dnl Comment these out until libtool support is enabled. dnl May need to change this anyway, since libtoolize dnl does not seem to understand builtin dnl builtin(include,libtool.m4) dnl builtin(include,ltoptions.m4) dnl builtin(include,ltversion.m4) dnl builtin(include,ltsugar.m4) dnl builtin(include,lt~obsolete.m4) armci-mpi/m4/aclocal_shl.m40000644000175000017500000003522612662706250015250 0ustar mbanckmbanckdnl dnl Definitions for creating shared libraries dnl dnl The purpose of these definitions is to provide common support for dnl shared libraries, with *or without* the use of the GNU Libtool package. dnl For many of our important platforms, the Libtool approach is overkill, dnl and can be particularly painful for developers. dnl dnl To use libtool, you need macros that are defined by libtool for libtool dnl Don't even think about the consequences of this for updating and for dnl using user-versions of libtool :( dnl dnl !!!!!!!!!!!!!!!!!!!!! dnl libtool requires ac 2.50 !!!!!!!!!!!!!!!!! dnl dnl builtin(include,libtool.m4) dnl dnl/*D dnl PAC_ARG_SHAREDLIBS - Add --enable-sharedlibs=kind to configure. dnl dnl Synopsis: dnl PAC_ARG_SHAREDLIBS dnl dnl Output effects: dnl Adds '--enable-sharedlibs=kind' to the command line. If this is enabled, dnl then based on the value of 'kind', programs are selected for the dnl names 'CC_SHL' and 'CC_LINK_SHL' that configure will substitute for in dnl 'Makefile.in's. These symbols are generated by 'simplemake' when dnl shared library support is selected. dnl The variable 'C_LINKPATH_SHL' is set to the option to specify the dnl path to search at runtime for libraries (-rpath in gcc/GNU ld). dnl This can be turned off with --disable-rpath , which is appropriate dnl for libraries and for executables that may be installed in different dnl locations. dnl The variable 'SHLIB_EXT' is set to the extension used by shared dnl libraries; under most forms of Unix, this is 'so'; under Mac OS/X, this dnl is 'dylib', and under Windows (including cygwin), this is 'dll'. dnl dnl Supported values of 'kind' include \: dnl+ gcc - Use gcc to create both shared objects and libraries dnl. osx-gcc - Use gcc on Mac OS/X to create both shared objects and dnl libraries dnl. solaris-cc - Use native Solaris cc to create shared objects and dnl libraries dnl. cygwin-gcc - Use gcc on Cygwin to create shared objects and libraries dnl- none - The same as '--disable-sharedlibs' dnl dnl Others will be added as experience dictates. Likely names are dnl + libtool - For general GNU libtool dnl - linux-pgcc - For Portland group under Linux dnl dnl Notes: dnl Shared libraries are only partially implemented. Additional symbols dnl will probably be defined, including symbols to specify how shared library dnl search paths are specified and how shared library names are set. dnl D*/ AC_DEFUN([PAC_ARG_SHAREDLIBS],[ AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared], [Enable shared library builds]),, enable_shared=no) AC_ARG_ENABLE(rpath, AC_HELP_STRING([--enable-rpath], [Determine whether the rpath is set when programs are compiled and linked when shared libraries are built. The default is yes; use --disable-rpath to turn this feature off; in that case, shared libraries will be found according to the rules for your system (e.g., in LD_LIBRARY_PATH)]),,enable_rpath=yes) AC_ARG_ENABLE(sharedlibs, [ --enable-sharedlibs=kind - Enable shared libraries. kind may be gcc - Standard gcc and GNU ld options for creating shared libraries osx-gcc - Special options for gcc needed only on OS/X solaris-cc - Solaris native (SPARC) compilers for 32 bit systems cygwin-gcc - Special options for gcc needed only for cygwin none - same as --disable-sharedlibs Only gcc, osx-gcc, and solaris-cc are currently supported ],,enable_sharedlibs=default) if test "$enable_sharedlibs" = "default" ; then if test "$enable_shared" = "yes" ; then AS_CASE([$host], [*-*-darwin*], [enable_sharedlibs=gcc-osx], [*-*-cygwin*|*-*-mingw*|*-*-pw32*|*-*-cegcc*], [enable_sharedlibs=cygwin-gcc], [*-*-sunos*], [enable_sharedlibs=solaris-gcc], [enable_sharedlibs=gcc]) else enable_sharedlibs=none fi fi # If --enable-sharedlibs is given, but --enable-shared is not, throw # an error if test "$enable_sharedlibs" != "no" -a "$enable_sharedlibs" != "none" ; then if test "$enable_shared" = "no" ; then AC_MSG_ERROR([--enable-sharedlibs cannot be used without --enable-shared]) fi fi CC_SHL=true C_LINK_SHL=true C_LINKPATH_SHL="" SHLIB_EXT=unknown SHLIB_FROM_LO=no SHLIB_INSTALL='$(INSTALL_PROGRAM)' case "$enable_sharedlibs" in no|none) ;; gcc-osx|osx-gcc) AC_MSG_RESULT([Creating shared libraries using GNU for Mac OSX]) C_LINK_SHL='${CC} -dynamiclib -undefined suppress -single_module -flat_namespace' CC_SHL='${CC} -fPIC' # No way in osx to specify the location of the shared libraries at link # time (see the code in createshlib in mpich2/src/util) # As of 10.5, -Wl,-rpath,dirname should work . The dirname # must be a single directory, not a colon-separated list (use multiple # -Wl,-rpath,path for each of the paths in the list). However, os x # apparently records the library full path, so rpath isn't as useful # as it is on other systems C_LINKPATH_SHL="" SHLIB_EXT="dylib" enable_sharedlibs="osx-gcc" ;; gcc) AC_MSG_RESULT([Creating shared libraries using GNU]) # Not quite right yet. See mpich/util/makesharedlib # Use syntax that works in both Make and the shell #C_LINK_SHL='${CC} -shared -Wl,-r' C_LINK_SHL='${CC} -shared' # For example, include the libname as ${LIBNAME_SHL} #C_LINK_SHL='${CC} -shared -Wl,-h,' # May need -fPIC . Test to see which one works. for sh_arg in "-fPIC" "-fpic" "-KPIC" ; do PAC_C_CHECK_COMPILER_OPTION($sh_arg,works=yes,works=no) if test "$works" = "yes" ; then CC_SHL="${CC} ${sh_arg}" break fi done if test "$works" != "yes"; then AC_MSG_ERROR([Cannot build shared libraries with this compiler]) fi # This used to have -Wl,-rpath earlier, but that causes problems # on many systems. if test $enable_rpath = "yes" ; then C_LINKPATH_SHL="-Wl,-rpath," fi SHLIB_EXT=so # We need to test that this isn't osx. The following is a # simple hack osname=`uname -s` case $osname in *Darwin*|*darwin*) AC_MSG_ERROR([You must specify --enable-sharedlibs=osx-gcc for Mac OS/X]) ;; *CYGWIN*|*cygwin*) AC_MSG_ERROR([You must specify --enable-sharedlibs=cygwin-gcc for Cygwin]) ;; *SunOS*) AC_MSG_ERROR([You must specify --enable-sharedlibs=solaris-gcc for Solaris with gcc]) ;; esac ;; cygwin|cygwin-gcc|gcc-cygwin) AC_MSG_RESULT([Creating shared libraries using GNU under CYGWIN]) C_LINK_SHL='${CC} -shared' CC_SHL='${CC}' # DLL Libraries need to be in the user's path (!) C_LINKPATH_SHL="" SHLIB_EXT="dll" enable_sharedlibs="cygwin-gcc" ;; libtool) # set TRY_LIBTOOL to yes to experiment with libtool. You are on your # own - only send fixes, not bug reports. if test "$TRY_LIBTOOL" != yes ; then AC_MSG_ERROR([Creating shared libraries using libtool not yet supported]) else # Using libtool requires a heavy-weight process to test for # various stuff that libtool needs. Without this, you'll get a # bizarre error message about libtool being unable to find # configure.in or configure.ac (!) # Libtool expects to see at least enable-shared. if test "X$enable_shared" = "X" ; then enable_shared=yes ; fi # Initialize libtool # This works, but libtool version 2 places the object files # in a different place, making it harder to integrate with # our base approach. Disabling for now dnl LT_PREREQ([2.2.6]) dnl LT_INIT([disable-shared]) AC_MSG_ERROR([To use this test verison, edit aclocal_shl.m4]) # Likely to be # either CC or CC_SHL is libtool $cc CC_SHL='${LIBTOOL} --mode=compile ${CC}' # CC_LINK_SHL includes the final installation path # For many systems, the link may need to include *all* libraries # (since many systems don't allow any unsatisfied dependencies) # We need to give libtool the .lo file, not the .o files SHLIB_FROM_LO=yes # We also need to add -no-undefined when the compiler is gcc and # we are building under cygwin sysname=`uname -s | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` isCygwin=no case "$sysname" in *CYGWIN*) isCygwin=yes ;; esac if test "$isCygwin" = yes ; then C_LINK_SHL='${LIBTOOL} --mode=link ${CC} -no-undefined -rpath ${libdir}' else C_LINK_SHL='${LIBTOOL} --mode=link ${CC} -rpath ${libdir}' fi if test $enable_rpath = "yes" ; then C_LINKPATH_SHL="-rpath " fi # We also need a special install process with libtool. Note that this # will also install the static libraries SHLIB_INSTALL='$(LIBTOOL) --mode=install $(INSTALL_PROGRAM)' # Note we may still need to add #'$(LIBTOOL) --mode=finish $(libdir)' fi ;; dnl dnl Other, such as solaris-cc solaris|solaris-cc) AC_MSG_RESULT([Creating shared libraries using Solaris]) # pic32 is appropriate for both 32 and 64 bit Solaris C_LINK_SHL='${CC} -G -xcode=pic32' CC_SHL='${CC} -xcode=pic32' if test $enable_rpath = "yes" ; then C_LINKPATH_SHL="-R" fi SHLIB_EXT=so enable_sharedlibs="solaris-cc" ;; solaris-gcc) # This is the same as gcc, except for the C_LINKPATH_SHL AC_MSG_RESULT([Creating shared libraries using Solaris with gcc]) C_LINK_SHL='${CC} -shared' CC_SHL='${CC} -fPIC' if test $enable_rpath = "yes" ; then C_LINKPATH_SHL="-R" fi SHLIB_EXT=so enable_sharedlibs="solaris-gcc" ;; linuxppc-xlc) # This is only the beginning of xlc support, thanks to andy@vpac.org CC_SHL='${CC} -qmkshrobj' # More recent versions allow multiple args, separated by commas if test $enable_rpath = "yes" ; then C_LINKPATH_SHL="-Wl,-rpath," fi #C_LINKPATH_SHL="-Wl,-rpath -Wl," C_LINK_SHL='${CC} -shared -qmkshrobj' SHLIB_EXT=so # Note that the full line should be more like # $CLINKER -shared -qmkshrobj -Wl,-h,$libbase.$slsuffix -o ../shared/$libbase.$slsuffix *.o $OtherLibs # for the appropriate values of $libbase and $slsuffix # The -h name sets the name of the object; this is necessary to # ensure that the dynamic linker can find the proper shared library. ;; *) AC_MSG_ERROR([Unknown value $enable_sharedlibs for enable-sharedlibs. Values should be gcc or osx-gcc]) enable_sharedlibs=no ;; esac # Check for the shared-library extension PAC_CC_SHLIB_EXT dnl AC_SUBST(CC_SHL) AC_SUBST(C_LINK_SHL) AC_SUBST(C_LINKPATH_SHL) AC_SUBST(SHLIB_EXT) AC_SUBST(SHLIB_FROM_LO) AC_SUBST(SHLIB_INSTALL) ]) dnl /*D dnl PAC_xx_SHAREDLIBS - Get compiler and linker for shared libraries dnl These routines may be used to determine the compiler and the dnl linker to be used in creating shared libraries dnl Rather than set predefined variable names, they set an argument dnl (if provided) dnl dnl Synopsis dnl PAC_CC_SHAREDLIBS(type,CCvar,CLINKvar) dnl D*/ AC_DEFUN([PAC_CC_SHAREDLIBS], [ pac_kinds=$1 ifelse($1,,[ pac_prog="" AC_CHECK_PROG(pac_prog,gcc,yes,no) # If we are gcc but OS X, set the special type # We need a similar setting for cygwin if test "$pac_prog" = yes ; then osname=`uname -s` case $osname in *Darwin*|*darwin*) pac_kinds=gcc-osx ;; *) pac_kinds=gcc ;; esac fi pac_prog="" AC_CHECK_PROG(pac_prog,libtool,yes,no) if test "$pac_prog" = yes ; then pac_kinds="$pac_kinds libtool" ; fi ]) for pac_arg in $pac_kinds ; do case $pac_arg in gcc) # For example, include the libname as ${LIBNAME_SHL} #C_LINK_SHL='${CC} -shared -Wl,-h,' pac_cc_sharedlibs='gcc -shared' # Make sure we select the correct fpic option PAC_C_CHECK_COMPILER_OPTION(-fPIC,fPIC_OK=yes,fPIC_OK=no) if test "$fPIC_OK" != yes ; then PAC_C_CHECK_COMPILER_OPTION(-fpic,fpic_ok=yes,fpic_ok=no) if test "$fpic_ok" != yes ; then AC_MSG_ERROR([Neither -fpic nor -fPIC accepted by $CC]) else pac_cc_sharedlibs="$pac_cc_sharedlibs -fpic" fi else pac_cc_sharedlibs="$pac_cc_sharedlibs -fPIC" fi pac_clink_sharedlibs='gcc -shared' pac_type_sharedlibs=gcc ;; gcc-osx|osx-gcc) pac_clink_sharedlibs='${CC} -dynamiclib -undefined suppress -single_module -flat_namespace' pac_cc_sharedlibs='${CC} -fPIC' pac_type_sharedlibs=gcc-osx ;; libtool) AC_CHECK_PROGS(LIBTOOL,libtool,false) if test "$LIBTOOL" = "false" ; then AC_MSG_WARN([Could not find libtool]) else # Likely to be # either CC or CC_SHL is libtool $cc pac_cc_sharedlibs'${LIBTOOL} -mode=compile ${CC}' pac_clink_sharedlibs='${LIBTOOL} -mode=link ${CC} -rpath ${libdir}' pac_type_sharedlibs=libtool fi ;; *) ;; esac if test -n "$pac_cc_sharedlibs" ; then break ; fi done if test -z "$pac_cc_sharedlibs" ; then pac_cc_sharedlibs=true ; fi if test -z "$pac_clink_sharedlibs" ; then pac_clink_sharedlibs=true ; fi ifelse($2,,CC_SHL=$pac_cc_sharedlibs,$2=$pac_cc_sharedlibs) ifelse($3,,C_LINK_SHL=$pac_clink_sharedlibs,$3=$pac_clink_sharedlibs) ifelse($4,,SHAREDLIB_TYPE=$pac_type_sharedlibs,$4=$pac_type_sharedlibs) ]) dnl This macro ensures that all of the necessary substitutions are dnl made by any subdirectory configure (which may simply SUBST the dnl necessary values rather than trying to determine them from scratch) dnl This is a more robust (and, in the case of libtool, only dnl managable) method. AC_DEFUN([PAC_CC_SUBDIR_SHLIBS],[ AC_SUBST(CC_SHL) AC_SUBST(C_LINK_SHL) AC_SUBST(LIBTOOL) AC_SUBST(ENABLE_SHLIB) AC_SUBST(SHLIB_EXT) if test "$ENABLE_SHLIB" = "libtool" ; then if test -z "$LIBTOOL" ; then AC_MSG_WARN([libtool selected for shared library support but LIBTOOL is not defined]) fi # Libtool needs master_top_builddir if test "X$master_top_builddir" = "X" ; then AC_MSG_ERROR([Libtool requires master_top_builddir - check configure.in sources]) fi AC_SUBST(master_top_builddir) fi ]) dnl PAC_CC_SHLIB_EXT - get the extension for shared libraries dnl Set the variable SHLIB_EXT if it is other than unknown. AC_DEFUN([PAC_CC_SHLIB_EXT],[ # Not all systems use .so as the extension for shared libraries (cygwin # and OSX are two important examples). If we did not set the SHLIB_EXT, # then try and determine it. We need this to properly implement # clean steps that look for libfoo.$SHLIB_EXT . if test "$SHLIB_EXT" = "unknown" ; then osname=`uname -s` case $osname in *Darwin*|*darwin*) SHLIB_EXT=dylib ;; *CYGWIN*|*cygwin*) SHLIB_EXT=dll ;; *Linux*|*LINUX*|*SunOS*) SHLIB_EXT=so ;; esac fi ]) armci-mpi/m4/aclocal_bugfix.m40000644000175000017500000000515312662706250015742 0ustar mbanckmbanckdnl This internal macro fails to work properly with OTHER internal macros. dnl Basically, if the prologue is [], then no message should be generated. dnl This macro is in autoconf 2.52 m4_define([AC_LANG_PROGRAM(Fortran 77)], [m4_if([$1],[[[]]],,[m4_ifval([$1], [m4_warn([syntax], [$0: ignoring PROLOGUE: $1])])])dnl program main $2 end]) dnl/*D dnl PAC_PROG_CHECK_INSTALL_WORKS - Check whether the install program in INSTALL dnl works. dnl dnl Synopsis: dnl PAC_PROG_CHECK_INSTALL_WORKS dnl dnl Output Effect: dnl Sets the variable 'INSTALL' to the value of 'ac_sh_install' if dnl a file cannot be installed into a local directory with the 'INSTALL' dnl program dnl dnl Notes: dnl The 'AC_PROG_INSTALL' scripts tries to avoid broken versions of dnl install by avoiding directories such as '/usr/sbin' where some dnl systems are known to have bad versions of 'install'. Unfortunately, dnl this is exactly the sort of test-on-name instead of test-on-capability dnl that 'autoconf' is meant to eliminate. The test in this script dnl is very simple but has been adequate for working around problems dnl on Solaris, where the '/usr/sbin/install' program (known by dnl autoconf to be bad because it is in /usr/sbin) is also reached by a dnl soft link through /bin, which autoconf believes is good. dnl dnl No variables are cached to ensure that we do not make a mistake in dnl our choice of install program. dnl dnl The Solaris configure requires the directory name to immediately dnl follow the '-c' argument, rather than the more common dnl.vb dnl args sourcefiles destination-dir dnl.ve dnl D*/ AC_DEFUN([PAC_PROG_CHECK_INSTALL_WORKS],[ if test -z "$INSTALL" ; then AC_MSG_RESULT([No install program available]) else # first make any "confdb/install-sh -c" into an absolute path # this is a hack, but it's still much cleaner than anything else I could # come up with (see tt#1007) [goodell@] AS_CASE(["$INSTALL"], [/*],[:], [*install-sh*],[INSTALL="$master_top_srcdir/$INSTALL"]) # Check that this install really works rm -f conftest echo "Test file" > conftest if test ! -d .conftest ; then mkdir .conftest ; fi AC_MSG_CHECKING([whether install works]) if $INSTALL conftest .conftest >/dev/null 2>&1 ; then installOk=yes else installOk=no fi rm -rf .conftest conftest AC_MSG_RESULT($installOk) if test "$installOk" = no ; then if test -n "$ac_install_sh" ; then INSTALL=$ac_install_sh else AC_MSG_ERROR([Unable to find working install]) fi fi fi ]) armci-mpi/m4/ax_pthread.m40000644000175000017500000003267612663426407015135 0ustar mbanckmbanck# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. e.g. you should link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threads programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 21 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case ${host_os} in solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; darwin*) ax_pthread_flags="-pthread $ax_pthread_flags" ;; esac # Clang doesn't consider unrecognized options an error unless we specify # -Werror. We throw in some extra Clang-specific options to ensure that # this doesn't happen for GCC, which also accepts -Werror. AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) save_CFLAGS="$CFLAGS" ax_pthread_extra_flags="-Werror" CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], [AC_MSG_RESULT([yes])], [ax_pthread_extra_flags= AC_MSG_RESULT([no])]) CFLAGS="$save_CFLAGS" if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT([$ax_pthread_ok]) if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $attr; return attr /* ; */])], [attr_name=$attr; break], []) done AC_MSG_RESULT([$attr_name]) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case ${host_os} in aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; osf* | hpux*) flag="-D_REENTRANT";; solaris*) if test "$GCC" = "yes"; then flag="-D_REENTRANT" else # TODO: What about Clang on Solaris? flag="-mt -D_REENTRANT" fi ;; esac AC_MSG_RESULT([$flag]) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: compile with *_r variant if test "x$GCC" != xyes; then case $host_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD armci-mpi/m4/aclocal_make.m40000644000175000017500000001745612662706250015404 0ustar mbanckmbanckdnl dnl We need routines to check that make works. Possible problems with dnl make include dnl dnl It is really gnumake, and contrary to the documentation on gnumake, dnl it insists on screaming everytime a directory is changed. The fix dnl is to add the argument --no-print-directory to the make dnl dnl It is really BSD 4.4 make, and can't handle 'include'. For some dnl systems, this can be fatal; there is no fix (other than removing this dnl alleged make). dnl dnl It is the OSF V3 make, and can't handle a comment in a block of target dnl code. There is no acceptable fix. dnl dnl dnl dnl dnl Find a make program if none is defined. AC_DEFUN([PAC_PROG_MAKE_PROGRAM],[true if test "X$MAKE" = "X" ; then AC_CHECK_PROGS(MAKE,make gnumake nmake pmake smake) fi ])dnl dnl/*D dnl PAC_PROG_MAKE_INCLUDE - Check whether make supports include dnl dnl Synopsis: dnl PAC_PROG_MAKE_INCLUDE([action if true],[action if false]) dnl dnl Output Effect: dnl None dnl dnl Notes: dnl This checks for makes that do not support 'include filename'. Some dnl versions of BSD 4.4 make required '#include' instead; some versions of dnl 'pmake' have the same syntax. dnl dnl See Also: dnl PAC_PROG_MAKE dnl dnl D*/ AC_DEFUN([PAC_PROG_MAKE_INCLUDE],[ AC_CACHE_CHECK([whether make supports include],pac_cv_prog_make_include,[ AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest cat > conftest <<. ALL: @echo "success" . cat > conftest1 <<. include conftest . pac_str=`$MAKE -f conftest1 2>&1` # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest conftest1 if test "$pac_str" != "success" ; then pac_cv_prog_make_include="no" else pac_cv_prog_make_include="yes" fi ]) if test "$pac_cv_prog_make_include" = "no" ; then ifelse([$2],,:,[$2]) else ifelse([$1],,:,[$1]) fi ])dnl dnl/*D dnl PAC_PROG_MAKE_ALLOWS_COMMENTS - Check whether comments are allowed in dnl shell commands in a makefile dnl dnl Synopsis: dnl PAC_PROG_MAKE_ALLOWS_COMMENTS([false text]) dnl dnl Output Effect: dnl Issues a warning message if comments are not allowed in a makefile. dnl Executes the argument if one is given. dnl dnl Notes: dnl Some versions of OSF V3 make do not all comments in action commands. dnl dnl See Also: dnl PAC_PROG_MAKE dnl D*/ dnl AC_DEFUN([PAC_PROG_MAKE_ALLOWS_COMMENTS],[ AC_CACHE_CHECK([whether make allows comments in actions], pac_cv_prog_make_allows_comments,[ AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest cat > conftest <<. SHELL=/bin/sh ALL: @# This is a valid comment! @echo "success" . pac_str=`$MAKE -f conftest 2>&1` # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest if test "$pac_str" != "success" ; then pac_cv_prog_make_allows_comments="no" else pac_cv_prog_make_allows_comments="yes" fi ]) if test "$pac_cv_prog_make_allows_comments" = "no" ; then AC_MSG_WARN([Your make does not allow comments in target code. Using this make may cause problems when building programs. You should consider using gnumake instead.]) ifelse([$1],,[$1]) fi ])dnl dnl/*D dnl PAC_PROG_MAKE_VPATH - Check whether make supports source-code paths. dnl dnl Synopsis: dnl PAC_PROG_MAKE_VPATH dnl dnl Output Effect: dnl Sets the variable 'VPATH' to either dnl.vb dnl VPATH = .:${srcdir} dnl.ve dnl or dnl.vb dnl .PATH: . ${srcdir} dnl.ve dnl dnl Notes: dnl The test checks that the path works with implicit targets (some makes dnl support only explicit targets with 'VPATH' or 'PATH'). dnl dnl NEED TO DO: Check that $< works on explicit targets. dnl dnl See Also: dnl PAC_PROG_MAKE dnl dnl D*/ AC_DEFUN([PAC_PROG_MAKE_VPATH],[ AC_SUBST(VPATH) dnl AM_IGNORE(VPATH) AC_CACHE_CHECK([for virtual path format], pac_cv_prog_make_vpath,[ AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -rf conftest* mkdir conftestdir cat >conftestdir/a.c < conftest <&1 | grep 'conftestdir/a.c'` if test -n "$ac_out" ; then pac_cv_prog_make_vpath="VPATH" else rm -f conftest cat > conftest <&1 | grep 'conftestdir/a.c'` if test -n "$ac_out" ; then pac_cv_prog_make_vpath=".PATH" else pac_cv_prog_make_vpath="neither VPATH nor .PATH works" fi fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -rf conftest* ]) if test "$pac_cv_prog_make_vpath" = "VPATH" ; then VPATH='VPATH=.:${srcdir}' elif test "$pac_cv_prog_make_vpath" = ".PATH" ; then VPATH='.PATH: . ${srcdir}' fi ])dnl dnl/*D dnl PAC_PROG_MAKE_SET_CFLAGS - Check whether make sets CFLAGS dnl dnl Synopsis: dnl PAC_PROG_MAKE_SET_CFLAGS([action if true],[action if false]) dnl dnl Output Effects: dnl Executes the first argument if 'CFLAGS' is set by 'make'; executes dnl the second argument if 'CFLAGS' is not set by 'make'. dnl dnl Notes: dnl If 'CFLAGS' is set by make, you may wish to override that choice in your dnl makefile. dnl dnl See Also: dnl PAC_PROG_MAKE dnl D*/ AC_DEFUN([PAC_PROG_MAKE_SET_CFLAGS],[ AC_CACHE_CHECK([whether make sets CFLAGS], pac_cv_prog_make_set_cflags,[ AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest cat > conftest <&1` # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest if test "$pac_str" = "XX" ; then pac_cv_prog_make_set_cflags="no" else pac_cv_prog_make_set_cflags="yes" fi ]) if test "$pac_cv_prog_make_set_cflags" = "no" ; then ifelse([$2],,:,[$2]) else ifelse([$1],,:,[$1]) fi ])dnl dnl/*D dnl PAC_PROG_MAKE_CLOCK_SKEW - Check whether there is a problem with dnl clock skew in suing make. dnl dnl Effect: dnl Sets the cache variable 'pac_cv_prog_make_found_clock_skew' to yes or no dnl D*/ AC_DEFUN([PAC_PROG_MAKE_CLOCK_SKEW],[ AC_CACHE_CHECK([whether clock skew breaks make], pac_cv_prog_make_found_clock_skew,[ AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* cat > conftest < conftest.out 2>&1 if grep -i skew conftest >/dev/null 2>&1 ; then pac_cv_prog_make_found_clock_skew=yes else pac_cv_prog_make_found_clock_skew=no fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* ]) dnl We should really do something if we detect clock skew. The question is, dnl what? if test "$pac_cv_prog_make_found_clock_skew" = "yes" ; then AC_MSG_WARN([Clock skew found by make. The configure and build may fail. Consider building in a local instead of NFS filesystem.]) fi ]) dnl/*D dnl PAC_PROG_MAKE - Checks for the varieties of MAKE, including support for dnl VPATH dnl dnl Synopsis: dnl PAC_PROG_MAKE dnl dnl Output Effect: dnl Sets 'MAKE' to the make program to use if 'MAKE' is not already set. dnl Sets the variable 'SET_CFLAGS' to 'CFLAGS =' if make sets 'CFLAGS'. dnl dnl Notes: dnl This macro uses 'PAC_PROG_MAKE_INCLUDE', dnl 'PAC_PROG_MAKE_ALLOWS_COMMENTS', 'PAC_PROG_MAKE_VPATH', and dnl 'PAC_PROG_MAKE_SET_CFLAGS'. See those commands for details about their dnl actions. dnl dnl It may call 'AC_PROG_MAKE_SET', which sets 'SET_MAKE' to 'MAKE = @MAKE@' dnl if the make program does not set the value of make, otherwise 'SET_MAKE' dnl is set to empty; if the make program echos the directory name, then dnl 'SET_MAKE' is set to 'MAKE = $MAKE'. dnl D*/ AC_DEFUN([PAC_PROG_MAKE],[ PAC_PROG_MAKE_PROGRAM PAC_PROG_MAKE_CLOCK_SKEW PAC_PROG_MAKE_INCLUDE PAC_PROG_MAKE_ALLOWS_COMMENTS PAC_PROG_MAKE_VPATH AC_SUBST(SET_CFLAGS) dnl AM_IGNORE(SET_CFLAGS) PAC_PROG_MAKE_SET_CFLAGS([SET_CFLAGS='CFLAGS=']) if test "$pac_cv_prog_make_echos_dir" = "no" ; then AC_PROG_MAKE_SET else SET_MAKE="MAKE=${MAKE-make}" fi ]) armci-mpi/m4/aclocal_cache.m40000644000175000017500000003134712662706250015525 0ustar mbanckmbanckdnl dnl/*D dnl AC_CACHE_LOAD - Replacement for autoconf cache load dnl dnl Notes: dnl Caching in autoconf is broken (at least through version 2.13). dnl The problem is that the cache is read dnl without any check for whether it makes any sense to read it. dnl A common problem is a build on a shared file system; connecting to dnl a different computer and then building within the same directory will dnl lead to at best error messages from configure and at worse a build that dnl is wrong but fails only at run time (e.g., wrong datatype sizes used). dnl Later versions of autoconf do include some checks for changes in the dnl environment that impact the choices, but still misses problems with dnl multiple different systems. dnl dnl This fixes that by requiring the user to explicitly enable caching dnl before the cache file will be loaded. dnl dnl To use this version of 'AC_CACHE_LOAD', you need to include dnl 'aclocal_cache.m4' in your 'aclocal.m4' file. The sowing 'aclocal.m4' dnl file includes this file. dnl dnl If no --enable-cache or --disable-cache option is selected, the dnl command causes configure to keep track of the system being configured dnl in a config.system file; if the current system matches the value stored dnl in that file (or there is neither a config.cache nor config.system file), dnl configure will enable caching. In order to ensure that the configure dnl tests make sense, the values of CC, F77, F90, and CXX are also included dnl in the config.system file. In addition, the value of PATH is included dnl to ensure that changes in the PATH that might select a different version dnl of a program with the same name (such as a native make versus gnumake) dnl are detected. dnl dnl Bugs: dnl This does not work with the Cygnus configure because the enable arguments dnl are processed *after* AC_CACHE_LOAD (!). To address this, we avoid dnl changing the value of enable_cache, and use real_enable_cache, duplicating dnl the "notgiven" value. dnl dnl The environment variable CONFIGURE_DEBUG_CACHE, if set to yes, dnl will cause additional data to be written out during the configure process. dnl This can be helpful in debugging the cache file process. dnl dnl See Also: dnl PAC_ARG_CACHING dnl D*/ define([AC_CACHE_LOAD], [if test "$CONFIGURE_DEBUG_CACHE" = yes ; then oldopts="$-" clearMinusX=no set -x if test "$oldopts" != "$-" ; then clearMinusX=yes fi fi if test "X$cache_system" = "X" ; then # A default file name, just in case cache_system="config.system" if test "$cache_file" != "/dev/null" ; then # Get the directory for the cache file, if any changequote(,) dnl Be careful to ensure that there is no doubled slash cache_system=`echo $cache_file | sed -e 's%^\(.*/\)[^/]*%\1config.system%'` changequote([,]) test "x$cache_system" = "x$cache_file" && cache_system="config.system" # else # We must *not* set enable_cache to no because we need to know if # enable_cache was not set. # enable_cache=no fi fi dnl dnl The "action-if-not-given" part of AC_ARG_ENABLE is not executed until dnl after the AC_CACHE_LOAD is executed (!). Thus, the value of dnl enable_cache if neither --enable-cache or --disable-cache is selected dnl is null. Just in case autoconf ever fixes this, we test both cases. dnl dnl Include PATH in the cache.system file since changing the path can dnl change which versions of programs are found (such as vendor make dnl or GNU make). dnl # # Get a test value and flag whether we should remove/replace the # cache_system file (do so unless cache_system_ok is yes) # FC and F77 should be synonyms. Save both in case # We include the xxxFLAGS in case the user is using the flags to change # the language (either input or output) of the compiler. E.g., # using -xarch=v9 on Solaris to select 64 bit output or using -D_BSD_SOURCE # with gcc to get different header files on input. cleanargs=`echo "$CC $F77 $FC $CXX $F90 $CFLAGS $FFLAGS $CXXFLAGS $F90FLAGS $PATH" | tr '"' ' '` if uname -srm >/dev/null 2>&1 ; then cache_system_text="`uname -srm` $cleanargs" else cache_system_text="-no-uname- $cleanargs" fi cache_system_ok=no # if test -z "$real_enable_cache" ; then real_enable_cache=$enable_cache if test -z "$real_enable_cache" ; then real_enable_cache="notgiven" ; fi fi if test "X$real_enable_cache" = "Xnotgiven" ; then # check for valid cache file if test -z "$cache_system" ; then cache_system="config.system" ; fi if uname -srm >/dev/null 2>&1 ; then if test -f "$cache_system" -a -n "$cache_system_text" ; then if test "$cache_system_text" = "`cat $cache_system`" ; then real_enable_cache="yes" cache_system_ok=yes fi elif test ! -f "$cache_system" -a -n "$cache_system_text" ; then # remove the cache file because it may not correspond to our # system if test "$cache_file" != "/dev/null" ; then rm -f $cache_file fi real_enable_cache="yes" fi fi fi if test "X$real_enable_cache" = "Xyes" -a "$cache_file" = "/dev/null" ; then real_enable_cache=no fi if test "X$real_enable_cache" = "Xyes" ; then if test -r "$cache_file" ; then echo "loading cache $cache_file" if test -w "$cache_file" ; then # Clean the cache file (ergh) PAC_CACHE_CLEAN fi . $cache_file else echo "Configure in `pwd` creating cache $cache_file" > $cache_file rm -f $cache_system fi else cache_file="/dev/null" fi # Remember our location and the name of the cachefile pac_cv_my_conf_dir=`pwd` dnl do not include the cachefile name, since this may contain the process dnl number and cause comparisons looking for changes to the cache file dnl to detect a change that isn't real. dnl pac_cv_my_cachefile=$cachefile # # Update the cache_system file if necessary if test "$cache_system_ok" != yes ; then if test -n "$cache_system" ; then rm -f $cache_system echo $cache_system_text > $cache_system fi fi if test "$clearMinusX" = yes ; then set +x fi ]) dnl dnl/*D dnl PAC_ARG_CACHING - Enable caching of results from a configure execution dnl dnl Synopsis: dnl PAC_ARG_CACHING dnl dnl Output Effects: dnl Adds '--enable-cache' and '--disable-cache' to the command line arguments dnl accepted by 'configure'. dnl dnl See Also: dnl AC_CACHE_LOAD dnl D*/ dnl Add this call to the other ARG_ENABLE calls. Note that the values dnl set here are redundant; the LOAD_CACHE call relies on the way autoconf dnl initially processes ARG_ENABLE commands. AC_DEFUN([PAC_ARG_CACHING],[ AC_ARG_ENABLE(cache, AC_HELP_STRING([--enable-cache], [Turn on configure caching]),, [enable_cache="notgiven"]) ]) dnl Clean the cache of extraneous quotes that AC_CACHE_SAVE may add dnl AC_DEFUN([PAC_CACHE_CLEAN],[ rm -f confcache sed -e "s/'\\\\''//g" -e "s/'\\\\/'/" -e "s/\\\\'/'/" \ -e "s/'\\\\''//g" $cache_file > confcache if cmp -s $cache_file confcache ; then : else if test -w $cache_file ; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache if test "$DEBUG_AUTOCONF_CACHE" = "yes" ; then echo "Results of cleaned cache file:" echo "--------------------------------------------------------" cat $cache_file echo "--------------------------------------------------------" fi ]) dnl/*D dnl PAC_SUBDIR_CACHE - Create a cache file before ac_output for subdirectory dnl configures. dnl dnl Synopsis: dnl PAC_SUBDIR_CACHE(when) dnl dnl Input Parameter: dnl . when - Indicates when the cache should be created (optional) dnl If 'always', create a new cache file. This option dnl should be used if any of the cache parameters (such as dnl CFLAGS or LDFLAGS) may have changed. dnl dnl Output Effects: dnl dnl Create a cache file before ac_output so that subdir configures don't dnl make mistakes. dnl We can't use OUTPUT_COMMANDS to remove the cache file, because those dnl commands are executed *before* the subdir configures. dnl dnl D*/ AC_DEFUN([PAC_SUBDIR_CACHE],[]) AC_DEFUN([PAC_SUBDIR_CACHE_OLD],[ if test "x$1" = "xalways" -o \( "$cache_file" = "/dev/null" -a "X$real_enable_cache" = "Xnotgiven" \) ; then # Use an absolute directory to help keep the subdir configures from getting # lost cache_file=`pwd`/$$conf.cache touch $cache_file dnl dnl For Autoconf 2.52+, we should ensure that the environment is set dnl for the cache. Make sure that we get the values and set the dnl xxx_set variables properly ac_cv_env_CC_set=set ac_cv_env_CC_value=$CC ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_cv_env_CPP_set=set ac_cv_env_CPP_value=$CPP ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LIBS_set=${LIBS+set} ac_cv_env_LIBS_value=$LIBS ac_cv_env_FC_set=${FC+set} ac_cv_env_FC_value=$FC ac_cv_env_F77_set=${F77+set} ac_cv_env_F77_value=$F77 ac_cv_env_F90_set=${F90+set} ac_cv_env_F90_value=$F90 ac_cv_env_FFLAGS_set=${FFLAGS+set} ac_cv_env_FFLAGS_value=$FFLAGS ac_cv_env_CXX_set=${CXX+set} ac_cv_env_CXX_value=$CXX ac_env_CC_set=set ac_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_env_CPP_set=set ac_env_CPP_value=$CPP ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_env_LIBS_set=${LIBS+set} ac_env_LIBS_value=$LIBS ac_env_FC_set=${FC+set} ac_env_FC_value=$FC ac_env_F77_set=${F77+set} ac_env_F77_value=$F77 ac_env_F90_set=${F90+set} ac_env_F90_value=$F90 ac_env_FFLAGS_set=${FFLAGS+set} ac_env_FFLAGS_value=$FFLAGS ac_env_CXX_set=${CXX+set} ac_env_CXX_value=$CXX dnl other parameters are dnl build_alias, host_alias, target_alias # It turns out that A C CACHE_SAVE can't be invoked more than once # with data that contains blanks. What happens is that the quotes # that it adds get quoted and then added again. To avoid this, # we strip off the outer quotes for all cached variables dnl We add pac_cv_my_conf_dir to give the source of this cachefile, dnl and pac_cv_my_cachefile to indicate how it chose the cachefile. pac_cv_my_conf_dir=`pwd` pac_cv_my_cachefile=$cachefile AC_CACHE_SAVE PAC_CACHE_CLEAN ac_configure_args="$ac_configure_args -enable-cache" fi dnl Unconditionally export these values. Subdir configures break otherwise export CC export CFLAGS export LDFLAGS export LIBS export CPPFLAGS export CPP export FC export F77 export F90 export CXX export FFLAGS export CCFLAGS ]) AC_DEFUN([PAC_SUBDIR_CACHE_CLEANUP],[]) AC_DEFUN([PAC_SUBDIR_CACHE_CLEANUP_OLD],[ if test "$cache_file" != "/dev/null" -a "X$real_enable_cache" = "Xnotgiven" ; then rm -f $cache_file cache_file=/dev/null fi ]) dnl dnl The following three macros support the sharing of configure results dnl by configure scripts, including ones that are not run with dnl AC_CONFIG_SUBDIRS (the cachefiles managed by --enable-cache can dnl only be used with AC_CONFIG_SUBDIRS; creating a autoconf-style dnl cachefile before the the end of the autoconf process will often dnl cause problems. dnl AC_DEFUN([PAC_CREATE_BASE_CACHE],[ AC_ARG_ENABLE(base-cache, AC_HELP_STRING([--enable-base-cache], [Enable the use of a simple cache for the subsidiary configure scripts]),,enable_base_cache=default) # The default case is controlled by the environment variable CONF_USE_CACHEFILE if test "$enable_base_cache" = "default" ; then if test "$CONF_USE_CACHEFILE" = yes ; then enable_base_cache=yes else enable_base_cache=no fi fi if test "$enable_base_cache" != no ; then if test "$enable_base_cache" = yes ; then basecachefile=`pwd`/cache.base else basecachefile=`pwd`/$enable_base_cache fi set | grep ac_cv > $basecachefile # Tell other configures to load this file echo "Creating and exporting the base cache file $basecachefile" CONF_BASE_CACHEFILE=$basecachefile export CONF_BASE_CACHEFILE fi ]) AC_DEFUN([PAC_LOAD_BASE_CACHE],[ if test -n "$CONF_BASE_CACHEFILE" -a -s "$CONF_BASE_CACHEFILE" ; then echo "Loading base cachefile $CONF_BASE_CACHEFILE" . $CONF_BASE_CACHEFILE export CONF_BASE_CACHEFILE fi ]) AC_DEFUN([PAC_UPDATE_BASE_CACHE],[ if test -n "$CONF_BASE_CACHEFILE" -a -s "$CONF_BASE_CACHEFILE" ; then set | grep ac_cv > $CONF_BASE_CACHEFILE.new if cmp -s $CONF_BASE_CACHEFILE.new $CONF_BASE_CACHEFILE ; then : else echo "Replacing $CONF_BASE_CACHEFILE" mv $CONF_BASE_CACHEFILE.new $CONF_BASE_CACHEFILE fi fi ]) armci-mpi/m4/aclocal_romio.m40000644000175000017500000006001112662706250015575 0ustar mbanckmbanckdnl dnl This files contains additional macros for using autoconf to dnl build configure scripts. dnl dnl Almost all of this file is taken from the aclocal.m4 of MPICH dnl dnl Get the format of Fortran names. Uses F77, FFLAGS, and sets WDEF. dnl If the test fails, sets NOF77 to 1, HAVE_FORTRAN to 0. dnl dnl AC_DEFUN([PAC_GET_FORTNAMES],[ rm -f confftest.f confftest.o cat > confftest.f < /dev/null 2>&1 if test ! -s confftest.o ; then AC_MSG_WARN([Unable to test Fortran compiler. Compiling a test program failed to produce an object file]) NOF77=1 elif test -z "$FORTRANNAMES" ; then # MAC OS X (and probably FreeBSD need strings - (not strings -a) # Cray doesn't accept -a ... allstrings="-a" if test $arch_CRAY ; then allstrings="" elif strings - confftest.o < /dev/null >/dev/null 2>&1 ; then allstrings="-" elif strings -a confftest.o < /dev/null >/dev/null 2>&1 ; then allstrings="-a" fi nameform1=`strings $allstrings confftest.o | grep mpir_init_fop_ | head -1` nameform2=`strings $allstrings confftest.o | grep MPIR_INIT_FOP | head -1` nameform3=`strings $allstrings confftest.o | grep mpir_init_fop | head -1` nameform4=`strings $allstrings confftest.o | grep mpir_init_fop__ | head -1` rm -f confftest.f confftest.o if test -n "$nameform4" ; then echo "Fortran externals are lower case and have two trailing underscores" FORTRANNAMES="FORTRANDOUBLEUNDERSCORE" elif test -n "$nameform1" ; then # We don't set this in CFLAGS; it is a default case echo "Fortran externals have a trailing underscore and are lowercase" FORTRANNAMES="FORTRANUNDERSCORE" elif test -n "$nameform2" ; then echo "Fortran externals are uppercase" FORTRANNAMES="FORTRANCAPS" elif test -n "$nameform3" ; then echo "Fortran externals are lower case" FORTRANNAMES="FORTRANNOUNDERSCORE" else AC_MSG_WARN([Unable to determine the form of Fortran external names. Make sure that the compiler $F77 can be run on this system. Turning off Fortran (-nof77 being assumed)]) NOF77=1 fi fi if test -n "$FORTRANNAMES" ; then WDEF="-D$FORTRANNAMES" fi # Delete confftest files with any extension. This catches the case # where auxillary files, such as coverage files, are removed. rm -f confftest.* ])dnl dnl define(PAC_GET_SPECIAL_SYSTEM_INFO,[ # if test -n "$arch_IRIX"; then AC_MSG_CHECKING(for IRIX OS version) dnl This block of code replaces a generic "IRIX" arch value with dnl IRIX__ dnl For example dnl IRIX_5_4400 (IRIX 5.x, using MIPS 4400) osversion=`uname -r | sed 's/\..*//'` dnl Note that we need to allow brackets here, so we briefly turn off dnl the macro quotes changequote(,)dnl dnl Get the second field (looking for 6.1) osvminor=`uname -r | sed 's/[0-9]\.\([0-9]*\)\..*/\1/'` changequote([,])dnl AC_MSG_RESULT($osversion) dnl Get SGI processor count by quick hack AC_MSG_CHECKING(for IRIX cpucount) changequote(,)dnl cpucount=`hinv | grep '[0-9]* [0-9]* MHZ IP[0-9]* Proc' | cut -f 1 -d' '` if test "$cpucount" = "" ; then cpucount=`hinv | grep 'Processor [0-9]*:' | wc -l | sed -e 's/ //g'` fi changequote([,])dnl if test "$cpucount" = "" ; then AC_MSG_RESULT([Could not determine cpucount. Please send]) hinv AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) fi AC_MSG_RESULT($cpucount) dnl AC_MSG_CHECKING(for IRIX cpumodel) dnl The tail -1 is necessary for multiple processor SGI boxes dnl We might use this to detect SGI multiprocessors and recommend dnl -comm=shared cputype=`hinv -t cpu | tail -1 | cut -f 3 -d' '` if test -z "$cputype" ; then AC_MSG_RESULT([Could not get cputype from hinv -t cpu command. Please send]) hinv -t cpu 2>&1 hinv -t cpu | cut -f 3 -d' ' 2>&1 AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) fi AC_MSG_RESULT($cputype) dnl echo "checking for osversion and cputype" dnl cputype may contain R4400, R2000A/R3000, or something else. dnl We may eventually need to look at it. if test -z "$osversion" ; then AC_MSG_RESULT([Could not determine OS version. Please send]) uname -a AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) elif test $osversion = 4 ; then true elif test $osversion = 5 ; then true elif test $osversion = 6 ; then true else AC_MSG_RESULT([Could not recognize the version of IRIX (got $osversion). ROMIO knows about versions 4, 5 and 6; the version being returned from uname -r is $osversion. Please send]) uname -a 2>&1 hinv 2>&1 AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) fi AC_MSG_CHECKING(for cputype) OLD_ARCH=IRIX IRIXARCH="$ARCH_$osversion" dnl Now, handle the chip set changequote(,)dnl cputype=`echo $cputype | sed -e 's%.*/%%' -e 's/R//' | tr -d "[A-Z]"` changequote([,])dnl case $cputype in 3000) ;; 4000) ;; 4400) ;; 4600) ;; 5000) ;; 8000) ;; 10000);; 12000);; *) AC_MSG_WARN([Unexpected IRIX/MIPS chipset $cputype. Please send the output]) uname -a 2>&1 hinv 2>&1 AC_MSG_WARN([to romio-maint@mcs.anl.gov ROMIO will continue and assume that the cputype is compatible with a MIPS 4400 processor.]) cputype=4400 ;; esac AC_MSG_RESULT($cputype) IRIXARCH="$IRIXARCH_$cputype" echo "IRIX-specific architecture is $IRIXARCH" fi ])dnl dnl dnl define(PAC_TEST_MPI,[ AC_MSG_CHECKING(if a simple MPI program compiles and links) rm -f mpitest.c cat > mpitest.c <&5 $cmd >&5 2>&5 if test ! -x conftest ; then echo "$as_me:$LINENO: failed program was:" >&5 sed 's/^/| /' mpitest.c >&5 rm -f conftest mpitest.c AC_MSG_ERROR([Unable to compile a simple MPI program. Use environment variables to provide the location of MPI libraries and include directories]) else rm -f conftest mpitest.c fi AC_MSG_RESULT(yes) ])dnl dnl dnl dnl define(PAC_NEEDS_FINT,[ AC_MSG_CHECKING(if MPI_Fint is defined in the MPI implementation) cat > mpitest1.c < /dev/null 2>&1 if test ! -s mpitest1.o ; then NEEDS_MPI_FINT="#define NEEDS_MPI_FINT" CFLAGS="$CFLAGS -DNEEDS_MPI_FINT" AC_MSG_RESULT(no) rm -f mpitest1.o mpitest1.c else NEEDS_MPI_FINT="" AC_MSG_RESULT(yes) rm -f mpitest1.o mpitest1.c fi ])dnl dnl define(PAC_MPI_LONG_LONG_INT,[ AC_MSG_CHECKING(if MPI_LONG_LONG_INT is defined in mpi.h) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_MPI_LONG_LONG_INT,,[Define if mpi has long long it]) else AC_MSG_RESULT(no) fi rm -f conftest mpitest.c ])dnl dnl dnl PAC_LONG_LONG_64: check if there is a 64-bit long long dnl define(PAC_LONG_LONG_64,[ if test -n "$longlongsize" ; then if test "$longlongsize" = 8 ; then echo "defining MPI_Offset as long long in C and integer*8 in Fortran" AC_DEFINE(HAVE_LONG_LONG_64,,[Define if long long is 64 bits]) DEFINE_MPI_OFFSET="typedef long long MPI_Offset;" FORTRAN_MPI_OFFSET="integer*8" LL="\%lld" elif test "$longlongsize" = "int" ; then # a hack to set MPI_Offset as int echo "defining MPI_Offset as int in C and integer in Fortran" DEFINE_MPI_OFFSET="typedef int MPI_Offset;" FORTRAN_MPI_OFFSET="integer" AC_DEFINE(MPI_OFFSET_IS_INT,,[Define if MPI_Offset is int]) LL="\%d" MPI_OFFSET_KIND1="!" MPI_OFFSET_KIND2="!" else echo "defining MPI_Offset as long in C and integer in Fortran" DEFINE_MPI_OFFSET="typedef long MPI_Offset;" FORTRAN_MPI_OFFSET="integer" LL="\%ld" MPI_OFFSET_KIND1="!" MPI_OFFSET_KIND2="!" fi else PAC_GET_TYPE_SIZE(long long, longlongsize) if test -n "$longlongsize" ; then if test "$longlongsize" = 8 ; then PAC_TEST_LONG_LONG() else echo "defining MPI_Offset as long in C and integer in Fortran" DEFINE_MPI_OFFSET="typedef long MPI_Offset;" FORTRAN_MPI_OFFSET="integer" LL="\%ld" MPI_OFFSET_KIND1="!" MPI_OFFSET_KIND2="!" fi else dnl check if longlong is not supported or only its size cannot be determined dnl because the program cannot be run. rm -f ltest.c cat > ltest.c < /dev/null 2>&1 if test -x conftest ; then echo "assuming size of long long is 8bytes; use '-longlongsize' to indicate otherwise" rm -f conftest ltest.c echo "defining MPI_Offset as long long in C and integer*8 in Fortran" AC_DEFINE(HAVE_LONG_LONG_64,,[Define if long long is 64 bits]) DEFINE_MPI_OFFSET="typedef long long MPI_Offset;" FORTRAN_MPI_OFFSET="integer*8" LL="\%lld" else echo "assuming long long is not available; use '-longlongsize' to indicate otherwise" echo "defining MPI_Offset as long in C and integer in Fortran" DEFINE_MPI_OFFSET="typedef long MPI_Offset;" FORTRAN_MPI_OFFSET="integer" LL="\%ld" MPI_OFFSET_KIND1="!" MPI_OFFSET_KIND2="!" fi fi fi ])dnl dnl dnl define(PAC_MPI_INFO,[ AC_MSG_CHECKING(if MPI_Info functions are defined in the MPI implementation) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_MPI_INFO,1,[Define if MPI_Info available]) HAVE_MPI_INFO="#define HAVE_MPI_INFO" MPI_FINFO1="!" MPI_FINFO2="!" MPI_FINFO3="!" MPI_FINFO4="!" else AC_MSG_RESULT(no) BUILD_MPI_INFO=1 MPI_FINFO1=" INTEGER MPI_MAX_INFO_KEY, MPI_MAX_INFO_VAL" MPI_FINFO2=" PARAMETER (MPI_MAX_INFO_KEY=255, MPI_MAX_INFO_VAL=1024)" MPI_FINFO3=" INTEGER MPI_INFO_NULL" MPI_FINFO4=" PARAMETER (MPI_INFO_NULL=0)" fi rm -f conftest mpitest.c ])dnl dnl dnl define(PAC_MPI_DARRAY_SUBARRAY,[ AC_MSG_CHECKING(if darray and subarray constructors are defined in the MPI implementation) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_MPI_DARRAY_SUBARRAY,,[Define if MPI Darray available]) HAVE_MPI_DARRAY_SUBARRAY="#define HAVE_MPI_DARRAY_SUBARRAY" MPI_FARRAY1="!" MPI_FARRAY2="!" MPI_FARRAY3="!" MPI_FARRAY4="!" MPI_FARRAY5="!" MPI_FARRAY6="!" MPI_FARRAY7="!" else AC_MSG_RESULT(no) BUILD_MPI_ARRAY=1 MPI_FARRAY1=" INTEGER MPI_ORDER_C, MPI_ORDER_FORTRAN" MPI_FARRAY2=" PARAMETER (MPI_ORDER_C=56, MPI_ORDER_FORTRAN=57)" MPI_FARRAY3=" INTEGER MPI_DISTRIBUTE_BLOCK, MPI_DISTRIBUTE_CYCLIC" MPI_FARRAY4=" INTEGER MPI_DISTRIBUTE_NONE, MPI_DISTRIBUTE_DFLT_DARG" MPI_FARRAY5=" PARAMETER (MPI_DISTRIBUTE_BLOCK=121, MPI_DISTRIBUTE_CYCLIC=122)" MPI_FARRAY6=" PARAMETER (MPI_DISTRIBUTE_NONE=123)" MPI_FARRAY7=" PARAMETER (MPI_DISTRIBUTE_DFLT_DARG=-49767)" fi rm -f conftest mpitest.c ])dnl dnl dnl define(PAC_CHECK_MPI_SGI_INFO_NULL,[ AC_MSG_CHECKING([if MPI_INFO_NULL is defined in mpi.h]) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) cp adio/sgi/mpi3.1/*.h include else AC_MSG_RESULT(no) fi rm -f conftest mpitest.c ])dnl dnl dnl dnl define(PAC_CHECK_MPIOF_H,[ AC_MSG_CHECKING(if mpiof.h is included in mpif.h) rm -f mpitest.f cat > mpitest.f < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) MPIOF_H_INCLUDED=1 else AC_MSG_RESULT(no) fi rm -f conftest mpitest.f ])dnl dnl dnl dnl check if pread64 is defined in IRIX. needed on IRIX 6.5 dnl define(PAC_HAVE_PREAD64,[ AC_MSG_CHECKING(if pread64 is defined) rm -f conftest.c cat > conftest.c < main() { int fd=0, buf=0, i=0; off64_t off=0; pread64(fd, &buf, i, off); } EOF rm -f conftest $CC $USER_CFLAGS -o conftest conftest.c > /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PREAD64,,[Define if pread64 available]) else AC_MSG_RESULT(no) fi rm -f conftest conftest.c ])dnl dnl dnl define(PAC_TEST_MPI_SGI_type_is_contig,[ AC_MSG_CHECKING(if MPI_SGI_type_is_contig is defined) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_DEFINE(NO_MPI_SGI_type_is_contig,,[Define if no MPI type is contig]) fi rm -f conftest mpitest.c ])dnl dnl dnl dnl define(PAC_TEST_MPI_COMBINERS,[ AC_MSG_CHECKING(if MPI-2 combiners are defined in mpi.h) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_MPI_COMBINERS,,[Define if MPI combiners available]) else AC_MSG_RESULT(no) fi rm -f conftest mpitest.c ])dnl dnl dnl dnl PAC_MPI_OFFSET_KIND() dnl dnl tries to determine the Fortran 90 kind parameter for 8-byte integers dnl define(PAC_MPI_OFFSET_KIND, [ # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* # Determine the extension for Fortran 90 files (not all compilers accept # .f and not all accept .f90) if test -z "$ac_f90ext" ; then if test -z "$F90" ; then AC_CHECK_PROGS(F90,f90 xlf90 pgf90 ifort epcf90 f95 fort xlf95 lf95 pathf90 g95 fc ifc efc) fi AC_MSG_CHECKING([for extension for Fortran 90 programs]) ac_f90ext="f90" ac_f90compile='${F90-f90} -c $F90FLAGS conftest.$ac_f90ext 1>&AC_FD_CC' cat > conftest.$ac_f90ext < conftest.$ac_f90ext < conftest.$ac_f90ext program main integer i i = selected_int_kind(16) open(8, file="conftest.out", form="formatted") write (8,*) i close(8) stop end EOF if test -z "$F90" ; then F90=f90 fi KINDVAL="" if $F90 -o conftest conftest.$ac_f90ext >/dev/null 2>&1 ; then ./conftest >/dev/null 2>&1 if test -s conftest.out ; then KINDVAL=`cat conftest.out` fi fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -f conftest* if test -n "$KINDVAL" -a "$KINDVAL" != "-1" ; then AC_MSG_RESULT($KINDVAL) MPI_OFFSET_KIND1=" INTEGER MPI_OFFSET_KIND" MPI_OFFSET_KIND2=" PARAMETER (MPI_OFFSET_KIND=$KINDVAL)" else AC_MSG_RESULT(unavailable) fi ])dnl dnl dnl define(PAC_TEST_MPI_HAVE_OFFSET_KIND,[ AC_MSG_CHECKING(if MPI_OFFSET_KIND is defined in mpif.h) rm -f mpitest.f cat > mpitest.f < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) MPI_OFFSET_KIND1="!" MPI_OFFSET_KIND2="!" else AC_MSG_RESULT(no) fi rm -f conftest mpitest.f ])dnl dnl dnl dnl PAC_GET_XFS_MEMALIGN dnl dnl define(PAC_GET_XFS_MEMALIGN, [AC_MSG_CHECKING([for memory alignment needed for direct I/O]) rm -f memalignval rm -f /tmp/romio_tmp.bin AC_TEST_PROGRAM([#include #include #include #include main() { struct dioattr st; int fd = open("/tmp/romio_tmp.bin", O_RDWR | O_CREAT, 0644); FILE *f=fopen("memalignval","w"); if (fd == -1) exit(1); if (!f) exit(1); fcntl(fd, F_DIOINFO, &st); fprintf( f, "%u\n", st.d_mem); exit(0); }],Pac_CV_NAME=`cat memalignval`,Pac_CV_NAME="") rm -f memalignval rm -f /tmp/romio_tmp.bin if test -n "$Pac_CV_NAME" -a "$Pac_CV_NAME" != 0 ; then AC_MSG_RESULT($Pac_CV_NAME) CFLAGS="$CFLAGS -DXFS_MEMALIGN=$Pac_CV_NAME" else AC_MSG_RESULT(unavailable, assuming 128) CFLAGS="$CFLAGS -DXFS_MEMALIGN=128" fi ])dnl dnl dnl dnl Look for a style of VPATH. Known forms are dnl VPATH = .:dir dnl .PATH: . dir dnl dnl Defines VPATH or .PATH with . $(srcdir) dnl Requires that vpath work with implicit targets dnl NEED TO DO: Check that $< works on explicit targets. dnl define(PAC_MAKE_VPATH,[ AC_SUBST(VPATH) AC_MSG_CHECKING(for virtual path format) # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -rf conftest* mkdir conftestdir cat >conftestdir/a.c < conftest <&1 | grep 'conftestdir/a.c'` if test -n "$ac_out" ; then AC_MSG_RESULT(VPATH) VPATH='VPATH=.:$(srcdir)' else rm -f conftest cat > conftest <&1 | grep 'conftestdir/a.c'` if test -n "$ac_out" ; then AC_MSG_RESULT(.PATH) VPATH='.PATH: . $(srcdir)' else AC_MSG_RESULT(neither VPATH nor .PATH works) fi fi # This is needed for Mac OSX 10.5 rm -rf conftest.dSYM rm -rf conftest* ])dnl dnl define(PAC_HAVE_MOUNT_NFS,[ AC_MSG_CHECKING([if MOUNT_NFS is defined in the include files]) rm -f conftest.c cat > conftest.c < #include main() { int i=MOUNT_NFS; } EOF rm -f conftest $CC $USER_CFLAGS -o conftest conftest.c > /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) ROMIO_HAVE_MOUNT_NFS=1 AC_DEFINE(HAVE_MOUNT_NFS,,[Define if MOUNT_NFS defined]) else ROMIO_HAVE_MOUNT_NFS=0 AC_MSG_RESULT(no) fi rm -f conftest conftest.c ])dnl dnl dnl dnl PAC_MPI_OFFSET_KIND_4BYTE() dnl dnl tries to determine the Fortran 90 kind parameter for 4-byte integers dnl define(PAC_MPI_OFFSET_KIND_4BYTE, [AC_MSG_CHECKING([for Fortran 90 KIND parameter for 4-byte integers]) rm -f kind.f kind.o kind cat < kind.f program main integer i i = selected_int_kind(8) open(8, file="k.out", form="formatted") write (8,*) i close(8) stop end EOF if test -z "$F90" ; then F90=f90 fi KINDVAL="" if $F90 -o kind kind.f >/dev/null 2>&1 ; then ./kind >/dev/null 2>&1 if test -s k.out ; then KINDVAL=`cat k.out` fi fi rm -f kind k.out kind.f kind.o if test -n "$KINDVAL" -a "$KINDVAL" != "-1" ; then AC_MSG_RESULT($KINDVAL) MPI_OFFSET_KIND1=" INTEGER MPI_OFFSET_KIND" MPI_OFFSET_KIND2=" PARAMETER (MPI_OFFSET_KIND=$KINDVAL)" else AC_MSG_RESULT(unavailable) fi ])dnl dnl dnl define(PAC_FUNC_STRERROR,[ AC_MSG_CHECKING([for strerror()]) rm -f conftest.c cat > conftest.c < main() { char *s = strerror(5); } EOF rm -f conftest $CC $USER_CFLAGS -o conftest conftest.c >> config.log 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_STRERROR,,[Define if strerror available]) else AC_MSG_RESULT(no) AC_MSG_CHECKING([for sys_errlist]) rm -f conftest.c changequote(,) cat > conftest.c < main() { extern char *sys_errlist[]; printf("%s\n", sys_errlist[34]); } EOF changequote([,]) rm -f conftest $CC $USER_CFLAGS -o conftest conftest.c > config.log 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_SYSERRLIST,,[Define if syserrlist available]) else AC_MSG_RESULT(no) fi fi rm -f conftest conftest.c ])dnl dnl define(PAC_TEST_MPIR_STATUS_SET_BYTES,[ AC_MSG_CHECKING(if MPIR_Status_set_bytes is defined) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_STATUS_SET_BYTES,,[Define if status set bytes available]) else AC_MSG_RESULT(no) fi rm -f conftest mpitest.c ])dnl define(PAC_TEST_MPIU_FUNCS,[ AC_MSG_CHECKING(support for MPICH2 memory macros) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_MPIU_FUNCS,1,[Define if MPICH2 memory tracing macros defined]) else AC_MSG_RESULT(no) fi rm -f conftest mpitest.c ])dnl dnl define(PAC_TEST_MPI_GREQUEST,[ AC_MSG_CHECKING(support for generalized requests) rm -f mpitest.c cat > mpitest.c < /dev/null 2>&1 if test -x conftest ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_MPI_GREQUEST,1,[Define if generalized requests avaliable]) DEFINE_HAVE_MPI_GREQUEST="#define HAVE_MPI_GREQUEST 1" else AC_MSG_RESULT(no) fi rm -f conftest mpitest.c ])dnl armci-mpi/m4/aclocal_f77new.m40000644000175000017500000000307112662706250015570 0ustar mbanckmbanckdnl /*D dnl PAC_F77_WORKS_WITH_CPP dnl dnl Checks if Fortran 77 compiler works with C preprocessor dnl dnl Most systems allow the Fortran compiler to process .F and .F90 files dnl using the C preprocessor. However, some systems either do not dnl allow this or have serious bugs (OSF Fortran compilers have a bug dnl that generates an error message from cpp). The following test dnl checks to see if .F works, and if not, whether "cpp -P -C" can be used dnl D*/ AC_DEFUN([PAC_F77_WORKS_WITH_CPP],[ AC_REQUIRE([AC_PROG_CPP]) AC_MSG_CHECKING([whether Fortran 77 compiler processes .F files with C preprocessor]) AC_LANG_PUSH([Fortran 77]) saved_f77_ext=${ac_ext} ac_ext="F" saved_FFLAGS="$FFLAGS" FFLAGS="$FFLAGS $CPPFLAGS" AC_LANG_CONFTEST([ AC_LANG_SOURCE([ program main #define ASIZE 10 integer a(ASIZE) end ]) ]) AC_COMPILE_IFELSE([],[ pac_cv_f77_accepts_F=yes ifelse([$1],[],[],[$1=""]) ],[ pac_cv_f77_accepts_F=no ifelse([$1],[],[:],[$1="false"]) ]) # Restore Fortran 77's ac_ext but not FFLAGS ac_ext="$saved_f77_ext" if test "$pac_cv_f77_accepts_F" != "yes" ; then pac_cpp_f77="$ac_cpp -C -P conftest.F > conftest.$ac_ext" PAC_RUNLOG_IFELSE([$pac_cpp_f77],[ if test -s conftest.${ac_ext} ; then AC_COMPILE_IFELSE([],[ pac_cv_f77_accepts_F="no, use cpp" ifelse([$1],[],[],[$1="$CPP -C -P"]) ],[]) rm -f conftest.${ac_ext} fi ],[]) fi FFLAGS="$saved_FFLAGS" rm -f conftest.F AC_LANG_POP([Fortran 77]) AC_MSG_RESULT([$pac_cv_f77_accepts_F]) ]) armci-mpi/m4/aclocal_subcfg.m40000644000175000017500000001275712662706250015737 0ustar mbanckmbanckdnl PAC_RESET_ALL_FLAGS - Reset precious flags to those set by the user AC_DEFUN([PAC_RESET_ALL_FLAGS],[ if test "$FROM_MPICH2" = "yes" ; then CFLAGS="$USER_CFLAGS" CPPFLAGS="$USER_CPPFLAGS" CXXFLAGS="$USER_CXXFLAGS" FFLAGS="$USER_FFLAGS" FCFLAGS="$USER_FCFLAGS" LDFLAGS="$USER_LDFLAGS" LIBS="$USER_LIBS" fi ]) dnl PAC_RESET_LINK_FLAGS - Reset precious link flags to those set by the user AC_DEFUN([PAC_RESET_LINK_FLAGS],[ if test "$FROM_MPICH2" = "yes" ; then LDFLAGS="$USER_LDFLAGS" LIBS="$USER_LIBS" fi ]) dnl Sandbox configure with additional arguments dnl Usage: PAC_CONFIG_SUBDIR_ARGS(subdir,configure-args,action-if-success,action-if-failure) dnl dnl The subconfigure argument list is created based on "ac_precious_vars" dnl instead of explicitly use of well-known Makefile variables, like dnl CC/CFLAGS/CPPFLAGS..., this generalization is effective as long as dnl calling configure.in declares the needed variables to be passed down dnl to subconfigure as "precious" appropriately. The precious variable dnl can be created in the following ways: dnl 1) implicit declaration through use of autoconf macros, like dnl AC_PROG_CC (declares CC/CFLAGS/CPPFLAGS/LIBS/LDFLAGS), or dnl AC_PROG_F77 (declares F77/FFLAGS/FLIBS) ... dnl which are in turns invoked by other subconfigure. dnl When in doubt, check "ac_precious_var" in the calling configure. dnl 2) explicit "precious" declaration through AC_ARG_VAR. dnl Without correct "precious" declaration in the calling configure.in, dnl there would be variables not being included in the subconfigure dnl argument list. dnl dnl Note: I suspect this DEFUN body is underquoted in places, but it does not dnl seem to cause problems in practice yet. [goodell@ 2010-05-18] AC_DEFUN([PAC_CONFIG_SUBDIR_ARGS],[ AC_MSG_NOTICE([===== configuring $1 =====]) PAC_MKDIRS($1) pac_abs_srcdir=`(cd $srcdir && pwd)` if test -f $pac_abs_srcdir/$1/setup ; then . $pac_abs_srcdir/$1/setup fi pac_subconfigure_file="$pac_abs_srcdir/$1/configure" if test -x $pac_subconfigure_file ; then pac_subconfig_args="$2" # Set IFS so ac_configure_args can be tokenized # with extra " " tokens being skipped. saved_IFS="$IFS" IFS="'" for pac_arg in $ac_configure_args ; do case "$pac_arg" in # Ignore any null and leading blank strings. ""|" "*) ;; *) pac_pval="" # Restore saved IFS so ac_precious_vars which has # " " as separator can be correctly tokenized IFS="$saved_IFS" for pac_pvar in $ac_precious_vars ; do # check if configure argument token contains the # precious variable, i.e. "name_of_prec_var=". pvar_in_arg=`echo $pac_arg | grep "$pac_pvar="` if test "X$pvar_in_arg" != "X" ; then # check if current precious variable is set in env eval pvar_set=\${$pac_pvar+set} if test "$pvar_set" = "set" ; then # Append 'name_of_prec_var=value_of_prec_var' # to the subconfigure arguments list, where # value_of_prec_var is fetched from the env. eval pac_pval=\${$pac_pvar} pac_subconfig_args="$pac_subconfig_args '$pac_pvar=$pac_pval'" break fi fi done # since the precious variable is not set in the env., # append the corresponding configure argument token # to the subconfigure argument list. if test "X$pac_pval" = "X" ; then pac_subconfig_args="$pac_subconfig_args '$pac_arg'" fi # reset "'" as IFS to process ac_configure_args saved_IFS="$IFS" IFS="'" ;; esac done # Restore IFS. IFS="$saved_IFS" dnl echo "pac_subconfig_args = |$pac_subconfig_args|" dnl Add option to disable configure options checking if test "$enable_option_checking" = no ; then pac_subconfig_args="$pac_subconfig_args --disable-option-checking" fi AC_MSG_NOTICE([executing: $pac_subconfigure_file $pac_subconfig_args]) if (cd $1 && eval $pac_subconfigure_file $pac_subconfig_args) ; then ifelse([$3],[],[:],[$3]) else ifelse([$4],[],[:],[$4]) fi else if test -e $pac_subconfigure_file ; then AC_MSG_WARN([$pac_subconfigure_file exists but is not executable]) else AC_MSG_WARN([$pac_subconfigure_file does not exist]) fi fi AC_MSG_NOTICE([===== done with $1 configure =====]) # Check for any localdefs files. These may be created, so we # look in the local directory first. if test -f $1/localdefs ; then . $1/localdefs elif test -f $pac_abs_srcdir/$1/localdefs ; then . $pac_abs_srcdir/$1/localdefs fi ]) dnl Sandbox configure dnl Usage: PAC_CONFIG_SUBDIR(subdir,action-if-success,action-if-failure) AC_DEFUN([PAC_CONFIG_SUBDIR],[PAC_CONFIG_SUBDIR_ARGS([$1],[],[$2],[$3])]) armci-mpi/README.md0000644000175000017500000001654412663426407013507 0ustar mbanckmbanck# Authors James Dinan (MPI-2 implementation) Jeff Hammond (MPI-3 implementation) # Introduction This project provides a full, high performance, portable implementation of the ARMCI runtime system using MPI's remote memory access (RMA) functionality. # Installing Only ARMCI-MPI ARMCI-MPI uses autoconf and must be configured before compiling: ``` $ ./configure ``` Many configure options are provided, run `configure --help` for details. After configuring the source tree, the code can be built and installed by running: $ make && make install The quality of MPI-RMA implementations varies. As of August, 2011 the following MPI-2 implementations are known to work correctly with ARMCI-MPI: * MPICH2 and MPICH 3+ * MVAPICH2 1.6 * Cray MPI on Cray XE6 * IBM MPI on BG/P (set `ARMCI_STRIDED_METHOD=IOV` and `ARMCI_IOV_METHOD=BATCHED` for _performance reasons_) * OpenMPI 1.5.4 (set `ARMCI_STRIDED_METHOD=IOV` and `ARMCI_IOV_METHOD=BATCHED` for _correctness reasons_) The following MPI-2 implementations are known to fail with ARMCI-MPI: * MVAPICH2 prior to 1.6 As of April 2014, the following MPI-3 implementations are know to work correctly with ARMCI-MPI (`mpi3rma` branch): * MPICH 3.0.4 and later on Mac, Linux SMPs and SGI SMPs. * MVAPICH2 2.0a and later on Linux InfiniBand clusters. * CrayMPI 6.1.0 and later on Cray XC30. * SGI MPT 2.09 on SGI SMPs. * OpenMPI development version on Mac (set `ARMCI_STRIDED_METHOD=IOV` and `ARMCI_IOV_METHOD=BATCHED`) Note that a bug in MPICH that propagated to MVAPICH2, Cray MPI and Intel MPI affects correctness when windows are backed by shared-memory. This bug affects `ARMCI_Rmw` and is avoided with the default settings, which use `MPI_Win_create`. This may negatively affect performance in some cases and prevents one from using Casper. To utilize `MPI_Win_allocate`, do one of the following: * Build with the `--enable-win-allocate` option to `configure`. * Set `ARMCI_USE_WIN_ALLOCATE=1` in your runtime environment. # Installing Global Arrays with ARMCI-MPI ARMCI-MPI2 has been tested with GA 5.0.2. To build GA with ARMCI-MPI2, rename this directory to "armci" and substitute it for the "armci" directory in the GA distribution. Configure and build GA as usual; no special flags are required. To build GA 5.2 with ARMCI-MPI (any version), use the configure option `--with-armci=$(PATH_TO_ARMCI_MPI)` and make sure that you use the same MPI implementation with GA that was used to compile ARMCI-MPI. ARMCI-MPI3 has been tested extensively with GA 5.2 and 5.3. # The ARMCI-MPI Test Suite ARMCI-MPI includes a set of testing and benchmark programs located under `tests/` and `benchmarks/`. These programs can be compiled and run via: ``` $ make check MPIEXEC="mpiexec -n 4" ``` The `MPIEXEC` variable is optional and is used to override the default MPI launch command. If you want only to build the test suite, the following target can be used: ``` $ make checkprogs ``` # ARMCI-MPI Errata Direct access to local buffers: * Because of MPI-2's semantics, you are not allowed to access shared memory directly, it must be through put/get. Alternatively you can use the new ARMCI_Access_begin/end() functions. * MPI-3 allows direct access provided one uses a synchronization operation afterwards. The ARMCI_Access_begin/end() functions are also valid. Progress semantics: * On some MPI implementations and networks you may need to enable implicit progress. In many cases this is done through an environment variable. For MPICH2: set `MPICH_ASYNC_PROGRESS`; for MVAPICH2 recompile with `--enable-async-progress` and set `MPICH_ASYNC_PROGRESS`; set `DCMF_INTERRUPTS=1` for MPI on BGP; etc. See [this page](https://github.com/jeffhammond/HPCInfo/tree/master/mpi#asynchronous-progress) for more information on activating asynchronous progress in MPI. However, we find that most platforms show no improvement and often a decrease in performance, provided the application makes calls to GA/ARMCI/MPI frequently enough on all processes. # Environment Variables: Boolean environment variables are enabled when set to a value beginning with 't', 'T', 'y', 'Y', or '1'; any other value is interpreted as false. ##Debugging Options ARMCI_VERBOSE (boolean) Enable extra status output from ARMCI-MPI. ARMCI_DEBUG_ALLOC (boolean) Turn on extra shared allocation debugging. ARMCI_FLUSH_BARRIERS (boolean) (deprecated) Enable/disable extra communication flushing in ARMCI_Barrier. Extra flushes are present to help make unsafe DLA safer. (This option is deprecated with the ARMCI-MPI3 implementation.) ## Performance Options ARMCI_CACHE_RANK_TRANSLATION (boolean) Create a table to more quickly translate between absolute and group ranks. ARMCI_PROGRESS_THREAD (boolean) Create a Pthread to poke the MPI progress engine. ARMCI_PROGRESS_USLEEP (int) Argument to `usleep()` to pause the progress polling loop. ## Noncollective Groups ARMCI_NONCOLLECTIVE_GROUPS (boolean) Enable noncollective ARMCI group formation; group creation is collective on the output group rather than the parent group. ## Shared Buffer Protection ARMCI_SHR_BUF_METHOD = { COPY (default), NOGUARD } ARMCI policy for managing shared origin buffers in communication operations: lock the buffer (unsafe, but fast), copy the buffer (safe), or don't guard the buffer - assume that the system is cache coherent and MPI supports unlocked load/store. ## Strided Options ARMCI_STRIDED_METHOD = { DIRECT (default), IOV } Select the method for processing strided operations. ## I/O Vector Options ARMCI_IOV_METHOD = { AUTO (default), CONSRV, BATCHED, DIRECT } Select the IO vector communication strategy: automatic; a "conservative" implementation that does lock/unlock around each operation; an implementation that issues batches of operations within a single lock/unlock epoch; and a direct implementation that generates datatypes for the origin and target and issues a single operation using them. ARMCI_IOV_CHECKS (boolean) Enable (expensive) IOV safety/debugging checks (not recommended for performance runs). ARMCI_IOV_BATCHED_LIMIT = { 0 (default), 1, ... } Set the maximum number of one-sided operations per epoch for the BATCHED IOV method. Zero (default) is unlimited. # Status Right now, we are seeing failures caused by OpenMPI bugs, not because ARMCI-MPI itself is broken. * `master`: [![Build Status](https://travis-ci.org/jeffhammond/armci-mpi.svg?branch=master)](https://travis-ci.org/jeffhammond/armci-mpi) * `mpi2rma`: [![Build Status](https://travis-ci.org/jeffhammond/armci-mpi.svg?branch=mpi2rma)](https://travis-ci.org/jeffhammond/armci-mpi) * `mpi2rma-plus-rmw`: [![Build Status](https://travis-ci.org/jeffhammond/armci-mpi.svg?branch=mpi2rma-plus-rmw)](https://travis-ci.org/jeffhammond/armci-mpi) * `mpi3rma`: [![Build Status](https://travis-ci.org/jeffhammond/armci-mpi.svg?branch=mpi3rma)](https://travis-ci.org/jeffhammond/armci-mpi) The `master` branch is still only for MPI-2 RMA. The `mpi2rma` branch is essentially the same, except it is ABI-compatible with the MPI-3 branch. The `mpi2rma-plus-rmw` uses mostly MPI-2 features except for MPI-3 atomics. Because it uses MPI-2 RMA synchronization, it is _conservative_ and thus may work with an otherwise buggy implementation of MPI-3 RMA. It exists primarily for historical purposes. The `mpi3rma` branch is what one should use on the majority of platforms, provided MPI-3 RMA is working. armci-mpi/autogen.sh0000755000175000017500000000012712662706250014213 0ustar mbanckmbanck#! /bin/sh autoreconf=${AUTORECONF:-autoreconf} $autoreconf ${autoreconf_args:-"-vif"} armci-mpi/.travis.yml0000644000175000017500000000405712663426407014335 0ustar mbanckmbancksudo: false language: c os: # osx starts faster because homebrew installs beat building from source - osx - linux compiler: # nothing in ARMCI-MPI should be compiler-dependent, # so test with the more strict of the two... - clang #- gcc matrix: allow_failures: - env: MPI_IMPL=openmpi - env: MPI_IMPL=openmpi ARMCI_STRIDED_METHOD=DIRECT ARMCI_IOV_METHOD=DIRECT ARMCI_USE_WIN_ALLOCATE=0 env: # # MPICH # # with datatypes - MPI_IMPL=mpich ARMCI_STRIDED_METHOD=DIRECT ARMCI_IOV_METHOD=DIRECT ARMCI_USE_WIN_ALLOCATE=0 - MPI_IMPL=mpich ARMCI_STRIDED_METHOD=DIRECT ARMCI_IOV_METHOD=DIRECT ARMCI_USE_WIN_ALLOCATE=1 # without datatypes - MPI_IMPL=mpich ARMCI_STRIDED_METHOD=IOV ARMCI_IOV_METHOD=BATCHED ARMCI_USE_WIN_ALLOCATE=0 - MPI_IMPL=mpich ARMCI_STRIDED_METHOD=IOV ARMCI_IOV_METHOD=BATCHED ARMCI_USE_WIN_ALLOCATE=1 # # Open-MPI # # with datatypes - MPI_IMPL=openmpi ARMCI_STRIDED_METHOD=DIRECT ARMCI_IOV_METHOD=DIRECT ARMCI_USE_WIN_ALLOCATE=0 - MPI_IMPL=openmpi ARMCI_STRIDED_METHOD=DIRECT ARMCI_IOV_METHOD=DIRECT ARMCI_USE_WIN_ALLOCATE=1 # deal with ordering issue - MPI_IMPL=openmpi ARMCI_STRIDED_METHOD=DIRECT ARMCI_IOV_METHOD=DIRECT ARMCI_NO_FLUSH_LOCAL=1 ARMCI_USE_WIN_ALLOCATE=0 - MPI_IMPL=openmpi ARMCI_STRIDED_METHOD=DIRECT ARMCI_IOV_METHOD=DIRECT ARMCI_NO_FLUSH_LOCAL=1 ARMCI_USE_WIN_ALLOCATE=1 # without datatypes - MPI_IMPL=openmpi ARMCI_STRIDED_METHOD=IOV ARMCI_IOV_METHOD=BATCHED ARMCI_USE_WIN_ALLOCATE=0 - MPI_IMPL=openmpi ARMCI_STRIDED_METHOD=IOV ARMCI_IOV_METHOD=BATCHED ARMCI_USE_WIN_ALLOCATE=1 before_install: - export TRAVIS_ROOT=$HOME/travis - mkdir $TRAVIS_ROOT - sh ./travis/install-autotools.sh $TRAVIS_ROOT install: - sh ./travis/install-mpi.sh $TRAVIS_ROOT $MPI_IMPL script: - sh ./travis/build-run.sh $TRAVIS_ROOT $MPI_IMPL after_failure: - cat ./config.log - cat ./test-suite.log - find . -name "*.log" -exec head -n 100 {} ";" armci-mpi/COPYRIGHT0000644000175000017500000000455712663426407013524 0ustar mbanckmbanck The following is a notice of limited availability of the code, and disclaimer which must be included in the prologue of the code and in all source listings of the code. Copyright (c) 2010-2013 Mathematics and Computer Science, Argonne National Laboratory Copyright (c) 2010-2014 Argonne Leadership Computing Facility, Argonne National Laboratory Copyright (c) 2010 Futures Laboratory, Oak Ridge National Laboratory Copyright (c) 2014-2015 Intel Corporation Permission is hereby granted to use, reproduce, prepare derivative works, and to redistribute to others. LICENSE Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer listed in this license in the documentation and/or other materials provided with the distribution. - Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. The copyright holders provide no reassurances that the source code provided does not infringe any patent, copyright, or any other intellectual property rights of third parties. The copyright holders disclaim any liability to any recipient for claims brought against recipient by any third party for infringement of that parties intellectual property rights. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. armci-mpi/Makefile.am0000644000175000017500000000343712663426407014261 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = -I$(top_srcdir)/src EXTRA_DIST = VERSION lib_LTLIBRARIES = libarmci.la # Needed to connect with the GA build system noinst_LTLIBRARIES = libarmcii.la libarmci_la_SOURCES = src/buffer.c \ src/debug.c \ src/groups.c \ src/internals.c \ src/malloc.c \ src/gmr.c \ src/gmr-extras.c \ src/message.c \ src/message_gop.c \ src/mutex.c \ src/mutex_hdl_queue.c \ src/onesided.c \ src/onesided_nb.c \ src/rmw.c \ src/strided.c \ src/strided_nb.c \ src/topology.c \ src/util.c \ src/value_ops.c \ src/vector.c \ src/vector_nb.c \ src/init_finalize.c \ src/conflict_tree.c \ src/parmci.c libarmci_la_LDFLAGS = -version-info $(libarmci_abi_version) libarmcii_la_SOURCES = $(libarmci_la_SOURCES) libarmcii_la_LDFLAGS = $(libarmci_abi_version) include_HEADERS = src/armciconf.h src/armci.h src/armci_internals.h src/armcix.h src/conflict_tree.h src/debug.h src/gmr.h src/message.h src/mp3.h bin_PROGRAMS = check_PROGRAMS = TESTS = XFAIL_TESTS = MPIEXEC = mpiexec -n 2 LOG_COMPILER=$(MPIEXEC) include benchmarks/Makefile.mk include tests/Makefile.mk .PHONY: checkprogs checkprogs: $(check_PROGRAMS) armci-mpi/configure.ac0000644000175000017500000001525312663426407014512 0ustar mbanckmbanckdnl dnl Copyright (C) 2010. See COPYRIGHT in top-level directory. dnl AC_PREREQ(2.62) AC_INIT([armci],[0.1]) AC_CONFIG_AUX_DIR(m4) AC_CONFIG_MACRO_DIR(m4) AM_INIT_AUTOMAKE([-Wall -Werror foreign 1.11 color-tests parallel-tests subdir-objects]) LT_PREREQ([2.2.6]) ## Bug in libtool adds -O2 and -g by default if test ! -z "$MPICC" ; then CC=$MPICC export CC fi PAC_PUSH_FLAG(CFLAGS) AC_PROG_CC(mpicc) AM_PROG_CC_C_O # automake 1.12 seems to require this, but automake 1.11 doesn't recognize it # must come before LT_INIT m4_ifdef([AM_PROG_AR],[AM_PROG_AR]) LT_INIT(disable-shared) PAC_POP_FLAG(CFLAGS) ## Non-verbose make m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) ## Version checks if test -s "$srcdir/VERSION" ; then . $srcdir/VERSION else AC_MSG_ERROR([Version information not found. Configuration aborted.]) fi ARMCI_VERSION=${PACKAGE_VERSION} export ARMCI_VERSION # ABI version AC_SUBST(libarmci_abi_version) # Release version # Produce a numeric version assuming the following format: # Version: [MAJ].[MIN].[REV][EXT][EXT_NUMBER] # Example: 1.0.7rc1 has # MAJ = 1 # MIN = 0 # REV = 7 # EXT = rc # EXT_NUMBER = 1 # # Converting to numeric version will convert EXT to a format number: # ALPHA (a) = 0 # BETA (b) = 1 # RC (rc) = 2 # PATCH (p) = 3 # Regular releases are treated as patch 0 # # Numeric version will have 1 digit for MAJ, 2 digits for MIN, # 2 digits for REV, 1 digit for EXT and 2 digits for EXT_NUMBER. changequote(<<,>>) V1=`expr $ARMCI_VERSION : '\([0-9]*\)\.[0-9]*\.*[0-9]*[a-zA-Z]*[0-9]*'` V2=`expr $ARMCI_VERSION : '[0-9]*\.\([0-9]*\)\.*[0-9]*[a-zA-Z]*[0-9]*'` V3=`expr $ARMCI_VERSION : '[0-9]*\.[0-9]*\.*\([0-9]*\)[a-zA-Z]*[0-9]*'` V4=`expr $ARMCI_VERSION : '[0-9]*\.[0-9]*\.*[0-9]*\([a-zA-Z]*\)[0-9]*'` V5=`expr $ARMCI_VERSION : '[0-9]*\.[0-9]*\.*[0-9]*[a-zA-Z]*\([0-9]*\)'` changequote([,]) if test "$V2" -le 9 ; then V2=0$V2 ; fi if test "$V3" = "" ; then V3=0; fi if test "$V3" -le 9 ; then V3=0$V3 ; fi if test "$V4" = "a" ; then V4=0 elif test "$V4" = "b" ; then V4=1 elif test "$V4" = "rc" ; then V4=2 elif test "$V4" = "" ; then V4=3 V5=0 elif test "$V4" = "p" ; then V4=3 fi if test "$V5" -le 9 ; then V5=0$V5 ; fi ARMCI_NUMVERSION=`expr $V1$V2$V3$V4$V5 + 0` AC_SUBST(ARMCI_NUMVERSION) AC_SUBST(ARMCI_VERSION) AC_CONFIG_HEADER(src/armciconf.h) AH_TOP([/* -*- Mode: C; c-basic-offset:4 ; -*- */ /* * (C) 2010 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #ifndef _ARMCICONF_H_ #define _ARMCICONF_H_ ]) AH_BOTTOM([#endif /* _ARMCICONF_H_ */]) PAC_ARG_STRICT PAC_CC_FUNCTION_NAME_SYMBOL ## Error checking functionality #AC_ARG_ENABLE(error-checking, #AC_HELP_STRING([--enable-error-checking],[Enable error checking functionality]), #enable_error_checking=$enableval, #enable_error_checking=yes) #if test "$enable_error_checking" = "yes" ; then #AC_DEFINE(ERROR_CHECKING,1,[Define if error checking is enabled]) #fi ## Check if __VA_ARGS__ is defined by the compiler PAC_C_MACRO_VA_ARGS ## const and restrict AC_C_CONST AC_C_RESTRICT ## Check for C99 AC_PROG_CC_C99 if test "$ac_cv_prog_cc_c99" = "no" ; then AC_ERROR([C99 not supported by the compiler]) fi AC_CHECK_HEADERS([execinfo.h stdint.h inttypes.h unistd.h time.h]) AC_TYPE_UINT8_T AX_PTHREAD([AC_DEFINE(HAVE_PTHREADS,1,[Defined when Pthread library is detected])]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" AC_CHECK_FUNC([usleep], [AC_DEFINE([HAVE_USLEEP], [1], [Define if usleep exists.])]) AC_CHECK_FUNC([nanosleep], [AC_DEFINE([HAVE_NANOSLEEP], [1], [Define if nanosleep exists.])]) ## Debugging support AC_ARG_ENABLE(g, AC_HELP_STRING([--enable-g],[Enable Debugging]), [ debug=$enableval ], [ debug=no ]) AC_MSG_CHECKING(debugging support) AC_MSG_RESULT($debug) if test "$debug" = "yes"; then CFLAGS="$CFLAGS -g -O0" fi ## Safety checks AC_ARG_ENABLE(safety-checks, AC_HELP_STRING([--disable-safety-checks],[Disable safety checks for better performance]), [ safety_enabled=$enableval ], [ safety_enabled=yes ]) AC_MSG_CHECKING(whether safety checks are enabled) AC_MSG_RESULT($safety_enabled) if test "$safety_enabled" = "no"; then AC_DEFINE(NO_SEATBELTS,1,[Defined when safety checks are disabled]) fi ## ARMCI Groups AC_ARG_ENABLE(armci-group, AC_HELP_STRING([--enable-armci-group],[Enable ARMCI subset-collective group formation]), [ armci_group_enabled=$enableval ], [ armci_group_enabled=no ]) AC_MSG_CHECKING(whether ARMCI subset-collective group formation is enabled) AC_MSG_RESULT($armci_group_enabled) if test "$armci_group_enabled" = "yes"; then AC_DEFINE(ARMCI_GROUP,1,[Defined when ARMCI subset-collective group formation is enabled]) fi ## Make explicit progress in nonblocking operations AC_ARG_ENABLE(explicit-progress, AC_HELP_STRING([--enable-explicit-progress],[Enable explicit MPI progress during nonblocking calls]), [ explicit_progress_enabled=$enableval ], [ explicit_progress_enabled=no ]) AC_MSG_CHECKING(whether explicit MPI progress during nonblocking calls is enabled) AC_MSG_RESULT($explicit_progress_enabled) if test "$explicit_progress_enabled" = "yes"; then AC_DEFINE(EXPLICIT_PROGRESS,1,[Defined when explicit MPI progress during nonblocking calls is enabled]) fi ## Active MPI_Win_allocate when we know it works AC_ARG_ENABLE(win-allocate, AC_HELP_STRING([--enable-win-allocate],[Use MPI_WIN_ALLOCATE.]), [ win_allocate_enabled=$enableval ], [ win_allocate_enabled=no ]) AC_MSG_CHECKING(whether MPI_WIN_ALLOCATE will be used) AC_MSG_RESULT($win_allocate_enabled) if test "$win_allocate_enabled" = "yes"; then AC_DEFINE(USE_WIN_ALLOCATE,1,[Defined when the use of MPI_WIN_ALLOCATE is enabled]) fi # Check for support for weak symbols. AC_ARG_ENABLE(weak-symbols, AC_HELP_STRING([--enable-weak-symbols], [Use weak symbols to implement PARMCI routines (default)]),, enable_weak_symbols=yes) if test $enable_weak_symbols = yes ; then # Turn off weak symbols if they aren't available PAC_PROG_C_WEAK_SYMBOLS(,enable_weak_symbols=no) fi if test $enable_weak_symbols = "yes" ; then AC_DEFINE(USE_WEAK_SYMBOLS,1,[Define if weak symbols should be used]) # Check for the ability to support multiple weak symbols if test "$pac_cv_prog_c_weak_symbols" = "pragma weak" ; then PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS(AC_DEFINE(HAVE_MULTIPLE_PRAGMA_WEAK,1,[Define if multiple weak symbols may be defined])) fi fi ## Documentation AC_PATH_PROG([DOXYGEN],[doxygen],,$PATH) AC_SUBST(DOXYGEN) AC_SUBST(top_srcdir) ## Final output AC_OUTPUT(Makefile) armci-mpi/src/0000755000175000017500000000000012663426407013005 5ustar mbanckmbanckarmci-mpi/src/vector_nb.c0000644000175000017500000001311012663426407015126 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbPutV = PARMCI_NbPutV #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbPutV ARMCI_NbPutV #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbPutV as PARMCI_NbPutV #endif /* -- end weak symbols block -- */ /** Generalized I/O vector one-sided put. * * @param[in] iov Vector of transfer information. * @param[in] iov_len Length of iov. * @param[in] proc Target process. * @return Success 0, otherwise non-zero. */ int PARMCI_NbPutV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle) { int v; int blocking = 0; if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) { blocking = 1; } for (v = 0; v < iov_len; v++) { void **src_buf; int overlapping, same_alloc; if (iov[v].ptr_array_len == 0) continue; // NOP // if (iov[v].bytes == 0) continue; // NOP // overlapping = ARMCII_Iov_check_overlap(iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes); same_alloc = ARMCII_Iov_check_same_allocation(iov[v].dst_ptr_array, iov[v].ptr_array_len, proc); ARMCII_Buf_prepare_read_vec(iov[v].src_ptr_array, &src_buf, iov[v].ptr_array_len, iov[v].bytes); ARMCII_Iov_op_dispatch(ARMCII_OP_PUT, src_buf, iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes, 0, overlapping, same_alloc, proc, blocking); ARMCII_Buf_finish_read_vec(iov[v].src_ptr_array, src_buf, iov[v].ptr_array_len, iov[v].bytes); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = proc; } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbGetV = PARMCI_NbGetV #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbGetV ARMCI_NbGetV #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbGetV as PARMCI_NbGetV #endif /* -- end weak symbols block -- */ /** Generalized I/O vector one-sided get. * * @param[in] iov Vector of transfer information. * @param[in] iov_len Length of iov. * @param[in] proc Target process. * @return Success 0, otherwise non-zero. */ int PARMCI_NbGetV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle) { int v; int blocking = 0; if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) { blocking = 1; } for (v = 0; v < iov_len; v++) { void **dst_buf; int overlapping, same_alloc; if (iov[v].ptr_array_len == 0) continue; // NOP // if (iov[v].bytes == 0) continue; // NOP // // overlapping = ARMCII_Iov_check_overlap(iov[v].src_ptr_array, iov[v].ptr_array_len, iov[v].bytes); overlapping = ARMCII_Iov_check_overlap(iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes); same_alloc = ARMCII_Iov_check_same_allocation(iov[v].src_ptr_array, iov[v].ptr_array_len, proc); ARMCII_Buf_prepare_write_vec(iov[v].dst_ptr_array, &dst_buf, iov[v].ptr_array_len, iov[v].bytes); ARMCII_Iov_op_dispatch(ARMCII_OP_GET, iov[v].src_ptr_array, dst_buf, iov[v].ptr_array_len, iov[v].bytes, 0, overlapping, same_alloc, proc, blocking); ARMCII_Buf_finish_write_vec(iov[v].dst_ptr_array, dst_buf, iov[v].ptr_array_len, iov[v].bytes); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = proc; } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbAccV = PARMCI_NbAccV #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbAccV ARMCI_NbAccV #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbAccV as PARMCI_NbAccV #endif /* -- end weak symbols block -- */ /** Generalized I/O vector one-sided accumulate. * * @param[in] iov Vector of transfer information. * @param[in] iov_len Length of iov. * @param[in] proc Target process. * @return Success 0, otherwise non-zero. */ int PARMCI_NbAccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle) { int v; int blocking = 0; if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) { blocking = 1; } for (v = 0; v < iov_len; v++) { void **src_buf; int overlapping, same_alloc; if (iov[v].ptr_array_len == 0) continue; // NOP // if (iov[v].bytes == 0) continue; // NOP // overlapping = ARMCII_Iov_check_overlap(iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes); same_alloc = ARMCII_Iov_check_same_allocation(iov[v].dst_ptr_array, iov[v].ptr_array_len, proc); ARMCII_Buf_prepare_acc_vec(iov[v].src_ptr_array, &src_buf, iov[v].ptr_array_len, iov[v].bytes, datatype, scale); ARMCII_Iov_op_dispatch(ARMCII_OP_ACC, src_buf, iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes, datatype, overlapping, same_alloc, proc, blocking); ARMCII_Buf_finish_acc_vec(iov[v].src_ptr_array, src_buf, iov[v].ptr_array_len, iov[v].bytes); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = proc; } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return 0; } armci-mpi/src/debug.c0000644000175000017500000000443312662706250014237 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include /* Set the default debugging message classes to enable. */ unsigned DEBUG_CATS_ENABLED = DEBUG_CAT_NONE; // DEBUG_CAT_ALL; // DEBUG_CAT_ALLOC; // DEBUG_CAT_ALLOC | DEBUG_CAT_MEM_REGION; // DEBUG_CAT_MUTEX; // DEBUG_CAT_GROUPS; /** Print an assertion failure message and abort the program. */ void ARMCII_Assert_fail(const char *expr, const char *msg, const char *file, int line, const char *func) { int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (msg == NULL) fprintf(stderr, "[%d] ARMCI assert fail in %s() [%s:%d]: \"%s\"\n", rank, func, file, line, expr); else fprintf(stderr, "[%d] ARMCI assert fail in %s() [%s:%d]: \"%s\"\n" "[%d] Message: \"%s\"\n", rank, func, file, line, expr, rank, msg); #if HAVE_EXECINFO_H { #include const int SIZE = 100; int j, nframes; void *frames[SIZE]; char **symbols; nframes = backtrace(frames, SIZE); symbols = backtrace_symbols(frames, nframes); if (symbols == NULL) perror("Backtrace failure"); fprintf(stderr, "[%d] Backtrace:\n", rank); for (j = 0; j < nframes; j++) fprintf(stderr, "[%d] %2d - %s\n", rank, nframes-j-1, symbols[j]); free(symbols); } #endif fflush(NULL); { double stall = MPI_Wtime(); while (MPI_Wtime() - stall < 1) ; } MPI_Abort(MPI_COMM_WORLD, -1); } /** Print a debugging message. */ void ARMCII_Dbg_print_impl(const char *func, const char *format, ...) { va_list etc; int disp; char string[500]; disp = 0; disp += snprintf(string, 500, "[%d] %s: ", ARMCI_GROUP_WORLD.rank, func); va_start(etc, format); disp += vsnprintf(string+disp, 500-disp, format, etc); va_end(etc); fprintf(stderr, "%s", string); } /** Print an ARMCI warning message. */ void ARMCII_Warning(const char *fmt, ...) { va_list etc; int disp; char string[500]; disp = 0; disp += snprintf(string, 500, "[%d] ARMCI Warning: ", ARMCI_GROUP_WORLD.rank); va_start(etc, fmt); disp += vsnprintf(string+disp, 500-disp, fmt, etc); va_end(etc); fprintf(stderr, "%s", string); fflush(NULL); } armci-mpi/src/mp3.fh0000644000175000017500000000024712662706250014022 0ustar mbanckmbanck#include "mpif.h" #define MP_TIMER() mpi_wtime() #define MP_FINALIZE() mpi_finalize(ierr) #ifndef MP_DEFINES_ONLY integer ierr call mpi_init(ierr) #endif armci-mpi/src/mp3def.fh0000644000175000017500000000010112662706250014466 0ustar mbanckmbanck#define MP_DEFINES_ONLY #include "mp3.fh" #undef MP_DEFINES_ONLY armci-mpi/src/strided.c0000644000175000017500000006021412663426407014612 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include /** Convert an ARMCI strided access description into an MPI subarray datatype. * * @param[in] stride_array Array of strides * @param[in] count Array of transfer counts * @param[in] stride_levels Number of levels of striding * @param[in] old_type Type of the data element described by count and stride_array * @param[out] new_type New MPI type for the given strided access */ void ARMCII_Strided_to_dtype(int stride_array[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, MPI_Datatype old_type, MPI_Datatype *new_type) { int sizes [stride_levels+1]; int subsizes[stride_levels+1]; int starts [stride_levels+1]; int i, old_type_size; MPI_Type_size(old_type, &old_type_size); /* Eliminate counts that don't count (all 1 counts at the end) */ for (i = stride_levels+1; (i > 0) && (stride_levels > 0) && (count[i-1] == 1); i--) stride_levels--; /* A correct strided spec should me monotonic increasing and stride_array[i+1] should be a multiple of stride_array[i]. */ if (stride_levels > 0) { for (i = 1; i < stride_levels; i++) { ARMCII_Assert(stride_array[i] >= stride_array[i-1]); /* This assertion is violated by what seems to be valid usage resulting from * the new GA API call nga_strided_get during the stride test in GA 5.2. * ARMCII_Assert((stride_array[i] % stride_array[i-1]) == 0); */ } } /* Test for a contiguous transfer */ if (stride_levels == 0) { int elem_count = count[0]/old_type_size; ARMCII_Assert((count[0] % old_type_size) == 0); MPI_Type_contiguous(elem_count, old_type, new_type); } /* Transfer is non-contiguous */ else { for (i = 0; i < stride_levels+1; i++) starts[i] = 0; sizes [stride_levels] = stride_array[0]/old_type_size; subsizes[stride_levels] = count[0]/old_type_size; ARMCII_Assert((stride_array[0] % old_type_size) == 0); ARMCII_Assert((count[0] % old_type_size) == 0); for (i = 1; i < stride_levels; i++) { /* Convert strides into dimensions by dividing out contributions from lower dims */ sizes [stride_levels-i] = stride_array[i]/stride_array[i-1]; subsizes[stride_levels-i] = count[i]; /* This assertion is violated by what seems to be valid usage resulting from * the new GA API call nga_strided_get during the stride test in GA 5.2. * ARMCII_Assert_msg((stride_array[i] % stride_array[i-1]) == 0, "Invalid striding"); */ } sizes [0] = count[stride_levels]; subsizes[0] = count[stride_levels]; MPI_Type_create_subarray(stride_levels+1, sizes, subsizes, starts, MPI_ORDER_C, old_type, new_type); } } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_PutS = PARMCI_PutS #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_PutS ARMCI_PutS #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_PutS as PARMCI_PutS #endif /* -- end weak symbols block -- */ /** Blocking operation that transfers data from the calling process to the * memory of the remote process. The data transfer is strided and blocking. * * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * @param[in] proc Remote process ID (destination). * * @return Zero on success, error code otherwise. */ int PARMCI_PutS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc) { int err; if (ARMCII_GLOBAL_STATE.strided_method == ARMCII_STRIDED_DIRECT) { void *src_buf = NULL; gmr_t *mreg, *gmr_loc = NULL; MPI_Datatype src_type, dst_type; /* COPY: Guard shared buffers */ if (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY) { gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); if (gmr_loc != NULL) { int i, size; for (i = 1, size = count[0]; i < stride_levels+1; i++) size *= count[i]; MPI_Alloc_mem(size, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); armci_write_strided(src_ptr, stride_levels, src_stride_ar, count, src_buf); MPI_Type_contiguous(size, MPI_BYTE, &src_type); } } else { /* Jeff: WIN_UNIFIED should allow overlap to work but we * do a memory barrier here to be safe. */ gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); gmr_sync(gmr_loc); } /* NOGUARD: If src_buf hasn't been assigned to a copy, the strided source * buffer is going to be used directly. */ if (src_buf == NULL) { src_buf = src_ptr; ARMCII_Strided_to_dtype(src_stride_ar, count, stride_levels, MPI_BYTE, &src_type); } ARMCII_Strided_to_dtype(dst_stride_ar, count, stride_levels, MPI_BYTE, &dst_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); mreg = gmr_lookup(dst_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid shared pointer"); gmr_put_typed(mreg, src_buf, 1, src_type, dst_ptr, 1, dst_type, proc); gmr_flush(mreg, proc, 1); /* flush_local */ MPI_Type_free(&src_type); MPI_Type_free(&dst_type); /* COPY: Free temporary buffer */ if (src_buf != src_ptr) { MPI_Free_mem(src_buf); } err = 0; } else { armci_giov_t iov; ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels); err = PARMCI_PutV(&iov, 1, proc); free(iov.src_ptr_array); free(iov.dst_ptr_array); } return err; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_GetS = PARMCI_GetS #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_GetS ARMCI_GetS #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_GetS as PARMCI_GetS #endif /* -- end weak symbols block -- */ /** Blocking operation that transfers data from the remote process to the * memory of the calling process. The data transfer is strided and blocking. * * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * @param[in] proc Remote process ID (destination). * * @return Zero on success, error code otherwise. */ int PARMCI_GetS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc) { int err; if (ARMCII_GLOBAL_STATE.strided_method == ARMCII_STRIDED_DIRECT) { void *dst_buf = NULL; gmr_t *mreg, *gmr_loc = NULL; MPI_Datatype src_type, dst_type; /* COPY: Guard shared buffers */ if (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY) { gmr_loc = gmr_lookup(dst_ptr, ARMCI_GROUP_WORLD.rank); if (gmr_loc != NULL) { int i, size; for (i = 1, size = count[0]; i < stride_levels+1; i++) size *= count[i]; MPI_Alloc_mem(size, MPI_INFO_NULL, &dst_buf); ARMCII_Assert(dst_buf != NULL); MPI_Type_contiguous(size, MPI_BYTE, &dst_type); } } else { /* Jeff: WIN_UNIFIED should allow overlap to work but we * do a memory barrier here to be safe. */ gmr_loc = gmr_lookup(dst_ptr, ARMCI_GROUP_WORLD.rank); gmr_sync(gmr_loc); } /* NOGUARD: If dst_buf hasn't been assigned to a copy, the strided source * buffer is going to be used directly. */ if (dst_buf == NULL) { dst_buf = dst_ptr; ARMCII_Strided_to_dtype(dst_stride_ar, count, stride_levels, MPI_BYTE, &dst_type); } ARMCII_Strided_to_dtype(src_stride_ar, count, stride_levels, MPI_BYTE, &src_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); mreg = gmr_lookup(src_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid shared pointer"); gmr_get_typed(mreg, src_ptr, 1, src_type, dst_buf, 1, dst_type, proc); gmr_flush(mreg, proc, 0); /* COPY: Finish the transfer */ if (dst_buf != dst_ptr) { armci_read_strided(dst_ptr, stride_levels, dst_stride_ar, count, dst_buf); MPI_Free_mem(dst_buf); } MPI_Type_free(&src_type); MPI_Type_free(&dst_type); err = 0; } else { armci_giov_t iov; ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels); err = PARMCI_GetV(&iov, 1, proc); free(iov.src_ptr_array); free(iov.dst_ptr_array); } return err; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_AccS = PARMCI_AccS #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_AccS ARMCI_AccS #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_AccS as PARMCI_AccS #endif /* -- end weak symbols block -- */ /** Blocking operation that accumulates data from the local process into the * memory of the remote process. The data transfer is strided and blocking. * * @param[in] datatype Type of data to be transferred. * @param[in] scale Pointer to the value that input data should be scaled by. * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * @param[in] proc Remote process ID (destination). * * @return Zero on success, error code otherwise. */ int PARMCI_AccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc) { int err; if (ARMCII_GLOBAL_STATE.strided_method == ARMCII_STRIDED_DIRECT) { void *src_buf = NULL; gmr_t *mreg, *gmr_loc = NULL; MPI_Datatype src_type, dst_type, mpi_datatype; int scaled, mpi_datatype_size; int src_size, dst_size; ARMCII_Acc_type_translate(datatype, &mpi_datatype, &mpi_datatype_size); scaled = ARMCII_Buf_acc_is_scaled(datatype, scale); /* SCALE: copy and scale if requested */ if (scaled) { armci_giov_t iov; int i, nelem; if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); for (i = 1, nelem = count[0]/mpi_datatype_size; i < stride_levels+1; i++) nelem *= count[i]; MPI_Alloc_mem(nelem*mpi_datatype_size, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); /* Shoehorn the strided information into an IOV */ ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, src_ptr, src_stride_ar, count, stride_levels); for (i = 0; i < iov.ptr_array_len; i++) ARMCII_Buf_acc_scale(iov.src_ptr_array[i], ((uint8_t*)src_buf) + i*iov.bytes, iov.bytes, datatype, scale); free(iov.src_ptr_array); free(iov.dst_ptr_array); MPI_Type_contiguous(nelem, mpi_datatype, &src_type); } /* COPY: Guard shared buffers */ else if (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY) { gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); if (gmr_loc != NULL) { int i, nelem; for (i = 1, nelem = count[0]/mpi_datatype_size; i < stride_levels+1; i++) nelem *= count[i]; MPI_Alloc_mem(nelem*mpi_datatype_size, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); armci_write_strided(src_ptr, stride_levels, src_stride_ar, count, src_buf); MPI_Type_contiguous(nelem, mpi_datatype, &src_type); } } else { /* Jeff: WIN_UNIFIED should allow overlap to work but we * do a memory barrier here to be safe. */ gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); gmr_sync(gmr_loc); } /* NOGUARD: If src_buf hasn't been assigned to a copy, the strided source * buffer is going to be used directly. */ if (src_buf == NULL) { src_buf = src_ptr; ARMCII_Strided_to_dtype(src_stride_ar, count, stride_levels, mpi_datatype, &src_type); } ARMCII_Strided_to_dtype(dst_stride_ar, count, stride_levels, mpi_datatype, &dst_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); MPI_Type_size(src_type, &src_size); MPI_Type_size(dst_type, &dst_size); ARMCII_Assert(src_size == dst_size); mreg = gmr_lookup(dst_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid shared pointer"); gmr_accumulate_typed(mreg, src_buf, 1, src_type, dst_ptr, 1, dst_type, proc); gmr_flush(mreg, proc, 1); /* flush_local */ MPI_Type_free(&src_type); MPI_Type_free(&dst_type); /* COPY/SCALE: Free temp buffer */ if (src_buf != src_ptr) { MPI_Free_mem(src_buf); } err = 0; } else { armci_giov_t iov; ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels); err = PARMCI_AccV(datatype, scale, &iov, 1, proc); free(iov.src_ptr_array); free(iov.dst_ptr_array); } return err; } /** Translate a strided operation into a more general IO Vector. * * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * * @return Zero on success, error code otherwise. */ void ARMCII_Strided_to_iov(armci_giov_t *iov, void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels) { int i; iov->bytes = count[0]; iov->ptr_array_len = 1; for (i = 0; i < stride_levels; i++) iov->ptr_array_len *= count[i+1]; iov->src_ptr_array = malloc(iov->ptr_array_len*sizeof(void*)); iov->dst_ptr_array = malloc(iov->ptr_array_len*sizeof(void*)); ARMCII_Assert((iov->src_ptr_array != NULL) && (iov->dst_ptr_array != NULL)); // Case 1: Non-strided transfer if (stride_levels == 0) { iov->src_ptr_array[0] = src_ptr; iov->dst_ptr_array[0] = dst_ptr; // Case 2: Strided transfer } else { int idx[stride_levels]; int xfer; for (i = 0; i < stride_levels; i++) idx[i] = 0; for (xfer = 0; idx[stride_levels-1] < count[stride_levels]; xfer++) { int disp_src = 0; int disp_dst = 0; ARMCII_Assert(xfer < iov->ptr_array_len); // Calculate displacements from base pointers for (i = 0; i < stride_levels; i++) { disp_src += src_stride_ar[i]*idx[i]; disp_dst += dst_stride_ar[i]*idx[i]; } // Add to the IO Vector iov->src_ptr_array[xfer] = ((uint8_t*)src_ptr) + disp_src; iov->dst_ptr_array[xfer] = ((uint8_t*)dst_ptr) + disp_dst; // Increment innermost index idx[0] += 1; // Propagate "carry" overflows outward. We're done when the outermost // index is greater than the requested count. for (i = 0; i < stride_levels-1; i++) { if (idx[i] >= count[i+1]) { idx[i] = 0; idx[i+1] += 1; } } } ARMCII_Assert(xfer == iov->ptr_array_len); } } /** Translate a strided operation into a more general IO Vector iterator. * * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * * @return ARMCI IOV iterator corresponding to the strided parameters. */ armcii_iov_iter_t *ARMCII_Strided_to_iov_iter( void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels) { int i; armcii_iov_iter_t *it = malloc(sizeof(armcii_iov_iter_t)); ARMCII_Assert(it != NULL); it->src = src_ptr; it->dst = dst_ptr; it->stride_levels = stride_levels; it->base_ptr = malloc(sizeof(int)*(4*stride_levels+1)); it->was_contiguous= 0; ARMCII_Assert( it->base_ptr != NULL ); it->src_stride_ar = &it->base_ptr[0*stride_levels]; it->dst_stride_ar = &it->base_ptr[1*stride_levels]; it->count = &it->base_ptr[2*stride_levels]; it->idx = &it->base_ptr[3*stride_levels+1]; for (i = 0; i < stride_levels; i++) { it->src_stride_ar[i] = src_stride_ar[i]; it->dst_stride_ar[i] = dst_stride_ar[i]; it->count[i] = count[i]; it->idx[i] = 0; } return it; } /** Free an iterator. * * @param[in] it IOV iterator */ void ARMCII_Iov_iter_free(armcii_iov_iter_t *it) { free(it->base_ptr); free(it); } /** Query whether the iterator has another iteration. * * @param[in] it IOV iterator * * @return True if another iteration exists */ int ARMCII_Iov_iter_has_next(armcii_iov_iter_t *it) { return ((it->idx[it->stride_levels-1] < it->count[it->stride_levels]) && (!it->was_contiguous)); } /** Get the next source/destination pointer pair from the IOV iterator. * * @param[in] it IOV iterator * @param[out] src Source adress * @param[out] dst Destination adress * * @return True if another iteration existed */ int ARMCII_Iov_iter_next(armcii_iov_iter_t *it, void **src, void **dst) { if (!ARMCII_Iov_iter_has_next(it)) { *src = NULL; *dst = NULL; return 0; } // Case 1: Non-strided transfer if (it->stride_levels == 0) { *src = src; *dst = dst; it->was_contiguous = 1; // Case 2: Strided transfer } else { int i, disp_src = 0, disp_dst = 0; // Calculate displacements from base pointers for (i = 0; i < it->stride_levels; i++) { disp_src += it->src_stride_ar[i]*it->idx[i]; disp_dst += it->dst_stride_ar[i]*it->idx[i]; } // Add to the IO Vector *src = ((uint8_t*)it->src) + disp_src; *dst = ((uint8_t*)it->dst) + disp_dst; // Increment innermost index it->idx[0] += 1; // Propagate "carry" overflows outward. We're done when the outermost // index is greater than the requested count. for (i = 0; i < it->stride_levels-1; i++) { if (it->idx[i] >= it->count[i+1]) { it->idx[i] = 0; it->idx[i+1] += 1; } } } return 1; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_PutS_flag = PARMCI_PutS_flag #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_PutS_flag ARMCI_PutS_flag #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_PutS_flag as PARMCI_PutS_flag #endif /* -- end weak symbols block -- */ /** Blocking operation that transfers data from the calling process to the * memory of the remote process. The data transfer is strided and blocking. * After the transfer completes, the given flag is set on the remote process. * * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * @param[in] flag Location of the flag buffer * @param[in] value Value to set the flag to * @param[in] proc Remote process ID (destination). * * @return Zero on success, error code otherwise. */ int PARMCI_PutS_flag(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int *flag, int value, int proc) { /* TODO: This can be optimized with a more direct implementation, especially in the * case where RMA is ordered; in that case, the Fence (Flush) is not necessary. */ PARMCI_PutS(src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, proc); PARMCI_Fence(proc); PARMCI_Put(&value, flag, sizeof(int), proc); return 1; } /* Pack strided data into a contiguous destination buffer. This is a local operation. * * @param[in] src Pointer to the strided buffer * @param[in] stride_levels Number of levels of striding * @param[in] src_stride_arr Array of length stride_levels of stride lengths * @param[in] count Array of length stride_levels+1 of the number of * units at each stride level (lowest is contiguous) * @param[in] dst Destination contiguous buffer */ void armci_write_strided(void *src, int stride_levels, int src_stride_arr[], int count[], char *dst) { armci_giov_t iov; int i; // Shoehorn the strided information into an IOV ARMCII_Strided_to_iov(&iov, src, src_stride_arr, src, src_stride_arr, count, stride_levels); for (i = 0; i < iov.ptr_array_len; i++) ARMCI_Copy(iov.src_ptr_array[i], dst + i*count[0], iov.bytes); free(iov.src_ptr_array); free(iov.dst_ptr_array); } /* Unpack strided data from a contiguous source buffer. This is a local operation. * * @param[in] src Pointer to the contiguous buffer * @param[in] stride_levels Number of levels of striding * @param[in] dst_stride_arr Array of length stride_levels of stride lengths * @param[in] count Array of length stride_levels+1 of the number of * units at each stride level (lowest is contiguous) * @param[in] dst Destination strided buffer */ void armci_read_strided(void *dst, int stride_levels, int dst_stride_arr[], int count[], char *src) { armci_giov_t iov; int i; // Shoehorn the strided information into an IOV ARMCII_Strided_to_iov(&iov, dst, dst_stride_arr, dst, dst_stride_arr, count, stride_levels); for (i = 0; i < iov.ptr_array_len; i++) ARMCI_Copy(src + i*count[0], iov.dst_ptr_array[i], iov.bytes); free(iov.src_ptr_array); free(iov.dst_ptr_array); } armci-mpi/src/value_ops.c0000644000175000017500000001426612662706250015153 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include /* Put value operations */ /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_PutValueInt = PARMCI_PutValueInt #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_PutValueInt ARMCI_PutValueInt #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_PutValueInt as PARMCI_PutValueInt #endif /* -- end weak symbols block -- */ int PARMCI_PutValueInt(int src, void *dst, int proc) { return PARMCI_Put(&src, dst, sizeof(int), proc); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_PutValueLong = PARMCI_PutValueLong #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_PutValueLong ARMCI_PutValueLong #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_PutValueLong as PARMCI_PutValueLong #endif /* -- end weak symbols block -- */ int PARMCI_PutValueLong(long src, void *dst, int proc) { return PARMCI_Put(&src, dst, sizeof(long), proc); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_PutValueFloat = PARMCI_PutValueFloat #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_PutValueFloat ARMCI_PutValueFloat #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_PutValueFloat as PARMCI_PutValueFloat #endif /* -- end weak symbols block -- */ int PARMCI_PutValueFloat(float src, void *dst, int proc) { return PARMCI_Put(&src, dst, sizeof(float), proc); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_PutValueDouble = PARMCI_PutValueDouble #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_PutValueDouble ARMCI_PutValueDouble #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_PutValueDouble as PARMCI_PutValueDouble #endif /* -- end weak symbols block -- */ int PARMCI_PutValueDouble(double src, void *dst, int proc) { return PARMCI_Put(&src, dst, sizeof(double), proc); } /* Non-blocking put operations */ /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbPutValueInt = PARMCI_NbPutValueInt #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbPutValueInt ARMCI_NbPutValueInt #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbPutValueInt as PARMCI_NbPutValueInt #endif /* -- end weak symbols block -- */ int PARMCI_NbPutValueInt(int src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPut(&src, dst, sizeof(int), proc, hdl); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbPutValueLong = PARMCI_NbPutValueLong #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbPutValueLong ARMCI_NbPutValueLong #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbPutValueLong as PARMCI_NbPutValueLong #endif /* -- end weak symbols block -- */ int PARMCI_NbPutValueLong(long src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPut(&src, dst, sizeof(long), proc, hdl); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbPutValueFloat = PARMCI_NbPutValueFloat #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbPutValueFloat ARMCI_NbPutValueFloat #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbPutValueFloat as PARMCI_NbPutValueFloat #endif /* -- end weak symbols block -- */ int PARMCI_NbPutValueFloat(float src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPut(&src, dst, sizeof(float), proc, hdl); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbPutValueDouble = PARMCI_NbPutValueDouble #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbPutValueDouble ARMCI_NbPutValueDouble #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbPutValueDouble as PARMCI_NbPutValueDouble #endif /* -- end weak symbols block -- */ int PARMCI_NbPutValueDouble(double src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPut(&src, dst, sizeof(double), proc, hdl); } /* Get value operations */ /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_GetValueInt = PARMCI_GetValueInt #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_GetValueInt ARMCI_GetValueInt #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_GetValueInt as PARMCI_GetValueInt #endif /* -- end weak symbols block -- */ int PARMCI_GetValueInt(void *src, int proc) { int val; PARMCI_Get(src, &val, sizeof(int), proc); return val; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_GetValueLong = PARMCI_GetValueLong #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_GetValueLong ARMCI_GetValueLong #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_GetValueLong as PARMCI_GetValueLong #endif /* -- end weak symbols block -- */ long PARMCI_GetValueLong(void *src, int proc) { long val; PARMCI_Get(src, &val, sizeof(long), proc); return val; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_GetValueFloat = PARMCI_GetValueFloat #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_GetValueFloat ARMCI_GetValueFloat #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_GetValueFloat as PARMCI_GetValueFloat #endif /* -- end weak symbols block -- */ float PARMCI_GetValueFloat(void *src, int proc) { float val; PARMCI_Get(src, &val, sizeof(float), proc); return val; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_GetValueDouble = PARMCI_GetValueDouble #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_GetValueDouble ARMCI_GetValueDouble #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_GetValueDouble as PARMCI_GetValueDouble #endif /* -- end weak symbols block -- */ double PARMCI_GetValueDouble(void *src, int proc) { double val; PARMCI_Get(src, &val, sizeof(double), proc); return val; } armci-mpi/src/mutex_hdl_queue.c0000644000175000017500000001475612662706250016357 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #define ARMCI_MUTEX_TAG 100 /* TODO: Make these all no-ops for sequential runs */ /** Create a group of ARMCI mutexes. Collective onthe ARMCI group. * * @param[in] count Number of mutexes on the local process. * @param[in] pgroup ARMCI group on which to create mutexes * @return Handle to the mutex group. */ armcix_mutex_hdl_t ARMCIX_Create_mutexes_hdl(int my_count, ARMCI_Group *pgroup) { int rank, nproc, max_count, i; armcix_mutex_hdl_t hdl; hdl = malloc(sizeof(struct armcix_mutex_hdl_s)); ARMCII_Assert(hdl != NULL); ARMCIX_Group_dup(pgroup, &hdl->grp); MPI_Comm_rank(hdl->grp.comm, &rank); MPI_Comm_size(hdl->grp.comm, &nproc); hdl->my_count = my_count; /* Find the max. count to determine how many windows we need. */ MPI_Allreduce(&my_count, &max_count, 1, MPI_INT, MPI_MAX, hdl->grp.comm); ARMCII_Assert_msg(max_count > 0, "Invalid number of mutexes"); hdl->max_count = max_count; hdl->windows = malloc(sizeof(MPI_Win)*max_count); if (my_count > 0) { hdl->bases = malloc(sizeof(uint8_t*)*my_count); } else { hdl->bases = NULL; } /* We need multiple windows here: one for each mutex. Otherwise performance will suffer due to exclusive access epochs. */ for (i = 0; i < max_count; i++) { int size = 0; void *base = NULL; if (i < my_count) { MPI_Alloc_mem(nproc, MPI_INFO_NULL, &hdl->bases[i]); ARMCII_Assert(hdl->bases[i] != NULL); ARMCII_Bzero(hdl->bases[i], nproc); base = hdl->bases[i]; size = nproc; } MPI_Win_create(base, size, sizeof(uint8_t), MPI_INFO_NULL, hdl->grp.comm, &hdl->windows[i]); } return hdl; } /** Destroy a group of ARMCI mutexes. Collective. * * @param[in] hdl Handle to the group that should be destroyed. * @return Zero on success, non-zero otherwise. */ int ARMCIX_Destroy_mutexes_hdl(armcix_mutex_hdl_t hdl) { int i; for (i = 0; i < hdl->max_count; i++) { MPI_Win_free(&hdl->windows[i]); } if (hdl->bases != NULL) { for (i = 0; i < hdl->my_count; i++) MPI_Free_mem(hdl->bases[i]); free(hdl->bases); } ARMCI_Group_free(&hdl->grp); free(hdl->windows); free(hdl); return 0; } /** Lock a mutex. * * @param[in] hdl Mutex group that the mutex belongs to. * @param[in] mutex Desired mutex number [0..count-1] * @param[in] world_proc Absolute ID of process where the mutex lives */ void ARMCIX_Lock_hdl(armcix_mutex_hdl_t hdl, int mutex, int world_proc) { int rank, nproc, already_locked, i, proc; uint8_t *buf; ARMCII_Assert(mutex >= 0 && mutex < hdl->max_count); MPI_Comm_rank(hdl->grp.comm, &rank); MPI_Comm_size(hdl->grp.comm, &nproc); /* User gives us the absolute ID. Translate to the rank in the mutex's group. */ proc = ARMCII_Translate_absolute_to_group(&hdl->grp, world_proc); ARMCII_Assert(proc >= 0); buf = malloc(nproc*sizeof(uint8_t)); ARMCII_Assert(buf != NULL); buf[rank] = 1; /* Get all data from the lock_buf, except the byte belonging to * me. Set the byte belonging to me to 1. */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->windows[mutex]); MPI_Put(&buf[rank], 1, MPI_BYTE, proc, rank, 1, MPI_BYTE, hdl->windows[mutex]); /* Get data to the left of rank */ if (rank > 0) { MPI_Get(buf, rank, MPI_BYTE, proc, 0, rank, MPI_BYTE, hdl->windows[mutex]); } /* Get data to the right of rank */ if (rank < nproc - 1) { MPI_Get(&buf[rank+1], nproc-1-rank, MPI_BYTE, proc, rank + 1, nproc-1-rank, MPI_BYTE, hdl->windows[mutex]); } MPI_Win_unlock(proc, hdl->windows[mutex]); ARMCII_Assert(buf[rank] == 1); for (i = already_locked = 0; i < nproc; i++) if (buf[i] && i != rank) already_locked = 1; /* Wait for notification */ if (already_locked) { MPI_Status status; ARMCII_Dbg_print(DEBUG_CAT_MUTEX, "waiting for notification [proc = %d, mutex = %d]\n", proc, mutex); MPI_Recv(NULL, 0, MPI_BYTE, MPI_ANY_SOURCE, ARMCI_MUTEX_TAG+mutex, hdl->grp.comm, &status); } ARMCII_Dbg_print(DEBUG_CAT_MUTEX, "lock acquired [proc = %d, mutex = %d]\n", proc, mutex); free(buf); } /** Attempt to lock a mutex (implemented as a blocking call). * * @param[in] hdl Mutex group that the mutex belongs to. * @param[in] mutex Desired mutex number [0..count-1] * @param[in] world_proc Absolute ID of process where the mutex lives * @return 0 on success, non-zero on failure */ int ARMCIX_Trylock_hdl(armcix_mutex_hdl_t hdl, int mutex, int world_proc) { ARMCII_Assert(mutex >= 0 && mutex < hdl->max_count); ARMCIX_Lock_hdl(hdl, mutex, world_proc); return 0; } /** Unlock a mutex. * * @param[in] hdl Mutex group that the mutex belongs to. * @param[in] mutex Desired mutex number [0..count-1] * @param[in] world_proc Absolute ID of process where the mutex lives */ void ARMCIX_Unlock_hdl(armcix_mutex_hdl_t hdl, int mutex, int world_proc) { int rank, nproc, i, proc; uint8_t *buf; ARMCII_Assert(mutex >= 0 && mutex < hdl->max_count); MPI_Comm_rank(hdl->grp.comm, &rank); MPI_Comm_size(hdl->grp.comm, &nproc); proc = ARMCII_Translate_absolute_to_group(&hdl->grp, world_proc); ARMCII_Assert(proc >= 0); buf = malloc(nproc*sizeof(uint8_t)); buf[rank] = 0; /* Get all data from the lock_buf, except the byte belonging to * me. Set the byte belonging to me to 0. */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->windows[mutex]); MPI_Put(&buf[rank], 1, MPI_BYTE, proc, rank, 1, MPI_BYTE, hdl->windows[mutex]); /* Get data to the left of rank */ if (rank > 0) { MPI_Get(buf, rank, MPI_BYTE, proc, 0, rank, MPI_BYTE, hdl->windows[mutex]); } /* Get data to the right of rank */ if (rank < nproc - 1) { MPI_Get(&buf[rank+1], nproc-1-rank, MPI_BYTE, proc, rank + 1, nproc-1-rank, MPI_BYTE, hdl->windows[mutex]); } MPI_Win_unlock(proc, hdl->windows[mutex]); ARMCII_Assert(buf[rank] == 0); /* Notify the next waiting process, starting to my right for fairness */ for (i = 1; i < nproc; i++) { int p = (rank + i) % nproc; if (buf[p] == 1) { ARMCII_Dbg_print(DEBUG_CAT_MUTEX, "notifying %d [proc = %d, mutex = %d]\n", p, proc, mutex); MPI_Send(NULL, 0, MPI_BYTE, p, ARMCI_MUTEX_TAG+mutex, hdl->grp.comm); break; } } ARMCII_Dbg_print(DEBUG_CAT_MUTEX, "lock released [proc = %d, mutex = %d]\n", proc, mutex); free(buf); } armci-mpi/src/vector.c0000644000175000017500000003655712663426407014473 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #ifndef NO_USE_CTREE #include #endif /** Check an I/O vector operation's buffers for overlap. * * @param[in] iov Vector of transfer information. * @return Logical true when regions overlap, 0 otherwise. */ int ARMCII_Iov_check_overlap(void **ptrs, int count, int size) { #ifndef NO_CHECK_OVERLAP #ifdef NO_USE_CTREE int i, j; if (!ARMCII_GLOBAL_STATE.iov_checks) return 0; for (i = 0; i < count; i++) { for (j = i+1; j < count; j++) { const uint8_t *ptr_1_lo = ptrs[i]; const uint8_t *ptr_1_hi = ((uint8_t*)ptrs[i]) + size - 1; const uint8_t *ptr_2_lo = ptrs[j]; const uint8_t *ptr_2_hi = ((uint8_t*)ptrs[j]) + size - 1; if ( (ptr_1_lo >= ptr_2_lo && ptr_1_lo <= ptr_2_hi) || (ptr_1_hi >= ptr_2_lo && ptr_1_hi <= ptr_2_hi) || (ptr_1_lo < ptr_2_lo && ptr_1_hi > ptr_2_hi)) { ARMCII_Dbg_print(DEBUG_CAT_IOV, "IOV regions overlap: [%p, %p] - [%p, %p]\n", ptr_1_lo, ptr_1_hi, ptr_2_lo, ptr_2_hi); return 1; } } } #else int i; ctree_t ctree = CTREE_EMPTY; if (!ARMCII_GLOBAL_STATE.iov_checks) return 0; for (i = 0; i < count; i++) { int conflict = ctree_insert(&ctree, ptrs[i], ((uint8_t*)ptrs[i]) + size - 1); if (conflict) { ctree_t cnode = ctree_locate(ctree, ptrs[i], ((uint8_t*)ptrs[i]) + size - 1); ARMCII_Dbg_print(DEBUG_CAT_IOV, "IOV regions overlap: [%p, %p] - [%p, %p]\n", ptrs[i], ((uint8_t*)ptrs[i]) + size - 1, cnode->lo, cnode->hi); ctree_destroy(&ctree); return 1; } } ctree_destroy(&ctree); #endif /* NO_USE_CTREE */ #endif /* NO_CHECK_OVERLAP */ return 0; } /** Check if a set of pointers all corresponds to the same allocation. * * @param[in] ptrs An array of count shared pointers valid on proc. * @param[in] count Size of the ptrs array. * @param[in] proc Process on which the pointers are valid. * @return Non-zero (true) on success, zero (false) otherwise. */ int ARMCII_Iov_check_same_allocation(void **ptrs, int count, int proc) { int i; gmr_t *mreg; void *base, *extent; if (!ARMCII_GLOBAL_STATE.iov_checks) return 1; mreg = gmr_lookup(ptrs[0], proc); /* If local, all must be local */ if (mreg == NULL) { for (i = 1; i < count; i++) { mreg = gmr_lookup(ptrs[i], proc); if (mreg != NULL) return 0; } } /* If shared, all must fall in this region */ else { base = mreg->slices[proc].base; extent = ((uint8_t*) base) + mreg->slices[proc].size; for (i = 1; i < count; i++) if ( !(ptrs[i] >= base && ptrs[i] < extent) ) return 0; } return 1; } /** Perform an I/O vector operation. Local buffers must be private. * * @param[in] op Operation to be performed (ARMCII_OP_PUT, ...) * @param[in] src Array of source pointers * @param[in] dst Array of destination pointers * @param[in] count Length of pointer arrays * @param[in] size Size of each transfer * @param[in] datatype Data type for accumulate op (ignored for all others) * @param[in] overlapping Do remote regions overlap? * @param[in] same_alloc Do remote regions correspond to the same allocation? * @param[in] proc Target process * @return Zero on success, error code otherwise */ int ARMCII_Iov_op_dispatch(enum ARMCII_Op_e op, void **src, void **dst, int count, int size, int datatype, int overlapping, int same_alloc, int proc, int blocking) { MPI_Datatype type; int type_count, type_size; if (op == ARMCII_OP_ACC) { ARMCII_Acc_type_translate(datatype, &type, &type_size); type_count = size/type_size; ARMCII_Assert_msg(size % type_size == 0, "Transfer size is not a multiple of type size"); } else { type = MPI_BYTE; MPI_Type_size(type, &type_size); type_count = size/type_size; ARMCII_Assert_msg(size % type_size == 0, "Transfer size is not a multiple of type size"); } // CONSERVATIVE CASE: If remote pointers overlap or remote pointers correspond to // multiple allocations, use the safe implementation to avoid invalid MPI // use. if (overlapping || !same_alloc || ARMCII_GLOBAL_STATE.iov_method == ARMCII_IOV_CONSRV) { if (overlapping) ARMCII_Warning("IOV remote buffers overlap\n"); if (!same_alloc) ARMCII_Warning("IOV remote buffers are not within the same allocation\n"); #if 0 return ARMCII_Iov_op_safe(op, src, dst, count, type_count, type, proc); #else /* Jeff: We are going to always block when there is buffer overlap. */ return ARMCII_Iov_op_batched(op, src, dst, count, type_count, type, proc, 1 /* consrv */, 1 /* blocking */); #endif } // OPTIMIZED CASE: It's safe for us to issue all the operations under a // single lock. else if ( ARMCII_GLOBAL_STATE.iov_method == ARMCII_IOV_DIRECT || ARMCII_GLOBAL_STATE.iov_method == ARMCII_IOV_AUTO ) { return ARMCII_Iov_op_datatype(op, src, dst, count, type_count, type, proc, blocking); } else if (ARMCII_GLOBAL_STATE.iov_method == ARMCII_IOV_BATCHED) { return ARMCII_Iov_op_batched(op, src, dst, count, type_count, type, proc, 0 /* not consrv */, blocking); } else { ARMCII_Error("unknown iov method (%d)\n", ARMCII_GLOBAL_STATE.iov_method); return 1; } } #if 0 /** Safe implementation of the ARMCI IOV operation */ int ARMCII_Iov_op_safe(enum ARMCII_Op_e op, void **src, void **dst, int count, int elem_count, MPI_Datatype type, int proc) { int i; int flush_local = 0; /* used only for MPI-3 */ for (i = 0; i < count; i++) { gmr_t *mreg; void *shr_ptr; switch(op) { case ARMCII_OP_ACC: case ARMCII_OP_PUT: shr_ptr = dst[i]; break; case ARMCII_OP_GET: shr_ptr = src[i]; break; default: ARMCII_Error("unknown operation (%d)", op); return 1; } mreg = gmr_lookup(shr_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid remote pointer"); switch(op) { case ARMCII_OP_PUT: gmr_put(mreg, src[i], dst[i], elem_count, proc); flush_local = 1; break; case ARMCII_OP_GET: gmr_get(mreg, src[i], dst[i], elem_count, proc); flush_local = 0; break; case ARMCII_OP_ACC: gmr_accumulate(mreg, src[i], dst[i], elem_count, type, proc); flush_local = 1; break; default: ARMCII_Error("unknown operation (%d)", op); return 1; } gmr_flush(mreg, proc, flush_local); } return 0; } #endif /** Optimized implementation of the ARMCI IOV operation that uses a single * lock/unlock pair. */ int ARMCII_Iov_op_batched(enum ARMCII_Op_e op, void **src, void **dst, int count, int elem_count, MPI_Datatype type, int proc, int consrv, int blocking) { int i; int flush_local = 1; /* used only for MPI-3 */ gmr_t *mreg; void *shr_ptr; switch(op) { case ARMCII_OP_ACC: case ARMCII_OP_PUT: shr_ptr = dst[0]; break; case ARMCII_OP_GET: shr_ptr = src[0]; break; default: ARMCII_Error("unknown operation (%d)", op); return 1; } mreg = gmr_lookup(shr_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid remote pointer"); for (i = 0; i < count; i++) { if ( blocking && i > 0 && ( consrv || ( ARMCII_GLOBAL_STATE.iov_batched_limit > 0 && i % ARMCII_GLOBAL_STATE.iov_batched_limit == 0) ) ) { gmr_flush(mreg, proc, flush_local); } switch(op) { case ARMCII_OP_PUT: gmr_put(mreg, src[i], dst[i], elem_count, proc); flush_local = 1; break; case ARMCII_OP_GET: gmr_get(mreg, src[i], dst[i], elem_count, proc); flush_local = 0; break; case ARMCII_OP_ACC: gmr_accumulate(mreg, src[i], dst[i], elem_count, type, proc); flush_local = 1; break; default: ARMCII_Error("unknown operation (%d)", op); return 1; } } if (blocking) { gmr_flush(mreg, proc, flush_local); } return 0; } /** Optimized implementation of the ARMCI IOV operation that uses an MPI * datatype to achieve a one-sided gather/scatter. */ int ARMCII_Iov_op_datatype(enum ARMCII_Op_e op, void **src, void **dst, int count, int elem_count, MPI_Datatype type, int proc, int blocking) { gmr_t *mreg; MPI_Datatype type_loc, type_rem; MPI_Aint disp_loc[count]; int disp_rem[count]; int block_len[count]; void *dst_win_base; int dst_win_size, i, type_size; void **buf_rem, **buf_loc; MPI_Aint base_rem; int flush_local = 0; /* used only for MPI-3 */ switch(op) { case ARMCII_OP_ACC: case ARMCII_OP_PUT: buf_rem = dst; buf_loc = src; break; case ARMCII_OP_GET: buf_rem = src; buf_loc = dst; break; default: ARMCII_Error("unknown operation (%d)", op); return 1; } MPI_Type_size(type, &type_size); mreg = gmr_lookup(buf_rem[0], proc); ARMCII_Assert_msg(mreg != NULL, "Invalid remote pointer"); dst_win_base = mreg->slices[proc].base; dst_win_size = mreg->slices[proc].size; MPI_Get_address(dst_win_base, &base_rem); for (i = 0; i < count; i++) { MPI_Aint target_rem; MPI_Get_address(buf_loc[i], &disp_loc[i]); MPI_Get_address(buf_rem[i], &target_rem); disp_rem[i] = (target_rem - base_rem)/type_size; block_len[i] = elem_count; ARMCII_Assert_msg((target_rem - base_rem) % type_size == 0, "Transfer size is not a multiple of type size"); ARMCII_Assert_msg(disp_rem[i] >= 0 && disp_rem[i] < dst_win_size, "Invalid remote pointer"); ARMCII_Assert_msg(((uint8_t*)buf_rem[i]) + block_len[i] <= ((uint8_t*)dst_win_base) + dst_win_size, "Transfer exceeds buffer length"); } MPI_Type_create_hindexed(count, block_len, disp_loc, type, &type_loc); MPI_Type_create_indexed_block(count, elem_count, disp_rem, type, &type_rem); /* MPI_Type_create_indexed_block should be more efficient than this: MPI_Type_indexed(count, block_len, disp_rem, type, &type_rem); */ MPI_Type_commit(&type_loc); MPI_Type_commit(&type_rem); switch(op) { case ARMCII_OP_PUT: gmr_put_typed(mreg, MPI_BOTTOM, 1, type_loc, MPI_BOTTOM, 1, type_rem, proc); flush_local = 1; break; case ARMCII_OP_GET: gmr_get_typed(mreg, MPI_BOTTOM, 1, type_rem, MPI_BOTTOM, 1, type_loc, proc); flush_local = 0; break; case ARMCII_OP_ACC: gmr_accumulate_typed(mreg, MPI_BOTTOM, 1, type_loc, MPI_BOTTOM, 1, type_rem, proc); flush_local = 1; break; default: ARMCII_Error("unknown operation (%d)", op); return 1; } if (blocking) { gmr_flush(mreg, proc, flush_local); } MPI_Type_free(&type_loc); MPI_Type_free(&type_rem); return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_PutV = PARMCI_PutV #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_PutV ARMCI_PutV #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_PutV as PARMCI_PutV #endif /* -- end weak symbols block -- */ /** Generalized I/O vector one-sided put. * * @param[in] iov Vector of transfer information. * @param[in] iov_len Length of iov. * @param[in] proc Target process. * @return Success 0, otherwise non-zero. */ int PARMCI_PutV(armci_giov_t *iov, int iov_len, int proc) { int v; for (v = 0; v < iov_len; v++) { void **src_buf; int overlapping, same_alloc; if (iov[v].ptr_array_len == 0) continue; // NOP // if (iov[v].bytes == 0) continue; // NOP // overlapping = ARMCII_Iov_check_overlap(iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes); same_alloc = ARMCII_Iov_check_same_allocation(iov[v].dst_ptr_array, iov[v].ptr_array_len, proc); ARMCII_Buf_prepare_read_vec(iov[v].src_ptr_array, &src_buf, iov[v].ptr_array_len, iov[v].bytes); ARMCII_Iov_op_dispatch(ARMCII_OP_PUT, src_buf, iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes, 0, overlapping, same_alloc, proc, 1 /* blocking */); ARMCII_Buf_finish_read_vec(iov[v].src_ptr_array, src_buf, iov[v].ptr_array_len, iov[v].bytes); } return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_GetV = PARMCI_GetV #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_GetV ARMCI_GetV #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_GetV as PARMCI_GetV #endif /* -- end weak symbols block -- */ /** Generalized I/O vector one-sided get. * * @param[in] iov Vector of transfer information. * @param[in] iov_len Length of iov. * @param[in] proc Target process. * @return Success 0, otherwise non-zero. */ int PARMCI_GetV(armci_giov_t *iov, int iov_len, int proc) { int v; for (v = 0; v < iov_len; v++) { void **dst_buf; int overlapping, same_alloc; if (iov[v].ptr_array_len == 0) continue; // NOP // if (iov[v].bytes == 0) continue; // NOP // // overlapping = ARMCII_Iov_check_overlap(iov[v].src_ptr_array, iov[v].ptr_array_len, iov[v].bytes); overlapping = ARMCII_Iov_check_overlap(iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes); same_alloc = ARMCII_Iov_check_same_allocation(iov[v].src_ptr_array, iov[v].ptr_array_len, proc); ARMCII_Buf_prepare_write_vec(iov[v].dst_ptr_array, &dst_buf, iov[v].ptr_array_len, iov[v].bytes); ARMCII_Iov_op_dispatch(ARMCII_OP_GET, iov[v].src_ptr_array, dst_buf, iov[v].ptr_array_len, iov[v].bytes, 0, overlapping, same_alloc, proc, 1 /* blocking */); ARMCII_Buf_finish_write_vec(iov[v].dst_ptr_array, dst_buf, iov[v].ptr_array_len, iov[v].bytes); } return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_AccV = PARMCI_AccV #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_AccV ARMCI_AccV #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_AccV as PARMCI_AccV #endif /* -- end weak symbols block -- */ /** Generalized I/O vector one-sided accumulate. * * @param[in] iov Vector of transfer information. * @param[in] iov_len Length of iov. * @param[in] proc Target process. * @return Success 0, otherwise non-zero. */ int PARMCI_AccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc) { int v; for (v = 0; v < iov_len; v++) { void **src_buf; int overlapping, same_alloc; if (iov[v].ptr_array_len == 0) continue; // NOP // if (iov[v].bytes == 0) continue; // NOP // overlapping = ARMCII_Iov_check_overlap(iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes); same_alloc = ARMCII_Iov_check_same_allocation(iov[v].dst_ptr_array, iov[v].ptr_array_len, proc); ARMCII_Buf_prepare_acc_vec(iov[v].src_ptr_array, &src_buf, iov[v].ptr_array_len, iov[v].bytes, datatype, scale); ARMCII_Iov_op_dispatch(ARMCII_OP_ACC, src_buf, iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes, datatype, overlapping, same_alloc, proc, 1 /* blocking */); ARMCII_Buf_finish_acc_vec(iov[v].src_ptr_array, src_buf, iov[v].ptr_array_len, iov[v].bytes); } return 0; } armci-mpi/src/armci.h0000644000175000017500000002660412663426407014261 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #ifndef _ARMCI_H_ #define _ARMCI_H_ #include #define ARMCI_MPI 3 enum ARMCI_Acc_e { ARMCI_ACC_INT /* int */, ARMCI_ACC_LNG /* long */, ARMCI_ACC_FLT /* float */, ARMCI_ACC_DBL /* double */, ARMCI_ACC_CPL /* complex */, ARMCI_ACC_DCP /* double complex */ }; typedef long armci_size_t; int ARMCI_Init(void); int ARMCI_Init_args(int *argc, char ***argv); int ARMCI_Initialized(void); int ARMCI_Finalize(void); void ARMCI_Cleanup(void); void ARMCI_Error(const char *msg, int code); int ARMCI_Malloc(void **base_ptrs, armci_size_t size); int ARMCI_Free(void *ptr); void *ARMCI_Malloc_local(armci_size_t size); int ARMCI_Free_local(void *ptr); void ARMCI_Barrier(void); void ARMCI_Fence(int proc); void ARMCI_AllFence(void); void ARMCI_Access_begin(void *ptr); /* NEW API */ void ARMCI_Access_end(void *ptr); /* NEW API */ void ARMCI_Copy(const void *src, void *dst, int size); int ARMCI_Get(void *src, void *dst, int size, int target); int ARMCI_Put(void *src, void *dst, int size, int target); int ARMCI_Acc(int datatype, void *scale, void *src, void *dst, int bytes, int proc); int ARMCI_PutS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc); int ARMCI_GetS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc); int ARMCI_AccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc); int ARMCI_Put_flag(void *src, void* dst, int size, int *flag, int value, int proc); int ARMCI_PutS_flag(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int *flag, int value, int proc); typedef struct armci_hdl_s { int target; /* we do not actually support individual completion */ int aggregate; } armci_hdl_t; void ARMCI_INIT_HANDLE(armci_hdl_t *hdl); void ARMCI_SET_AGGREGATE_HANDLE(armci_hdl_t* handle); void ARMCI_UNSET_AGGREGATE_HANDLE(armci_hdl_t* handle); int ARMCI_NbPut(void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl); int ARMCI_NbGet(void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl); int ARMCI_NbAcc(int datatype, void *scale, void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl); int ARMCI_Wait(armci_hdl_t* hdl); int ARMCI_Test(armci_hdl_t* hdl); int ARMCI_WaitProc(int proc); int ARMCI_WaitAll(void); int ARMCI_NbPutS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc, armci_hdl_t *hdl); int ARMCI_NbGetS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc, armci_hdl_t *hdl); int ARMCI_NbAccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc, armci_hdl_t *hdl); void armci_write_strided(void *ptr, int stride_levels, int stride_arr[], int count[], char *buf); void armci_read_strided(void *ptr, int stride_levels, int stride_arr[], int count[], char *buf); /** Generalized I/O Vector operations. */ typedef struct { void **src_ptr_array; // Source starting addresses of each data segment. void **dst_ptr_array; // Destination starting addresses of each data segment. int bytes; // The length of each segment in bytes. int ptr_array_len; // Number of data segment. } armci_giov_t; int ARMCI_PutV(armci_giov_t *iov, int iov_len, int proc); int ARMCI_GetV(armci_giov_t *iov, int iov_len, int proc); int ARMCI_AccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc); int ARMCI_NbPutV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle); int ARMCI_NbGetV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle); int ARMCI_NbAccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle); /** Scalar/value operations. */ int ARMCI_PutValueInt(int src, void *dst, int proc); int ARMCI_PutValueLong(long src, void *dst, int proc); int ARMCI_PutValueFloat(float src, void *dst, int proc); int ARMCI_PutValueDouble(double src, void *dst, int proc); int ARMCI_NbPutValueInt(int src, void *dst, int proc, armci_hdl_t *hdl); int ARMCI_NbPutValueLong(long src, void *dst, int proc, armci_hdl_t *hdl); int ARMCI_NbPutValueFloat(float src, void *dst, int proc, armci_hdl_t *hdl); int ARMCI_NbPutValueDouble(double src, void *dst, int proc, armci_hdl_t *hdl); int ARMCI_GetValueInt(void *src, int proc); long ARMCI_GetValueLong(void *src, int proc); float ARMCI_GetValueFloat(void *src, int proc); double ARMCI_GetValueDouble(void *src, int proc); /** Mutexes */ int ARMCI_Create_mutexes(int count); int ARMCI_Destroy_mutexes(void); void ARMCI_Lock(int mutex, int proc); void ARMCI_Unlock(int mutex, int proc); /** ARMCI Read-Modify-Write API */ enum ARMCI_Rmw_e { ARMCI_FETCH_AND_ADD, ARMCI_FETCH_AND_ADD_LONG, ARMCI_SWAP, ARMCI_SWAP_LONG }; int ARMCI_Rmw(int op, void *ploc, void *prem, int value, int proc); /** ARMCI Groups API */ typedef struct { MPI_Comm comm; MPI_Comm noncoll_pgroup_comm; int *grp_to_abs; int *abs_to_grp; int rank; int size; } ARMCI_Group; void ARMCI_Group_create(int grp_size, int *pid_list, ARMCI_Group *group_out); void ARMCI_Group_create_child(int grp_size, int *pid_list, ARMCI_Group *group_out, ARMCI_Group *group_parent); void ARMCI_Group_free(ARMCI_Group *group); int ARMCI_Group_rank(ARMCI_Group *group, int *rank); void ARMCI_Group_size(ARMCI_Group *group, int *size); void ARMCI_Group_set_default(ARMCI_Group *group); void ARMCI_Group_get_default(ARMCI_Group *group_out); void ARMCI_Group_get_world(ARMCI_Group *group_out); int ARMCI_Absolute_id(ARMCI_Group *group,int group_rank); int ARMCI_Malloc_group(void **ptr_arr, armci_size_t bytes, ARMCI_Group *group); int ARMCI_Free_group(void *ptr, ARMCI_Group *group); /** ARMCI Message API is in another file: */ #include /** Topology API */ enum armci_domain_e { ARMCI_DOMAIN_SMP }; typedef int armci_domain_t; int armci_domain_nprocs(armci_domain_t domain, int id); int armci_domain_id(armci_domain_t domain, int glob_proc_id); int armci_domain_glob_proc_id(armci_domain_t domain, int id, int loc_proc_id); int armci_domain_my_id(armci_domain_t domain); int armci_domain_count(armci_domain_t domain); int armci_domain_same_id(armci_domain_t domain, int proc); int ARMCI_Same_node(int proc); /** Odds and ends */ int ARMCI_Uses_shm(void); void ARMCI_Set_shm_limit(unsigned long shmemlimit); int ARMCI_Uses_shm_grp(ARMCI_Group *group); /** PARMCI -- Profiling Interface */ int PARMCI_Init(void); int PARMCI_Init_args(int *argc, char ***argv); int PARMCI_Initialized(void); int PARMCI_Finalize(void); int PARMCI_Malloc(void **base_ptrs, armci_size_t size); int PARMCI_Free(void *ptr); void *PARMCI_Malloc_local(armci_size_t size); int PARMCI_Free_local(void *ptr); void PARMCI_Barrier(void); void PARMCI_Fence(int proc); void PARMCI_AllFence(void); void PARMCI_Access_begin(void *ptr); void PARMCI_Access_end(void *ptr); int PARMCI_Get(void *src, void *dst, int size, int target); int PARMCI_Put(void *src, void *dst, int size, int target); int PARMCI_Acc(int datatype, void *scale, void *src, void *dst, int bytes, int proc); int PARMCI_PutS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc); int PARMCI_GetS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc); int PARMCI_AccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc); int PARMCI_Put_flag(void *src, void* dst, int size, int *flag, int value, int proc); int PARMCI_PutS_flag(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int *flag, int value, int proc); int PARMCI_PutV(armci_giov_t *iov, int iov_len, int proc); int PARMCI_GetV(armci_giov_t *iov, int iov_len, int proc); int PARMCI_AccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc); int PARMCI_Wait(armci_hdl_t* hdl); int PARMCI_Test(armci_hdl_t* hdl); int PARMCI_WaitProc(int proc); int PARMCI_WaitAll(void); int PARMCI_NbPut(void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl); int PARMCI_NbGet(void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl); int PARMCI_NbAcc(int datatype, void *scale, void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl); int PARMCI_NbPutS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc, armci_hdl_t *hdl); int PARMCI_NbGetS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc, armci_hdl_t *hdl); int PARMCI_NbAccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc, armci_hdl_t *hdl); int PARMCI_NbPutV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle); int PARMCI_NbGetV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle); int PARMCI_NbAccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle); int PARMCI_PutValueInt(int src, void *dst, int proc); int PARMCI_PutValueLong(long src, void *dst, int proc); int PARMCI_PutValueFloat(float src, void *dst, int proc); int PARMCI_PutValueDouble(double src, void *dst, int proc); int PARMCI_NbPutValueInt(int src, void *dst, int proc, armci_hdl_t *hdl); int PARMCI_NbPutValueLong(long src, void *dst, int proc, armci_hdl_t *hdl); int PARMCI_NbPutValueFloat(float src, void *dst, int proc, armci_hdl_t *hdl); int PARMCI_NbPutValueDouble(double src, void *dst, int proc, armci_hdl_t *hdl); int PARMCI_GetValueInt(void *src, int proc); long PARMCI_GetValueLong(void *src, int proc); float PARMCI_GetValueFloat(void *src, int proc); double PARMCI_GetValueDouble(void *src, int proc); int PARMCI_Create_mutexes(int count); int PARMCI_Destroy_mutexes(void); void PARMCI_Lock(int mutex, int proc); void PARMCI_Unlock(int mutex, int proc); int PARMCI_Rmw(int op, void *ploc, void *prem, int value, int proc); void parmci_msg_barrier(void); void parmci_msg_group_barrier(ARMCI_Group *group); #endif /* _ARMCI_H_ */ armci-mpi/src/onesided_nb.c0000644000175000017500000002012712663426407015424 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include /** Initialize Non-blocking handle. */ void ARMCI_INIT_HANDLE(armci_hdl_t *handle) { if (handle!=NULL) { handle->aggregate = 1; handle->target = -1; } else { ARMCII_Warning("ARMCI_INIT_HANDLE given NULL handle"); } return; } /** Mark a handle as aggregate. */ void ARMCI_SET_AGGREGATE_HANDLE(armci_hdl_t *handle) { if (handle!=NULL) { handle->aggregate = 1; } else { ARMCII_Warning("ARMCI_INIT_HANDLE given NULL handle"); } return; } /** Clear an aggregate handle. */ void ARMCI_UNSET_AGGREGATE_HANDLE(armci_hdl_t *handle) { if (handle!=NULL) { handle->aggregate = 0; } else { ARMCII_Warning("ARMCI_INIT_HANDLE given NULL handle"); } return; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbPut = PARMCI_NbPut #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbPut ARMCI_NbPut #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbPut as PARMCI_NbPut #endif /* -- end weak symbols block -- */ /** Non-blocking put operation. */ int PARMCI_NbPut(void *src, void *dst, int size, int target, armci_hdl_t *handle) { gmr_t *src_mreg, *dst_mreg; dst_mreg = gmr_lookup(dst, target); /* If NOGUARD is set, assume the buffer is not shared */ if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) src_mreg = gmr_lookup(src, ARMCI_GROUP_WORLD.rank); else src_mreg = NULL; ARMCII_Assert_msg(dst_mreg != NULL, "Invalid remote pointer"); /* Local operation */ if (target == ARMCI_GROUP_WORLD.rank && src_mreg == NULL) { ARMCI_Copy(src, dst, size); } else { gmr_put(dst_mreg, src, dst, size, target); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = target; } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbGet = PARMCI_NbGet #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbGet ARMCI_NbGet #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbGet as PARMCI_NbGet #endif /* -- end weak symbols block -- */ /** Non-blocking get operation. Note: the implementation is not non-blocking */ int PARMCI_NbGet(void *src, void *dst, int size, int target, armci_hdl_t *handle) { gmr_t *src_mreg, *dst_mreg; src_mreg = gmr_lookup(src, target); /* If NOGUARD is set, assume the buffer is not shared */ if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) dst_mreg = gmr_lookup(dst, ARMCI_GROUP_WORLD.rank); else dst_mreg = NULL; ARMCII_Assert_msg(src_mreg != NULL, "Invalid remote pointer"); /* Local operation */ if (target == ARMCI_GROUP_WORLD.rank && dst_mreg == NULL) { ARMCI_Copy(src, dst, size); } else { gmr_get(src_mreg, src, dst, size, target); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = target; } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbAcc = PARMCI_NbAcc #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbAcc ARMCI_NbAcc #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbAcc as PARMCI_NbAcc #endif /* -- end weak symbols block -- */ /** Non-blocking accumulate operation. Note: the implementation is not non-blocking */ int PARMCI_NbAcc(int datatype, void *scale, void *src, void *dst, int bytes, int target, armci_hdl_t *handle) { void *src_buf; int count, type_size, scaled; MPI_Datatype type; gmr_t *src_mreg, *dst_mreg; /* If NOGUARD is set, assume the buffer is not shared */ if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) src_mreg = gmr_lookup(src, ARMCI_GROUP_WORLD.rank); else src_mreg = NULL; dst_mreg = gmr_lookup(dst, target); ARMCII_Assert_msg(dst_mreg != NULL, "Invalid remote pointer"); /* Prepare the input data: Apply scaling if needed and acquire the DLA lock if * needed. We hold the DLA lock if (src_buf == src && src_mreg != NULL). */ scaled = ARMCII_Buf_acc_is_scaled(datatype, scale); if (scaled) { MPI_Alloc_mem(bytes, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); ARMCII_Buf_acc_scale(src, src_buf, bytes, datatype, scale); } else { src_buf = src; } /* Check if we need to copy: user requested it or same mem region */ if ( (src_buf == src) /* buf_prepare didn't make a copy */ && (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY || src_mreg == dst_mreg) ) { MPI_Alloc_mem(bytes, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); ARMCI_Copy(src, src_buf, bytes); } ARMCII_Acc_type_translate(datatype, &type, &type_size); count = bytes/type_size; ARMCII_Assert_msg(bytes % type_size == 0, "Transfer size is not a multiple of the datatype size"); /* TODO: Support a local accumulate operation more efficiently */ gmr_accumulate(dst_mreg, src_buf, dst, count, type, target); if (src_buf != src) { /* must wait for local completion to free source buffer */ gmr_flush(dst_mreg, target, 1); /* flush local only, unlike Fence */ MPI_Free_mem(src_buf); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = target; } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Wait = PARMCI_Wait #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Wait ARMCI_Wait #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Wait as PARMCI_Wait #endif /* -- end weak symbols block -- */ /** Wait for a non-blocking operation to finish. */ int PARMCI_Wait(armci_hdl_t* handle) { gmr_t *cur_mreg = gmr_list; if(handle->aggregate > 0) { while (cur_mreg) { gmr_flushall(cur_mreg, 1); /* local only */ cur_mreg = cur_mreg->next; } } else { int proc = handle->target; while (cur_mreg) { gmr_flush(cur_mreg, proc, 1); /* local only */ cur_mreg = cur_mreg->next; } } return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Test = PARMCI_Test #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Test ARMCI_Test #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Test as PARMCI_Test #endif /* -- end weak symbols block -- */ /** Check if a non-blocking operation has finished. */ int PARMCI_Test(armci_hdl_t* handle) { return PARMCI_Wait(handle); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_WaitProc = PARMCI_WaitProc #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_WaitProc ARMCI_WaitProc #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_WaitProc as PARMCI_WaitProc #endif /* -- end weak symbols block -- */ /** Wait for all outstanding non-blocking operations with implicit handles to a particular process to finish. */ int PARMCI_WaitProc(int proc) { gmr_t *cur_mreg = gmr_list; while (cur_mreg) { gmr_flush(cur_mreg, proc, 1); /* local only */ cur_mreg = cur_mreg->next; } return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_WaitAll = PARMCI_WaitAll #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_WaitAll ARMCI_WaitAll #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_WaitAll as PARMCI_WaitAll #endif /* -- end weak symbols block -- */ /** Wait for all non-blocking operations with implicit (NULL) handles to finish. */ int PARMCI_WaitAll(void) { gmr_t *cur_mreg = gmr_list; while (cur_mreg) { gmr_flushall(cur_mreg, 1); /* local only */ cur_mreg = cur_mreg->next; } return 0; } armci-mpi/src/onesided.c0000644000175000017500000002206512663426407014750 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Access_begin = PARMCI_Access_begin #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Access_begin ARMCI_Access_begin #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Access_begin as PARMCI_Access_begin #endif /* -- end weak symbols block -- */ /** Declare the start of a local access epoch. This allows direct access to * data in local memory. * * @param[in] ptr Pointer to the allocation that will be accessed directly */ void PARMCI_Access_begin(void *ptr) { gmr_t *mreg; mreg = gmr_lookup(ptr, ARMCI_GROUP_WORLD.rank); ARMCII_Assert_msg(mreg != NULL, "Invalid remote pointer"); gmr_sync(mreg); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Access_end = PARMCI_Access_end #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Access_end ARMCI_Access_end #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Access_end as PARMCI_Access_end #endif /* -- end weak symbols block -- */ /** Declare the end of a local access epoch. * * \note MPI-2 does not allow multiple locks at once, so you can have only one * access epoch open at a time and cannot do put/get/acc while in an access * region. * * @param[in] ptr Pointer to the allocation that was accessed directly */ void PARMCI_Access_end(void *ptr) { gmr_t *mreg; mreg = gmr_lookup(ptr, ARMCI_GROUP_WORLD.rank); ARMCII_Assert_msg(mreg != NULL, "Invalid remote pointer"); gmr_sync(mreg); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Get = PARMCI_Get #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Get ARMCI_Get #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Get as PARMCI_Get #endif /* -- end weak symbols block -- */ /** One-sided get operation. * * @param[in] src Source address (remote) * @param[in] dst Destination address (local) * @param[in] size Number of bytes to transfer * @param[in] target Process id to target * @return 0 on success, non-zero on failure */ int PARMCI_Get(void *src, void *dst, int size, int target) { gmr_t *src_mreg, *dst_mreg; src_mreg = gmr_lookup(src, target); /* If NOGUARD is set, assume the buffer is not shared */ if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) dst_mreg = gmr_lookup(dst, ARMCI_GROUP_WORLD.rank); else dst_mreg = NULL; ARMCII_Assert_msg(src_mreg != NULL, "Invalid remote pointer"); /* Local operation */ if (target == ARMCI_GROUP_WORLD.rank && dst_mreg == NULL) { ARMCI_Copy(src, dst, size); } /* Origin buffer is private */ else if (dst_mreg == NULL) { gmr_get(src_mreg, src, dst, size, target); gmr_flush(src_mreg, target, 0); /* it's a round trip so w.r.t. flush, local=remote */ } /* COPY: Either origin and target buffers are in the same window and we can't * lock the same window twice (MPI semantics) or the user has requested * always-copy mode. */ else { void *dst_buf; MPI_Alloc_mem(size, MPI_INFO_NULL, &dst_buf); ARMCII_Assert(dst_buf != NULL); gmr_get(src_mreg, src, dst_buf, size, target); gmr_flush(src_mreg, target, 0); /* it's a round trip so w.r.t. flush, local=remote */ ARMCI_Copy(dst_buf, dst, size); MPI_Free_mem(dst_buf); } return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Put = PARMCI_Put #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Put ARMCI_Put #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Put as PARMCI_Put #endif /* -- end weak symbols block -- */ /** One-sided put operation. * * @param[in] src Source address (remote) * @param[in] dst Destination address (local) * @param[in] size Number of bytes to transfer * @param[in] target Process id to target * @return 0 on success, non-zero on failure */ int PARMCI_Put(void *src, void *dst, int size, int target) { gmr_t *src_mreg, *dst_mreg; dst_mreg = gmr_lookup(dst, target); /* If NOGUARD is set, assume the buffer is not shared */ if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) src_mreg = gmr_lookup(src, ARMCI_GROUP_WORLD.rank); else src_mreg = NULL; ARMCII_Assert_msg(dst_mreg != NULL, "Invalid remote pointer"); /* Local operation */ if (target == ARMCI_GROUP_WORLD.rank && src_mreg == NULL) { ARMCI_Copy(src, dst, size); } /* Origin buffer is private */ else if (src_mreg == NULL) { gmr_put(dst_mreg, src, dst, size, target); gmr_flush(dst_mreg, target, 1); /* flush_local */ } /* COPY: Either origin and target buffers are in the same window and we can't * lock the same window twice (MPI semantics) or the user has requested * always-copy mode. */ else { void *src_buf; MPI_Alloc_mem(size, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); ARMCI_Copy(src, src_buf, size); gmr_put(dst_mreg, src_buf, dst, size, target); gmr_flush(dst_mreg, target, 1); /* flush_local */ MPI_Free_mem(src_buf); } return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Acc = PARMCI_Acc #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Acc ARMCI_Acc #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Acc as PARMCI_Acc #endif /* -- end weak symbols block -- */ /** One-sided accumulate operation. * * @param[in] datatype ARMCI data type for the accumulate operation (see armci.h) * @param[in] scale Pointer for a scalar of type datatype that will be used to * scale values in the source buffer * @param[in] src Source address (remote) * @param[in] dst Destination address (local) * @param[in] bytes Number of bytes to transfer * @param[in] proc Process id to target * @return 0 on success, non-zero on failure */ int PARMCI_Acc(int datatype, void *scale, void *src, void *dst, int bytes, int proc) { void *src_buf; int count, type_size, scaled; MPI_Datatype type; gmr_t *src_mreg, *dst_mreg; /* If NOGUARD is set, assume the buffer is not shared */ if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) src_mreg = gmr_lookup(src, ARMCI_GROUP_WORLD.rank); else src_mreg = NULL; dst_mreg = gmr_lookup(dst, proc); ARMCII_Assert_msg(dst_mreg != NULL, "Invalid remote pointer"); /* Prepare the input data: Apply scaling if needed and acquire the DLA lock if * needed. We hold the DLA lock if (src_buf == src && src_mreg != NULL). */ scaled = ARMCII_Buf_acc_is_scaled(datatype, scale); if (scaled) { MPI_Alloc_mem(bytes, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); ARMCII_Buf_acc_scale(src, src_buf, bytes, datatype, scale); } else { src_buf = src; } /* Check if we need to copy: user requested it or same mem region */ if ( (src_buf == src) /* buf_prepare didn't make a copy */ && (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY || src_mreg == dst_mreg) ) { MPI_Alloc_mem(bytes, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); ARMCI_Copy(src, src_buf, bytes); } ARMCII_Acc_type_translate(datatype, &type, &type_size); count = bytes/type_size; ARMCII_Assert_msg(bytes % type_size == 0, "Transfer size is not a multiple of the datatype size"); /* TODO: Support a local accumulate operation more efficiently */ gmr_accumulate(dst_mreg, src_buf, dst, count, type, proc); gmr_flush(dst_mreg, proc, 1); /* flush_local */ if (src_buf != src) MPI_Free_mem(src_buf); return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Put_flag = PARMCI_Put_flag #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Put_flag ARMCI_Put_flag #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Put_flag as PARMCI_Put_flag #endif /* -- end weak symbols block -- */ /** One-sided copy of data from the source to the destination. Set a flag on * the remote process when the transfer is complete. * * @param[in] src Source buffer * @param[in] dst Destination buffer on proc * @param[in] size Number of bytes to transfer * @param[in] flag Address of the flag buffer on proc * @param[in] value Value to set the flag to * @param[in] proc Process id of the target * @return 0 on success, non-zero on failure */ int PARMCI_Put_flag(void *src, void* dst, int size, int *flag, int value, int proc) { /* TODO: This can be optimized with a more direct implementation, especially in the * case where RMA is ordered; in that case, the Fence (Flush) is not necessary. */ PARMCI_Put(src, dst, size, proc); PARMCI_Fence(proc); PARMCI_Put(&value, flag, sizeof(int), proc); return 0; } armci-mpi/src/mp3.h0000644000175000017500000000074312662706250013655 0ustar mbanckmbanck#ifndef _MP3_H_ #define _MP3_H_ #include #define MP_INIT(ARGC,ARGV) MPI_Init(&(ARGC),&(ARGV)) #define MP_BARRIER() MPI_Barrier(MPI_COMM_WORLD) #define MP_FINALIZE() MPI_Finalize() #define MP_PROCS(X) MPI_Comm_size(MPI_COMM_WORLD,X) #define MP_MYID(X) MPI_Comm_rank(MPI_COMM_WORLD,X) #define MP_TIMER() MPI_Wtime() #define GA_INIT(ARGC,ARGV) GA_Initialize() #define ARMCI_INIT(ARGC,ARGV) ARMCI_Init() #endif /* _MP3_H_ */ armci-mpi/src/groups.c0000644000175000017500000002515212662706250014471 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include /** The ARMCI world group. This is accessed from outside via * ARMCI_Group_get_world. */ ARMCI_Group ARMCI_GROUP_WORLD = {0}; ARMCI_Group ARMCI_GROUP_DEFAULT = {0}; /** Initialize an ARMCI group's remaining fields using the communicator field. */ void ARMCII_Group_init_from_comm(ARMCI_Group *group) { if (group->comm != MPI_COMM_NULL) { MPI_Comm_size(group->comm, &group->size); MPI_Comm_rank(group->comm, &group->rank); } else { group->rank = -1; group->size = 0; } /* If noncollective groups are in use, create a separate communicator that can be used for noncollective group creation with this group as the parent. This ensures that calls to MPI_Intercomm_create can't clash with any user communication. */ if (ARMCII_GLOBAL_STATE.noncollective_groups && group->comm != MPI_COMM_NULL) MPI_Comm_dup(group->comm, &group->noncoll_pgroup_comm); else group->noncoll_pgroup_comm = MPI_COMM_NULL; /* Check if translation caching is enabled */ if (ARMCII_GLOBAL_STATE.cache_rank_translation) { if (group->comm != MPI_COMM_NULL) { int *ranks, i; MPI_Group world_group, sub_group; group->abs_to_grp = malloc(sizeof(int)*ARMCI_GROUP_WORLD.size); group->grp_to_abs = malloc(sizeof(int)*group->size); ranks = malloc(sizeof(int)*ARMCI_GROUP_WORLD.size); ARMCII_Assert(group->abs_to_grp != NULL && group->grp_to_abs != NULL && ranks != NULL); for (i = 0; i < ARMCI_GROUP_WORLD.size; i++) ranks[i] = i; MPI_Comm_group(ARMCI_GROUP_WORLD.comm, &world_group); MPI_Comm_group(group->comm, &sub_group); MPI_Group_translate_ranks(sub_group, group->size, ranks, world_group, group->grp_to_abs); MPI_Group_translate_ranks(world_group, ARMCI_GROUP_WORLD.size, ranks, sub_group, group->abs_to_grp); MPI_Group_free(&world_group); MPI_Group_free(&sub_group); free(ranks); } } /* Translation caching is disabled */ else { group->abs_to_grp = NULL; group->grp_to_abs = NULL; } } /** Create an ARMCI group that contains a subset of the nodes in the current * default group. Collective across the default group. * * @param[in] grp_size Number of entries in pid_list. * @param[in] pid_list List of process ids that will be in the new group. * @param[out] armci_grp_out The new ARMCI group. * @param[in] armci_grp_parent The parent of the new ARMCI group. */ void ARMCI_Group_create(int grp_size, int *pid_list, ARMCI_Group *group_out) { ARMCI_Group_create_child(grp_size, pid_list, group_out, &ARMCI_GROUP_DEFAULT); } /** Create an ARMCI group that contains a subset of the nodes in the parent * group. Collective across output group. * * @param[in] grp_size Number of entries in pid_list. * @param[in] pid_list List of process ids that will be in the new group. * @param[out] armci_grp_out The new ARMCI group, only valid on group members. * @param[in] armci_grp_parent The parent of the new ARMCI group. */ static inline void ARMCI_Group_create_comm_collective(int grp_size, int *pid_list, ARMCI_Group *armci_grp_out, ARMCI_Group *armci_grp_parent) { MPI_Group mpi_grp_parent; MPI_Group mpi_grp_child; MPI_Comm_group(armci_grp_parent->comm, &mpi_grp_parent); MPI_Group_incl(mpi_grp_parent, grp_size, pid_list, &mpi_grp_child); MPI_Comm_create(armci_grp_parent->comm, mpi_grp_child, &armci_grp_out->comm); MPI_Group_free(&mpi_grp_parent); MPI_Group_free(&mpi_grp_child); } /** Create an ARMCI group that contains a subset of the nodes in the parent * group. Collective across output group. * * @param[in] grp_size Number of entries in pid_list. * @param[in] pid_list Sorted list of process ids that will be in the new group. * @param[out] armci_grp_out The new ARMCI group, only valid on group members. * @param[in] armci_grp_parent The parent of the new ARMCI group. */ static inline void ARMCI_Group_create_comm_noncollective(int grp_size, int *pid_list, ARMCI_Group *armci_grp_out, ARMCI_Group *armci_grp_parent) { const int INTERCOMM_TAG = 42; int i, grp_me, me, merge_size; MPI_Comm pgroup, inter_pgroup; me = armci_grp_parent->rank; /* CHECK: If I'm not a member, return COMM_NULL */ grp_me = -1; for (i = 0; i < grp_size; i++) { if (pid_list[i] == me) { grp_me = i; break; } } if (grp_me < 0) { armci_grp_out->comm = MPI_COMM_NULL; return; } /* CASE: Group size 1 */ else if (grp_size == 1 && pid_list[0] == me) { MPI_Comm_dup(MPI_COMM_SELF, &armci_grp_out->comm); return; } pgroup = MPI_COMM_SELF; /* Recursively merge adjacent groups until only one group remains. */ for (merge_size = 1; merge_size < grp_size; merge_size *= 2) { int gid = grp_me / merge_size; MPI_Comm pgroup_old = pgroup; if (gid % 2 == 0) { /* Check if right partner doesn't exist */ if ((gid+1)*merge_size >= grp_size) continue; MPI_Intercomm_create(pgroup, 0, armci_grp_parent->noncoll_pgroup_comm, pid_list[(gid+1)*merge_size], INTERCOMM_TAG, &inter_pgroup); MPI_Intercomm_merge(inter_pgroup, 0 /* LOW */, &pgroup); } else { MPI_Intercomm_create(pgroup, 0, armci_grp_parent->noncoll_pgroup_comm, pid_list[(gid-1)*merge_size], INTERCOMM_TAG, &inter_pgroup); MPI_Intercomm_merge(inter_pgroup, 1 /* HIGH */, &pgroup); } MPI_Comm_free(&inter_pgroup); if (pgroup_old != MPI_COMM_SELF) MPI_Comm_free(&pgroup_old); } armci_grp_out->comm = pgroup; } /** Create an ARMCI group that contains a subset of the nodes in the parent * group. Collective. * * @param[in] grp_size Number of entries in pid_list. * @param[in] pid_list Sorted list of process ids that will be in the new group. * @param[out] armci_grp_out The new ARMCI group, only valid on group members. * @param[in] armci_grp_parent The parent of the new ARMCI group. */ void ARMCI_Group_create_child(int grp_size, int *pid_list, ARMCI_Group *armci_grp_out, ARMCI_Group *armci_grp_parent) { if (ARMCII_GLOBAL_STATE.noncollective_groups) ARMCI_Group_create_comm_noncollective(grp_size, pid_list, armci_grp_out, armci_grp_parent); else ARMCI_Group_create_comm_collective(grp_size, pid_list, armci_grp_out, armci_grp_parent); ARMCII_Group_init_from_comm(armci_grp_out); } /** Free an ARMCI group. Collective across group. * * @param[in] group The group to be freed */ void ARMCI_Group_free(ARMCI_Group *group) { if (group->comm != MPI_COMM_NULL) { MPI_Comm_free(&group->comm); if (ARMCII_GLOBAL_STATE.noncollective_groups) MPI_Comm_free(&group->noncoll_pgroup_comm); } /* If the group has translation caches, free them */ if (group->abs_to_grp != NULL) free(group->abs_to_grp); if (group->grp_to_abs != NULL) free(group->grp_to_abs); group->rank = -1; group->size = 0; } /** Query the calling process' rank in a given group. * * @param[in] group Group to query on. * @param[out] rank Location to store the rank. * @return Zero on success, error code otherwise. */ int ARMCI_Group_rank(ARMCI_Group *group, int *rank) { *rank = group->rank; if (*rank >= 0) return 0; else return 1; } /** Query the size of the given group. * * @param[in] group Group to query. * @param[out] size Variable to store the size in. */ void ARMCI_Group_size(ARMCI_Group *group, int *size) { *size = group->size; } /** Set the default group. * * @param[in] group The new default group */ void ARMCI_Group_set_default(ARMCI_Group *group) { ARMCI_GROUP_DEFAULT = *group; } /** Get the default group. * * @param[out] group_out Pointer to the default group. */ void ARMCI_Group_get_default(ARMCI_Group *group_out) { *group_out = ARMCI_GROUP_DEFAULT; } /** Fetch the world group. * * @param[out] group_out Output group. */ void ARMCI_Group_get_world(ARMCI_Group *group_out) { *group_out = ARMCI_GROUP_WORLD; } /** Translate a group process rank to the corresponding process rank in the * ARMCI world group. * * @param[in] group Group to translate from. * @param[in] group_rank Rank of the process in group. */ int ARMCI_Absolute_id(ARMCI_Group *group, int group_rank) { int world_rank; MPI_Group world_group, sub_group; ARMCII_Assert(group_rank >= 0 && group_rank < group->size); /* Check if group is the world group */ if (group->comm == ARMCI_GROUP_WORLD.comm) world_rank = group_rank; /* Check for translation cache */ else if (group->grp_to_abs != NULL) world_rank = group->grp_to_abs[group_rank]; else { /* Translate the rank */ MPI_Comm_group(ARMCI_GROUP_WORLD.comm, &world_group); MPI_Comm_group(group->comm, &sub_group); MPI_Group_translate_ranks(sub_group, 1, &group_rank, world_group, &world_rank); MPI_Group_free(&world_group); MPI_Group_free(&sub_group); } /* Check if translation failed */ if (world_rank == MPI_UNDEFINED) return -1; else return world_rank; } /** Split a parent group into multiple child groups. This is similar to * MPI_Comm_split. Collective across the parent group. * * @param[in] parent The parent group. * @param[in] color The id number of the new group. Processes are grouped * together so allthat give the same color will be placed * in the same new group. * @param[in] key Relative ordering of processes in the new group. * @param[out] new_group Pointer to a handle where group info will be stored. */ int ARMCIX_Group_split(ARMCI_Group *parent, int color, int key, ARMCI_Group *new_group) { int err; err = MPI_Comm_split(parent->comm, color, key, &new_group->comm); if (err != MPI_SUCCESS) return err; ARMCII_Group_init_from_comm(new_group); return 0; } /** Duplicate an ARMCI group. Collective across the parent group. * * @param[in] parent The parent group. * @param[in] color The id number of the new group. Processes are grouped * together so allthat give the same color will be placed * in the same new group. * @param[in] key Relative ordering of processes in the new group. * @param[out] new_group Pointer to a handle where group info will be stored. */ int ARMCIX_Group_dup(ARMCI_Group *parent, ARMCI_Group *new_group) { int err; err = MPI_Comm_dup(parent->comm, &new_group->comm); if (err != MPI_SUCCESS) return err; ARMCII_Group_init_from_comm(new_group); return 0; } armci-mpi/src/gmr.c0000644000175000017500000004055612663426407013750 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include #include /** Linked list of shared memory regions. */ gmr_t *gmr_list = NULL; /** Create a distributed shared memory region. Collective on ARMCI group. * * @param[in] local_size Size of the local slice of the memory region. * @param[out] base_ptrs Array of base pointers for each process in group. * @param[in] group Group on which to perform allocation. * @return Pointer to the memory region object. */ gmr_t *gmr_create(gmr_size_t local_size, void **base_ptrs, ARMCI_Group *group) { int i; gmr_size_t aggregate_size; int alloc_me, alloc_nproc; int world_me, world_nproc; MPI_Group world_group, alloc_group; gmr_t *mreg; gmr_slice_t *alloc_slices, gmr_slice; ARMCII_Assert(local_size >= 0); ARMCII_Assert(group != NULL); MPI_Comm_rank(group->comm, &alloc_me); MPI_Comm_size(group->comm, &alloc_nproc); MPI_Comm_rank(ARMCI_GROUP_WORLD.comm, &world_me); MPI_Comm_size(ARMCI_GROUP_WORLD.comm, &world_nproc); mreg = malloc(sizeof(gmr_t)); ARMCII_Assert(mreg != NULL); mreg->slices = malloc(sizeof(gmr_slice_t)*world_nproc); ARMCII_Assert(mreg->slices != NULL); alloc_slices = malloc(sizeof(gmr_slice_t)*alloc_nproc); ARMCII_Assert(alloc_slices != NULL); mreg->group = *group; /* NOTE: I think it is invalid in GA/ARMCI to free a group before its allocations. If this is not the case, then assignment here is incorrect and this should really duplicated the group (communicator). */ mreg->nslices = world_nproc; mreg->prev = NULL; mreg->next = NULL; /* Allocate my slice of the GMR */ alloc_slices[alloc_me].size = local_size; MPI_Info alloc_shm_info; if (ARMCII_GLOBAL_STATE.use_alloc_shm) { MPI_Info_create(&alloc_shm_info); MPI_Info_set(alloc_shm_info, "alloc_shm", "true"); } else /* no alloc_shm */ { alloc_shm_info = MPI_INFO_NULL; } if (ARMCII_GLOBAL_STATE.use_win_allocate) { MPI_Win_allocate( (MPI_Aint) local_size, 1, alloc_shm_info, group->comm, &(alloc_slices[alloc_me].base), &mreg->window); if (local_size == 0) { /* TODO: Is this necessary? Is it a good idea anymore? */ alloc_slices[alloc_me].base = NULL; } else { ARMCII_Assert(alloc_slices[alloc_me].base != NULL); } } else /* use win create */ { if (local_size == 0) { alloc_slices[alloc_me].base = NULL; } else { MPI_Alloc_mem(local_size, alloc_shm_info, &(alloc_slices[alloc_me].base)); ARMCII_Assert(alloc_slices[alloc_me].base != NULL); } MPI_Win_create(alloc_slices[alloc_me].base, (MPI_Aint) local_size, 1, MPI_INFO_NULL, group->comm, &mreg->window); } /* win allocate/create */ if (ARMCII_GLOBAL_STATE.use_alloc_shm) { MPI_Info_free(&alloc_shm_info); } /* Debugging: Zero out shared memory if enabled */ if (ARMCII_GLOBAL_STATE.debug_alloc && local_size > 0) { ARMCII_Bzero(alloc_slices[alloc_me].base, local_size); } /* All-to-all on to build up slices vector */ gmr_slice = alloc_slices[alloc_me]; MPI_Allgather( &gmr_slice, sizeof(gmr_slice_t), MPI_BYTE, alloc_slices, sizeof(gmr_slice_t), MPI_BYTE, group->comm); /* Check for a global size 0 allocation */ for (i = aggregate_size = 0; i < alloc_nproc; i++) { aggregate_size += alloc_slices[i].size; } /* Everyone asked for 0 bytes, return a NULL vector */ if (aggregate_size == 0) { free(alloc_slices); free(mreg->slices); free(mreg); for (i = 0; i < alloc_nproc; i++) base_ptrs[i] = NULL; return NULL; } /* Populate the base pointers array */ for (i = 0; i < alloc_nproc; i++) base_ptrs[i] = alloc_slices[i].base; /* We have to do lookup on global ranks, so shovel the contents of alloc_slices into the mreg->slices array which is indexed by global rank. */ memset(mreg->slices, 0, sizeof(gmr_slice_t)*world_nproc); MPI_Comm_group(ARMCI_GROUP_WORLD.comm, &world_group); MPI_Comm_group(group->comm, &alloc_group); for (i = 0; i < alloc_nproc; i++) { int world_rank; MPI_Group_translate_ranks(alloc_group, 1, &i, world_group, &world_rank); mreg->slices[world_rank] = alloc_slices[i]; } free(alloc_slices); MPI_Group_free(&world_group); MPI_Group_free(&alloc_group); MPI_Win_lock_all((ARMCII_GLOBAL_STATE.rma_nocheck) ? MPI_MODE_NOCHECK : 0, mreg->window); { void *attr_ptr; int *attr_val; int attr_flag; /* this function will always return flag=false in MPI-2 */ MPI_Win_get_attr(mreg->window, MPI_WIN_MODEL, &attr_ptr, &attr_flag); if (attr_flag) { attr_val = (int*)attr_ptr; if (world_me==0) { if ( (*attr_val)==MPI_WIN_SEPARATE ) { printf("MPI_WIN_MODEL = MPI_WIN_SEPARATE \n" ); } else if ( (*attr_val)==MPI_WIN_UNIFIED ) { #ifdef DEBUG printf("MPI_WIN_MODEL = MPI_WIN_UNIFIED \n" ); #endif } else { printf("MPI_WIN_MODEL = %d (not UNIFIED or SEPARATE) \n", *attr_val ); } } } else { if (world_me==0) printf("MPI_WIN_MODEL attribute missing \n"); } } /* Append the new region onto the region list */ if (gmr_list == NULL) { gmr_list = mreg; } else { gmr_t *parent = gmr_list; while (parent->next != NULL) parent = parent->next; parent->next = mreg; mreg->prev = parent; } return mreg; } /** Destroy/free a shared memory region. * * @param[in] ptr Pointer within range of the segment (e.g. base pointer). * @param[in] group Group on which to perform the free. */ void gmr_destroy(gmr_t *mreg, ARMCI_Group *group) { int search_proc_in, search_proc_out, search_proc_out_grp; void *search_base = NULL; int alloc_me, alloc_nproc; int world_me, world_nproc; MPI_Comm_rank(group->comm, &alloc_me); MPI_Comm_size(group->comm, &alloc_nproc); MPI_Comm_rank(ARMCI_GROUP_WORLD.comm, &world_me); MPI_Comm_size(ARMCI_GROUP_WORLD.comm, &world_nproc); /* All-to-all exchange of a pair. This is so that we * can support passing NULL into ARMCI_Free() which is permitted when a * process allocates 0 bytes. Unfortunately, in this case we still need to * identify the mem region and free it. */ if (mreg == NULL) search_proc_in = -1; else { search_proc_in = world_me; search_base = mreg->slices[world_me].base; } /* Collectively decide on who will provide the base address */ MPI_Allreduce(&search_proc_in, &search_proc_out, 1, MPI_INT, MPI_MAX, group->comm); /* Everyone passed NULL. Nothing to free. */ if (search_proc_out < 0) return; /* Translate world rank to group rank */ search_proc_out_grp = ARMCII_Translate_absolute_to_group(group, search_proc_out); /* Broadcast the base address */ MPI_Bcast(&search_base, sizeof(void*), MPI_BYTE, search_proc_out_grp, group->comm); /* If we were passed NULL, look up the mem region using the pair */ if (mreg == NULL) mreg = gmr_lookup(search_base, search_proc_out); /* If it's still not found, the user may have passed the wrong group */ ARMCII_Assert_msg(mreg != NULL, "Could not locate the desired allocation"); /* Remove from the list of mem regions */ if (mreg->prev == NULL) { ARMCII_Assert(gmr_list == mreg); gmr_list = mreg->next; if (mreg->next != NULL) mreg->next->prev = NULL; } else { mreg->prev->next = mreg->next; if (mreg->next != NULL) mreg->next->prev = mreg->prev; } ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); MPI_Win_unlock_all(mreg->window); /* Destroy the window and free all buffers */ MPI_Win_free(&mreg->window); if (!ARMCII_GLOBAL_STATE.use_win_allocate) { if (mreg->slices[world_me].base != NULL) { MPI_Free_mem(mreg->slices[world_me].base); } } free(mreg->slices); free(mreg); } /** Destroy all memory regions (called by finalize). * * @return Number of mem regions destroyed. */ int gmr_destroy_all(void) { int count = 0; while (gmr_list != NULL) { gmr_destroy(gmr_list, &gmr_list->group); count++; } return count; } /** Lookup a shared memory region using an address and process id. * * @param[in] ptr Pointer within range of the segment (e.g. base pointer). * @param[in] proc Process on which the data lives. * @return Pointer to the mem region object. */ gmr_t *gmr_lookup(void *ptr, int proc) { gmr_t *mreg; mreg = gmr_list; while (mreg != NULL) { ARMCII_Assert(proc < mreg->nslices); /* Jeff: Why is uint8_t used here? .base is (void*). */ if (proc < mreg->nslices) { const uint8_t *base = mreg->slices[proc].base; const gmr_size_t size = mreg->slices[proc].size; if ((uint8_t*) ptr >= base && (uint8_t*) ptr < base + size) break; } mreg = mreg->next; } return mreg; } /** One-sided put operation. Source buffer must be private. * * @param[in] mreg Memory region * @param[in] src Source address (local) * @param[in] dst Destination address (remote) * @param[in] size Number of bytes to transfer * @param[in] proc Absolute process id of target process * @return 0 on success, non-zero on failure */ int gmr_put(gmr_t *mreg, void *src, void *dst, int size, int proc) { ARMCII_Assert_msg(src != NULL, "Invalid local address"); return gmr_put_typed(mreg, src, size, MPI_BYTE, dst, size, MPI_BYTE, proc); } /** One-sided put operation with type arguments. Source buffer must be private. * * @param[in] mreg Memory region * @param[in] src Address of source data * @param[in] src_count Number of elements of the given type at the source * @param[in] src_type MPI datatype of the source elements * @param[in] dst Address of destination buffer * @param[in] dst_count Number of elements of the given type at the destination * @param[in] src_type MPI datatype of the destination elements * @param[in] size Number of bytes to transfer * @param[in] proc Absolute process id of target process * @return 0 on success, non-zero on failure */ int gmr_put_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *dst, int dst_count, MPI_Datatype dst_type, int proc) { int grp_proc; gmr_size_t disp; MPI_Aint lb, extent; grp_proc = ARMCII_Translate_absolute_to_group(&mreg->group, proc); ARMCII_Assert(grp_proc >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); // Calculate displacement from beginning of the window if (dst == MPI_BOTTOM) disp = 0; else disp = (gmr_size_t) ((uint8_t*)dst - (uint8_t*)mreg->slices[proc].base); // Perform checks MPI_Type_get_true_extent(dst_type, &lb, &extent); ARMCII_Assert_msg(disp >= 0 && disp < mreg->slices[proc].size, "Invalid remote address"); ARMCII_Assert_msg(disp + dst_count*extent <= mreg->slices[proc].size, "Transfer is out of range"); if (ARMCII_GLOBAL_STATE.rma_atomicity) { MPI_Accumulate(src, src_count, src_type, grp_proc, (MPI_Aint) disp, dst_count, dst_type, MPI_REPLACE, mreg->window); } else { MPI_Put(src, src_count, src_type, grp_proc, (MPI_Aint) disp, dst_count, dst_type, mreg->window); } return 0; } /** One-sided get operation. Destination buffer must be private. * * @param[in] mreg Memory region * @param[in] src Source address (remote) * @param[in] dst Destination address (local) * @param[in] size Number of bytes to transfer * @param[in] proc Absolute process id of target process * @return 0 on success, non-zero on failure */ int gmr_get(gmr_t *mreg, void *src, void *dst, int size, int proc) { ARMCII_Assert_msg(dst != NULL, "Invalid local address"); return gmr_get_typed(mreg, src, size, MPI_BYTE, dst, size, MPI_BYTE, proc); } /** One-sided get operation with type arguments. Destination buffer must be private. * * @param[in] mreg Memory region * @param[in] src Address of source data * @param[in] src_count Number of elements of the given type at the source * @param[in] src_type MPI datatype of the source elements * @param[in] dst Address of destination buffer * @param[in] dst_count Number of elements of the given type at the destination * @param[in] src_type MPI datatype of the destination elements * @param[in] size Number of bytes to transfer * @param[in] proc Absolute process id of target process * @return 0 on success, non-zero on failure */ int gmr_get_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *dst, int dst_count, MPI_Datatype dst_type, int proc) { int grp_proc; gmr_size_t disp; MPI_Aint lb, extent; grp_proc = ARMCII_Translate_absolute_to_group(&mreg->group, proc); ARMCII_Assert(grp_proc >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); // Calculate displacement from beginning of the window if (src == MPI_BOTTOM) disp = 0; else disp = (gmr_size_t) ((uint8_t*)src - (uint8_t*)mreg->slices[proc].base); // Perform checks MPI_Type_get_true_extent(src_type, &lb, &extent); ARMCII_Assert_msg(disp >= 0 && disp < mreg->slices[proc].size, "Invalid remote address"); ARMCII_Assert_msg(disp + src_count*extent <= mreg->slices[proc].size, "Transfer is out of range"); if (ARMCII_GLOBAL_STATE.rma_atomicity) { MPI_Get_accumulate(NULL, 0, MPI_BYTE, dst, dst_count, dst_type, grp_proc, (MPI_Aint) disp, src_count, src_type, MPI_NO_OP, mreg->window); } else { MPI_Get(dst, dst_count, dst_type, grp_proc, (MPI_Aint) disp, src_count, src_type, mreg->window); } return 0; } /** One-sided accumulate operation. Source buffer must be private. * * @param[in] mreg Memory region * @param[in] src Source address (local) * @param[in] dst Destination address (remote) * @param[in] type MPI type of the given buffers * @param[in] count Number of elements of the given type to transfer * @param[in] proc Absolute process id of the target * @return 0 on success, non-zero on failure */ int gmr_accumulate(gmr_t *mreg, void *src, void *dst, int count, MPI_Datatype type, int proc) { ARMCII_Assert_msg(src != NULL, "Invalid local address"); return gmr_accumulate_typed(mreg, src, count, type, dst, count, type, proc); } /** One-sided accumulate operation with typed arguments. Source buffer must be private. * * @param[in] mreg Memory region * @param[in] src Address of source data * @param[in] src_count Number of elements of the given type at the source * @param[in] src_type MPI datatype of the source elements * @param[in] dst Address of destination buffer * @param[in] dst_count Number of elements of the given type at the destination * @param[in] dst_type MPI datatype of the destination elements * @param[in] size Number of bytes to transfer * @param[in] proc Absolute process id of target process * @return 0 on success, non-zero on failure */ int gmr_accumulate_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *dst, int dst_count, MPI_Datatype dst_type, int proc) { int grp_proc; gmr_size_t disp; MPI_Aint lb, extent; grp_proc = ARMCII_Translate_absolute_to_group(&mreg->group, proc); ARMCII_Assert(grp_proc >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); // Calculate displacement from beginning of the window if (dst == MPI_BOTTOM) disp = 0; else disp = (gmr_size_t) ((uint8_t*)dst - (uint8_t*)mreg->slices[proc].base); // Perform checks MPI_Type_get_true_extent(dst_type, &lb, &extent); ARMCII_Assert_msg(disp >= 0 && disp < mreg->slices[proc].size, "Invalid remote address"); ARMCII_Assert_msg(disp + dst_count*extent <= mreg->slices[proc].size, "Transfer is out of range"); MPI_Accumulate(src, src_count, src_type, grp_proc, (MPI_Aint) disp, dst_count, dst_type, MPI_SUM, mreg->window); return 0; } armci-mpi/src/gmr.h0000644000175000017500000000456112663426407013751 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #ifndef HAVE_GMR_H #define HAVE_GMR_H #include #include #include typedef armci_size_t gmr_size_t; typedef struct { void *base; gmr_size_t size; } gmr_slice_t; typedef struct gmr_s { MPI_Win window; /* MPI Window for this GMR */ ARMCI_Group group; /* Copy of the ARMCI group on which this GMR was allocated */ struct gmr_s *prev; /* Linked list pointers for GMR list */ struct gmr_s *next; gmr_slice_t *slices; /* Array of GMR slices for this allocation */ int nslices; } gmr_t; extern gmr_t *gmr_list; gmr_t *gmr_create(gmr_size_t local_size, void **base_ptrs, ARMCI_Group *group); void gmr_destroy(gmr_t *mreg, ARMCI_Group *group); int gmr_destroy_all(void); gmr_t *gmr_lookup(void *ptr, int proc); int gmr_get(gmr_t *mreg, void *src, void *dst, int size, int target); int gmr_put(gmr_t *mreg, void *src, void *dst, int size, int target); int gmr_accumulate(gmr_t *mreg, void *src, void *dst, int count, MPI_Datatype type, int proc); int gmr_get_accumulate(gmr_t *mreg, void *src, void *out, void *dst, int count, MPI_Datatype type, MPI_Op op, int proc); int gmr_fetch_and_op(gmr_t *mreg, void *src, void *out, void *dst, MPI_Datatype type, MPI_Op op, int proc); int gmr_get_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *dst, int dst_count, MPI_Datatype dst_type, int proc); int gmr_put_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *dst, int dst_count, MPI_Datatype dst_type, int proc); int gmr_accumulate_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *dst, int dst_count, MPI_Datatype dst_type, int proc); int gmr_get_accumulate_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *out, int out_count, MPI_Datatype out_type, void *dst, int dst_count, MPI_Datatype dst_type, MPI_Op op, int proc); int gmr_lockall(gmr_t *mreg); int gmr_unlockall(gmr_t *mreg); int gmr_flush(gmr_t *mreg, int proc, int local_only); int gmr_flushall(gmr_t *mreg, int local_only); int gmr_sync(gmr_t *mreg); void gmr_progress(void); #endif /* HAVE_GMR_H */ armci-mpi/src/gmr-extras.c0000644000175000017500000001707712663426407015256 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include #include /** One-sided get-accumulate operation. Source and output buffer must be private. * * @param[in] mreg Memory region * @param[in] src Source address (local) * @param[in] out Result address (local) * @param[in] dst Destination address (remote) * @param[in] type MPI type of the given buffers * @param[in] count Number of elements of the given type to transfer * @param[in] op MPI_Op to apply at the destination * @param[in] proc Absolute process id of the target * @return 0 on success, non-zero on failure */ int gmr_get_accumulate(gmr_t *mreg, void *src, void *out, void *dst, int count, MPI_Datatype type, MPI_Op op, int proc) { ARMCII_Assert_msg(src != NULL && out != NULL, "Invalid local address(es)"); return gmr_get_accumulate_typed(mreg, src, count, type, out, count, type, dst, count, type, op, proc); } /** One-sided get-accumulate operation with typed arguments. Source and output buffer must be private. * * @param[in] mreg Memory region * @param[in] src Address of source data * @param[in] src_count Number of elements of the given type at the source * @param[in] src_type MPI datatype of the source elements * @param[in] out Address of output buffer (same process as the source) * @param[in] out_count Number of elements of the given type at the ouput * @param[in] out_type MPI datatype of the output elements * @param[in] dst Address of destination buffer * @param[in] dst_count Number of elements of the given type at the destination * @param[in] dst_type MPI datatype of the destination elements * @param[in] size Number of bytes to transfer * @param[in] op MPI_Op to apply at the destination * @param[in] proc Absolute process id of target process * @return 0 on success, non-zero on failure */ int gmr_get_accumulate_typed(gmr_t *mreg, void *src, int src_count, MPI_Datatype src_type, void *out, int out_count, MPI_Datatype out_type, void *dst, int dst_count, MPI_Datatype dst_type, MPI_Op op, int proc) { int grp_proc; gmr_size_t disp; MPI_Aint lb, extent; grp_proc = ARMCII_Translate_absolute_to_group(&mreg->group, proc); ARMCII_Assert(grp_proc >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); // Calculate displacement from beginning of the window if (dst == MPI_BOTTOM) disp = 0; else disp = (gmr_size_t) ((uint8_t*)dst - (uint8_t*)mreg->slices[proc].base); // Perform checks MPI_Type_get_true_extent(dst_type, &lb, &extent); ARMCII_Assert_msg(disp >= 0 && disp < mreg->slices[proc].size, "Invalid remote address"); ARMCII_Assert_msg(disp + dst_count*extent <= mreg->slices[proc].size, "Transfer is out of range"); MPI_Get_accumulate(src, src_count, src_type, out, out_count, out_type, grp_proc, (MPI_Aint) disp, dst_count, dst_type, op, mreg->window); return 0; } /** One-sided fetch-and-op. Source and output buffer must be private. * * @param[in] mreg Memory region * @param[in] src Address of source data * @param[in] out Address of output buffer (same process as the source) * @param[in] dst Address of destination buffer * @param[in] type MPI datatype of the source, output and destination elements * @param[in] op MPI_Op to apply at the destination * @param[in] proc Absolute process id of target process * @return 0 on success, non-zero on failure */ int gmr_fetch_and_op(gmr_t *mreg, void *src, void *out, void *dst, MPI_Datatype type, MPI_Op op, int proc) { int grp_proc; gmr_size_t disp; grp_proc = ARMCII_Translate_absolute_to_group(&mreg->group, proc); ARMCII_Assert(grp_proc >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); /* built-in types only so no chance of seeing MPI_BOTTOM */ disp = (gmr_size_t) ((uint8_t*)dst - (uint8_t*)mreg->slices[proc].base); // Perform checks ARMCII_Assert_msg(disp >= 0 && disp < mreg->slices[proc].size, "Invalid remote address"); ARMCII_Assert_msg(disp <= mreg->slices[proc].size, "Transfer is out of range"); MPI_Fetch_and_op(src, out, type, grp_proc, (MPI_Aint) disp, op, mreg->window); return 0; } /** Lock a memory region at all targets so that one-sided operations can be performed. * * @param[in] mreg Memory region * @return 0 on success, non-zero on failure */ int gmr_lockall(gmr_t *mreg) { int grp_me = ARMCII_Translate_absolute_to_group(&mreg->group, ARMCI_GROUP_WORLD.rank); ARMCII_Assert(grp_me >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); MPI_Win_lock_all((ARMCII_GLOBAL_STATE.rma_nocheck) ? MPI_MODE_NOCHECK : 0, mreg->window); return 0; } /** Unlock a memory region at all targets. * * @param[in] mreg Memory region * @return 0 on success, non-zero on failure */ int gmr_unlockall(gmr_t *mreg) { int grp_me = ARMCII_Translate_absolute_to_group(&mreg->group, ARMCI_GROUP_WORLD.rank); ARMCII_Assert(grp_me >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); MPI_Win_unlock_all(mreg->window); return 0; } /** Flush a memory region for local or remote completion. * * @param[in] mreg Memory region * @param[in] proc Absolute process id of the target * @param[in] local_only Only flush the operation locally. * @return 0 on success, non-zero on failure */ int gmr_flush(gmr_t *mreg, int proc, int local_only) { int grp_proc = ARMCII_Translate_absolute_to_group(&mreg->group, proc); int grp_me = ARMCII_Translate_absolute_to_group(&mreg->group, ARMCI_GROUP_WORLD.rank); ARMCII_Assert(grp_proc >= 0 && grp_me >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); ARMCII_Assert_msg(grp_proc < mreg->group.size, "grp_proc exceeds group size!"); if (!local_only || ARMCII_GLOBAL_STATE.end_to_end_flush) { MPI_Win_flush(grp_proc, mreg->window); } else { MPI_Win_flush_local(grp_proc, mreg->window); } return 0; } /** Flush a memory region for remote completion to all targets. * * @param[in] mreg Memory region * @return 0 on success, non-zero on failure */ int gmr_flushall(gmr_t *mreg, int local_only) { int grp_me = ARMCII_Translate_absolute_to_group(&mreg->group, ARMCI_GROUP_WORLD.rank); ARMCII_Assert(grp_me >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); if (!local_only || ARMCII_GLOBAL_STATE.end_to_end_flush) { MPI_Win_flush_all(mreg->window); } else { MPI_Win_flush_local_all(mreg->window); } return 0; } /** Sync memory region so that public and private windows are the same. * * @param[in] mreg Memory region * @return 0 on success, non-zero on failure */ int gmr_sync(gmr_t *mreg) { int grp_me = ARMCII_Translate_absolute_to_group(&mreg->group, ARMCI_GROUP_WORLD.rank); ARMCII_Assert(grp_me >= 0); ARMCII_Assert_msg(mreg->window != MPI_WIN_NULL, "A non-null mreg contains a null window."); MPI_Win_sync(mreg->window); return 0; } void gmr_progress(void) { int flag; MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, ARMCI_GROUP_WORLD.comm, &flag, MPI_STATUS_IGNORE); return; } armci-mpi/src/debug.h0000644000175000017500000000333512662706250014244 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #ifndef _DEBUG_H_ #define _DEBUG_H_ #include #include #include enum debug_cats_e { DEBUG_CAT_ALL = -1, DEBUG_CAT_NONE = 0, DEBUG_CAT_MEM_REGION = 0x1, // 2^0 DEBUG_CAT_ALLOC = 0x2, // 2^1 DEBUG_CAT_MUTEX = 0x4, // 2^2 DEBUG_CAT_GROUPS = 0x8, // 2^3 DEBUG_CAT_CTREE = 0x10, // 2^4, ... DEBUG_CAT_IOV = 0x20 }; /* A logical OR of the debug message categories that are enabled. */ extern unsigned DEBUG_CATS_ENABLED; #ifdef NO_SEATBELTS #define ARMCII_Assert(X) ((void)0) #define ARMCII_Assert_msg(X,MSG) ((void)0) #else void ARMCII_Assert_fail(const char *expr, const char *msg, const char *file, int line, const char *func); #define ARMCII_Assert(EXPR) do { if (unlikely(!(EXPR))) ARMCII_Assert_fail(#EXPR, NULL, __FILE__, __LINE__, __func__); } while(0) #define ARMCII_Assert_msg(EXPR, MSG) do { if (unlikely(!(EXPR))) ARMCII_Assert_fail(#EXPR, MSG, __FILE__, __LINE__, __func__); } while(0) #endif /* NO_SEATBELTS */ #ifdef NO_SEATBELTS #define DEBUG_CAT_ENABLED(X) 0 #define ARMCII_Dbg_print(CAT,...) ((void)0) #else #define DEBUG_CAT_ENABLED(X) (DEBUG_CATS_ENABLED & (X)) void ARMCII_Dbg_print_impl(const char *func, const char *format, ...); #define ARMCII_Dbg_print(CAT,...) do { if (DEBUG_CAT_ENABLED(CAT)) ARMCII_Dbg_print_impl(__func__,__VA_ARGS__); } while (0) #endif /* NO_SEATBELTS */ #define ARMCII_Error(...) ARMCII_Error_impl(__FILE__,__LINE__,__func__,__VA_ARGS__) void ARMCII_Error_impl(const char *file, const int line, const char *func, const char *msg, ...); void ARMCII_Warning(const char *fmt, ...); #endif /* _DEBUG_H_ */ armci-mpi/src/conflict_tree.c0000644000175000017500000002043012662706250015764 0ustar mbanckmbanck/** Copyright (C) 2010. See COPYRIGHT in top-level directory. * * Conflict Tree -- James Dinan * * Conflict trees are used by ARMCI-MPI to detect conflicting accesses due to * overlapping memory regions. * * This implementation uses an AVL tree which is a self-balancing binary tree. * In contrast with interval and segment trees which can store mutiple * overlapping regions and support stabbing queries, the conflict tree does * not allow any overlap among elements in the tree. If an overlapping insert * is performed, it will fail. Thus, objects in the tree are totally ordered * and a standard binary tree (in this case, the AVL tree) is sufficient for * detecting conflicts. */ #include #include #include #include #define MAX(A,B) (((A) > (B)) ? A : B) static ctree_t ctree_balance(ctree_t node); static void ctree_destroy_rec(ctree_t root); static inline int ctree_node_height(ctree_t node); static inline void ctree_rotate_left(ctree_t node); static inline void ctree_rotate_right(ctree_t node); const ctree_t CTREE_EMPTY = NULL; /** Locate the node that conflicts with the given address range. * * @param[in] root Root of the ctree. * @param[in] lo Low end of the range. * @param[in] hi High end of the range. * @return Pointer to the ctree node or NULL if not found. */ ctree_t ctree_locate(ctree_t root, uint8_t *lo, uint8_t *hi) { ctree_t cur = root; while (cur != NULL) { if ( (lo >= cur->lo && lo <= cur->hi) || (hi >= cur->lo && hi <= cur->hi) || (lo < cur->lo && hi > cur->hi)) break; else if (lo < cur->lo) cur = cur->left; else /* lo > cur->hi */ cur = cur->right; } return cur; } /** Insert an address range into the conflict detection tree. * * @param[inout] root The root of the tree * @param[in] lo Lower bound of the address range * @param[in] hi Upper bound of the address range * @return Zero on success, nonzero when a conflict is detected. * When a conflict exists, the range is not added. */ int ctree_insert(ctree_t *root, uint8_t *lo, uint8_t *hi) { ctree_t cur; ctree_t new_node = (ctree_t) malloc(sizeof(struct ctree_node_s)); new_node->lo = lo; new_node->hi = hi; new_node->height = 1; new_node->parent = NULL; new_node->left = NULL; new_node->right = NULL; cur = *root; // CASE: Empty tree if (cur == NULL) { *root = new_node; return 0; } for (;;) { // Check for conflicts as we go if ( (lo >= cur->lo && lo <= cur->hi) || (hi >= cur->lo && hi <= cur->hi) || (lo < cur->lo && hi > cur->hi)) { ARMCII_Dbg_print(DEBUG_CAT_CTREE, "Conflict inserting [%p, %p] with [%p, %p]\n", lo, hi, cur->lo, cur->hi); free(new_node); return 1; } // Place in left subtree else if (lo < cur->lo) { if (cur->left == NULL) { new_node->parent = cur; cur->left = new_node; *root = ctree_balance(cur); return 0; } else { cur = cur->left; } } // Place in right subtree else /* lo > cur->hi */ { if (cur->right == NULL) { new_node->parent = cur; cur->right = new_node; *root = ctree_balance(cur); return 0; } else { cur = cur->right; } } } } /** Rotate the given pivot node to the left. * * @param[in] node This is the pivot node, it will be the new subtree root * after the rotation is performed. */ static inline void ctree_rotate_left(ctree_t node) { ctree_t old_root = node->parent; //ARMCII_Dbg_print(DEBUG_CAT_CTREE, "[%10p, %10p] l=%d r=%d\n", node->lo, node->hi, // ctree_node_height(node->left), ctree_node_height(node->right)); ARMCII_Assert(old_root->right == node); // Set the parent pointer node->parent = old_root->parent; // Set the parent's child pointer if (node->parent != NULL) { if (node->parent->left == old_root) node->parent->left = node; else node->parent->right = node; } // Set child pointers and their parents old_root->right = node->left; if (old_root->right != NULL) old_root->right->parent = old_root; node->left = old_root; node->left->parent = node; old_root->height = MAX(ctree_node_height(old_root->left), ctree_node_height(old_root->right)) + 1; node->height = MAX(ctree_node_height(node->left), ctree_node_height(node->right)) + 1; } /** Rotate the given pivot node to the right. * * @param[in] node This is the pivot node, it will be the new subtree root * after the rotation is performed. */ static inline void ctree_rotate_right(ctree_t node) { ctree_t old_root = node->parent; //ARMCII_Dbg_print(DEBUG_CAT_CTREE, "[%10p, %10p] l=%d r=%d\n", node->lo, node->hi, // ctree_node_height(node->left), ctree_node_height(node->right)); ARMCII_Assert(old_root->left == node); // Set the parent pointer node->parent = old_root->parent; // Set the parent's child pointer if (node->parent != NULL) { if (node->parent->left == old_root) node->parent->left = node; else node->parent->right = node; } // Set child pointers and their parents old_root->left = node->right; if (old_root->left != NULL) old_root->left->parent = old_root; node->right = old_root; node->right->parent = node; old_root->height = MAX(ctree_node_height(old_root->left), ctree_node_height(old_root->right)) + 1; node->height = MAX(ctree_node_height(node->left), ctree_node_height(node->right)) + 1; } /** Fetch the height of a given node. */ static inline int ctree_node_height(ctree_t node) { if (node == NULL) return 0; else return node->height; } /** Rebalance the tree starting with the current node and proceeding * upwards towards the root. */ static ctree_t ctree_balance(ctree_t node) { ctree_t root = node; while (node != NULL) { int height_l = ctree_node_height(node->left); int height_r = ctree_node_height(node->right); node->height = MAX(ctree_node_height(node->left), ctree_node_height(node->right)) + 1; // Rebalance to preserve the property that right and left heights // differ by at most 1. if (abs(height_l - height_r) >= 2) { // CASE: Right is heavy if (height_l - height_r == -2) { int height_r_l = ctree_node_height(node->right->left); int height_r_r = ctree_node_height(node->right->right); // CASE: Right, right if (height_r_l - height_r_r <= 0) { node = node->right; ctree_rotate_left(node); } // CASE: Right, left else { ctree_rotate_right(node->right->left); node = node->right; ctree_rotate_left(node); } // CASE: Left is heavy } else if (height_l - height_r == 2) { int height_l_l = ctree_node_height(node->left->left); int height_l_r = ctree_node_height(node->left->right); // CASE: Left, left if (height_l_l - height_l_r >= 0) { node = node->left; ctree_rotate_right(node); } // CASE: Left, right else { ctree_rotate_left(node->left->right); node = node->left; ctree_rotate_right(node); } } else { ARMCII_Error("CTree invariant violated, height difference of %d is too large", height_l - height_r); } } root = node; node = node->parent; } return root; } /** Recursive function to traverse a tree and destroy all its nodes. */ static void ctree_destroy_rec(ctree_t root) { if (root == NULL) return; ctree_destroy_rec(root->left); ctree_destroy_rec(root->right); free(root); } /** Destroy a conflict tree. */ void ctree_destroy(ctree_t *root) { ctree_destroy_rec(*root); *root = NULL; } /** Print out the contents of the conflict detection tree. */ void ctree_print(ctree_t root) { if (root != NULL) { int i,idx; char s[32] = ""; ctree_print(root->left); for (i = 1, idx = 0; i < 32-1 && i < root->height; i++) idx += sprintf(s+idx, "\t"); printf("%10p:%s[%p, %p] p=%p h=%d\n", (void*)root, s, root->lo, root->hi, (void*)(root->parent), root->height); ctree_print(root->right); } } armci-mpi/src/mutex.c0000644000175000017500000000630612662706250014314 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #define MAX_TIMEOUT 1000 #define TIMEOUT_MUL 2 #define MIN(A,B) (((A) < (B)) ? (A) : (B)) /** This is the handle for the "default" group of mutexes used by the * standard ARMCI mutex API */ static armcix_mutex_hdl_t armci_mutex_hdl = NULL; /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Create_mutexes = PARMCI_Create_mutexes #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Create_mutexes ARMCI_Create_mutexes #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Create_mutexes as PARMCI_Create_mutexes #endif /* -- end weak symbols block -- */ /** Create ARMCI mutexes. Collective. * * @param[in] count Number of mutexes to create on the calling process */ int PARMCI_Create_mutexes(int count) { if (armci_mutex_hdl != NULL) ARMCII_Error("attempted to create ARMCI mutexes multiple times"); armci_mutex_hdl = ARMCIX_Create_mutexes_hdl(count, &ARMCI_GROUP_WORLD); if (armci_mutex_hdl != NULL) return 0; else return 1; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Destroy_mutexes = PARMCI_Destroy_mutexes #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Destroy_mutexes ARMCI_Destroy_mutexes #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Destroy_mutexes as PARMCI_Destroy_mutexes #endif /* -- end weak symbols block -- */ /** Destroy/free ARMCI mutexes. Collective. */ int PARMCI_Destroy_mutexes(void) { int err; if (armci_mutex_hdl == NULL) ARMCII_Error("attempted to free unallocated ARMCI mutexes"); err = ARMCIX_Destroy_mutexes_hdl(armci_mutex_hdl); armci_mutex_hdl = NULL; return err; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Lock = PARMCI_Lock #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Lock ARMCI_Lock #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Lock as PARMCI_Lock #endif /* -- end weak symbols block -- */ /** Lock a mutex. * * @param[in] mutex Number of the mutex to lock * @param[in] proc Target process for the lock operation */ void PARMCI_Lock(int mutex, int proc) { if (armci_mutex_hdl == NULL) ARMCII_Error("attempted to lock on unallocated ARMCI mutexes"); ARMCIX_Lock_hdl(armci_mutex_hdl, mutex, proc); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Unlock = PARMCI_Unlock #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Unlock ARMCI_Unlock #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Unlock as PARMCI_Unlock #endif /* -- end weak symbols block -- */ /** Unlock a mutex. * * @param[in] mutex Number of the mutex to unlock * @param[in] proc Target process for the unlock operation */ void PARMCI_Unlock(int mutex, int proc) { if (armci_mutex_hdl == NULL) ARMCII_Error("attempted to unlock on unallocated ARMCI mutexes"); ARMCIX_Unlock_hdl(armci_mutex_hdl, mutex, proc); } armci-mpi/src/message.c0000644000175000017500000003014012663426407014573 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include /** Query process rank from messaging (MPI) layer. */ int armci_msg_me(void) { int me; MPI_Comm_rank(ARMCI_GROUP_WORLD.comm, &me); return me; } /** Query number of processes. */ int armci_msg_nproc(void) { int nproc; MPI_Comm_size(ARMCI_GROUP_WORLD.comm, &nproc); return nproc; } /** Abort the application. * * @param[in] code Exit error code */ void armci_msg_abort(int code) { MPI_Abort(ARMCI_GROUP_WORLD.comm, code); } /** Get the wall clock time. * * @return Wall clock time */ double armci_timer(void) { return MPI_Wtime(); } /** Broadcast a message. Collective. * * @param[in] buffer Source buffer on root, destination elsewhere. * @param[in] len Length of the message in bytes. * @param[in] root Rank of the root process. */ void armci_msg_bcast(void *buf_in, int len, int root) { void **buf; /* Is the buffer an input or an output? */ if (ARMCI_GROUP_WORLD.rank == root) ARMCII_Buf_prepare_read_vec(&buf_in, &buf, 1, len); else ARMCII_Buf_prepare_write_vec(&buf_in, &buf, 1, len); MPI_Bcast(buf[0], len, MPI_BYTE, root, ARMCI_GROUP_WORLD.comm); if (ARMCI_GROUP_WORLD.rank == root) ARMCII_Buf_finish_read_vec(&buf_in, buf, 1, len); else ARMCII_Buf_finish_write_vec(&buf_in, buf, 1, len); } /** Broadcast a message. Collective. * * @param[in] buffer Source buffer on root, destination elsewhere. * @param[in] len Length of the message in bytes. * @param[in] root Rank of the root process. */ void armci_msg_brdcst(void *buffer, int len, int root) { armci_msg_bcast(buffer, len, root); } /** Broadcast a message on the given scope. Collective. * * @param[in] scope Scope for the broadcast * @param[in] buffer Source buffer on root, destination elsewhere. * @param[in] len Length of the message in bytes. * @param[in] root Rank of the root process. */ void armci_msg_bcast_scope(int scope, void *buffer, int len, int root) { armci_msg_group_bcast_scope(scope, buffer, len, root, &ARMCI_GROUP_WORLD); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak armci_msg_barrier = parmci_msg_barrier #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF parmci_msg_barrier armci_msg_barrier #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate armci_msg_barrier as parmci_msg_barrier #endif /* -- end weak symbols block -- */ /** Barrier from the messaging layer. */ void parmci_msg_barrier(void) { MPI_Barrier(ARMCI_GROUP_WORLD.comm); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak armci_msg_group_barrier = parmci_msg_group_barrier #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF parmci_msg_group_barrier armci_msg_group_barrier #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate armci_msg_group_barrier as parmci_msg_group_barrier #endif /* -- end weak symbols block -- */ /** Message barrier on a group. * * @param[in] group Group on which to perform barrier */ void parmci_msg_group_barrier(ARMCI_Group *group) { MPI_Barrier(group->comm); } /** Broadcast on a group. Collective. * * @param[in] scope ARMCI scope * @param[inout] buf Input on the root, output on all other processes * @param[in] len Number of bytes in the message * @param[in] abs_root Absolute rank of the process at the root of the broadcast * @param[in] group ARMCI group on which to perform communication */ void armci_msg_group_bcast_scope(int scope, void *buf_in, int len, int abs_root, ARMCI_Group *group) { int grp_root; void **buf; if (scope == SCOPE_ALL || scope == SCOPE_MASTERS) { /* Is the buffer an input or an output? */ if (ARMCI_GROUP_WORLD.rank == abs_root) ARMCII_Buf_prepare_read_vec(&buf_in, &buf, 1, len); else ARMCII_Buf_prepare_write_vec(&buf_in, &buf, 1, len); grp_root = ARMCII_Translate_absolute_to_group(group, abs_root); ARMCII_Assert(grp_root >= 0 && grp_root < group->size); MPI_Bcast(buf[0], len, MPI_BYTE, grp_root, group->comm); if (ARMCI_GROUP_WORLD.rank == abs_root) ARMCII_Buf_finish_read_vec(&buf_in, buf, 1, len); else ARMCII_Buf_finish_write_vec(&buf_in, buf, 1, len); } else /* SCOPE_NODE */ { grp_root = 0; /* This is a self-broadcast, which is a no-op. */ } } /** Send a two-sided message. * * @param[in] tag Message tag (must match on sender and receiver) * @param[in] buf Buffer containing the message * @param[in] nbytes Length of the message in bytes * @param[in] dest Destination process id */ void armci_msg_snd(int tag, void *buf_in, int nbytes, int dest) { void **buf; ARMCII_Buf_prepare_read_vec(&buf_in, &buf, 1, nbytes); MPI_Send(buf[0], nbytes, MPI_BYTE, dest, tag, ARMCI_GROUP_WORLD.comm); ARMCII_Buf_finish_read_vec(&buf_in, buf, 1, nbytes); } /** Receive a two-sided message. * * @param[in] tag Message tag (must match on sender and receiver) * @param[in] buf Buffer containing the message * @param[in] nbytes_buf Size of the buffer in bytes * @param[out] nbytes_msg Length of the message received in bytes (NULL to ignore) * @param[in] src Source process id */ void armci_msg_rcv(int tag, void *buf_out, int nbytes_buf, int *nbytes_msg, int src) { void **buf; MPI_Status status; ARMCII_Buf_prepare_write_vec(&buf_out, &buf, 1, nbytes_buf); MPI_Recv(buf[0], nbytes_buf, MPI_BYTE, src, tag, ARMCI_GROUP_WORLD.comm, &status); ARMCII_Buf_finish_write_vec(&buf_out, buf, 1, nbytes_buf); if (nbytes_msg != NULL) MPI_Get_count(&status, MPI_BYTE, nbytes_msg); } /** Receive a two-sided message from any source. * * @param[in] tag Message tag (must match on sender and receiver) * @param[in] buf Buffer containing the message * @param[in] nbytes_buf Size of the buffer in bytes * @param[out] nbytes_msg Length of the message received in bytes (NULL to ignore) * @return Rank of the message source */ int armci_msg_rcvany(int tag, void *buf_out, int nbytes_buf, int *nbytes_msg) { void **buf; MPI_Status status; ARMCII_Buf_prepare_write_vec(&buf_out, &buf, 1, nbytes_buf); MPI_Recv(buf[0], nbytes_buf, MPI_BYTE, MPI_ANY_SOURCE, tag, ARMCI_GROUP_WORLD.comm, &status); ARMCII_Buf_finish_write_vec(&buf_out, buf, 1, nbytes_buf); if (nbytes_msg != NULL) MPI_Get_count(&status, MPI_BYTE, nbytes_msg); return status.MPI_SOURCE; } void armci_msg_reduce(void *x, int n, char *op, int type) { armci_msg_reduce_scope(SCOPE_ALL, x, n, op, type); } void armci_msg_reduce_scope(int scope, void *x, int n, char *op, int type) { ARMCII_Error("unimplemented"); // TODO } /** Map process IDs onto a binary tree. * * @param[in] scope Scope of processes involved * @param[out] root Process id of the root * @param[out] up Process id of my parent * @param[out] left Process id of my left child * @param[out] right Process if of my right child */ void armci_msg_bintree(int scope, int *root, int *up, int *left, int *right) { int me, nproc; if (scope == SCOPE_NODE) { *root = 0; *left = -1; *right = -1; return; } me = armci_msg_me(); nproc = armci_msg_nproc(); *root = 0; *up = (me == 0) ? -1 : (me - 1) / 2; *left = 2*me + 1; if (*left >= nproc) *left = -1; *right = 2*me + 2; if (*right >= nproc) *right = -1; } /** Data packet for a select operation. Data entry is a struct from GA's * runtime where the first element is a value and later parts are indices of * the element in the GA. */ typedef struct { int contribute; int type; uint8_t data[1]; } sel_data_t; /** Select operations to be used in allreduce. */ MPI_Op MPI_SELMIN_OP; MPI_Op MPI_SELMAX_OP; /** Min operator for armci_msg_sel */ void ARMCII_Msg_sel_min_op(void *data_in, void *data_inout, int *len, MPI_Datatype *datatype) { sel_data_t *sd_1, *sd_2; sd_1 = (sel_data_t*) data_in; sd_2 = (sel_data_t*) data_inout; if (sd_1->contribute && !sd_2->contribute) { ARMCI_Copy(data_in, data_inout, *len); } else if (sd_1->contribute && sd_2->contribute) { #define MSG_SEL_MIN_OP(X,Y,LEN,TYPE) \ do { \ if (*(TYPE*)((sel_data_t*)X)->data < *(TYPE*)((sel_data_t*)Y)->data) \ ARMCI_Copy(X, Y, LEN); \ } while (0) switch (sd_1->type) { case ARMCI_INT: MSG_SEL_MIN_OP(data_in, data_inout, *len, int); break; case ARMCI_LONG: MSG_SEL_MIN_OP(data_in, data_inout, *len, long); break; case ARMCI_LONG_LONG: MSG_SEL_MIN_OP(data_in, data_inout, *len, long long); break; case ARMCI_FLOAT: MSG_SEL_MIN_OP(data_in, data_inout, *len, float); break; case ARMCI_DOUBLE: MSG_SEL_MIN_OP(data_in, data_inout, *len, double); break; default: ARMCII_Error("Invalid data type (%d)", sd_1->type); } #undef MSG_SEL_MIN_OP } /* else: no need to copy, data_inout already contains what we want to return */ } /** Min operator for armci_msg_sel */ void ARMCII_Msg_sel_max_op(void *data_in, void *data_inout, int *len, MPI_Datatype *datatype) { sel_data_t *sd_1, *sd_2; sd_1 = (sel_data_t*) data_in; sd_2 = (sel_data_t*) data_inout; if (sd_1->contribute && !sd_2->contribute) { ARMCI_Copy(data_in, data_inout, *len); } else if (sd_1->contribute && sd_2->contribute) { #define MSG_SEL_MAX_OP(X,Y,LEN,TYPE) \ do { \ if (*(TYPE*)((sel_data_t*)X)->data > *(TYPE*)((sel_data_t*)Y)->data) \ ARMCI_Copy(X, Y, LEN); \ } while (0) switch (sd_1->type) { case ARMCI_INT: MSG_SEL_MAX_OP(data_in, data_inout, *len, int); break; case ARMCI_LONG: MSG_SEL_MAX_OP(data_in, data_inout, *len, long); break; case ARMCI_LONG_LONG: MSG_SEL_MAX_OP(data_in, data_inout, *len, long long); break; case ARMCI_FLOAT: MSG_SEL_MAX_OP(data_in, data_inout, *len, float); break; case ARMCI_DOUBLE: MSG_SEL_MAX_OP(data_in, data_inout, *len, double); break; default: ARMCII_Error("Invalid data type (%d)", sd_1->type); } #undef MSG_SEL_MIN_OP } /* else: no need to copy, data_inout already contains what we want to return */ } /** Collective index selection reduce operation. */ void armci_msg_sel(void *x, int n, char *op, int type, int contribute) { armci_msg_sel_scope(SCOPE_ALL, x, n, op, type, contribute); } /** Collective index selection reduce operation (scoped). */ void armci_msg_sel_scope(int scope, void *x, int n, char* op, int type, int contribute) { MPI_Comm sel_comm; sel_data_t *data_in, *data_out; void **x_buf; /* printf("[%d] armci_msg_sel_scope(scope=%d, x=%p, n=%d, op=%s, type=%d, contribute=%d)\n", ARMCI_GROUP_WORLD.rank, scope, x, n, op, type, contribute); */ /* Determine the scope of the collective operation */ if (scope == SCOPE_ALL || scope == SCOPE_MASTERS) sel_comm = ARMCI_GROUP_WORLD.comm; else sel_comm = MPI_COMM_SELF; data_in = malloc(sizeof(sel_data_t)+n-1); data_out = malloc(sizeof(sel_data_t)+n-1); ARMCII_Assert(data_in != NULL && data_out != NULL); ARMCII_Buf_prepare_read_vec(&x, &x_buf, 1, n); data_in->contribute = contribute; data_in->type = type; if (contribute) ARMCI_Copy(x, data_in->data, n); if (strncmp(op, "min", 3) == 0) { MPI_Allreduce(data_in, data_out, sizeof(sel_data_t)+n-1, MPI_BYTE, MPI_SELMIN_OP, sel_comm); } else if (strncmp(op, "max", 3) == 0) { MPI_Allreduce(data_in, data_out, sizeof(sel_data_t)+n-1, MPI_BYTE, MPI_SELMAX_OP, sel_comm); } else { ARMCII_Error("Invalid operation (%s)", op); } ARMCI_Copy(data_out->data, x, n); ARMCII_Buf_finish_write_vec(&x, x_buf, 1, n); free(data_in); free(data_out); } armci-mpi/src/topology.c0000644000175000017500000000272112662706250015023 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include /** NOTE: Domains are not implemented. These dummy wrappers assume that all * domains are of size 1. */ /** Query the size of a given domain. * * @param[in] domain Desired domain. * @param[in] domain_id Domain id or -1 for my domain. */ int armci_domain_nprocs(armci_domain_t domain, int domain_id) { return 1; } /** Query which domain a process belongs to. */ int armci_domain_id(armci_domain_t domain, int glob_proc_id) { return glob_proc_id; } /** Translate a domain process ID to a global process ID. */ int armci_domain_glob_proc_id(armci_domain_t domain, int domain_id, int loc_proc_id) { ARMCII_Assert(loc_proc_id == 0); // Groups must be size 1 return domain_id; } /** Query the ID of my domain. */ int armci_domain_my_id(armci_domain_t domain) { return ARMCI_GROUP_WORLD.rank; } /** Query the number of domains. */ int armci_domain_count(armci_domain_t domain) { return ARMCI_GROUP_WORLD.size; } /** Query if the given process shared a domain with me. */ int armci_domain_same_id(armci_domain_t domain, int glob_proc_id) { return glob_proc_id == ARMCI_GROUP_WORLD.rank; } /** Query if a process is on the same node as the caller. * * @param[in] proc Process id in question */ int ARMCI_Same_node(int proc) { return proc == ARMCI_GROUP_WORLD.rank; } armci-mpi/src/message_gop.c0000644000175000017500000001734212662706250015445 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include /* MPI Operations, registered in Init */ MPI_Op MPI_ABSMIN_OP; MPI_Op MPI_ABSMAX_OP; #define IABS(X) (((X) > 0 ) ? X : -X) #define FABS(X) (((X) > 0.0) ? X : -X) #define MIN(X,Y) (((X) < (Y)) ? X : Y) #define MAX(X,Y) (((X) > (Y)) ? X : Y) #define ABSMIN(IN,INOUT,COUNT,DTYPE,ABSOP) \ do { \ int i; \ DTYPE *in = (DTYPE *)IN; \ DTYPE *io = (DTYPE *)INOUT; \ for (i = 0; i < COUNT; i++) { \ const DTYPE x = ABSOP(in[i]); \ const DTYPE y = ABSOP(io[i]); \ io[i] = MIN(x,y); \ } \ } while (0) /** MPI reduction operator that computes the minimum absolute value. */ void ARMCII_Absmin_op(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype) { const int count = *len; MPI_Datatype dt = *datatype; if (dt == MPI_INT) { ABSMIN(invec, inoutvec, count, int, IABS); } else if (dt == MPI_LONG) { ABSMIN(invec, inoutvec, count, long, IABS); } else if (dt == MPI_LONG_LONG) { ABSMIN(invec, inoutvec, count, long long, IABS); } else if (dt == MPI_FLOAT) { ABSMIN(invec, inoutvec, count, float, FABS); } else if (dt == MPI_DOUBLE) { ABSMIN(invec, inoutvec, count, double, FABS); } else { ARMCII_Error("unknown type (%d)", *datatype); } } #undef ABSMIN #define ABSMAX(IN,INOUT,COUNT,DTYPE,ABSOP) \ do { \ int i; \ DTYPE *in = (DTYPE *)IN; \ DTYPE *io = (DTYPE *)INOUT; \ for (i = 0; i < COUNT; i++) { \ const DTYPE x = ABSOP(in[i]); \ const DTYPE y = ABSOP(io[i]); \ io[i] = MAX(x,y); \ } \ } while (0) /** MPI reduction operator that computes the maximum absolute value. */ void ARMCII_Absmax_op(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype) { const int count = *len; MPI_Datatype dt = *datatype; if (dt == MPI_INT) { ABSMAX(invec, inoutvec, count, int, IABS); } else if (dt == MPI_LONG) { ABSMAX(invec, inoutvec, count, long, IABS); } else if (dt == MPI_LONG_LONG) { ABSMAX(invec, inoutvec, count, long long, IABS); } else if (dt == MPI_FLOAT) { ABSMAX(invec, inoutvec, count, float, FABS); } else if (dt == MPI_DOUBLE) { ABSMAX(invec, inoutvec, count, double, FABS); } else { ARMCII_Error("unknown type (%d)", *datatype); } } #undef ABSMAX #define ABSV(IN,INOUT,COUNT,DTYPE,ABSOP) \ do { \ int i; \ DTYPE *in = (DTYPE *)IN; \ DTYPE *io = (DTYPE *)INOUT; \ for (i = 0; i < COUNT; i++) \ io[i] = ABSOP(in[i]); \ } while (0) /** Compute the absolute value. */ void ARMCII_Absv_op(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype) { const int count = *len; MPI_Datatype dt = *datatype; if (dt == MPI_INT) { ABSV(invec, inoutvec, count, int, IABS); } else if (dt == MPI_LONG) { ABSV(invec, inoutvec, count, long, IABS); } else if (dt == MPI_LONG_LONG) { ABSV(invec, inoutvec, count, long long, IABS); } else if (dt == MPI_FLOAT) { ABSV(invec, inoutvec, count, float, FABS); } else if (dt == MPI_DOUBLE) { ABSV(invec, inoutvec, count, double, FABS); } else { ARMCII_Error("unknown type (%d)", *datatype); } } #undef ABSV /** General ARMCI global operation (reduction). Collective on group. * * @param[in] scope Scope in which to perform the GOP (only SCOPE_ALL is supported) * @param[inout] x Vector of n data elements, contains input and will contain output. * @param[in] n Length of x * @param[in] op One of '+', '*', 'max', 'min', 'absmax', 'absmin' * @param[in] type Data type of x (e.g. ARMCI_INT, ...) * @param[in] group Group on which to perform the GOP */ void armci_msg_group_gop_scope(int scope, void *x, int n, char *op, int type, ARMCI_Group *group) { void *out, **x_buf; MPI_Op mpi_op; MPI_Datatype mpi_type; MPI_Comm comm; int mpi_type_size; /* FIXME: scope argument presently ignored */ if (scope == SCOPE_ALL || scope == SCOPE_MASTERS) comm = group->comm; else comm = MPI_COMM_SELF; if (op[0] == '+') { mpi_op = MPI_SUM; } else if (op[0] == '*') { mpi_op = MPI_PROD; } else if (strncmp(op, "max", 3) == 0) { mpi_op = MPI_MAX; } else if (strncmp(op, "min", 3) == 0) { mpi_op = MPI_MIN; } else if (strncmp(op, "or", 2) == 0) { mpi_op = MPI_BOR; } else if (strncmp(op, "absmax", 6) == 0) { mpi_op = MPI_ABSMAX_OP; } else if (strncmp(op, "absmin", 6) == 0) { mpi_op = MPI_ABSMIN_OP; } else { ARMCII_Error("unknown operation \'%s\'", op); return; } switch(type) { case ARMCI_INT: mpi_type = MPI_INT; break; case ARMCI_LONG: mpi_type = MPI_LONG; break; case ARMCI_LONG_LONG: mpi_type = MPI_LONG_LONG; break; case ARMCI_FLOAT: mpi_type = MPI_FLOAT; break; case ARMCI_DOUBLE: mpi_type = MPI_DOUBLE; break; default: ARMCII_Error("unknown type (%d)", type); return; } MPI_Type_size(mpi_type, &mpi_type_size); ARMCII_Buf_prepare_read_vec(&x, &x_buf, 1, n*mpi_type_size); // ABS MAX/MIN are unary as well as binary. We need to also apply abs in the // single processor case when reduce would normally just be a no-op. if (group->size == 1 && (mpi_op == MPI_ABSMAX_OP || mpi_op == MPI_ABSMIN_OP)) { ARMCII_Absv_op(x_buf[0], x_buf[0], &n, &mpi_type); } else { out = malloc(n*mpi_type_size); ARMCII_Assert(out != NULL); MPI_Allreduce(x_buf[0], out, n, mpi_type, mpi_op, comm); ARMCI_Copy(out, x_buf[0], n*mpi_type_size); free(out); } ARMCII_Buf_finish_write_vec(&x, x_buf, 1, n*mpi_type_size); } void armci_msg_group_igop(int *x, int n, char *op, ARMCI_Group *group) { armci_msg_group_gop_scope(SCOPE_ALL, x, n, op, ARMCI_INT, group); } void armci_msg_group_lgop(long *x, int n, char *op, ARMCI_Group *group) { armci_msg_group_gop_scope(SCOPE_ALL, x, n, op, ARMCI_LONG, group); } void armci_msg_group_llgop(long long *x, int n, char *op, ARMCI_Group *group) { armci_msg_group_gop_scope(SCOPE_ALL, x, n, op, ARMCI_LONG_LONG, group); } void armci_msg_group_fgop(float *x, int n, char *op, ARMCI_Group *group) { armci_msg_group_gop_scope(SCOPE_ALL, x, n, op, ARMCI_FLOAT, group); } void armci_msg_group_dgop(double *x, int n, char *op, ARMCI_Group *group) { armci_msg_group_gop_scope(SCOPE_ALL, x, n, op, ARMCI_DOUBLE, group); } void armci_msg_gop_scope(int scope, void *x, int n, char *op, int type) { armci_msg_group_gop_scope(scope, x, n, op, type, &ARMCI_GROUP_WORLD); } void armci_msg_igop(int *x, int n, char *op) { armci_msg_gop_scope(SCOPE_ALL, x, n, op, ARMCI_INT); } void armci_msg_lgop(long *x, int n, char *op) { armci_msg_gop_scope(SCOPE_ALL, x, n, op, ARMCI_LONG); } void armci_msg_llgop(long long *x, int n, char *op) { armci_msg_gop_scope(SCOPE_ALL, x, n, op, ARMCI_LONG_LONG); } void armci_msg_fgop(float *x, int n, char *op) { armci_msg_gop_scope(SCOPE_ALL, x, n, op, ARMCI_FLOAT); } void armci_msg_dgop(double *x, int n, char *op) { armci_msg_gop_scope(SCOPE_ALL, x, n, op, ARMCI_DOUBLE); } armci-mpi/src/buffer.c0000644000175000017500000003031412663426407014423 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include /** Prepare a set of buffers for use with a put operation. The returned set of * buffers is guaranteed to be in private space. Copies will be made if needed, * the result should be completed by finish. * * @param[in] orig_bufs Original set of buffers. * @param[out] new_bufs Pointer to the set of private buffers. * @param[in] count Number of entries in the buffer list. * @param[in] size The size of the buffers (all are of the same size). * @return Number of buffers that were moved. */ int ARMCII_Buf_prepare_read_vec(void **orig_bufs, void ***new_bufs_ptr, int count, int size) { int num_moved = 0; if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) { void **new_bufs = malloc(count*sizeof(void*)); int i; for (i = 0; i < count; i++) new_bufs[i] = NULL; for (i = 0; i < count; i++) { // Check if the source buffer is within a shared region. If so, copy it // into a private buffer. gmr_t *mreg = gmr_lookup(orig_bufs[i], ARMCI_GROUP_WORLD.rank); if (mreg != NULL) { MPI_Alloc_mem(size, MPI_INFO_NULL, &new_bufs[i]); ARMCII_Assert(new_bufs[i] != NULL); ARMCI_Copy(orig_bufs[i], new_bufs[i], size); // gmr_get(mreg, orig_bufs[i], new_bufs[i], size, ARMCI_GROUP_WORLD.rank); num_moved++; } else { new_bufs[i] = orig_bufs[i]; } } *new_bufs_ptr = new_bufs; } else { *new_bufs_ptr = orig_bufs; } return num_moved; } /** Finish a set of prepared buffers. Will perform communication and copies as * needed to ensure results are in the original buffers. Temporary space will be * freed. * * @param[in] orig_bufs Original set of buffers. * @param[out] new_bufs Set of private buffers. * @param[in] count Number of entries in the buffer list. * @param[in] size The size of the buffers (all are of the same size). */ void ARMCII_Buf_finish_read_vec(void **orig_bufs, void **new_bufs, int count, int size) { if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) { int i; for (i = 0; i < count; i++) { if (orig_bufs[i] != new_bufs[i]) { MPI_Free_mem(new_bufs[i]); } } free(new_bufs); } } /** Prepare a set of buffers for use with an accumulate operation. The * returned set of buffers is guaranteed to be in private space and scaled. * Copies will be made if needed, the result should be completed by finish. * * @param[in] orig_bufs Original set of buffers. * @param[out] new_bufs Pointer to the set of private buffers. * @param[in] count Number of entries in the buffer list. * @param[in] size The size of the buffers (all are of the same size). * @param[in] datatype The type of the buffer. * @param[in] scale Scaling constant to apply to each buffer. * @return Number of buffers that were moved. */ int ARMCII_Buf_prepare_acc_vec(void **orig_bufs, void ***new_bufs_ptr, int count, int size, int datatype, void *scale) { void **new_bufs; int i, scaled, num_moved = 0; new_bufs = malloc(count*sizeof(void*)); ARMCII_Assert(new_bufs != NULL); scaled = ARMCII_Buf_acc_is_scaled(datatype, scale); for (i = 0; i < count; i++) { gmr_t *mreg = NULL; // Check if the source buffer is within a shared region. if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) mreg = gmr_lookup(orig_bufs[i], ARMCI_GROUP_WORLD.rank); if (scaled) { MPI_Alloc_mem(size, MPI_INFO_NULL, &new_bufs[i]); ARMCII_Assert(new_bufs[i] != NULL); ARMCII_Buf_acc_scale(orig_bufs[i], new_bufs[i], size, datatype, scale); } else { new_bufs[i] = orig_bufs[i]; } if (mreg != NULL) { // If the buffer wasn't copied, we should copy it into a private buffer if (new_bufs[i] == orig_bufs[i]) { MPI_Alloc_mem(size, MPI_INFO_NULL, &new_bufs[i]); ARMCII_Assert(new_bufs[i] != NULL); ARMCI_Copy(orig_bufs[i], new_bufs[i], size); } } if (new_bufs[i] == orig_bufs[i]) num_moved++; } *new_bufs_ptr = new_bufs; return num_moved; } /** Finish a set of prepared buffers. Will perform communication and copies as * needed to ensure results are in the original buffers. Temporary space will be * freed. * * @param[in] orig_bufs Original set of buffers. * @param[out] new_bufs Set of private buffers. * @param[in] count Number of entries in the buffer list. * @param[in] size The size of the buffers (all are of the same size). */ void ARMCII_Buf_finish_acc_vec(void **orig_bufs, void **new_bufs, int count, int size) { int i; for (i = 0; i < count; i++) { if (orig_bufs[i] != new_bufs[i]) { MPI_Free_mem(new_bufs[i]); } } free(new_bufs); } /** Prepare a set of buffers for use with a get operation. The returned set of * buffers is guaranteed to be in private space. Copies will be made if needed, * the result should be completed by finish. * * @param[in] orig_bufs Original set of buffers. * @param[out] new_bufs Pointer to the set of private buffers. * @param[in] count Number of entries in the buffer list. * @param[in] size The size of the buffers (all are of the same size). * @return Number of buffers that were moved. */ int ARMCII_Buf_prepare_write_vec(void **orig_bufs, void ***new_bufs_ptr, int count, int size) { int num_moved = 0; if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) { void **new_bufs = malloc(count*sizeof(void*)); int i; for (i = 0; i < count; i++) new_bufs[i] = NULL; for (i = 0; i < count; i++) { // Check if the destination buffer is within a shared region. If not, create // a temporary private buffer to hold the result. gmr_t *mreg = gmr_lookup(orig_bufs[i], ARMCI_GROUP_WORLD.rank); if (mreg != NULL) { MPI_Alloc_mem(size, MPI_INFO_NULL, &new_bufs[i]); ARMCII_Assert(new_bufs[i] != NULL); num_moved++; } else { new_bufs[i] = orig_bufs[i]; } } *new_bufs_ptr = new_bufs; } else { *new_bufs_ptr = orig_bufs; } return num_moved; } /** Finish a set of prepared buffers. Will perform communication and copies as * needed to ensure results are in the original buffers. Temporary space will be * freed. * * @param[in] orig_bufs Original set of buffers. * @param[out] new_bufs Set of private buffers. * @param[in] count Number of entries in the buffer list. * @param[in] size The size of the buffers (all are of the same size). */ void ARMCII_Buf_finish_write_vec(void **orig_bufs, void **new_bufs, int count, int size) { if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) { int i; for (i = 0; i < count; i++) { if (orig_bufs[i] != new_bufs[i]) { gmr_t *mreg = gmr_lookup(orig_bufs[i], ARMCI_GROUP_WORLD.rank); ARMCII_Assert(mreg != NULL); ARMCI_Copy(new_bufs[i], orig_bufs[i], size); // gmr_put(mreg, new_bufs[i], orig_bufs[i], size, ARMCI_GROUP_WORLD.rank); MPI_Free_mem(new_bufs[i]); } } free(new_bufs); } } #define ARMCII_IS_EQUAL(op,thresh,a,b) (op((a)-(b)) < thresh) /** Check if an operation with the given parameters requires scaling. * * @param[in] datatype Type of the data involved in the operation * @param[in] scale Value of type datatype to scale * @return Nonzero if scale is not the identity scale */ int ARMCII_Buf_acc_is_scaled(int datatype, void *scale) { switch (datatype) { case ARMCI_ACC_INT: if (*((int*)scale) == 1) return 0; break; case ARMCI_ACC_LNG: if (*((long*)scale) == 1) return 0; break; case ARMCI_ACC_FLT: if (fabsf(*((float*)scale)-1.0) < FLT_EPSILON) return 0; break; case ARMCI_ACC_DBL: if (fabs(*((double*)scale)-1.0) < DBL_EPSILON) return 0; break; case ARMCI_ACC_CPL: if (fabsf(((float*)scale)[0]-1.0) < FLT_EPSILON && fabsf(((float*)scale)[1]-0.0) < FLT_EPSILON) return 0; break; case ARMCI_ACC_DCP: if (fabs(((double*)scale)[0]-1.0) < DBL_EPSILON && fabs(((double*)scale)[1]-0.0) < DBL_EPSILON) return 0; break; default: ARMCII_Error("unknown data type (%d)", datatype); } return 1; } /** Prepare a set of buffers for use with an accumulate operation. The * returned set of buffers is guaranteed to be in private space and scaled. * Copies will be made if needed, the result should be completed by finish. * * @param[in] buf Original set of buffers. * @param[in] count Number of entries in the buffer list. * @param[in] size The size of the buffers (all are of the same size). * @param[in] datatype The type of the buffer. * @param[in] scale Scaling constant to apply to each buffer. * @return Pointer to the new buffer or buf */ void ARMCII_Buf_acc_scale(void *buf_in, void *buf_out, int size, int datatype, void *scale) { int j, nelem; int type_size = -1; switch (datatype) { case ARMCI_ACC_INT: MPI_Type_size(MPI_INT, &type_size); nelem= size/type_size; { int *src_i = (int*) buf_in; int *scl_i = (int*) buf_out; const int s = *((int*) scale); for (j = 0; j < nelem; j++) scl_i[j] = src_i[j]*s; } break; case ARMCI_ACC_LNG: MPI_Type_size(MPI_LONG, &type_size); nelem= size/type_size; { long *src_l = (long*) buf_in; long *scl_l = (long*) buf_out; const long s = *((long*) scale); for (j = 0; j < nelem; j++) scl_l[j] = src_l[j]*s; } break; case ARMCI_ACC_FLT: MPI_Type_size(MPI_FLOAT, &type_size); nelem= size/type_size; { float *src_f = (float*) buf_in; float *scl_f = (float*) buf_out; const float s = *((float*) scale); for (j = 0; j < nelem; j++) scl_f[j] = src_f[j]*s; } break; case ARMCI_ACC_DBL: MPI_Type_size(MPI_DOUBLE, &type_size); nelem= size/type_size; { double *src_d = (double*) buf_in; double *scl_d = (double*) buf_out; const double s = *((double*) scale); for (j = 0; j < nelem; j++) scl_d[j] = src_d[j]*s; } break; case ARMCI_ACC_CPL: MPI_Type_size(MPI_FLOAT, &type_size); nelem= size/type_size; { float *src_fc = (float*) buf_in; float *scl_fc = (float*) buf_out; const float s_r = ((float*)scale)[0]; const float s_c = ((float*)scale)[1]; for (j = 0; j < nelem; j += 2) { // Complex multiplication: (a + bi)*(c + di) const float src_fc_j = src_fc[j]; const float src_fc_j_1 = src_fc[j+1]; /* scl_fc[j] = src_fc[j]*s_r - src_fc[j+1]*s_c; scl_fc[j+1] = src_fc[j+1]*s_r + src_fc[j]*s_c; */ scl_fc[j] = src_fc_j*s_r - src_fc_j_1*s_c; scl_fc[j+1] = src_fc_j_1*s_r + src_fc_j*s_c; } } break; case ARMCI_ACC_DCP: MPI_Type_size(MPI_DOUBLE, &type_size); nelem= size/type_size; { double *src_dc = (double*) buf_in; double *scl_dc = (double*) buf_out; const double s_r = ((double*)scale)[0]; const double s_c = ((double*)scale)[1]; for (j = 0; j < nelem; j += 2) { // Complex multiplication: (a + bi)*(c + di) const double src_dc_j = src_dc[j]; const double src_dc_j_1 = src_dc[j+1]; /* scl_dc[j] = src_dc[j]*s_r - src_dc[j+1]*s_c; scl_dc[j+1] = src_dc[j+1]*s_r + src_dc[j]*s_c; */ scl_dc[j] = src_dc_j*s_r - src_dc_j_1*s_c; scl_dc[j+1] = src_dc_j_1*s_r + src_dc_j*s_c; } } break; default: ARMCII_Error("unknown data type (%d)", datatype); } ARMCII_Assert_msg(size % type_size == 0, "Transfer size is not a multiple of the datatype size"); } armci-mpi/src/message.h0000644000175000017500000000634512662706250014606 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #ifndef HAVE_ARMCI_MSG_H #define HAVE_ARMCI_MSG_H #include /** Note on scopes: * * SCOPE_NODE - Include all processes on the current node. In the current * implementation we use MPI_COMM_SELF for this. * SCOPE_MASTERS - Includes one rank from every node. Currently the same as SCOPE_ALL. * SCOPE_ALL - Includes all processes. */ enum armci_scope_e { SCOPE_ALL, SCOPE_NODE, SCOPE_MASTERS}; enum armci_type_e { ARMCI_INT, ARMCI_LONG, ARMCI_LONG_LONG, ARMCI_FLOAT, ARMCI_DOUBLE }; /* Utility routines */ int armci_msg_me(void); int armci_msg_nproc(void); void armci_msg_abort(int code); double armci_timer(void); /* Send/Recv */ void armci_msg_snd(int tag, void *buffer, int len, int to); void armci_msg_rcv(int tag, void *buffer, int buflen, int *msglen, int from); int armci_msg_rcvany(int tag, void *buffer, int buflen, int *msglen); /* Assorted Collectives */ void armci_msg_barrier(void); void armci_msg_group_barrier(ARMCI_Group *group); void armci_msg_bintree(int scope, int *Root, int *Up, int *Left, int *Right); void armci_msg_bcast(void *buffer, int len, int root); void armci_msg_bcast_scope(int scope, void *buffer, int len, int root); void armci_msg_brdcst(void *buffer, int len, int root); void armci_msg_group_bcast_scope(int scope, void *buf, int len, int root, ARMCI_Group *group); /* TODO */ void armci_msg_reduce(void *x, int n, char *op, int type); /* TODO */ void armci_msg_reduce_scope(int scope, void *x, int n, char *op, int type); void armci_msg_sel(void *x, int n, char *op, int type, int contribute); void armci_msg_sel_scope(int scope, void *x, int n, char *op, int type, int contribute); /* TODO */ void armci_exchange_address(void *ptr_ar[], int n); /* TODO */ void armci_msg_clus_brdcst(void *buf, int len); /* TODO */ void armci_msg_clus_igop(int *x, int n, char *op); /* TODO */ void armci_msg_clus_fgop(float *x, int n, char *op); /* TODO */ void armci_msg_clus_lgop(long *x, int n, char *op); /* TODO */ void armci_msg_clus_llgop(long long *x, int n, char *op); /* TODO */ void armci_msg_clus_dgop(double *x, int n, char *op); /* TODO */ void armci_exchange_address_grp(void *ptr_arr[], int n, ARMCI_Group *group); /* TODO */ void armci_grp_clus_brdcst(void *buf, int len, int grp_master, int grp_clus_nproc,ARMCI_Group *mastergroup); /* Global Operations / Reduction Operations */ void armci_msg_gop_scope(int scope, void *x, int n, char *op, int type); void armci_msg_igop(int *x, int n, char *op); void armci_msg_lgop(long *x, int n, char *op); void armci_msg_llgop(long long *x, int n, char *op); void armci_msg_fgop(float *x, int n, char *op); void armci_msg_dgop(double *x, int n, char *op); void armci_msg_group_gop_scope(int scope, void *x, int n, char *op, int type, ARMCI_Group *group); void armci_msg_group_igop(int *x, int n, char *op, ARMCI_Group *group); void armci_msg_group_lgop(long *x, int n, char *op, ARMCI_Group *group); void armci_msg_group_llgop(long long *x, int n, char *op, ARMCI_Group *group); void armci_msg_group_fgop(float *x, int n, char *op, ARMCI_Group *group); void armci_msg_group_dgop(double *x, int n,char *op, ARMCI_Group *group); #endif /* HAVE_ARMCI_MSG_H */ armci-mpi/src/conflict_tree.h0000644000175000017500000000115112662706250015770 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #ifndef _CONFLICT_TREE_H #define _CONFLICT_TREE_H #include struct ctree_node_s { uint8_t *lo; uint8_t *hi; int height; struct ctree_node_s *parent; struct ctree_node_s *left; struct ctree_node_s *right; }; typedef struct ctree_node_s * ctree_t; extern const ctree_t CTREE_EMPTY; int ctree_insert(ctree_t *root, uint8_t *lo, uint8_t *hi); ctree_t ctree_locate(ctree_t root, uint8_t *lo, uint8_t *hi); void ctree_destroy(ctree_t *root); void ctree_print(ctree_t root); #endif /* _CONFLICT_TREE_H */ armci-mpi/src/mutex_hdl_spin.c0000644000175000017500000001515612662706250016177 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /* These mutexes are built using only MPI-2 atomic accumulate. The only * drawback is that they are vulnerable to livelock. Here's how the lock * algorithm works: * * Let mutex be an integer that is initially 0. I hold the mutex when after * adding my rank to it, it is equal to my rank. * * function lock(mutex, p): * * acc(mutex, p, me) // mutex = mutex + me * * while (get(mutex, p) != me) { * acc(mutex, p, -1*me) // -1*me is the value to be accumulated * sleep(random) // Try to avoid livelock/do some backoff * acc(mutex, p, me) * } * * function unlock(mutex, p) * acc(mutex, p, -1*me) */ // TODO: Should each mutex be in a different window? #include #include #include #include #include #include #include #include #define MAX_TIMEOUT 1000 #define TIMEOUT_MUL 2 #define MIN(A,B) (((A) < (B)) ? (A) : (B)) /** Create a mutex group. Collective. * * @param[in] count Number of mutexes to create on the calling process * @return Handle to the mutex group */ armcix_mutex_hdl_t ARMCIX_Create_mutexes_hdl(int count, ARMCI_Group *pgroup) { int ierr, i; armcix_mutex_hdl_t hdl; hdl = malloc(sizeof(struct armcix_mutex_hdl_s)); ARMCII_Assert(hdl != NULL); MPI_Comm_dup(pgroup->comm, &hdl->comm); if (count > 0) { MPI_Alloc_mem(count*sizeof(long), MPI_INFO_NULL, &hdl->base); ARMCII_Assert(hdl->base != NULL); } else { hdl->base = NULL; } hdl->count = count; // Initialize mutexes to 0 for (i = 0; i < count; i++) hdl->base[i] = 0; ierr = MPI_Win_create(hdl->base, count*sizeof(long), sizeof(long) /* displacement size */, MPI_INFO_NULL, hdl->comm, &hdl->window); ARMCII_Assert(ierr == MPI_SUCCESS); return hdl; } /** Destroy/free a mutex group. Collective. * * @param[in] hdl Group to destroy */ int ARMCIX_Destroy_mutexes_hdl(armcix_mutex_hdl_t hdl) { MPI_Win_free(&hdl->window); if (hdl->base) MPI_Free_mem(hdl->base); MPI_Comm_free(&hdl->comm); free(hdl); return 0; } /** Lock a mutex. * * @param[in] hdl Mutex group that the mutex belongs to. * @param[in] mutex Desired mutex number [0..count-1] * @param[in] world_proc Absolute ID of process where the mutex lives */ void ARMCIX_Lock_hdl(armcix_mutex_hdl_t hdl, int mutex, int world_proc) { int rank, nproc, proc; long lock_val, unlock_val, lock_out; int timeout = 1; MPI_Comm_rank(hdl->comm, &rank); MPI_Comm_size(hdl->comm, &nproc); /* User gives us the absolute ID. Translate to the rank in the mutex's group. */ proc = ARMCII_Translate_absolute_to_group(hdl->comm, world_proc); ARMCII_Assert(proc >= 0); lock_val = rank+1; // Map into range 1..nproc unlock_val = -1 * (rank+1); /* mutex <- mutex + rank */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Accumulate(&lock_val, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, MPI_SUM, hdl->window); MPI_Win_unlock(proc, hdl->window); for (;;) { /* read mutex value */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Get(&lock_out, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, hdl->window); MPI_Win_unlock(proc, hdl->window); ARMCII_Assert(lock_out > 0); ARMCII_Assert(lock_out <= nproc*(nproc+1)/2); // Must be < sum of all ranks /* We are holding the mutex */ if (lock_out == rank+1) break; /* mutex <- mutex - rank */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Accumulate(&unlock_val, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, MPI_SUM, hdl->window); MPI_Win_unlock(proc, hdl->window); /* Exponential backoff */ usleep(timeout + rand()%timeout); timeout = MIN(timeout*TIMEOUT_MUL, MAX_TIMEOUT); if (rand() % nproc == 0) // Chance to reset timeout timeout = 1; /* mutex <- mutex + rank */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Accumulate(&lock_val, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, MPI_SUM, hdl->window); MPI_Win_unlock(proc, hdl->window); } } /** Attempt to lock a mutex (non-blocking). * * @param[in] hdl Mutex group that the mutex belongs to. * @param[in] mutex Desired mutex number [0..count-1] * @param[in] world_proc Absolute ID of process where the mutex lives * @return 0 on success, non-zero on failure */ int ARMCIX_Trylock_hdl(armcix_mutex_hdl_t hdl, int mutex, int world_proc) { int rank, nproc, proc; long lock_val, unlock_val, lock_out; ARMCII_Assert(mutex >= 0); MPI_Comm_rank(hdl->comm, &rank); MPI_Comm_size(hdl->comm, &nproc); /* User gives us the absolute ID. Translate to the rank in the mutex's group. */ proc = ARMCII_Translate_absolute_to_group(hdl->comm, world_proc); ARMCII_Assert(proc >= 0); lock_val = rank+1; unlock_val = -1 * (rank+1); /* mutex <- mutex + rank */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Accumulate(&lock_val, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, MPI_SUM, hdl->window); MPI_Win_unlock(proc, hdl->window); /* read mutex value */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Get(&lock_out, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, hdl->window); MPI_Win_unlock(proc, hdl->window); ARMCII_Assert(lock_out > 0); ARMCII_Assert(lock_out <= nproc*(nproc+1)/2); // Must be < sum of all ranks /* We are holding the mutex */ if (lock_out == rank+1) return 0; /* mutex <- mutex - rank */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Accumulate(&unlock_val, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, MPI_SUM, hdl->window); MPI_Win_unlock(proc, hdl->window); return 1; } /** Unlock a mutex. * * @param[in] hdl Mutex group that the mutex belongs to. * @param[in] mutex Desired mutex number [0..count-1] * @param[in] world_proc Absolute ID of process where the mutex lives */ void ARMCIX_Unlock_hdl(armcix_mutex_hdl_t hdl, int mutex, int world_proc) { int rank, nproc, proc; long unlock_val; ARMCII_Assert(mutex >= 0); MPI_Comm_rank(hdl->comm, &rank); MPI_Comm_size(hdl->comm, &nproc); /* User gives us the absolute ID. Translate to the rank in the mutex's group. */ proc = ARMCII_Translate_absolute_to_group(hdl->comm, world_proc); ARMCII_Assert(proc >= 0); unlock_val = -1 * (rank+1); /* mutex <- mutex - rank */ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->window); MPI_Accumulate(&unlock_val, 1, MPI_LONG, proc, mutex, 1, MPI_LONG, MPI_SUM, hdl->window); MPI_Win_unlock(proc, hdl->window); } armci-mpi/src/init_finalize.c0000644000175000017500000003321012663426407015774 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include #ifdef HAVE_PTHREADS #include #if defined(HAVE_NANOSLEEP) #include #elif defined(HAVE_USLEEP) #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #include /* usleep */ #else #warning No naptime available! #endif int progress_active; pthread_t ARMCI_Progress_thread; static void * progress_function(void * arg) { volatile int * active = (volatile int*)arg; #if defined(HAVE_NANOSLEEP) int naptime = 1000 * ARMCII_GLOBAL_STATE.progress_usleep; struct timespec napstruct = { .tv_sec = 0, .tv_nsec = naptime }; #elif defined(HAVE_USLEEP) int naptime = ARMCII_GLOBAL_STATE.progress_usleep; #endif while(*active) { ARMCIX_Progress(); #if defined(HAVE_NANOSLEEP) if (naptime) nanosleep(&napstruct,NULL); #elif defined(HAVE_USLEEP) if (naptime) usleep(naptime); #endif } pthread_exit(NULL); return NULL; } #endif /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Init = PARMCI_Init #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Init ARMCI_Init #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Init as PARMCI_Init #endif /* -- end weak symbols block -- */ /** Initialize ARMCI. MPI must be initialized before this can be called. It * invalid to make ARMCI calls before initialization. Collective on the world * group. * * @return Zero on success */ int PARMCI_Init(void) { char *var; /* GA/TCGMSG end up calling ARMCI_Init() multiple times. */ if (ARMCII_GLOBAL_STATE.init_count > 0) { ARMCII_GLOBAL_STATE.init_count++; return 0; } /* Check for MPI initialization */ { int mpi_is_init, mpi_is_fin; MPI_Initialized(&mpi_is_init); MPI_Finalized(&mpi_is_fin); if (!mpi_is_init || mpi_is_fin) ARMCII_Error("MPI must be initialized before calling ARMCI_Init"); } #ifdef HAVE_PTHREADS /* Check progress thread settings */ { int mpi_thread_level; MPI_Query_thread(&mpi_thread_level); ARMCII_GLOBAL_STATE.progress_thread = ARMCII_Getenv_bool("ARMCI_PROGRESS_THREAD", 0); ARMCII_GLOBAL_STATE.progress_usleep = ARMCII_Getenv_int("ARMCI_PROGRESS_USLEEP", 0); if (ARMCII_GLOBAL_STATE.progress_thread && (mpi_thread_level!=MPI_THREAD_MULTIPLE)) { ARMCII_Warning("ARMCI progress thread requires MPI_THREAD_MULTIPLE (%d); progress thread disabled.\n", mpi_thread_level); ARMCII_GLOBAL_STATE.progress_thread = 0; } if (ARMCII_GLOBAL_STATE.progress_thread && (ARMCII_GLOBAL_STATE.progress_usleep < 0)) { ARMCII_Warning("ARMCI progress thread is not a time machine. (%d)\n", ARMCII_GLOBAL_STATE.progress_usleep); ARMCII_GLOBAL_STATE.progress_usleep = -ARMCII_GLOBAL_STATE.progress_usleep; } } #endif /* Set defaults */ #ifdef ARMCI_GROUP ARMCII_GLOBAL_STATE.noncollective_groups = 1; #endif #ifdef NO_SEATBELTS ARMCII_GLOBAL_STATE.iov_checks = 0; #endif /* Check for debugging flags */ ARMCII_GLOBAL_STATE.debug_alloc = ARMCII_Getenv_bool("ARMCI_DEBUG_ALLOC", 0); { int junk; junk = ARMCII_Getenv_bool("ARMCI_FLUSH_BARRIERS", -1); if (junk != -1) ARMCII_Warning("ARMCI_FLUSH_BARRIERS is deprecated. Use ARMCI_SYNC_AT_BARRIERS instead. \n"); } ARMCII_GLOBAL_STATE.verbose = ARMCII_Getenv_bool("ARMCI_VERBOSE", 0); /* Group formation options */ ARMCII_GLOBAL_STATE.cache_rank_translation=ARMCII_Getenv_bool("ARMCI_CACHE_RANK_TRANSLATION", 1); if (ARMCII_Getenv("ARMCI_NONCOLLECTIVE_GROUPS")) ARMCII_GLOBAL_STATE.noncollective_groups = ARMCII_Getenv_bool("ARMCI_NONCOLLECTIVE_GROUPS", 0); /* Check for IOV flags */ ARMCII_GLOBAL_STATE.iov_checks = ARMCII_Getenv_bool("ARMCI_IOV_CHECKS", 0); ARMCII_GLOBAL_STATE.iov_batched_limit = ARMCII_Getenv_int("ARMCI_IOV_BATCHED_LIMIT", 0); if (ARMCII_GLOBAL_STATE.iov_batched_limit < 0) { ARMCII_Warning("Ignoring invalid value for ARMCI_IOV_BATCHED_LIMIT (%d)\n", ARMCII_GLOBAL_STATE.iov_batched_limit); ARMCII_GLOBAL_STATE.iov_batched_limit = 0; } #if defined(OPEN_MPI) ARMCII_GLOBAL_STATE.iov_method = ARMCII_IOV_BATCHED; #else /* DIRECT leads to addr=NULL errors when ARMCI_{GetV,PutV} are used * Jeff: Is this still true? */ ARMCII_GLOBAL_STATE.iov_method = ARMCII_IOV_DIRECT; #endif var = ARMCII_Getenv("ARMCI_IOV_METHOD"); if (var != NULL) { if (strcmp(var, "AUTO") == 0) ARMCII_GLOBAL_STATE.iov_method = ARMCII_IOV_AUTO; else if (strcmp(var, "CONSRV") == 0) ARMCII_GLOBAL_STATE.iov_method = ARMCII_IOV_CONSRV; else if (strcmp(var, "BATCHED") == 0) ARMCII_GLOBAL_STATE.iov_method = ARMCII_IOV_BATCHED; else if (strcmp(var, "DIRECT") == 0) ARMCII_GLOBAL_STATE.iov_method = ARMCII_IOV_DIRECT; else if (ARMCI_GROUP_WORLD.rank == 0) ARMCII_Warning("Ignoring unknown value for ARMCI_IOV_METHOD (%s)\n", var); } /* Check for Strided flags */ #if defined(OPEN_MPI) ARMCII_GLOBAL_STATE.strided_method = ARMCII_STRIDED_IOV; #else ARMCII_GLOBAL_STATE.strided_method = ARMCII_STRIDED_DIRECT; #endif var = ARMCII_Getenv("ARMCI_STRIDED_METHOD"); if (var != NULL) { if (strcmp(var, "IOV") == 0) ARMCII_GLOBAL_STATE.strided_method = ARMCII_STRIDED_IOV; else if (strcmp(var, "DIRECT") == 0) ARMCII_GLOBAL_STATE.strided_method = ARMCII_STRIDED_DIRECT; else if (ARMCI_GROUP_WORLD.rank == 0) ARMCII_Warning("Ignoring unknown value for ARMCI_STRIDED_METHOD (%s)\n", var); } #ifdef OPEN_MPI if (ARMCII_GLOBAL_STATE.iov_method == ARMCII_IOV_DIRECT || ARMCII_GLOBAL_STATE.strided_method == ARMCII_STRIDED_DIRECT) ARMCII_Warning("MPI Datatypes are broken in RMA in OpenMPI!!!!\n"); #endif /* Shared buffer handling method */ ARMCII_GLOBAL_STATE.shr_buf_method = ARMCII_SHR_BUF_COPY; var = ARMCII_Getenv("ARMCI_SHR_BUF_METHOD"); if (var != NULL) { if (strcmp(var, "COPY") == 0) ARMCII_GLOBAL_STATE.shr_buf_method = ARMCII_SHR_BUF_COPY; else if (strcmp(var, "NOGUARD") == 0) ARMCII_GLOBAL_STATE.shr_buf_method = ARMCII_SHR_BUF_NOGUARD; else if (ARMCI_GROUP_WORLD.rank == 0) ARMCII_Warning("Ignoring unknown value for ARMCI_SHR_BUF_METHOD (%s)\n", var); } /* Use win_allocate or not, to work around MPI-3 RMA implementation bugs (now fixed) in MPICH. */ #ifdef USE_WIN_ALLOCATE int win_alloc_default = 1; #else int win_alloc_default = 0; #endif ARMCII_GLOBAL_STATE.use_win_allocate=ARMCII_Getenv_bool("ARMCI_USE_WIN_ALLOCATE", win_alloc_default); /* Pass alloc_shm to win_allocate / alloc_mem */ ARMCII_GLOBAL_STATE.use_alloc_shm=ARMCII_Getenv_bool("ARMCI_USE_ALLOC_SHM", 1); /* Enable RMA element-wise atomicity */ ARMCII_GLOBAL_STATE.rma_atomicity=ARMCII_Getenv_bool("ARMCI_RMA_ATOMICITY", 1); /* Flush_local becomes flush */ ARMCII_GLOBAL_STATE.end_to_end_flush=ARMCII_Getenv_bool("ARMCI_NO_FLUSH_LOCAL", 0); /* Use MPI_MODE_NOCHECK assertion */ ARMCII_GLOBAL_STATE.rma_nocheck=ARMCII_Getenv_bool("ARMCI_RMA_NOCHECK", 1); /* Setup groups and communicators */ MPI_Comm_dup(MPI_COMM_WORLD, &ARMCI_GROUP_WORLD.comm); ARMCII_Group_init_from_comm(&ARMCI_GROUP_WORLD); ARMCI_GROUP_DEFAULT = ARMCI_GROUP_WORLD; /* Create GOP operators */ MPI_Op_create(ARMCII_Absmin_op, 1 /* commute */, &MPI_ABSMIN_OP); MPI_Op_create(ARMCII_Absmax_op, 1 /* commute */, &MPI_ABSMAX_OP); MPI_Op_create(ARMCII_Msg_sel_min_op, 1 /* commute */, &MPI_SELMIN_OP); MPI_Op_create(ARMCII_Msg_sel_max_op, 1 /* commute */, &MPI_SELMAX_OP); ARMCII_GLOBAL_STATE.init_count++; if (ARMCII_GLOBAL_STATE.verbose) { if (ARMCI_GROUP_WORLD.rank == 0) { int major, minor; MPI_Get_version(&major, &minor); printf("ARMCI-MPI initialized with %d process%s, MPI v%d.%d\n", ARMCI_GROUP_WORLD.size, ARMCI_GROUP_WORLD.size > 1 ? "es":"", major, minor); #ifdef NO_SEATBELTS printf(" NO_SEATBELTS = ENABLED\n"); #endif #ifdef HAVE_PTHREADS printf(" PROGRESS_THREAD = %s\n", ARMCII_GLOBAL_STATE.progress_thread ? "ENABLED" : "DISABLED"); if (ARMCII_GLOBAL_STATE.progress_thread) { printf(" PROGRESS_USLEEP = %d\n", ARMCII_GLOBAL_STATE.progress_usleep); } #endif printf(" ALLOC_SHM used = %s\n", ARMCII_GLOBAL_STATE.use_alloc_shm ? "TRUE" : "FALSE"); printf(" WINDOW type used = %s\n", ARMCII_GLOBAL_STATE.use_win_allocate ? "ALLOCATE" : "CREATE"); if (ARMCII_GLOBAL_STATE.use_win_allocate) { /* Jeff: Using win_allocate leads to correctness issues with some * MPI implementations since 3c4ad2abc8c387fcdec3a7f3f44fa5fd75653ece. */ /* This is required on Cray systems with CrayMPI 7.0.0 (at least) */ /* Update (Feb. 2015): Xin and Min found the bug in Fetch_and_op and * it is fixed upstream. */ ARMCII_Warning("MPI_Win_allocate can lead to correctness issues.\n"); } printf(" STRIDED_METHOD = %s\n", ARMCII_Strided_methods_str[ARMCII_GLOBAL_STATE.strided_method]); printf(" IOV_METHOD = %s\n", ARMCII_Iov_methods_str[ARMCII_GLOBAL_STATE.iov_method]); if ( ARMCII_GLOBAL_STATE.iov_method == ARMCII_IOV_BATCHED || ARMCII_GLOBAL_STATE.iov_method == ARMCII_IOV_AUTO) { if (ARMCII_GLOBAL_STATE.iov_batched_limit > 0) printf(" IOV_BATCHED_LIMIT = %d\n", ARMCII_GLOBAL_STATE.iov_batched_limit); else printf(" IOV_BATCHED_LIMIT = UNLIMITED\n"); } printf(" IOV_CHECKS = %s\n", ARMCII_GLOBAL_STATE.iov_checks ? "TRUE" : "FALSE"); printf(" SHR_BUF_METHOD = %s\n", ARMCII_Shr_buf_methods_str[ARMCII_GLOBAL_STATE.shr_buf_method]); printf(" NONCOLLECTIVE_GROUPS = %s\n", ARMCII_GLOBAL_STATE.noncollective_groups ? "TRUE" : "FALSE"); printf(" CACHE_RANK_TRANSLATION = %s\n", ARMCII_GLOBAL_STATE.cache_rank_translation ? "TRUE" : "FALSE"); printf(" DEBUG_ALLOC = %s\n", ARMCII_GLOBAL_STATE.debug_alloc ? "TRUE" : "FALSE"); printf("\n"); fflush(NULL); } MPI_Barrier(ARMCI_GROUP_WORLD.comm); } #ifdef HAVE_PTHREADS /* Create the asynchronous progress thread */ { if(ARMCII_GLOBAL_STATE.progress_thread) { progress_active = 1; int rc = pthread_create(&ARMCI_Progress_thread, NULL, &progress_function, &progress_active); if (rc) { ARMCII_Warning("ARMCI progress thread creation failed (%d).\n", rc); } } } #endif return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Init_args = PARMCI_Init_args #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Init_args ARMCI_Init_args #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Init_args as PARMCI_Init_args #endif /* -- end weak symbols block -- */ /** Initialize ARMCI. MPI must be initialized before this can be called. It * is invalid to make ARMCI calls before initialization. Collective on the * world group. * * @param[inout] argc Command line argument count * @param[inout] argv Command line arguments * @return Zero on success */ int PARMCI_Init_args(int *argc, char ***argv) { return PARMCI_Init(); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Initialized = PARMCI_Initialized #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Initialized ARMCI_Initialized #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Initialized as PARMCI_Initialized #endif /* -- end weak symbols block -- */ /** Check if ARMCI has been initialized. * * @return Non-zero if ARMCI has been initialized. */ int PARMCI_Initialized(void) { return ARMCII_GLOBAL_STATE.init_count > 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Finalize = PARMCI_Finalize #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Finalize ARMCI_Finalize #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Finalize as PARMCI_Finalize #endif /* -- end weak symbols block -- */ /** Finalize ARMCI. Must be called before MPI is finalized. ARMCI calls are * not valid after finalization. Collective on world group. * * @return Zero on success */ int PARMCI_Finalize(void) { int nfreed; /* GA/TCGMSG end up calling ARMCI_Finalize() multiple times. */ if (ARMCII_GLOBAL_STATE.init_count == 0) { return 0; } ARMCII_GLOBAL_STATE.init_count--; /* Only finalize on the last matching call */ if (ARMCII_GLOBAL_STATE.init_count > 0) { return 0; } #ifdef HAVE_PTHREADS /* Destroy the asynchronous progress thread */ { if(ARMCII_GLOBAL_STATE.progress_thread) { progress_active = 0; int rc = pthread_join(ARMCI_Progress_thread, NULL); if (rc) { ARMCII_Warning("ARMCI progress thread join failed (%d).\n", rc); } } } #endif nfreed = gmr_destroy_all(); if (nfreed > 0 && ARMCI_GROUP_WORLD.rank == 0) ARMCII_Warning("Freed %d leaked allocations\n", nfreed); /* Free GOP operators */ MPI_Op_free(&MPI_ABSMIN_OP); MPI_Op_free(&MPI_ABSMAX_OP); MPI_Op_free(&MPI_SELMIN_OP); MPI_Op_free(&MPI_SELMAX_OP); ARMCI_Cleanup(); ARMCI_Group_free(&ARMCI_GROUP_WORLD); return 0; } /** Cleaup ARMCI resources. Call finalize instead. */ void ARMCI_Cleanup(void) { return; } armci-mpi/src/internals.c0000644000175000017500000000710712663426407015155 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include /** ARMCI Internal global state */ global_state_t ARMCII_GLOBAL_STATE = { 0 }; /** Enum strings */ char ARMCII_Strided_methods_str[][10] = { "IOV", "DIRECT" }; char ARMCII_Iov_methods_str[][10] = { "AUTO", "CONSRV", "BATCHED", "DIRECT" }; char ARMCII_Shr_buf_methods_str[][10] = { "COPY", "NOGUARD" }; /** Raise an internal fatal ARMCI error. * * @param[in] file Current file name (__FILE__) * @param[in] line Current line numeber (__LINE__) * @param[in] func Current function name (__func__) * @param[in] msg Message to be printed * @param[in] code Exit error code */ void ARMCII_Error_impl(const char *file, const int line, const char *func, const char *msg, ...) { va_list ap; int disp; char string[500]; disp = 0; va_start(ap, msg); disp += vsnprintf(string, 500, msg, ap); va_end(ap); fprintf(stderr, "[%d] ARMCI Internal error in %s (%s:%d)\n[%d] Message: %s\n", ARMCI_GROUP_WORLD.rank, func, file, line, ARMCI_GROUP_WORLD.rank, string); MPI_Abort(ARMCI_GROUP_WORLD.comm, 100); } /** Translate a world process rank to the corresponding process rank in the * ARMCI group. * * @param[in] group Group to translate to. * @param[in] world_rank Rank of the process in the world group. * @return Rank in group or -1 if not in the group. */ int ARMCII_Translate_absolute_to_group(ARMCI_Group *group, int world_rank) { int group_rank; MPI_Group world_group, sub_group; ARMCII_Assert(world_rank >= 0 && world_rank < ARMCI_GROUP_WORLD.size); if (!(0 <= world_rank && world_rank < ARMCI_GROUP_WORLD.size)) { ARMCII_Warning("world_rank (%d) is not in the range [0,ARMCI_GROUP_WORLD.size=%d)!\n", world_rank, ARMCI_GROUP_WORLD.size); } /* Check if group is the world group */ if (group->comm == ARMCI_GROUP_WORLD.comm) { group_rank = world_rank; } /* Check for translation cache */ else if (group->grp_to_abs != NULL) { group_rank = group->abs_to_grp[world_rank]; } else { /* Translate the rank */ MPI_Comm_group(ARMCI_GROUP_WORLD.comm, &world_group); MPI_Comm_group(group->comm, &sub_group); MPI_Group_translate_ranks(world_group, 1, &world_rank, sub_group, &group_rank); MPI_Group_free(&world_group); MPI_Group_free(&sub_group); } /* Check if translation failed */ if (group_rank == MPI_UNDEFINED) return -1; else return group_rank; } /** Translate an ARMCI accumulate data type into an MPI type so we can pass it * to mem regions. * * @param[in] armci_datatype ARMCI accumulate data type * @param[out] mpi_type MPI data type * @param[out] type_size Size of the MPI data type */ void ARMCII_Acc_type_translate(int armci_datatype, MPI_Datatype *mpi_type, int *type_size) { // Determine the MPI type for the transfer switch (armci_datatype) { case ARMCI_ACC_INT: *mpi_type = MPI_INT; break; case ARMCI_ACC_LNG: *mpi_type = MPI_LONG; break; case ARMCI_ACC_FLT: *mpi_type = MPI_FLOAT; break; case ARMCI_ACC_DBL: *mpi_type = MPI_DOUBLE; break; case ARMCI_ACC_CPL: *mpi_type = MPI_FLOAT; break; case ARMCI_ACC_DCP: *mpi_type = MPI_DOUBLE; break; default: ARMCII_Error("unknown data type", 100); return; } MPI_Type_size(*mpi_type, type_size); } armci-mpi/src/rmw.c0000644000175000017500000000637712663426407013773 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Rmw = PARMCI_Rmw #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Rmw ARMCI_Rmw #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Rmw as PARMCI_Rmw #endif /* -- end weak symbols block -- */ /** Perform atomic read-modify-write on the given integer or long location and * return the location's original value. * * \note ARMCI RMW operations are atomic with respect to other RMW operations, * but not with respect to other one-sided operations (get, put, acc, etc). * * @param[in] op Operation to be performed: * ARMCI_FETCH_AND_ADD (int) * ARMCI_FETCH_AND_ADD_LONG * ARMCI_SWAP (int) * ARMCI_SWAP_LONG * @param[out] ploc Location to store the original value. * @param[in] prem Location on which to perform atomic operation. * @param[in] value Value to add to remote location (ignored for swap). * @param[in] proc Process rank for the target buffer. */ int PARMCI_Rmw(int op, void *ploc, void *prem, int value, int proc) { int is_swap = 0, is_long = 0; MPI_Datatype type; MPI_Op rop; gmr_t *src_mreg, *dst_mreg; /* If NOGUARD is set, assume the buffer is not shared */ if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) src_mreg = gmr_lookup(ploc, ARMCI_GROUP_WORLD.rank); else src_mreg = NULL; dst_mreg = gmr_lookup(prem, proc); ARMCII_Assert_msg(dst_mreg != NULL, "Invalid remote pointer"); if (op == ARMCI_SWAP_LONG || op == ARMCI_FETCH_AND_ADD_LONG) { is_long = 1; type = MPI_LONG; } else type = MPI_INT; if (op == ARMCI_SWAP || op == ARMCI_SWAP_LONG) { is_swap = 1; rop = MPI_REPLACE; } else if (op == ARMCI_FETCH_AND_ADD || op == ARMCI_FETCH_AND_ADD_LONG) rop = MPI_SUM; else ARMCII_Error("invalid operation (%d)", op); /* We hold the DLA lock if (src_mreg != NULL). */ if (is_swap) { long out_val_l, src_val_l = *((long*)ploc); int out_val_i, src_val_i = *((int*)ploc); gmr_fetch_and_op(dst_mreg, is_long ? (void*) &src_val_l : (void*) &src_val_i /* src */, is_long ? (void*) &out_val_l : (void*) &out_val_i /* out */, prem /* dst */, type, rop, proc); gmr_flush(dst_mreg, proc, 0); /* it's a round trip so w.r.t. flush, local=remote */ if (is_long) *(long*) ploc = out_val_l; else *(int*) ploc = out_val_i; } else /* fetch-and-add */ { long fetch_val_l, add_val_l = value; int fetch_val_i, add_val_i = value; gmr_fetch_and_op(dst_mreg, is_long ? (void*) &add_val_l : (void*) &add_val_i /* src */, is_long ? (void*) &fetch_val_l : (void*) &fetch_val_i /* out */, prem /* dst */, type, rop, proc); gmr_flush(dst_mreg, proc, 0); /* it's a round trip so w.r.t. flush, local=remote */ if (is_long) *(long*) ploc = fetch_val_l; else *(int*) ploc = fetch_val_i; } return 0; } armci-mpi/src/armci_internals.h0000644000175000017500000002002312663426407016325 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #ifndef HAVE_ARMCI_INTERNALS_H #define HAVE_ARMCI_INTERNALS_H #include #include #if HAVE_STDINT_H # include #elif HAVE_INTTYPES_H # include #endif #ifdef HAVE_PTHREADS # include #endif /* Likely/Unlikely macros borrowed from MPICH: */ /* These likely/unlikely macros provide static branch prediction hints to the * compiler, if such hints are available. Simply wrap the relevant expression in * the macro, like this: * * if (unlikely(ptr == NULL)) { * // ... some unlikely code path ... * } * * They should be used sparingly, especially in upper-level code. It's easy to * incorrectly estimate branching likelihood, while the compiler can often do a * decent job if left to its own devices. * * These macros are not namespaced because the namespacing is cumbersome. */ /* safety guard for now, add a configure check in the future */ #if ( defined(__GNUC__) && (__GNUC__ >= 3) ) || defined(__IBMC__) || defined(__INTEL_COMPILER) || defined(__clang__) # define unlikely(x_) __builtin_expect(!!(x_),0) # define likely(x_) __builtin_expect(!!(x_),1) #else # define unlikely(x_) (x_) # define likely(x_) (x_) #endif /* Disable safety checks if the user asks for it */ #ifdef NO_SEATBELTS #define NO_CHECK_OVERLAP /* Disable checks for overlapping IOV operations */ //#define NO_USE_CTREE /* Use the slower O(N) check instead of the conflict tree */ #define NO_CHECK_BUFFERS /* Disable checking for shared origin buffers */ #else #endif /* Internal types */ enum ARMCII_Op_e { ARMCII_OP_PUT, ARMCII_OP_GET, ARMCII_OP_ACC }; enum ARMCII_Strided_methods_e { ARMCII_STRIDED_IOV, ARMCII_STRIDED_DIRECT }; enum ARMCII_Iov_methods_e { ARMCII_IOV_AUTO, ARMCII_IOV_CONSRV, ARMCII_IOV_BATCHED, ARMCII_IOV_DIRECT }; enum ARMCII_Shr_buf_methods_e { ARMCII_SHR_BUF_COPY, ARMCII_SHR_BUF_NOGUARD }; extern char ARMCII_Strided_methods_str[][10]; extern char ARMCII_Iov_methods_str[][10]; extern char ARMCII_Shr_buf_methods_str[][10]; typedef struct { int init_count; /* Number of times ARMCI_Init has been called */ int debug_alloc; /* Do extra debuggin on memory allocation */ int iov_checks; /* Disable IOV same allocation and overlapping checks */ int iov_batched_limit; /* Max number of ops per epoch for BATCHED IOV method */ int noncollective_groups; /* Use noncollective group creation algorithm */ int cache_rank_translation; /* Enable caching of translation between absolute and group ranks */ int verbose; /* ARMCI should produce extra status output */ #ifdef HAVE_PTHREADS int progress_thread; /* Create progress thread */ int progress_usleep; /* Argument to usleep() to throttling polling */ #endif int use_win_allocate; /* Use win_allocate or win_create */ int use_alloc_shm; /* Pass alloc_shm info to win_allocate / alloc_mem */ int rma_atomicity; /* Use Accumulate and Get_accumulate for Put and Get */ int end_to_end_flush; /* All flush_local calls become flush */ int rma_nocheck; /* Use MPI_MODE_NOCHECK on synchronization calls that take assertion */ enum ARMCII_Strided_methods_e strided_method; /* Strided transfer method */ enum ARMCII_Iov_methods_e iov_method; /* IOV transfer method */ enum ARMCII_Shr_buf_methods_e shr_buf_method; /* Shared buffer management method */ } global_state_t; /* Global data */ extern ARMCI_Group ARMCI_GROUP_WORLD; extern ARMCI_Group ARMCI_GROUP_DEFAULT; extern MPI_Op MPI_ABSMIN_OP; extern MPI_Op MPI_ABSMAX_OP; extern MPI_Op MPI_SELMIN_OP; extern MPI_Op MPI_SELMAX_OP; extern global_state_t ARMCII_GLOBAL_STATE; #ifdef HAVE_PTHREADS extern pthread_t ARMCI_Progress_thread; #endif /* Utility functions */ void ARMCII_Bzero(void *buf, armci_size_t size); int ARMCII_Log2(unsigned int val); char *ARMCII_Getenv(const char *varname); int ARMCII_Getenv_bool(const char *varname, int default_value); int ARMCII_Getenv_int(const char *varname, int default_value); /* Synchronization */ void ARMCII_Sync_local(void); /* GOP Operators */ void ARMCII_Absmin_op(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype); void ARMCII_Absmax_op(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype); void ARMCII_Absv_op(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype); void ARMCII_Msg_sel_min_op(void *data_in, void *data_inout, int *len, MPI_Datatype *datatype); void ARMCII_Msg_sel_max_op(void *data_in, void *data_inout, int *len, MPI_Datatype *datatype); /* Group helper routines */ int ARMCII_Translate_absolute_to_group(ARMCI_Group *group, int world_rank); void ARMCII_Group_init_from_comm(ARMCI_Group *group); /* I/O Vector data management and implementation */ /** ARMCI IOV Iterator */ typedef struct { /* Strided Representation */ void *src; void *dst; int stride_levels; int *base_ptr; int *src_stride_ar; int *dst_stride_ar; int *count; /* Iterator State */ int was_contiguous; int *idx; } armcii_iov_iter_t; void ARMCII_Acc_type_translate(int armci_datatype, MPI_Datatype *type, int *type_size); int ARMCII_Iov_check_overlap(void **ptrs, int count, int size); int ARMCII_Iov_check_same_allocation(void **ptrs, int count, int proc); void ARMCII_Strided_to_iov(armci_giov_t *iov, void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels); void ARMCII_Strided_to_dtype(int stride_array[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, MPI_Datatype old_type, MPI_Datatype *new_type); int ARMCII_Iov_op_dispatch(enum ARMCII_Op_e op, void **src, void **dst, int count, int size, int datatype, int overlapping, int same_alloc, int proc, int blocking); int ARMCII_Iov_op_batched(enum ARMCII_Op_e op, void **src, void **dst, int count, int elem_count, MPI_Datatype type, int proc, int consrv /* if 1, batched = safe */, int blocking); int ARMCII_Iov_op_datatype(enum ARMCII_Op_e op, void **src, void **dst, int count, int elem_count, MPI_Datatype type, int proc, int blocking); armcii_iov_iter_t *ARMCII_Strided_to_iov_iter( void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels); void ARMCII_Iov_iter_free(armcii_iov_iter_t *it); int ARMCII_Iov_iter_has_next(armcii_iov_iter_t *it); int ARMCII_Iov_iter_next(armcii_iov_iter_t *it, void **src, void **dst); /* Shared to private buffer management routines */ int ARMCII_Buf_prepare_read_vec(void **orig_bufs, void ***new_bufs_ptr, int count, int size); void ARMCII_Buf_finish_read_vec(void **orig_bufs, void **new_bufs, int count, int size); int ARMCII_Buf_prepare_acc_vec(void **orig_bufs, void ***new_bufs_ptr, int count, int size, int datatype, void *scale); void ARMCII_Buf_finish_acc_vec(void **orig_bufs, void **new_bufs, int count, int size); int ARMCII_Buf_prepare_write_vec(void **orig_bufs, void ***new_bufs_ptr, int count, int size); void ARMCII_Buf_finish_write_vec(void **orig_bufs, void **new_bufs, int count, int size); int ARMCII_Buf_acc_is_scaled(int datatype, void *scale); void ARMCII_Buf_acc_scale(void *buf_in, void *buf_out, int size, int datatype, void *scale); #endif /* HAVE_ARMCI_INTERNALS_H */ armci-mpi/src/malloc.c0000644000175000017500000001042112663426407014416 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Malloc = PARMCI_Malloc #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Malloc ARMCI_Malloc #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Malloc as PARMCI_Malloc #endif /* -- end weak symbols block -- */ /** Allocate a shared memory segment. Collective. * * @param[out] base_ptrs Array of length nproc that will contain pointers to * the base address of each process' patch of the * segment. * @param[in] size Number of bytes to allocate on the local process. */ int PARMCI_Malloc(void **ptr_arr, armci_size_t bytes) { return ARMCI_Malloc_group(ptr_arr, bytes, &ARMCI_GROUP_WORLD); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Free = PARMCI_Free #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Free ARMCI_Free #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Free as PARMCI_Free #endif /* -- end weak symbols block -- */ /** Free a shared memory allocation. Collective. * * @param[in] ptr Pointer to the local patch of the allocation */ int PARMCI_Free(void *ptr) { return ARMCI_Free_group(ptr, &ARMCI_GROUP_WORLD); } /** Allocate a shared memory segment. Collective. * * @param[out] base_ptrs Array that will contain pointers to the base address of * each process' patch of the segment. Array is of length * equal to the number of processes in the group. * @param[in] size Number of bytes to allocate on the local process. */ int ARMCI_Malloc_group(void **base_ptrs, armci_size_t size, ARMCI_Group *group) { int i; gmr_t *mreg; ARMCII_Assert(PARMCI_Initialized()); mreg = gmr_create(size, base_ptrs, group); if (DEBUG_CAT_ENABLED(DEBUG_CAT_ALLOC)) { #define BUF_LEN 1000 char ptr_string[BUF_LEN]; int count = 0; if (mreg == NULL) { strncpy(ptr_string, "NULL", 5); } else { for (i = 0; i < mreg->nslices && count < BUF_LEN; i++) count += snprintf(ptr_string+count, BUF_LEN-count, (i == mreg->nslices-1) ? "%p" : "%p ", base_ptrs[i]); } ARMCII_Dbg_print(DEBUG_CAT_ALLOC, "base ptrs [%s]\n", ptr_string); #undef BUF_LEN } return 0; } /** Free a shared memory allocation. Collective. * * @param[in] ptr Pointer to the local patch of the allocation */ int ARMCI_Free_group(void *ptr, ARMCI_Group *group) { gmr_t *mreg; if (ptr != NULL) { mreg = gmr_lookup(ptr, ARMCI_GROUP_WORLD.rank); ARMCII_Assert_msg(mreg != NULL, "Invalid shared pointer"); } else { ARMCII_Dbg_print(DEBUG_CAT_ALLOC, "given NULL\n"); mreg = NULL; } gmr_destroy(mreg, group); return 0; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Malloc_local = PARMCI_Malloc_local #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Malloc_local ARMCI_Malloc_local #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Malloc_local as PARMCI_Malloc_local #endif /* -- end weak symbols block -- */ /** Allocate a local buffer suitable for use in one-sided communication * * @param[in] size Number of bytes to allocate * @return Pointer to the local buffer */ void *PARMCI_Malloc_local(armci_size_t size) { void *buf; MPI_Alloc_mem((MPI_Aint) size, MPI_INFO_NULL, &buf); if (ARMCII_GLOBAL_STATE.debug_alloc) { ARMCII_Bzero(buf, size); } return buf; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Free_local = PARMCI_Free_local #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Free_local ARMCI_Free_local #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Free_local as PARMCI_Free_local #endif /* -- end weak symbols block -- */ /** Free memory allocated with ARMCI_Malloc_local * * @param[in] buf Pointer to local buffer to free */ int PARMCI_Free_local(void *buf) { MPI_Free_mem(buf); return 0; } armci-mpi/src/strided_nb.c0000644000175000017500000003100212663426407015262 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbPutS = PARMCI_NbPutS #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbPutS ARMCI_NbPutS #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbPutS as PARMCI_NbPutS #endif /* -- end weak symbols block -- */ /** Non-blocking operation that transfers data from the calling process to the * memory of the remote process. The data transfer is strided and blocking. * * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * @param[in] proc Remote process ID (destination). * * @return Zero on success, error code otherwise. */ int PARMCI_NbPutS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc, armci_hdl_t *handle) { int err; if (ARMCII_GLOBAL_STATE.strided_method == ARMCII_STRIDED_DIRECT) { void *src_buf = NULL; gmr_t *mreg, *gmr_loc = NULL; MPI_Datatype src_type, dst_type; /* COPY: Guard shared buffers */ if (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY) { gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); if (gmr_loc != NULL) { int i, size; for (i = 1, size = count[0]; i < stride_levels+1; i++) size *= count[i]; MPI_Alloc_mem(size, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); armci_write_strided(src_ptr, stride_levels, src_stride_ar, count, src_buf); MPI_Type_contiguous(size, MPI_BYTE, &src_type); } } else { /* Jeff: WIN_UNIFIED should allow overlap to work but we * do a memory barrier here to be safe. */ gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); gmr_sync(gmr_loc); } /* NOGUARD: If src_buf hasn't been assigned to a copy, the strided source * buffer is going to be used directly. */ if (src_buf == NULL) { src_buf = src_ptr; ARMCII_Strided_to_dtype(src_stride_ar, count, stride_levels, MPI_BYTE, &src_type); } ARMCII_Strided_to_dtype(dst_stride_ar, count, stride_levels, MPI_BYTE, &dst_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); mreg = gmr_lookup(dst_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid shared pointer"); gmr_put_typed(mreg, src_buf, 1, src_type, dst_ptr, 1, dst_type, proc); MPI_Type_free(&src_type); MPI_Type_free(&dst_type); /* COPY: Free temporary buffer */ if (src_buf != src_ptr) { gmr_flush(mreg, proc, 1); /* flush_local */ MPI_Free_mem(src_buf); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = proc; } err = 0; } else { armci_giov_t iov; ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels); err = PARMCI_NbPutV(&iov, 1, proc, handle); free(iov.src_ptr_array); free(iov.dst_ptr_array); } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return err; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbGetS = PARMCI_NbGetS #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbGetS ARMCI_NbGetS #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbGetS as PARMCI_NbGetS #endif /* -- end weak symbols block -- */ /** Non-blocking operation that transfers data from the remote process to the * memory of the calling process. The data transfer is strided and blocking. * * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * @param[in] proc Remote process ID (destination). * * @return Zero on success, error code otherwise. */ int PARMCI_NbGetS(void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc, armci_hdl_t *handle) { int err; if (ARMCII_GLOBAL_STATE.strided_method == ARMCII_STRIDED_DIRECT) { void *dst_buf = NULL; gmr_t *mreg, *gmr_loc = NULL; MPI_Datatype src_type, dst_type; /* COPY: Guard shared buffers */ if (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY) { gmr_loc = gmr_lookup(dst_ptr, ARMCI_GROUP_WORLD.rank); if (gmr_loc != NULL) { int i, size; for (i = 1, size = count[0]; i < stride_levels+1; i++) size *= count[i]; MPI_Alloc_mem(size, MPI_INFO_NULL, &dst_buf); ARMCII_Assert(dst_buf != NULL); MPI_Type_contiguous(size, MPI_BYTE, &dst_type); } } else { /* Jeff: WIN_UNIFIED should allow overlap to work but we * do a memory barrier here to be safe. */ gmr_loc = gmr_lookup(dst_ptr, ARMCI_GROUP_WORLD.rank); gmr_sync(gmr_loc); } /* NOGUARD: If dst_buf hasn't been assigned to a copy, the strided source * buffer is going to be used directly. */ if (dst_buf == NULL) { dst_buf = dst_ptr; ARMCII_Strided_to_dtype(dst_stride_ar, count, stride_levels, MPI_BYTE, &dst_type); } ARMCII_Strided_to_dtype(src_stride_ar, count, stride_levels, MPI_BYTE, &src_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); mreg = gmr_lookup(src_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid shared pointer"); gmr_get_typed(mreg, src_ptr, 1, src_type, dst_buf, 1, dst_type, proc); /* COPY: Finish the transfer */ if (dst_buf != dst_ptr) { gmr_flush(mreg, proc, 1); armci_read_strided(dst_ptr, stride_levels, dst_stride_ar, count, dst_buf); MPI_Free_mem(dst_buf); } MPI_Type_free(&src_type); MPI_Type_free(&dst_type); if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = proc; } err = 0; } else { armci_giov_t iov; ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels); err = PARMCI_NbGetV(&iov, 1, proc, handle); free(iov.src_ptr_array); free(iov.dst_ptr_array); } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return err; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_NbAccS = PARMCI_NbAccS #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_NbAccS ARMCI_NbAccS #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_NbAccS as PARMCI_NbAccS #endif /* -- end weak symbols block -- */ /** Non-blocking operation that accumulates data from the local process into the * memory of the remote process. The data transfer is strided and blocking. * * @param[in] datatype Type of data to be transferred. * @param[in] scale Pointer to the value that input data should be scaled by. * @param[in] src_ptr Source starting address of the data block to put. * @param[in] src_stride_arr Source array of stride distances in bytes. * @param[in] dst_ptr Destination starting address to put data. * @param[in] dst_stride_ar Destination array of stride distances in bytes. * @param[in] count Block size in each dimension. count[0] should be the * number of bytes of contiguous data in leading dimension. * @param[in] stride_levels The level of strides. * @param[in] proc Remote process ID (destination). * * @return Zero on success, error code otherwise. */ int PARMCI_NbAccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[/*stride_levels*/], void *dst_ptr, int dst_stride_ar[/*stride_levels*/], int count[/*stride_levels+1*/], int stride_levels, int proc, armci_hdl_t *handle) { int err; if (ARMCII_GLOBAL_STATE.strided_method == ARMCII_STRIDED_DIRECT) { void *src_buf = NULL; gmr_t *mreg, *gmr_loc = NULL; MPI_Datatype src_type, dst_type, mpi_datatype; int scaled, mpi_datatype_size; ARMCII_Acc_type_translate(datatype, &mpi_datatype, &mpi_datatype_size); scaled = ARMCII_Buf_acc_is_scaled(datatype, scale); /* SCALE: copy and scale if requested */ if (scaled) { armci_giov_t iov; int i, nelem; if (ARMCII_GLOBAL_STATE.shr_buf_method != ARMCII_SHR_BUF_NOGUARD) gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); for (i = 1, nelem = count[0]/mpi_datatype_size; i < stride_levels+1; i++) nelem *= count[i]; MPI_Alloc_mem(nelem*mpi_datatype_size, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); /* Shoehorn the strided information into an IOV */ ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, src_ptr, src_stride_ar, count, stride_levels); for (i = 0; i < iov.ptr_array_len; i++) ARMCII_Buf_acc_scale(iov.src_ptr_array[i], ((uint8_t*)src_buf) + i*iov.bytes, iov.bytes, datatype, scale); free(iov.src_ptr_array); free(iov.dst_ptr_array); MPI_Type_contiguous(nelem, mpi_datatype, &src_type); } /* COPY: Guard shared buffers */ else if (ARMCII_GLOBAL_STATE.shr_buf_method == ARMCII_SHR_BUF_COPY) { gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); if (gmr_loc != NULL) { int i, nelem; for (i = 1, nelem = count[0]/mpi_datatype_size; i < stride_levels+1; i++) nelem *= count[i]; MPI_Alloc_mem(nelem*mpi_datatype_size, MPI_INFO_NULL, &src_buf); ARMCII_Assert(src_buf != NULL); armci_write_strided(src_ptr, stride_levels, src_stride_ar, count, src_buf); MPI_Type_contiguous(nelem, mpi_datatype, &src_type); } } else { /* Jeff: WIN_UNIFIED should allow overlap to work but we * do a memory barrier here to be safe. */ gmr_loc = gmr_lookup(src_ptr, ARMCI_GROUP_WORLD.rank); gmr_sync(gmr_loc); } /* NOGUARD: If src_buf hasn't been assigned to a copy, the strided source * buffer is going to be used directly. */ if (src_buf == NULL) { src_buf = src_ptr; ARMCII_Strided_to_dtype(src_stride_ar, count, stride_levels, mpi_datatype, &src_type); } ARMCII_Strided_to_dtype(dst_stride_ar, count, stride_levels, mpi_datatype, &dst_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); int src_size, dst_size; MPI_Type_size(src_type, &src_size); MPI_Type_size(dst_type, &dst_size); ARMCII_Assert(src_size == dst_size); mreg = gmr_lookup(dst_ptr, proc); ARMCII_Assert_msg(mreg != NULL, "Invalid shared pointer"); gmr_accumulate_typed(mreg, src_buf, 1, src_type, dst_ptr, 1, dst_type, proc); MPI_Type_free(&src_type); MPI_Type_free(&dst_type); /* COPY/SCALE: Free temp buffer */ if (src_buf != src_ptr) { gmr_flush(mreg, proc, 1); /* flush_local */ MPI_Free_mem(src_buf); } if (handle!=NULL) { /* Regular (not aggregate) handles merely store the target for future flushing. */ handle->target = proc; } err = 0; } else { armci_giov_t iov; ARMCII_Strided_to_iov(&iov, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels); err = PARMCI_NbAccV(datatype, scale, &iov, 1, proc, handle); free(iov.src_ptr_array); free(iov.dst_ptr_array); } #ifdef EXPLICIT_PROGRESS gmr_progress(); #endif return err; } armci-mpi/src/parmci.c0000644000175000017500000002034412662706250014423 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /* If no weak symbols support */ #if !defined(HAVE_PRAGMA_WEAK) && !defined(HAVE_PRAGMA_HP_SEC_DEF) && !defined(HAVE_PRAGMA_CRI_DUP) #include "armci.h" #pragma weak ARMCI_Init int ARMCI_Init(void) { return PARMCI_Init(); } #pragma weak ARMCI_Init_args int ARMCI_Init_args(int *argc, char ***argv) { return PARMCI_Init_args(argc, argv); } #pragma weak ARMCI_Initialized int ARMCI_Initialized(void) { return PARMCI_Initialized(); } #pragma weak ARMCI_Finalize int ARMCI_Finalize(void) { return PARMCI_Finalize(); } #pragma weak ARMCI_Malloc int ARMCI_Malloc(void **base_ptrs, armci_size_t size) { return PARMCI_Malloc(base_ptrs, size); } #pragma weak ARMCI_Free int ARMCI_Free(void *ptr) { return PARMCI_Free(ptr); } #pragma weak ARMCI_Malloc_local void *ARMCI_Malloc_local(armci_size_t size) { return PARMCI_Malloc_local(size); } #pragma weak ARMCI_Free_local int ARMCI_Free_local(void *ptr) { return PARMCI_Free_local(ptr); } #pragma weak ARMCI_Barrier void ARMCI_Barrier(void) { PARMCI_Barrier(); return; } #pragma weak ARMCI_Fence void ARMCI_Fence(int proc) { PARMCI_Fence(proc); return; } #pragma weak ARMCI_AllFence void ARMCI_AllFence(void) { PARMCI_AllFence(); return; } #pragma weak ARMCI_Access_begin void ARMCI_Access_begin(void *ptr) { PARMCI_Access_begin(ptr); return; } #pragma weak ARMCI_Access_end void ARMCI_Access_end(void *ptr) { PARMCI_Access_end(ptr); return; } #pragma weak ARMCI_Get int ARMCI_Get(void *src, void *dst, int size, int target) { return PARMCI_Get(src, dst, size, target); } #pragma weak ARMCI_Put int ARMCI_Put(void *src, void *dst, int size, int target) { return PARMCI_Put(src, dst, size, target); } #pragma weak ARMCI_Acc int ARMCI_Acc(int datatype, void *scale, void *src, void *dst, int bytes, int proc) { return PARMCI_Acc(datatype, scale, src, dst, bytes, proc); } #pragma weak ARMCI_PutS int ARMCI_PutS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc) { return PARMCI_PutS(src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, proc); } #pragma weak ARMCI_GetS int ARMCI_GetS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc) { return PARMCI_GetS(src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, proc); } #pragma weak ARMCI_AccS int ARMCI_AccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc) { return PARMCI_AccS(datatype, scale, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, proc); } #pragma weak ARMCI_Put_flag int ARMCI_Put_flag(void *src, void* dst, int size, int *flag, int value, int proc) { return PARMCI_Put_flag(src, dst, size, flag, value, proc); } #pragma weak ARMCI_PutS_flag int ARMCI_PutS_flag(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int *flag, int value, int proc) { return PARMCI_PutS_flag(src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, flag, value, proc); } #pragma weak ARMCI_PutV int ARMCI_PutV(armci_giov_t *iov, int iov_len, int proc) { return PARMCI_PutV(iov, iov_len, proc); } #pragma weak ARMCI_GetV int ARMCI_GetV(armci_giov_t *iov, int iov_len, int proc) { return PARMCI_GetV(iov, iov_len, proc); } #pragma weak ARMCI_AccV int ARMCI_AccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc) { return PARMCI_AccV(datatype, scale, iov, iov_len, proc); } #pragma weak ARMCI_Wait int ARMCI_Wait(armci_hdl_t* hdl) { return PARMCI_Wait(hdl); } #pragma weak ARMCI_Test int ARMCI_Test(armci_hdl_t* hdl) { return PARMCI_Test(hdl); } #pragma weak ARMCI_WaitAll int ARMCI_WaitAll(void) { return PARMCI_WaitAll(); } #pragma weak ARMCI_NbPut int ARMCI_NbPut(void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl) { return PARMCI_NbPut(src, dst, bytes, proc, hdl); } #pragma weak ARMCI_NbGet int ARMCI_NbGet(void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl) { return PARMCI_NbGet(src, dst, bytes, proc, hdl); } #pragma weak ARMCI_NbAcc int ARMCI_NbAcc(int datatype, void *scale, void *src, void *dst, int bytes, int proc, armci_hdl_t *hdl) { return PARMCI_NbAcc(datatype, scale, src, dst, bytes, proc, hdl); } #pragma weak ARMCI_NbPutS int ARMCI_NbPutS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc, armci_hdl_t *hdl) { return PARMCI_NbPutS(src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, proc, hdl); } #pragma weak ARMCI_NbGetS int ARMCI_NbGetS(void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc, armci_hdl_t *hdl) { return PARMCI_NbGetS(src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, proc, hdl); } #pragma weak ARMCI_NbAccS int ARMCI_NbAccS(int datatype, void *scale, void *src_ptr, int src_stride_ar[], void *dst_ptr, int dst_stride_ar[], int count[], int stride_levels, int proc, armci_hdl_t *hdl) { return PARMCI_NbAccS(datatype, scale, src_ptr, src_stride_ar, dst_ptr, dst_stride_ar, count, stride_levels, proc, hdl); } #pragma weak ARMCI_NbPutV int ARMCI_NbPutV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle) { return PARMCI_NbPutV(iov, iov_len, proc, handle); } #pragma weak ARMCI_NbGetV int ARMCI_NbGetV(armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle) { return PARMCI_NbGetV(iov, iov_len, proc, handle); } #pragma weak ARMCI_NbAccV int ARMCI_NbAccV(int datatype, void *scale, armci_giov_t *iov, int iov_len, int proc, armci_hdl_t* handle) { return PARMCI_NbAccV(datatype, scale, iov, iov_len, proc, handle); } #pragma weak ARMCI_PutValueInt int ARMCI_PutValueInt(int src, void *dst, int proc) { return PARMCI_PutValueInt(src, dst, proc); } #pragma weak ARMCI_PutValueLong int ARMCI_PutValueLong(long src, void *dst, int proc) { return PARMCI_PutValueLong(src, dst, proc); } #pragma weak ARMCI_PutValueFloat int ARMCI_PutValueFloat(float src, void *dst, int proc) { return PARMCI_PutValueFloat(src, dst, proc); } #pragma weak ARMCI_PutValueDouble int ARMCI_PutValueDouble(double src, void *dst, int proc) { return PARMCI_PutValueDouble(src, dst, proc); } #pragma weak ARMCI_NbPutValueInt int ARMCI_NbPutValueInt(int src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPutValueInt(src, dst, proc, hdl); } #pragma weak ARMCI_NbPutValueLong int ARMCI_NbPutValueLong(long src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPutValueLong(src, dst, proc, hdl); } #pragma weak ARMCI_NbPutValueFloat int ARMCI_NbPutValueFloat(float src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPutValueFloat(src, dst, proc, hdl); } #pragma weak ARMCI_NbPutValueDouble int ARMCI_NbPutValueDouble(double src, void *dst, int proc, armci_hdl_t *hdl) { return PARMCI_NbPutValueDouble(src, dst, proc, hdl); } #pragma weak ARMCI_GetValueInt int ARMCI_GetValueInt(void *src, int proc) { return PARMCI_GetValueInt(src, proc); } #pragma weak ARMCI_GetValueLong long ARMCI_GetValueLong(void *src, int proc) { return PARMCI_GetValueLong(src, proc); } #pragma weak ARMCI_GetValueFloat float ARMCI_GetValueFloat(void *src, int proc) { return PARMCI_GetValueFloat(src, proc); } #pragma weak ARMCI_GetValueDouble double ARMCI_GetValueDouble(void *src, int proc) { return PARMCI_GetValueDouble(src, proc); } #pragma weak ARMCI_Create_mutexes int ARMCI_Create_mutexes(int count) { return PARMCI_Create_mutexes(count); } #pragma weak ARMCI_Destroy_mutexes int ARMCI_Destroy_mutexes(void) { return PARMCI_Destroy_mutexes(); } #pragma weak ARMCI_Lock void ARMCI_Lock(int mutex, int proc) { PARMCI_Lock(mutex, proc); return; } #pragma weak ARMCI_Unlock void ARMCI_Unlock(int mutex, int proc) { PARMCI_Unlock(mutex, proc); return; } #pragma weak ARMCI_Rmw int ARMCI_Rmw(int op, void *ploc, void *prem, int value, int proc) { return PARMCI_Rmw(op, ploc, prem, value, proc); } #pragma weak armci_msg_barrier void armci_msg_barrier(void) { parmci_msg_barrier(); return; } #pragma weak armci_msg_group_barrier void armci_msg_group_barrier(ARMCI_Group *group) { parmci_msg_group_barrier(group); return; } #endif armci-mpi/src/armcix.h0000644000175000017500000000230112663426407014435 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #ifndef _ARMCIX_H_ #define _ARMCIX_H_ #include #include #if HAVE_STDINT_H # include #elif HAVE_INTTYPES_H # include #endif /** Processor group extensions. */ int ARMCIX_Group_split(ARMCI_Group *parent, int color, int key, ARMCI_Group *new_group); int ARMCIX_Group_dup(ARMCI_Group *parent, ARMCI_Group *new_group); /** Mutex handles: These improve on basic ARMCI mutexes by allowing you to * create multiple batches of mutexes. This is needed to allow libraries access to * mutexes. */ struct armcix_mutex_hdl_s { int my_count; int max_count; ARMCI_Group grp; MPI_Win *windows; uint8_t **bases; }; typedef struct armcix_mutex_hdl_s * armcix_mutex_hdl_t; armcix_mutex_hdl_t ARMCIX_Create_mutexes_hdl(int count, ARMCI_Group *pgroup); int ARMCIX_Destroy_mutexes_hdl(armcix_mutex_hdl_t hdl); void ARMCIX_Lock_hdl(armcix_mutex_hdl_t hdl, int mutex, int proc); int ARMCIX_Trylock_hdl(armcix_mutex_hdl_t hdl, int mutex, int proc); void ARMCIX_Unlock_hdl(armcix_mutex_hdl_t hdl, int mutex, int proc); void ARMCIX_Progress(void); #endif /* _ARMCIX_H_ */ armci-mpi/src/util.c0000644000175000017500000001255212663426407014133 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #include #include #include /** Fatal error, print the message and abort the program with the provided * error code. */ void ARMCI_Error(const char *msg, int code) { fprintf(stderr, "[%d] ARMCI Error: %s\n", ARMCI_GROUP_WORLD.rank, msg); fflush(NULL); MPI_Abort(ARMCI_GROUP_WORLD.comm, code); } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Barrier = PARMCI_Barrier #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Barrier ARMCI_Barrier #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Barrier as PARMCI_Barrier #endif /* -- end weak symbols block -- */ /** Barrier synchronization. Collective on the world group (not the default * group!). */ void PARMCI_Barrier(void) { gmr_t *cur_mreg = gmr_list; PARMCI_AllFence(); MPI_Barrier(ARMCI_GROUP_WORLD.comm); while (cur_mreg) { gmr_sync(cur_mreg); cur_mreg = cur_mreg->next; } } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_Fence = PARMCI_Fence #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_Fence ARMCI_Fence #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_Fence as PARMCI_Fence #endif /* -- end weak symbols block -- */ /** Wait for remote completion on one-sided operations targeting process proc. * In MPI-2, this is a no-op since get/put/acc already guarantee remote * completion. * * @param[in] proc Process to target */ void PARMCI_Fence(int proc) { gmr_t *cur_mreg = gmr_list; while (cur_mreg) { gmr_flush(cur_mreg, proc, 0); cur_mreg = cur_mreg->next; } return; } /* -- begin weak symbols block -- */ #if defined(HAVE_PRAGMA_WEAK) # pragma weak ARMCI_AllFence = PARMCI_AllFence #elif defined(HAVE_PRAGMA_HP_SEC_DEF) # pragma _HP_SECONDARY_DEF PARMCI_AllFence ARMCI_AllFence #elif defined(HAVE_PRAGMA_CRI_DUP) # pragma _CRI duplicate ARMCI_AllFence as PARMCI_AllFence #endif /* -- end weak symbols block -- */ /** Wait for remote completion on all one-sided operations. In MPI-2, this is * a no-op since get/put/acc already guarantee remote completion. */ void PARMCI_AllFence(void) { gmr_t *cur_mreg = gmr_list; while (cur_mreg) { gmr_flushall(cur_mreg, 0); cur_mreg = cur_mreg->next; } return; } int ARMCI_Uses_shm(void) { return 0; } void ARMCI_Set_shm_limit(unsigned long shmemlimit) { return; } int ARMCI_Uses_shm_grp(ARMCI_Group *group) { return 0; } /** Copy local data. * * @param[in] src Source buffer * @param[out] dst Destination buffer * @param[in] size Number of bytes to copy */ void ARMCI_Copy(const void *src, void *dst, int size) { #ifndef COPY_WITH_SENDRECV memcpy(dst, src, size); #else static MPI_Comm copy_comm = MPI_COMM_NULL; if (copy_comm == MPI_COMM_NULL) MPI_Comm_dup(MPI_COMM_SELF, ©_comm); MPI_Sendrecv(src, size, MPI_BYTE, 0 /* rank */, 0 /* tag */, dst, size, MPI_BYTE, 0 /* rank */, 0 /* tag */, copy_comm, MPI_STATUS_IGNORE); #endif } /** Zero out the given buffer. */ void ARMCII_Bzero(void *buf, armci_size_t size) { /* Jeff: Why not use memset? */ armci_size_t i; uint8_t *buf_b = (uint8_t *)buf; for (i = 0; i < size; i++) buf_b[i] = 0; } static const unsigned char log2_table[256] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; /** Calculate the base 2 logarithm of a given integer. */ int ARMCII_Log2(unsigned int val) { unsigned int v16, v8; int lg = 0; if (val == 0) return -1; if ((v16 = val >> 16)) lg = (v8 = v16 >> 8) ? log2_table[v8] + 24 : log2_table[v16] + 16; else lg = (v8 = val >> 8) ? log2_table[v8] + 8 : log2_table[val]; return lg; } /** Retrieve the value of a boolean environment variable. */ int ARMCII_Getenv_bool(const char *varname, int default_value) { const char *var = getenv(varname); if (var == NULL) return default_value; if (var[0] == 'T' || var[0] == 't' || var[0] == '1' || var[0] == 'y' || var[0] == 'Y') return 1; else return 0; } /** Retrieve the value of a environment variable. */ char *ARMCII_Getenv(const char *varname) { return getenv(varname); } /** Retrieve the value of an integer environment variable. */ int ARMCII_Getenv_int(const char *varname, int default_value) { const char *var = getenv(varname); if (var) return atoi(var); else return default_value; } void ARMCIX_Progress(void) { gmr_progress(); } armci-mpi/tests/0000755000175000017500000000000012663426407013360 5ustar mbanckmbanckarmci-mpi/tests/test_accs_dla.c0000644000175000017500000000537712662706250016324 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define XDIM 1024 #define YDIM 1024 #define ITERATIONS 10 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors, total_errors; double **buf_bvec, **src_bvec, *src_buf; int count[2], src_stride, trg_stride, stride_level; double scaling, time; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); buf_bvec = (double **) malloc(sizeof(double *) * nranks); src_bvec = (double **) malloc(sizeof(double *) * nranks); bufsize = XDIM * YDIM * sizeof(double); ARMCI_Malloc((void **) buf_bvec, bufsize); ARMCI_Malloc((void **) src_bvec, bufsize); src_buf = src_bvec[rank]; if (rank == 0) printf("ARMCI Strided DLA Accumulate Test:\n"); ARMCI_Access_begin(buf_bvec[rank]); ARMCI_Access_begin(src_buf); for (i = 0; i < XDIM*YDIM; i++) { *(buf_bvec[rank] + i) = 1.0 + rank; *(src_buf + i) = 1.0 + rank; } ARMCI_Access_end(src_buf); ARMCI_Access_end(buf_bvec[rank]); scaling = 2.0; src_stride = XDIM * sizeof(double); trg_stride = XDIM * sizeof(double); stride_level = 1; count[1] = YDIM; count[0] = XDIM * sizeof(double); ARMCI_Barrier(); time = MPI_Wtime(); peer = (rank+1) % nranks; for (i = 0; i < ITERATIONS; i++) { ARMCI_AccS(ARMCI_ACC_DBL, (void *) &scaling, src_buf, &src_stride, (void *) buf_bvec[peer], &trg_stride, count, stride_level, peer); } ARMCI_Barrier(); time = MPI_Wtime() - time; if (rank == 0) printf("Time: %f sec\n", time); ARMCI_Access_begin(buf_bvec[rank]); for (i = errors = 0; i < XDIM; i++) { for (j = 0; j < YDIM; j++) { const double actual = *(buf_bvec[rank] + i + j*XDIM); const double expected = (1.0 + rank) + scaling * (1.0 + ((rank+nranks-1)%nranks)) * (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } ARMCI_Access_end(buf_bvec[rank]); MPI_Allreduce(&errors, &total_errors, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); ARMCI_Free((void *) buf_bvec[rank]); ARMCI_Free((void *) src_bvec[rank]); free(buf_bvec); free(src_bvec); ARMCI_Finalize(); MPI_Finalize(); if (total_errors == 0) { if (rank == 0) printf("Success.\n"); return 0; } else { if (rank == 0) printf("Fail.\n"); return 1; } } armci-mpi/tests/test_mutex.c0000644000175000017500000000173312662706250015725 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /** ARMCI Mutex test -- James Dinan * * All processes create N mutexes then lock+unlock all mutexes on all * processes. */ #include #include #include #include #include #define NUM_MUTEXES 10 int main(int argc, char ** argv) { int rank, nproc, i, j; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI mutex test with %d processes\n", nproc); ARMCI_Create_mutexes(NUM_MUTEXES); for (i = 0; i < nproc; i++) for (j = 0; j < NUM_MUTEXES; j++) { ARMCI_Lock( j, (rank+i)%nproc); ARMCI_Unlock(j, (rank+i)%nproc); } printf(" + %3d done\n", rank); fflush(NULL); ARMCI_Destroy_mutexes(); if (rank == 0) printf("Test complete: PASS.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_mutex_trylock.c0000644000175000017500000000233412662706250017472 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /** ARMCI Mutex test -- James Dinan * * All processes create N mutexes then lock+unlock all mutexes on all * processes. Locking is accomplished via trylock in a loop. */ #include #include #include #include #include #include #include #define NUM_MUTEXES 10 int main(int argc, char ** argv) { int rank, nproc, i, j; armcix_mutex_hdl_t mhdl; ARMCI_Group world_group; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCIX mutex test with %d processes\n", nproc); ARMCI_Group_get_world(&world_group); mhdl = ARMCIX_Create_mutexes_hdl(NUM_MUTEXES, &world_group); for (i = 0; i < nproc; i++) for (j = 0; j < NUM_MUTEXES; j++) { while (ARMCIX_Trylock_hdl(mhdl, j, (rank+i)%nproc)) ; ARMCIX_Unlock_hdl(mhdl, j, (rank+i)%nproc); } printf(" + %3d done\n", rank); fflush(NULL); ARMCIX_Destroy_mutexes_hdl(mhdl); if (rank == 0) printf("Test complete: PASS.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_mutex_rmw.c0000644000175000017500000000320512662706250016606 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /** ARMCI Mutex RMW Test -- James Dinan * * A mutex and shared integer live on process 0. All processes lock, add a * value to the integer, and unlock. Process 0 confirms the final result. */ #include #include #include #include #include #define NITER 1000 #define ADDIN 5 int main(int argc, char ** argv) { int rank, nproc, val, i; void **base_ptrs; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI mutex read-modify-write test with %d processes\n", nproc); base_ptrs = malloc(nproc*sizeof(void*)); ARMCI_Create_mutexes(rank == 0 ? 1 : 0); ARMCI_Malloc(base_ptrs, (rank == 0) ? sizeof(int) : 0); // Proc 0 has a shared int if (rank == 0) { val = 0; ARMCI_Put(&val, base_ptrs[0], sizeof(int), 0); } ARMCI_Barrier(); for (i = 0; i < NITER; i++) { ARMCI_Lock(0, 0); ARMCI_Get(base_ptrs[0], &val, sizeof(int), 0); val += ADDIN; ARMCI_Put(&val, base_ptrs[0], sizeof(int), 0); ARMCI_Unlock(0, 0); } printf(" + %3d done\n", rank); fflush(NULL); ARMCI_Barrier(); if (rank == 0) { ARMCI_Get(base_ptrs[0], &val, sizeof(int), 0); if (val == ADDIN*nproc*NITER) printf("Test complete: PASS.\n"); else printf("Test complete: FAIL. Got %d, expected %d.\n", val, ADDIN*nproc*NITER); } ARMCI_Free(base_ptrs[rank]); ARMCI_Destroy_mutexes(); free(base_ptrs); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_malloc.c0000644000175000017500000000264412662706250016034 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /** ARMCI Malloc test -- James Dinan * * Perform a pile of allocations and then free them. */ #include #include #include #include #include #define DATA_NELTS 1000 #define NUM_ITERATIONS 100 #define DATA_SZ (DATA_NELTS*sizeof(int)) int main(int argc, char ** argv) { int rank, nproc, test_iter; void ***base_ptrs; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI memory allocation test with %d processes\n", nproc); base_ptrs = malloc(sizeof(void**)*NUM_ITERATIONS); // Perform a pile of allocations for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + allocation %d\n", test_iter); base_ptrs[test_iter] = malloc(sizeof(void*)*nproc); ARMCI_Malloc((void**)base_ptrs[test_iter], (test_iter % 4 == 0) ? 0 : DATA_SZ); } ARMCI_Barrier(); // Free all allocations for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + free %d\n", test_iter); ARMCI_Free(((void**)base_ptrs[test_iter])[rank]); free(base_ptrs[test_iter]); } free(base_ptrs); if (rank == 0) printf("Test complete: PASS.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_onesided.c0000644000175000017500000000606412663426407016363 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #define DATA_NELTS 1000 #define NUM_ITERATIONS 10 #define DATA_SZ (DATA_NELTS*sizeof(int)) int main(int argc, char ** argv) { int rank, nproc, i, test_iter; int *my_data, *buf; void **base_ptrs; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI test with %d processes\n", nproc); buf = malloc(DATA_SZ); base_ptrs = malloc(sizeof(void*)*nproc); for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + iteration %d\n", test_iter); /*** Allocate the shared array ***/ ARMCI_Malloc(base_ptrs, DATA_SZ); my_data = base_ptrs[rank]; /*** Get from our right neighbor and verify correct data ***/ ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank*test_iter; ARMCI_Access_end(my_data); ARMCI_Barrier(); // Wait for all updates to data to complete ARMCI_Get(base_ptrs[(rank+1) % nproc], buf, DATA_SZ, (rank+1) % nproc); for (i = 0; i < DATA_NELTS; i++) { if (buf[i] != ((rank+1) % nproc)*test_iter) { printf("%d: GET expected %d, got %d\n", rank, ((rank+1) % nproc)*test_iter, buf[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Barrier(); // Wait for all gets to complete /*** Put to our left neighbor and verify correct data ***/ for (i = 0; i < DATA_NELTS; i++) buf[i] = rank*test_iter; ARMCI_Put(buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); ARMCI_Barrier(); // Wait for all updates to data to complete ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != ((rank+1) % nproc)*test_iter) { printf("%d: PUT expected %d, got %d\n", rank, ((rank+1) % nproc)*test_iter, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); ARMCI_Barrier(); // Wait for all gets to complete /*** Accumulate to our left neighbor and verify correct data ***/ for (i = 0; i < DATA_NELTS; i++) buf[i] = rank; ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank; ARMCI_Access_end(my_data); ARMCI_Barrier(); int scale = test_iter; ARMCI_Acc(ARMCI_ACC_INT, &scale, buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); ARMCI_Barrier(); // Wait for all updates to data to complete ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != rank + ((rank+1) % nproc)*test_iter) { printf("%d: ACC expected %d, got %d\n", rank, ((rank+1) % nproc)*test_iter, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); ARMCI_Free(my_data); } free(buf); free(base_ptrs); if (rank == 0) printf("Test complete: PASS.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/ctree/0000755000175000017500000000000012662706250014456 5ustar mbanckmbanckarmci-mpi/tests/ctree/ctree_test.c0000644000175000017500000000270612662706250016770 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #define MAX 20 #define INC 4 int main(int argc, char **argv) { uint8_t *i; ctree_t ctree = CTREE_EMPTY; printf("========== FORWARD INSERT CHECK ==========\n"); for (i = 0; i <= (uint8_t*) MAX; i+=INC) { printf("----- Inserting [%10p, %10p] -----\n", i, i+INC-1); int conflict = ctree_insert(&ctree, i, i+INC-1); ctree_print(ctree); if (conflict) printf("Error, conflict inserting %p\n", i); } for (i = 0; i <= (uint8_t*) MAX; i+=INC) { printf("----- Checking [%10p, %10p] -----\n", i, i+INC-1); int conflict = ctree_insert(&ctree, i, i+INC-1); if (!conflict) printf("Error, no conflict inserting %p\n", i); } ctree_destroy(&ctree); printf("========== REVERSE INSERT CHECK ==========\n"); for (i = (uint8_t*) MAX+INC; i-INC >= (uint8_t*) 0 && i-INC <= (uint8_t*) MAX; i-=INC) { printf("----- Inserting [%10p, %10p] -----\n", i-INC, i-1); int conflict = ctree_insert(&ctree, i-INC, i-1); ctree_print(ctree); if (conflict) printf("Error, conflict inserting %p\n", i); } for (i = 0; i <= (uint8_t*) MAX; i+=INC) { printf("----- Checking [%10p, %10p] -----\n", i, i+INC-1); int conflict = ctree_insert(&ctree, i, i+INC-1); if (!conflict) printf("Error, no conflict inserting %p\n", i); } ctree_destroy(&ctree); return 0; } armci-mpi/tests/ctree/Makefile.mk0000644000175000017500000000103212662706250016520 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # check_PROGRAMS += tests/ctree/ctree_test \ tests/ctree/ctree_test_rand \ tests/ctree/ctree_test_rand_interval TESTS += tests/ctree/ctree_test \ tests/ctree/ctree_test_rand \ tests/ctree/ctree_test_rand_interval tests_ctree_ctree_test_LDADD = libarmci.la -lm tests_ctree_ctree_test_rand_LDADD = libarmci.la -lm tests_ctree_ctree_test_rand_interval_LDADD = libarmci.la -lm armci-mpi/tests/ctree/ctree_test_rand_interval.c0000644000175000017500000000375712662706250021707 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define MIN(X,Y) ((X) < (Y) ? X : Y) #define MAX(X,Y) ((X) > (Y) ? X : Y) #define MAX_INTVL 1000 #define NELT 1000 uint8_t *data[NELT][2]; int main(int argc, char **argv) { int i, next, upper_bound; ctree_t ctree = CTREE_EMPTY; srand(time(NULL)); // Generate random intervals that fully cover the space from [0,next) for (i = next = 0; i < NELT; i++, next++) { data[i][0] = ((uint8_t*) NULL) + next; next = next + rand()%MAX_INTVL; data[i][1] = ((uint8_t*) NULL) + next; upper_bound = next; } // Perform NELT random swaps so elements are inserted in random order for (i = 0; i < NELT; i++) { int j = rand() % NELT; int k = rand() % NELT; uint8_t *tmp[2]; tmp[0] = data[j][0]; tmp[1] = data[j][1]; data[j][0] = data[k][0]; data[j][1] = data[k][1]; data[k][0] = tmp[0]; data[k][1] = tmp[1]; } // Build the conflict tree for (i = 0; i < NELT; i++) { printf(" + Inserting [%p, %p]\n", data[i][0], data[i][1]); int conflict = ctree_insert(&ctree, data[i][0], data[i][1]); if (conflict) { printf("*** Error, conflict inserting [%p, %p]\n", data[i][0], data[i][1]); ctree_print(ctree); exit(1); } } printf("\n"); ctree_print(ctree); printf("\n"); // Generate random test samples for (i = 0; i < NELT; i++) { int x = rand() % upper_bound; int y = rand() % upper_bound; data[i][0] = ((uint8_t*) NULL) + MIN(x,y); data[i][1] = ((uint8_t*) NULL) + MAX(x,y); } for (i = 0; i < NELT; i++) { printf(" + Checking [%p, %p]\n", data[i][0], data[i][1]); int conflict = ctree_insert(&ctree, data[i][0], data[i][1]); if (!conflict) { printf("*** Error, no conflict inserting [%p, %p]\n", data[i][0], data[i][1]); ctree_print(ctree); exit(1); } } ctree_destroy(&ctree); return 0; } armci-mpi/tests/ctree/ctree_test_rand.c0000644000175000017500000000227212662706250017772 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define NELT 1000 uint8_t *data[NELT]; int main(int argc, char **argv) { int i; ctree_t ctree = CTREE_EMPTY; srand(time(NULL)); for (i = 0; i < NELT; i++) data[i] = ((uint8_t*) NULL) + i; // Perform NELT random swaps for (i = 0; i < NELT; i++) { int j = rand() % NELT; int k = rand() % NELT; uint8_t *tmp = data[j]; data[j] = data[k]; data[k] = tmp; } for (i = 0; i < NELT; i++) { printf(" + Inserting [%p, %p]\n", data[i], data[i]); int conflict = ctree_insert(&ctree, data[i], data[i]); if (conflict) { printf("*** Error, conflict inserting %p\n", data[i]); ctree_print(ctree); exit(1); } } printf("\n"); ctree_print(ctree); printf("\n"); for (i = 0; i < NELT; i++) { printf(" + Checking [%p, %p]\n", data[i], data[i]); int conflict = ctree_insert(&ctree, data[i], data[i]); if (!conflict) { printf("*** Error, no conflict inserting %p\n", data[i]); ctree_print(ctree); exit(1); } } ctree_destroy(&ctree); return 0; } armci-mpi/tests/test_onesided_shared.c0000644000175000017500000000722712662706250017707 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #define VERBOSE 0 #define DATA_NELTS 1000 #define NUM_ITERATIONS 10 #define DATA_SZ (DATA_NELTS*sizeof(int)) int main(int argc, char ** argv) { int rank, nproc, i, test_iter; int *my_data, *buf; void **base_ptrs; void **buf_shared; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI test with %d processes\n", nproc); base_ptrs = malloc(sizeof(void*)*nproc); buf_shared = malloc(sizeof(void*)*nproc); for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + iteration %d\n", test_iter); if (rank == 0 && VERBOSE) printf(" - Allocating shared buffers\n"); /*** Allocate the shared array ***/ ARMCI_Malloc(base_ptrs, DATA_SZ); ARMCI_Malloc(buf_shared, DATA_SZ); buf = buf_shared[rank]; my_data = base_ptrs[rank]; if (rank == 0 && VERBOSE) printf(" - Testing one-sided get\n"); /*** Get from our right neighbor and verify correct data ***/ ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank*test_iter; ARMCI_Access_end(my_data); ARMCI_Barrier(); // Wait for all updates to data to complete ARMCI_Get(base_ptrs[(rank+1) % nproc], buf, DATA_SZ, (rank+1) % nproc); ARMCI_Access_begin(buf); for (i = 0; i < DATA_NELTS; i++) { if (buf[i] != ((rank+1) % nproc)*test_iter) { printf("%d: GET expected %d, got %d\n", rank, (rank+1) % nproc, buf[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(buf); ARMCI_Barrier(); // Wait for all gets to complete if (rank == 0 && VERBOSE) printf(" - Testing one-sided put\n"); /*** Put to our left neighbor and verify correct data ***/ for (i = 0; i < DATA_NELTS; i++) buf[i] = rank*test_iter; ARMCI_Put(buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); ARMCI_Barrier(); // Wait for all updates to data to complete ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != ((rank+1) % nproc)*test_iter) { printf("%d: PUT expected %d, got %d\n", rank, (rank+1) % nproc, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); ARMCI_Barrier(); // Wait for all gets to complete if (rank == 0 && VERBOSE) printf(" - Testing one-sided accumlate\n"); /*** Accumulate to our left neighbor and verify correct data ***/ ARMCI_Access_begin(buf); for (i = 0; i < DATA_NELTS; i++) buf[i] = rank; ARMCI_Access_end(buf); ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank; ARMCI_Access_end(my_data); ARMCI_Barrier(); int scale = test_iter; ARMCI_Acc(ARMCI_ACC_INT, &scale, buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); ARMCI_Barrier(); // Wait for all updates to data to complete ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != rank + ((rank+1) % nproc)*test_iter) { printf("%d: ACC expected %d, got %d\n", rank, (rank+1) % nproc, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); if (rank == 0 && VERBOSE) printf(" - Freeing shared buffers\n"); ARMCI_Free(my_data); ARMCI_Free(buf); } free(base_ptrs); free(buf_shared); if (rank == 0) printf("Test complete: PASS.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/ARMCI_PutS_latency.c0000644000175000017500000001054612662706250017053 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define MAX_XDIM 1024 #define MAX_YDIM 1024 #define ITERATIONS 100 #define SKIP 10 int main(int argc, char *argv[]) { int i, j, rank, nranks; int xdim, ydim; long bufsize; double **buffer; double t_start=0.0, t_stop=0.0; int count[2], src_stride, trg_stride, stride_level, peer; double expected, actual; int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); if (nranks < 2) { printf("%s: Must be run with at least 2 processes\n", argv[0]); MPI_Abort(MPI_COMM_WORLD, 1); } ARMCI_Init_args(&argc, &argv); bufsize = MAX_XDIM * MAX_YDIM * sizeof(double); buffer = (double **) malloc(sizeof(double *) * nranks); ARMCI_Malloc((void **) buffer, bufsize); for(i=0; i< bufsize/sizeof(double); i++) { *(buffer[rank] + i) = 1.0 + rank; } if(rank == 0) { printf("ARMCI_PutS Latency - local and remote completions - in usec \n"); printf("%30s %22s %22s\n", "Dimensions(array of doubles)", "Latency-LocalCompeltion", "Latency-RemoteCompletion"); fflush(stdout); } src_stride = MAX_YDIM*sizeof(double); trg_stride = MAX_YDIM*sizeof(double); stride_level = 1; ARMCI_Barrier(); for(xdim=1; xdim<=MAX_XDIM; xdim*=2) { count[1] = xdim; for(ydim=1; ydim<=MAX_YDIM; ydim*=2) { count[0] = ydim*sizeof(double); if(rank == 0) { peer = 1; for(i=0; i #include #include #include #include int main(int argc, char ** argv) { MPI_Init(&argc, &argv); ARMCI_Init(); ARMCI_Get(NULL, NULL, 1, 0); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_malloc_irreg.c0000644000175000017500000000461112662706250017220 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /** ARMCI Irregular memory allocation test -- James Dinan * * Perform a series of allocations where all processes but one give zero bytes * to ARMCI_Malloc. The process that does a non-zero allocation initializes * their shared memory and then the data is fetched by a neighbor and tested. */ #include #include #include #include #include #define DATA_NELTS 1000 #define NUM_ITERATIONS 10 #define DATA_SZ (DATA_NELTS*sizeof(int)) int main(int argc, char ** argv) { int rank, nproc, test_iter, i; void ***base_ptrs; int *buf; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI irregular memory allocation test with %d processes\n", nproc); buf = malloc(DATA_SZ); base_ptrs = malloc(sizeof(void**)*NUM_ITERATIONS); // Perform a pile of allocations for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + allocation %d\n", test_iter); base_ptrs[test_iter] = malloc(sizeof(void*)*nproc); ARMCI_Malloc((void**)base_ptrs[test_iter], (test_iter % nproc == rank) ? DATA_SZ : 0); } ARMCI_Barrier(); // Initialize data to my rank for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (test_iter % nproc == rank) { ARMCI_Access_begin(base_ptrs[test_iter][rank]); for (i = 0; i < DATA_NELTS; i++) ((int*)base_ptrs[test_iter][rank])[i] = rank; ARMCI_Access_end(base_ptrs[test_iter][rank]); } } ARMCI_Barrier(); // Fetch and test for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { ARMCI_Get(base_ptrs[test_iter][test_iter%nproc], buf, DATA_SZ, test_iter%nproc); for (i = 0; i < DATA_NELTS; i++) { if (buf[i] != test_iter % nproc) printf("Error: got %d expected %d\n", buf[i], test_iter%nproc); } } // Free all allocations for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + free %d\n", test_iter); ARMCI_Free(((void**)base_ptrs[test_iter])[rank]); free(base_ptrs[test_iter]); } ARMCI_Barrier(); free(base_ptrs); free(buf); if (rank == 0) printf("Test complete: PASS.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_parmci.c0000644000175000017500000000707512662706250016043 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #define DATA_NELTS 1000 #define NUM_ITERATIONS 10 #define DATA_SZ (DATA_NELTS*sizeof(int)) int armci_calls = 0; extern int parmci_calls; int main(int argc, char ** argv) { int rank, nproc, i, test_iter; int *my_data, *buf; void **base_ptrs; MPI_Init(&argc, &argv); ARMCI_Init(); armci_calls++; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI test with %d processes\n", nproc); buf = malloc(DATA_SZ); base_ptrs = malloc(sizeof(void*)*nproc); for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + iteration %d\n", test_iter); /*** Allocate the shared array ***/ ARMCI_Malloc(base_ptrs, DATA_SZ); my_data = base_ptrs[rank]; /*** Get from our right neighbor and verify correct data ***/ ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank*test_iter; ARMCI_Access_end(my_data); ARMCI_Barrier(); // Wait for all updates to data to complete armci_calls++; ARMCI_Get(base_ptrs[(rank+1) % nproc], buf, DATA_SZ, (rank+1) % nproc); armci_calls++; for (i = 0; i < DATA_NELTS; i++) { if (buf[i] != ((rank+1) % nproc)*test_iter) { printf("%d: GET expected %d, got %d\n", rank, (rank+1) % nproc, buf[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Barrier(); // Wait for all gets to complete armci_calls++; /*** Put to our left neighbor and verify correct data ***/ for (i = 0; i < DATA_NELTS; i++) buf[i] = rank*test_iter; ARMCI_Put(buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); armci_calls++; ARMCI_Barrier(); // Wait for all updates to data to complete armci_calls++; ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != ((rank+1) % nproc)*test_iter) { printf("%d: PUT expected %d, got %d\n", rank, (rank+1) % nproc, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); ARMCI_Barrier(); // Wait for all gets to complete armci_calls++; /*** Accumulate to our left neighbor and verify correct data ***/ for (i = 0; i < DATA_NELTS; i++) buf[i] = rank; ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank; ARMCI_Access_end(my_data); ARMCI_Barrier(); armci_calls++; int scale = test_iter; ARMCI_Acc(ARMCI_ACC_INT, &scale, buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); ARMCI_Barrier(); // Wait for all updates to data to complete armci_calls++; ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != rank + ((rank+1) % nproc)*test_iter) { printf("%d: ACC expected %d, got %d\n", rank, (rank+1) % nproc, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); ARMCI_Free(my_data); } free(buf); free(base_ptrs); if (armci_calls == parmci_calls) { if (rank == 0) { printf("Profiling check ok: %d recorded == %d profiled calls\n", armci_calls, parmci_calls); printf("Test complete: PASS.\n"); } } else { printf("%d: Profiling check failed -- %d recorded != %d profiled calls\n", rank, armci_calls, parmci_calls); MPI_Abort(MPI_COMM_WORLD, 1); } ARMCI_Finalize(); armci_calls++; MPI_Finalize(); return 0; } armci-mpi/tests/mpi/0000755000175000017500000000000012663426407014145 5ustar mbanckmbanckarmci-mpi/tests/mpi/pgroup_bench.c0000644000175000017500000000701712662706250016765 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define INTERCOMM_TAG 0 #define NITER 1024 void pgroup_create(int grp_size, int *pid_list, MPI_Comm *group_out); void pgroup_free(MPI_Comm *group); /** Free a pgroup */ void pgroup_free(MPI_Comm *group) { /* Note: It's ok to compare predefined handles */ if (*group == MPI_COMM_NULL || *group == MPI_COMM_SELF) return; MPI_Comm_free(group); } /* Create a processor group containing the processes in pid_list. * * NOTE: pid_list list must be identical and sorted on all processes */ void pgroup_create(int grp_size, int *pid_list, MPI_Comm *group_out) { int i, grp_me, me, nproc, merge_size; MPI_Comm pgroup, inter_pgroup; MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); /* CASE: pgroup size 0 */ if (grp_size == 0) { *group_out = MPI_COMM_NULL; return; } /* CASE: pgroup size 1 */ else if (grp_size == 1 && pid_list[0] == me) { *group_out = MPI_COMM_SELF; return; } /* CHECK: If I'm not a member, return COMM_NULL */ grp_me = -1; for (i = 0; i < grp_size; i++) { if (pid_list[i] == me) { grp_me = i; break; } } if (grp_me < 0) { *group_out = MPI_COMM_NULL; return; } pgroup = MPI_COMM_SELF; for (merge_size = 1; merge_size < grp_size; merge_size *= 2) { int gid = grp_me / merge_size; MPI_Comm pgroup_old = pgroup; if (gid % 2 == 0) { /* Check if right partner doesn't exist */ if ((gid+1)*merge_size >= grp_size) continue; MPI_Intercomm_create(pgroup, 0, MPI_COMM_WORLD, pid_list[(gid+1)*merge_size], INTERCOMM_TAG, &inter_pgroup); MPI_Intercomm_merge(inter_pgroup, 0 /* LOW */, &pgroup); } else { MPI_Intercomm_create(pgroup, 0, MPI_COMM_WORLD, pid_list[(gid-1)*merge_size], INTERCOMM_TAG, &inter_pgroup); MPI_Intercomm_merge(inter_pgroup, 1 /* HIGH */, &pgroup); } MPI_Comm_free(&inter_pgroup); if (pgroup_old != MPI_COMM_SELF) MPI_Comm_free(&pgroup_old); } *group_out = pgroup; } int main(int argc, char **argv) { int me, nproc, i, j, *glist; MPI_Comm groups[NITER]; MPI_Group world_group; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); MPI_Comm_group(MPI_COMM_WORLD, &world_group); glist = (int*) malloc(nproc*sizeof(int)); for (i = 0; i < nproc; i++) glist[i] = i; if (me == 0) printf("Gsize\tPGgroup (sec)\tComm (sec)\n"); MPI_Barrier(MPI_COMM_WORLD); for (i = 1; i <= nproc; i*= 2) { double t_start, t_pg, t_comm; MPI_Group intracomm_group; /** Benchmark pgroup creation cost **/ MPI_Barrier(MPI_COMM_WORLD); t_start = MPI_Wtime(); for (j = 0; j < NITER; j++) pgroup_create(i, glist, &groups[j]); t_pg = MPI_Wtime() - t_start; for (j = 0; j < NITER; j++) pgroup_free(&groups[j]); /** Benchmark intracommunicator creation cost **/ MPI_Group_incl(world_group, i, glist, &intracomm_group); MPI_Barrier(MPI_COMM_WORLD); t_start = MPI_Wtime(); for (j = 0; j < NITER; j++) MPI_Comm_create(MPI_COMM_WORLD, intracomm_group, &groups[j]); t_comm = MPI_Wtime() - t_start; MPI_Group_free(&intracomm_group); for (j = 0; j < NITER; j++) pgroup_free(&groups[j]); if (me == 0) printf("%6d\t%0.9f\t%0.9f\n", i, t_pg/NITER, t_comm/NITER); } free(glist); MPI_Group_free(&world_group); MPI_Finalize(); return 0; } armci-mpi/tests/mpi/test_win_create.c0000644000175000017500000000222612662706250017466 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #define DATA_NELTS 1000 #define NUM_WIN 1000 // Error starts at 17. Up to 16 is ok. #define DATA_SZ (DATA_NELTS*sizeof(int)) int main(int argc, char ** argv) { int rank, nproc, i; void *base_ptrs[NUM_WIN]; MPI_Win windows[NUM_WIN]; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting MPI window creation test with %d processes\n", nproc); // Perform a pile of window creations for (i = 0; i < NUM_WIN; i++) { if (rank == 0) printf(" + Creating window %d\n", i); MPI_Alloc_mem(DATA_SZ, MPI_INFO_NULL, &base_ptrs[i]); MPI_Win_create(base_ptrs[i], DATA_SZ, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &windows[i]); } MPI_Barrier(MPI_COMM_WORLD); // Free all the windows for (i = 0; i < NUM_WIN; i++) { if (rank == 0) printf(" + Freeing window %d\n", i); MPI_Win_free(&windows[i]); MPI_Free_mem(base_ptrs[i]); } if (rank == 0) printf("Test complete: PASS.\n"); MPI_Finalize(); return 0; } armci-mpi/tests/mpi/ping-pong-mpi.c0000644000175000017500000000635612662706250017000 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #define MAX_SIZE (128*1024) #define NUM_ROUNDS 10000 #define PROBE_PROGRESS int main(int argc, char **argv) { int me, nproc, target; int msg_length, round, i; double t_start, t_stop; uint8_t *snd_buf; // Send buffer (byte array) uint8_t *rcv_buf; // Receive buffer (byte array) MPI_Win window; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (nproc < 2) { if (me == 0) printf("This benchmark should be run on at least two processes\n"); MPI_Abort(MPI_COMM_WORLD, 1); } if (me == 0) printf("MPI-2 passive ping-pong latency test, performing %d rounds at each xfer size.\n", NUM_ROUNDS); MPI_Alloc_mem(MAX_SIZE, MPI_INFO_NULL, &rcv_buf); MPI_Alloc_mem(MAX_SIZE, MPI_INFO_NULL, &snd_buf); MPI_Win_create(rcv_buf, MAX_SIZE, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &window); for (i = 0; i < MAX_SIZE; i++) { snd_buf[i] = 1; } for (target = 1; target < nproc; target++) { if (me == 0) printf("\n========== Process pair: %d and %d ==========\n\n", 0, target); for (msg_length = 1; msg_length <= MAX_SIZE; msg_length *= 2) { MPI_Barrier(MPI_COMM_WORLD); t_start = MPI_Wtime(); if (me == 0 || me == target) { // Perform NUM_ROUNDS ping-pongs for (round = 0; round < NUM_ROUNDS*2; round++) { int my_target = me == 0 ? target : 0; // I am the sender if ((round % 2 == 0 && me == 0) || (round % 2 != 0 && me != 0)) { // Clear start and end markers for next round MPI_Win_lock(MPI_LOCK_EXCLUSIVE, me, 0, window); rcv_buf[0] = 0; rcv_buf[msg_length-1] = 0; MPI_Win_unlock(me, window); MPI_Win_lock(MPI_LOCK_EXCLUSIVE, my_target, 0, window); MPI_Put(snd_buf, msg_length, MPI_BYTE, my_target, 0, msg_length, MPI_BYTE, window); MPI_Win_unlock(my_target, window); } // I am the receiver: Poll start and end markers else { uint8_t val; do { #ifdef PROBE_PROGRESS /* Needed for progress in many MPI implementations.. */ MPI_Iprobe(0, 0, MPI_COMM_WORLD, (void*) &val, MPI_STATUS_IGNORE); #endif MPI_Win_lock(MPI_LOCK_EXCLUSIVE, me, 0, window); val = ((volatile uint8_t*)rcv_buf)[0]; MPI_Win_unlock(me, window); } while (val == 0); do { #ifdef PROBE_PROGRESS MPI_Iprobe(0, 0, MPI_COMM_WORLD, (void*) &val, MPI_STATUS_IGNORE); #endif MPI_Win_lock(MPI_LOCK_EXCLUSIVE, me, 0, window); val = ((volatile uint8_t*)rcv_buf)[msg_length-1]; MPI_Win_unlock(me, window); } while (val == 0); } } } MPI_Barrier(MPI_COMM_WORLD); t_stop = MPI_Wtime(); if (me == 0) printf("%8d bytes \t %12.8f us\n", msg_length, (t_stop-t_start)/NUM_ROUNDS*1.0e6); } MPI_Barrier(MPI_COMM_WORLD); } MPI_Win_free(&window); MPI_Free_mem(snd_buf); MPI_Free_mem(rcv_buf); MPI_Finalize(); return 0; } armci-mpi/tests/mpi/test_mpi_indexed_puts_gets.c0000644000175000017500000001010712662706250021725 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /* One-Sided MPI 2-D Strided Accumulate Test * * Author: James Dinan * Date : December, 2010 * * This code performs N strided put operations followed by get operations into * a 2d patch of a shared array. The array has dimensions [X, Y] and the * subarray has dimensions [SUB_X, SUB_Y] and begins at index [0, 0]. The * input and output buffers are specified using an MPI indexed type. */ #include #include #include #define XDIM 8 #define YDIM 1024 #define SUB_XDIM 8 #define SUB_YDIM 255 #define ITERATIONS 1 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double *win_buf, *src_buf, *dst_buf; MPI_Win buf_win; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); bufsize = XDIM * YDIM * sizeof(double); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &win_buf); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &src_buf); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &dst_buf); if (rank == 0) printf("MPI RMA Strided Accumulate Test:\n"); for (i = 0; i < XDIM*YDIM; i++) { *(win_buf + i) = 1.0 + rank; *(src_buf + i) = 1.0 + rank; } MPI_Win_create(win_buf, bufsize, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &buf_win); peer = (rank+1) % nranks; // Perform ITERATIONS strided accumulate operations for (i = 0; i < ITERATIONS; i++) { MPI_Aint idx_loc[SUB_YDIM]; int idx_rem[SUB_YDIM]; int blk_len[SUB_YDIM]; MPI_Datatype src_type, dst_type; for (i = 0; i < SUB_YDIM; i++) { MPI_Get_address(&src_buf[i*XDIM], &idx_loc[i]); idx_rem[i] = i*XDIM; blk_len[i] = SUB_XDIM; } MPI_Type_indexed(SUB_YDIM, blk_len, idx_rem, MPI_DOUBLE, &src_type); MPI_Type_indexed(SUB_YDIM, blk_len, idx_rem, MPI_DOUBLE, &dst_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); MPI_Win_lock(MPI_LOCK_EXCLUSIVE, peer, 0, buf_win); MPI_Put(src_buf, 1, src_type, peer, 0, 1, dst_type, buf_win); MPI_Win_unlock(peer, buf_win); MPI_Win_lock(MPI_LOCK_EXCLUSIVE, peer, 0, buf_win); MPI_Get(dst_buf, 1, src_type, peer, 0, 1, dst_type, buf_win); MPI_Win_unlock(peer, buf_win); MPI_Type_free(&src_type); MPI_Type_free(&dst_type); } MPI_Barrier(MPI_COMM_WORLD); // Verify that the results are correct MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, buf_win); errors = 0; for (i = 0; i < SUB_XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = (1.0 + ((rank+nranks-1)%nranks)); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = SUB_XDIM; i < XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = 0; i < XDIM; i++) { for (j = SUB_YDIM; j < YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } MPI_Win_unlock(rank, buf_win); MPI_Win_free(&buf_win); MPI_Free_mem(win_buf); MPI_Free_mem(src_buf); MPI_Free_mem(dst_buf); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/mpi/test_mpi_indexed_gets.c0000644000175000017500000000730412662706250020657 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /* One-Sided MPI 2-D Strided Get Test * * Author: James Dinan * Date : December, 2010 * * This code performs N strided get operations from a 2d patch of a shared * array. The array has dimensions [X, Y] and the subarray has dimensions * [SUB_X, SUB_Y] and begins at index [0, 0]. The input and output buffers are * specified using an MPI indexed type. */ #include #include #include #define XDIM 8 #define YDIM 1024 #define SUB_XDIM 8 #define SUB_YDIM 256 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double *win_buf, *loc_buf; MPI_Win buf_win; MPI_Aint idx_loc[SUB_YDIM]; int idx_rem[SUB_YDIM]; int blk_len[SUB_YDIM]; MPI_Datatype loc_type, rem_type; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); bufsize = XDIM * YDIM * sizeof(double); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &win_buf); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &loc_buf); if (rank == 0) printf("MPI RMA Strided Get Test:\n"); for (i = 0; i < XDIM*YDIM; i++) *(win_buf + i) = 1.0 + rank; MPI_Win_create(win_buf, bufsize, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &buf_win); peer = (rank+1) % nranks; // Build the datatype for (i = 0; i < SUB_YDIM; i++) { MPI_Get_address(&loc_buf[i*XDIM], &idx_loc[i]); idx_rem[i] = i*XDIM; blk_len[i] = SUB_XDIM; } MPI_Type_indexed(SUB_YDIM, blk_len, idx_rem, MPI_DOUBLE, &loc_type); MPI_Type_indexed(SUB_YDIM, blk_len, idx_rem, MPI_DOUBLE, &rem_type); MPI_Type_commit(&loc_type); MPI_Type_commit(&rem_type); // Perform get operation MPI_Win_lock(MPI_LOCK_EXCLUSIVE, peer, 0, buf_win); MPI_Get(loc_buf, 1, loc_type, peer, 0, 1, rem_type, buf_win); // Use the datatype only on the remote side (must have SUB_XDIM == XDIM) // MPI_Get(loc_buf, SUB_XDIM*SUB_YDIM, MPI_DOUBLE, peer, 0, 1, rem_type, buf_win); MPI_Win_unlock(peer, buf_win); MPI_Type_free(&loc_type); MPI_Type_free(&rem_type); MPI_Barrier(MPI_COMM_WORLD); // Verify that the results are correct errors = 0; for (i = 0; i < SUB_XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(loc_buf + i + j*XDIM); const double expected = (1.0 + peer); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = SUB_XDIM; i < XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(loc_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = 0; i < XDIM; i++) { for (j = SUB_YDIM; j < YDIM; j++) { const double actual = *(loc_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } MPI_Win_free(&buf_win); MPI_Free_mem(win_buf); MPI_Free_mem(loc_buf); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/mpi/test_mpi_accs.c0000644000175000017500000000404012662706250017120 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #define XDIM 1024 #define YDIM 1024 #define ITERATIONS 10 int main(int argc, char **argv) { int itr, i, j, rank, nranks, peer, bufsize, errors = 0; double *buffer, *src_buf; MPI_Win buf_win; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); bufsize = XDIM * YDIM * sizeof(double); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &buffer); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &src_buf); if (rank == 0) printf("MPI RMA Strided Accumulate Test:\n"); for (i = 0; i < XDIM*YDIM; i++) { *(buffer + i) = 1.0 + rank; *(src_buf + i) = 1.0 + rank; } MPI_Win_create(buffer, bufsize, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &buf_win); peer = (rank+1) % nranks; for (itr = 0; itr < ITERATIONS; itr++) { MPI_Win_lock(MPI_LOCK_EXCLUSIVE, peer, 0, buf_win); for (j = 0; j < YDIM; j++) { MPI_Accumulate(src_buf + j*XDIM, XDIM, MPI_DOUBLE, peer, j*XDIM*sizeof(double), XDIM, MPI_DOUBLE, MPI_SUM, buf_win); } MPI_Win_unlock(peer, buf_win); } MPI_Barrier(MPI_COMM_WORLD); MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, buf_win); for (i = 0; i < XDIM; i++) { for (j = 0; j < YDIM; j++) { const double actual = *(buffer + i + j*XDIM); const double expected = (1.0 + rank) + (1.0 + ((rank+nranks-1)%nranks)) * (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } MPI_Win_unlock(rank, buf_win); MPI_Win_free(&buf_win); MPI_Free_mem(buffer); MPI_Free_mem(src_buf); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/mpi/test_dt.c0000644000175000017500000000156412663426407015765 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include int main(int argc, char ** argv) { int rank, nproc; MPI_Datatype emptyvec; MPI_Aint lb, ext; int size; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting MPI datatype test with %d processes\n", nproc); MPI_Type_vector(0,0,0,MPI_DOUBLE,&emptyvec); MPI_Type_commit(&emptyvec); MPI_Type_get_extent(emptyvec, &lb, &ext); MPI_Type_size(emptyvec, &size); if (rank == 0) printf("lb = %zu ext = %zu size = %d \n", lb, ext, size); MPI_Bcast(NULL, 0, emptyvec, 0, MPI_COMM_WORLD); MPI_Bcast(NULL, 1, emptyvec, 0, MPI_COMM_WORLD); MPI_Type_free(&emptyvec); if (rank == 0) printf("Test complete: PASS.\n"); MPI_Finalize(); return 0; } armci-mpi/tests/mpi/Makefile.mk0000644000175000017500000000306012663426407016212 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # check_PROGRAMS += \ tests/mpi/ping-pong-mpi \ tests/mpi/test_mpi_accs \ tests/mpi/test_mpi_dim \ tests/mpi/test_mpi_indexed_accs \ tests/mpi/test_mpi_indexed_gets \ tests/mpi/test_mpi_indexed_puts_gets \ tests/mpi/test_mpi_subarray_accs \ tests/mpi/test_win_create \ tests/mpi/test_win_model \ # end TESTS += \ tests/mpi/test_mpi_accs \ tests/mpi/test_mpi_dim \ tests/mpi/test_mpi_indexed_accs \ tests/mpi/test_mpi_indexed_gets \ tests/mpi/test_mpi_indexed_puts_gets \ tests/mpi/test_mpi_subarray_accs \ tests/mpi/test_win_create \ tests/mpi/test_win_model \ #tests/mpi/ping-pong-mpi \ # end tests_mpi_ping_pong_mpi_LDADD = libarmci.la tests_mpi_test_mpi_accs_LDADD = libarmci.la tests_mpi_test_mpi_indexed_accs_LDADD = libarmci.la tests_mpi_test_mpi_indexed_gets_LDADD = libarmci.la tests_mpi_test_mpi_indexed_puts_gets_LDADD = libarmci.la tests_mpi_test_mpi_subarray_accs_LDADD = libarmci.la tests_mpi_test_win_create_LDADD = libarmci.la tests_mpi_test_win_model_LDADD = libarmci.la armci-mpi/tests/mpi/copy_bench.c0000644000175000017500000000221112662706250016412 0ustar mbanckmbanck#include #include #include #include #define NITER 100000 #define MAXSZ 65536*2*2 int main(int argc, char **argv) { int i, j; char *in, *out; double t_start, t_stop; MPI_Comm copy_comm; MPI_Init(&argc, &argv); MPI_Comm_dup(MPI_COMM_SELF, ©_comm); in = malloc(MAXSZ); out = malloc(MAXSZ); for (i = 0; i < MAXSZ; i++) { in[i] = 0xAA; out[i] = 0x55; } for (i = 1; i <= MAXSZ; i *= 2) { t_start = MPI_Wtime(); for (j = 0; j < NITER; j++) { memcpy(out, in, i); } t_stop = MPI_Wtime(); printf("MEMCPY: %7d\t%0.9f\n", i, t_stop-t_start); } for (i = 0; i < MAXSZ; i++) { in[i] = 0xAA; out[i] = 0x55; } for (i = 1; i <= MAXSZ; i *= 2) { t_start = MPI_Wtime(); for (j = 0; j < NITER; j++) { MPI_Sendrecv(in, i, MPI_BYTE, 0 /* rank */, 0 /* tag */, out, i, MPI_BYTE, 0 /* rank */, 0 /* tag */, copy_comm, MPI_STATUS_IGNORE); } t_stop = MPI_Wtime(); printf("SNDRCV: %7d\t%0.9f\n", i, t_stop-t_start); } MPI_Comm_free(©_comm); MPI_Finalize(); return 0; } armci-mpi/tests/mpi/test_mpi_indexed_accs.c0000644000175000017500000001005512662706250020623 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /* One-Sided MPI 2-D Strided Accumulate Test * * Author: James Dinan * Date : December, 2010 * * This code performs N accumulates into a 2d patch of a shared array. The * array has dimensions [X, Y] and the subarray has dimensions [SUB_X, SUB_Y] * and begins at index [0, 0]. The input and output buffers are specified * using an MPI indexed type. */ #include #include #include #define XDIM 16 #define YDIM 16 #define SUB_XDIM 8 #define SUB_YDIM 8 #define ITERATIONS 1 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double *win_buf, *src_buf; MPI_Win buf_win; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); bufsize = XDIM * YDIM * sizeof(double); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &win_buf); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &src_buf); if (rank == 0) printf("MPI RMA Strided Accumulate Test:\n"); for (i = 0; i < XDIM*YDIM; i++) { *(win_buf + i) = 1.0 + rank; *(src_buf + i) = 1.0 + rank; } MPI_Win_create(win_buf, bufsize, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &buf_win); peer = (rank+1) % nranks; // Perform ITERATIONS strided accumulate operations for (i = 0; i < ITERATIONS; i++) { MPI_Aint idx_loc[SUB_YDIM]; int idx_rem[SUB_YDIM]; int blk_len[SUB_YDIM]; MPI_Datatype src_type, dst_type; for (i = 0; i < SUB_YDIM; i++) { MPI_Get_address(&src_buf[i*XDIM], &idx_loc[i]); idx_rem[i] = i*XDIM; blk_len[i] = SUB_XDIM; } #ifdef ABSOLUTE MPI_Type_hindexed(SUB_YDIM, blk_len, idx_loc, MPI_DOUBLE, &src_type); #else MPI_Type_indexed(SUB_YDIM, blk_len, idx_rem, MPI_DOUBLE, &src_type); #endif MPI_Type_indexed(SUB_YDIM, blk_len, idx_rem, MPI_DOUBLE, &dst_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); MPI_Win_lock(MPI_LOCK_EXCLUSIVE, peer, 0, buf_win); #ifdef ABSOLUTE MPI_Accumulate(MPI_BOTTOM, 1, src_type, peer, 0, 1, dst_type, MPI_SUM, buf_win); #else MPI_Accumulate(src_buf, 1, src_type, peer, 0, 1, dst_type, MPI_SUM, buf_win); #endif MPI_Win_unlock(peer, buf_win); MPI_Type_free(&src_type); MPI_Type_free(&dst_type); } MPI_Barrier(MPI_COMM_WORLD); // Verify that the results are correct MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, buf_win); errors = 0; for (i = 0; i < SUB_XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = (1.0 + rank) + (1.0 + ((rank+nranks-1)%nranks)) * (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = SUB_XDIM; i < XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = 0; i < XDIM; i++) { for (j = SUB_YDIM; j < YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } MPI_Win_unlock(rank, buf_win); MPI_Win_free(&buf_win); MPI_Free_mem(win_buf); MPI_Free_mem(src_buf); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/mpi/test_win_model.c0000644000175000017500000000311612663426407017326 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include int main(int argc, char ** argv) { int rank, nproc; void *ptr; MPI_Win win; int wsize = 1024*1024; void *attr_ptr; int *attr_val; int attr_flag; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting MPI window attribute test with %d processes\n", nproc); /* WIN_CREATE */ MPI_Alloc_mem(wsize, MPI_INFO_NULL, &ptr); MPI_Win_create(ptr, wsize, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win); /* this function will always return flag=false in MPI-2 */ MPI_Win_get_attr(win, MPI_WIN_MODEL, (void *)&attr_ptr, &attr_flag); if (!attr_flag && rank==0) printf("MPI_WIN_MODEL flag missing! \n"); attr_val = (int*)attr_ptr; if (attr_flag && (*attr_val)!=MPI_WIN_UNIFIED && rank==0) printf("MPI_WIN_MODEL = MPI_WIN_SEPARATE \n" ); MPI_Win_free(&win); MPI_Free_mem(ptr); /* WIN_ALLOCATE */ MPI_Win_allocate(wsize, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &ptr, &win); /* this function will always return flag=false in MPI-2 */ MPI_Win_get_attr(win, MPI_WIN_MODEL, (void *)&attr_ptr, &attr_flag); if (!attr_flag && rank==0) printf("MPI_WIN_MODEL flag missing! \n"); attr_val = (int*)attr_ptr; if (attr_flag && (*attr_val)!=MPI_WIN_UNIFIED && rank==0) printf("MPI_WIN_MODEL = MPI_WIN_SEPARATE \n" ); MPI_Win_free(&win); if (rank == 0) printf("ALL DONE\n"); /* WIN_ALLOCATE */ MPI_Finalize(); return 0; } armci-mpi/tests/mpi/test_mpi_dim.c0000644000175000017500000003331712663426407016775 0ustar mbanckmbanck#include #include #include #include #include #define MP_BARRIER() MPI_Barrier(MPI_COMM_WORLD) #define MP_FINALIZE() MPI_Finalize() #define MP_INIT(arc,argv) MPI_Init(&(argc),&(argv)) #define MP_MYID(pid) MPI_Comm_rank(MPI_COMM_WORLD, (pid)) #define MP_PROCS(pproc) MPI_Comm_size(MPI_COMM_WORLD, (pproc)) #define MP_FLUSH(proc) MPI_Win_flush_local(proc, win) #define ELEMS 500 #define DIM1 5 #define DIM2 3 #ifdef __sun /* Solaris has shared memory shortages in the default system configuration */ # define DIM3 6 # define DIM4 5 # define DIM5 4 #elif defined(__alpha__) # define DIM3 8 # define DIM4 5 # define DIM5 6 #else # define DIM3 8 # define DIM4 9 # define DIM5 7 #endif #define DIM6 3 #define DIM7 2 #define OFF 1 #define EDIM1 (DIM1+OFF) #define EDIM2 (DIM2+OFF) #define EDIM3 (DIM3+OFF) #define EDIM4 (DIM4+OFF) #define EDIM5 (DIM5+OFF) #define EDIM6 (DIM6+OFF) #define EDIM7 (DIM7+OFF) #define DIMS 4 #define MAXDIMS 7 #define MAX_DIM_VAL 50 #define LOOP 200 #define BASE 100. #define MAXPROC 128 #define TIMES 100 /***************************** macros ************************/ #define COPY(src, dst, bytes) memcpy((dst),(src),(bytes)) #define MAX(a,b) (((a) >= (b)) ? (a) : (b)) #define MIN(a,b) (((a) <= (b)) ? (a) : (b)) #define ABS(a) (((a) <0) ? -(a) : (a)) /***************************** global data *******************/ MPI_Win win; int me, nproc; void* work[MAXPROC]; /* work array for propagating addresses */ /*\ generate random range for a section of multidimensional array \*/ void get_range(int ndim, int dims[], int lo[], int hi[]) { int dim; for(dim=0; dim 0)? rand()%range : lo[dim]; new_lo[dim] = toss; new_hi[dim] = toss + diff -1; assert(new_hi[dim] < dims[dim]); assert(diff == (new_hi[dim] -new_lo[dim]+1)); } } /*\ print range of ndim dimensional array with two strings before and after \*/ void print_range(char *pre,int ndim, int lo[], int hi[], char* post) { int i; printf("%s[",pre); for(i=0;i 0) && (stride_levels > 0) && (count[i-1] == 1); i--) stride_levels--; /* A correct strided spec should me monotonic increasing and stride_array[i+1] should be a multiple of stride_array[i]. */ if (stride_levels > 0) { for (i = 1; i < stride_levels; i++) { assert(stride_array[i] >= stride_array[i-1]); /* This assertion is violated by what seems to be valid usage resulting from * the new GA API call nga_strided_get during the stride test in GA 5.2. * assert((stride_array[i] % stride_array[i-1]) == 0); */ } } /* Test for a contiguous transfer */ if (stride_levels == 0) { int elem_count = count[0]/old_type_size; assert((count[0] % old_type_size) == 0); MPI_Type_contiguous(elem_count, old_type, new_type); } /* Transfer is non-contiguous */ else { for (i = 0; i < stride_levels+1; i++) starts[i] = 0; sizes [stride_levels] = stride_array[0]/old_type_size; subsizes[stride_levels] = count[0]/old_type_size; assert((stride_array[0] % old_type_size) == 0); assert((count[0] % old_type_size) == 0); for (i = 1; i < stride_levels; i++) { /* Convert strides into dimensions by dividing out contributions from lower dims */ sizes [stride_levels-i] = stride_array[i]/stride_array[i-1]; subsizes[stride_levels-i] = count[i]; /* This assertion is violated by what seems to be valid usage resulting from * the new GA API call nga_strided_get during the stride test in GA 5.2. * assert_msg((stride_array[i] % stride_array[i-1]) == 0, "Invalid striding"); */ } sizes [0] = count[stride_levels]; subsizes[0] = count[stride_levels]; MPI_Type_create_subarray(stride_levels+1, sizes, subsizes, starts, MPI_ORDER_C, old_type, new_type); } } int loA[MAXDIMS], hiA[MAXDIMS]; int dimsA[MAXDIMS]={DIM1,DIM2,DIM3,DIM4,DIM5,DIM6, DIM7}; int loB[MAXDIMS], hiB[MAXDIMS]; int dimsB[MAXDIMS]={EDIM1,EDIM2,EDIM3,EDIM4,EDIM5,EDIM6,EDIM7}; int count[MAXDIMS]; int strideA[MAXDIMS], strideB[MAXDIMS]; int loC[MAXDIMS], hiC[MAXDIMS]; int idx[MAXDIMS]={0,0,0,0,0,0,0}; void test_dim(int ndim) { int dim,elems; int i,j, proc; /* double a[DIM4][DIM3][DIM2][DIM1], b[EDIM4][EDIM3][EDIM2][EDIM1];*/ double *b; double *a, *a1, *a2, *c; int ridx; MPI_Datatype typeA, typeB; int rstrideB[MAXDIMS]; int rcount[MAXDIMS]; int pidx1 = -1, pidx2 = -1, pidx3 = -1; elems = 1; strideA[0]=sizeof(double); strideB[0]=sizeof(double); for(i=0;i "); print_range("remote",ndim,loB, hiB,"-> "); print_range("local",ndim,loC, hiC,"\n"); } idx1 = Index(ndim, loA, dimsA); idx2 = Index(ndim, loB, dimsB); idx3 = Index(ndim, loC, dimsA); MPI_Sendrecv(&idx2, 1, MPI_INT, proc, 666, &ridx, 1, MPI_INT, proc, 666, MPI_COMM_WORLD, MPI_STATUS_IGNORE); for(j=0;j * Date : December, 2010 * * This code performs N accumulates into a 2d patch of a shared array. The * array has dimensions [X, Y] and the subarray has dimensions [SUB_X, SUB_Y] * and begins at index [0, 0]. The input and output buffers are specified * using an MPI subarray type. */ #include #include #include #define XDIM 1024 #define YDIM 1024 #define SUB_XDIM 512 #define SUB_YDIM 512 #define ITERATIONS 10 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double *win_buf, *src_buf; MPI_Win buf_win; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); bufsize = XDIM * YDIM * sizeof(double); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &win_buf); MPI_Alloc_mem(bufsize, MPI_INFO_NULL, &src_buf); if (rank == 0) printf("MPI RMA Strided Accumulate Test:\n"); for (i = 0; i < XDIM*YDIM; i++) { *(win_buf + i) = 1.0 + rank; *(src_buf + i) = 1.0 + rank; } MPI_Win_create(win_buf, bufsize, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &buf_win); peer = (rank+1) % nranks; // Perform ITERATIONS strided accumulate operations for (i = 0; i < ITERATIONS; i++) { int ndims = 2; int src_arr_sizes[2] = { XDIM, YDIM }; int src_arr_subsizes[2] = { SUB_XDIM, SUB_YDIM }; int src_arr_starts[2] = { 0, 0 }; int dst_arr_sizes[2] = { XDIM, YDIM }; int dst_arr_subsizes[2] = { SUB_XDIM, SUB_YDIM }; int dst_arr_starts[2] = { 0, 0 }; MPI_Datatype src_type, dst_type; MPI_Type_create_subarray(ndims, src_arr_sizes, src_arr_subsizes, src_arr_starts, MPI_ORDER_C, MPI_DOUBLE, &src_type); MPI_Type_create_subarray(ndims, dst_arr_sizes, dst_arr_subsizes, dst_arr_starts, MPI_ORDER_C, MPI_DOUBLE, &dst_type); MPI_Type_commit(&src_type); MPI_Type_commit(&dst_type); MPI_Win_lock(MPI_LOCK_EXCLUSIVE, peer, 0, buf_win); MPI_Accumulate(src_buf, 1, src_type, peer, 0, 1, dst_type, MPI_SUM, buf_win); MPI_Win_unlock(peer, buf_win); MPI_Type_free(&src_type); MPI_Type_free(&dst_type); } MPI_Barrier(MPI_COMM_WORLD); // Verify that the results are correct MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, buf_win); errors = 0; for (i = 0; i < SUB_XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = (1.0 + rank) + (1.0 + ((rank+nranks-1)%nranks)) * (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = SUB_XDIM; i < XDIM; i++) { for (j = 0; j < SUB_YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } for (i = 0; i < XDIM; i++) { for (j = SUB_YDIM; j < YDIM; j++) { const double actual = *(win_buf + i + j*XDIM); const double expected = 1.0 + rank; if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } MPI_Win_unlock(rank, buf_win); MPI_Win_free(&buf_win); MPI_Free_mem(win_buf); MPI_Free_mem(src_buf); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/ARMCI_AccS_latency.c0000644000175000017500000001451312662706250016767 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define MAX_XDIM 1024 #define MAX_YDIM 1024 #define ITERATIONS 10 #define SKIP 1 #ifdef VANILLA_ARMCI #define ARMCI_Access_begin(X) ((void*)0) #define ARMCI_Access_end(X) ((void*)0) #endif int main(int argc, char **argv) { int i, j, rank, nranks, peer; size_t xdim, ydim; unsigned long bufsize; double **buffer, *src_buf; double t_start=0.0, t_stop; int count[2], src_stride, trg_stride, stride_level; double scaling; int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); if (nranks < 2) { printf("%s: Must be run with at least 2 processes\n", argv[0]); MPI_Abort(MPI_COMM_WORLD, 1); } ARMCI_Init_args(&argc, &argv); buffer = (double **) malloc(sizeof(double *) * nranks); bufsize = MAX_XDIM * MAX_YDIM * sizeof(double); ARMCI_Malloc((void **) buffer, bufsize); src_buf = ARMCI_Malloc_local(bufsize); if (rank == 0) { printf("ARMCI_AccS Latency - local and remote completions - in usec \n"); printf("%30s %22s %22s\n", "Dimensions(array of double)", "Local Completion", "Remote completion"); fflush(stdout); } ARMCI_Access_begin(buffer[rank]); for (i = 0; i < bufsize / sizeof(double); i++) { *(buffer[rank] + i) = 1.0 + rank; *(src_buf + i) = 1.0 + rank; } ARMCI_Access_end(buffer[rank]); scaling = 2.0; src_stride = MAX_YDIM * sizeof(double); trg_stride = MAX_YDIM * sizeof(double); stride_level = 1; ARMCI_Barrier(); for (xdim = 1; xdim <= MAX_XDIM; xdim *= 2) { count[1] = xdim; for (ydim = 1; ydim <= MAX_YDIM; ydim *= 2) { count[0] = ydim * sizeof(double); if (rank == 0) { peer = 1; for (i = 0; i < ITERATIONS + SKIP; i++) { if (i == SKIP) t_start = MPI_Wtime(); ARMCI_AccS(ARMCI_ACC_DBL, (void *) &scaling, /* (void *) buffer[rank] */ src_buf, &src_stride, (void *) buffer[peer], &trg_stride, count, stride_level, 1); } t_stop = MPI_Wtime(); ARMCI_Fence(1); char temp[10]; sprintf(temp, "%dX%d", (int) xdim, (int) ydim); printf("%30s %20.2f ", temp, ((t_stop - t_start) * 1000000) / ITERATIONS); fflush(stdout); ARMCI_Barrier(); ARMCI_Barrier(); for (i = 0; i < ITERATIONS + SKIP; i++) { if (i == SKIP) t_start = MPI_Wtime(); ARMCI_AccS(ARMCI_ACC_DBL, (void *) &scaling, /* (void *) buffer[rank] */ src_buf, &src_stride, (void *) buffer[peer], &trg_stride, count, stride_level, 1); ARMCI_Fence(1); } t_stop = MPI_Wtime(); printf("%20.2f \n", ((t_stop - t_start) * 1000000) / ITERATIONS); fflush(stdout); ARMCI_Barrier(); ARMCI_Barrier(); } else { peer = 0; ARMCI_Barrier(); if (rank == 1) { ARMCI_Access_begin(buffer[rank]); for (i = 0; i < xdim; i++) { for (j = 0; j < ydim; j++) { if (*(buffer[rank] + i * MAX_XDIM + j) != ((1.0 + rank) + scaling * (1.0 + peer) * (ITERATIONS + SKIP))) { printf("Data validation failed at X: %d Y: %d Expected : %f Actual : %f \n", i, j, ((1.0 + rank) + scaling * (1.0 + peer)), *(buffer[rank] + i * MAX_YDIM + j)); fflush(stdout); ARMCI_Error("Bailing out", 1); } } } for (i = 0; i < bufsize / sizeof(double); i++) { *(buffer[rank] + i) = 1.0 + rank; } ARMCI_Access_end(buffer[rank]); } ARMCI_Barrier(); ARMCI_Barrier(); if (rank == 1) { ARMCI_Access_begin(buffer[rank]); for (i = 0; i < xdim; i++) { for (j = 0; j < ydim; j++) { if (*(buffer[rank] + i * MAX_XDIM + j) != ((1.0 + rank) + scaling * (1.0 + peer) * (ITERATIONS + SKIP))) { printf("Data validation failed at X: %d Y: %d Expected : %f Actual : %f \n", i, j, ((1.0 + rank) + scaling * (1.0 + peer)), *(buffer[rank] + i * MAX_YDIM + j)); fflush(stdout); ARMCI_Error("Bailing out", 1); } } } for (i = 0; i < bufsize / sizeof(double); i++) { *(buffer[rank] + i) = 1.0 + rank; } ARMCI_Access_end(buffer[rank]); } ARMCI_Barrier(); } } } ARMCI_Barrier(); ARMCI_Free((void *) buffer[rank]); ARMCI_Free_local(src_buf); free(buffer); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_putv.c0000644000175000017500000000436612663426407015572 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #define XDIM 1024 #define YDIM 1024 #define ITERATIONS 10 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double **buffer, *src_buf; armci_giov_t iov; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); buffer = (double **) malloc(sizeof(double *) * nranks); bufsize = XDIM * YDIM * sizeof(double); ARMCI_Malloc((void **) buffer, bufsize); src_buf = ARMCI_Malloc_local(bufsize); if (rank == 0) printf("ARMCI I/O Vector Put Test:\n"); peer = (rank+1) % nranks; iov.bytes = XDIM * sizeof(double); iov.ptr_array_len = YDIM; iov.src_ptr_array = malloc(iov.ptr_array_len*sizeof(void*)); iov.dst_ptr_array = malloc(iov.ptr_array_len*sizeof(void*)); for (i = 0; i < iov.ptr_array_len ; i++) { iov.src_ptr_array[i] = (void *)&src_buf[i*XDIM]; iov.dst_ptr_array[i] = (void *)&buffer[peer][i*XDIM]; } ARMCI_Barrier(); for (i = 0; i < ITERATIONS; i++) { for (j = 0; j < XDIM*YDIM; j++) { *(src_buf + j) = rank + i; } ARMCI_PutV(&iov, 1, peer); } ARMCI_Barrier(); free(iov.src_ptr_array); free(iov.dst_ptr_array); ARMCI_Access_begin(buffer[rank]); for (i = errors = 0; i < XDIM; i++) { for (j = 0; j < YDIM; j++) { const double actual = *(buffer[rank] + i + j*XDIM); const double expected = (1.0 + rank) + (1.0 + ((rank+nranks-1)%nranks)) + (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } ARMCI_Access_end(buffer[rank]); ARMCI_Free((void *) buffer[rank]); ARMCI_Free_local(src_buf); free(buffer); ARMCI_Finalize(); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/Makefile.mk0000644000175000017500000000661312663426407015434 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # check_PROGRAMS += tests/test_onesided \ tests/test_onesided_shared \ tests/test_onesided_shared_dla \ tests/test_mutex \ tests/test_mutex_rmw \ tests/test_mutex_trylock \ tests/test_malloc \ tests/test_malloc_irreg \ tests/ARMCI_PutS_latency \ tests/ARMCI_AccS_latency \ tests/test_groups \ tests/test_group_split \ tests/test_malloc_group \ tests/test_accs \ tests/test_accs_dla \ tests/test_puts \ tests/test_puts_gets \ tests/test_puts_gets_dla \ tests/test_putv \ tests/test_assert \ tests/test_igop \ tests/test_rmw_fadd \ tests/test_parmci \ # end TESTS += tests/test_onesided \ tests/test_onesided_shared \ tests/test_onesided_shared_dla \ tests/test_mutex \ tests/test_mutex_rmw \ tests/test_mutex_trylock \ tests/test_malloc \ tests/test_malloc_irreg \ tests/ARMCI_PutS_latency \ tests/ARMCI_AccS_latency \ tests/test_groups \ tests/test_group_split \ tests/test_malloc_group \ tests/test_accs \ tests/test_accs_dla \ tests/test_puts \ tests/test_puts_gets \ tests/test_puts_gets_dla \ tests/test_putv \ tests/test_igop \ tests/test_rmw_fadd \ tests/test_parmci \ # end XFAIL_TESTS += tests/test_assert \ # end tests_test_onesided_LDADD = libarmci.la tests_test_onesided_shared_LDADD = libarmci.la tests_test_onesided_shared_dla_LDADD = libarmci.la tests_test_mutex_LDADD = libarmci.la tests_test_mutex_rmw_LDADD = libarmci.la tests_test_mutex_trylock_LDADD = libarmci.la tests_test_malloc_LDADD = libarmci.la tests_test_malloc_irreg_LDADD = libarmci.la tests_ARMCI_PutS_latency_LDADD = libarmci.la tests_ARMCI_AccS_latency_LDADD = libarmci.la tests_test_groups_LDADD = libarmci.la tests_test_group_split_LDADD = libarmci.la tests_test_malloc_group_LDADD = libarmci.la tests_test_accs_LDADD = libarmci.la tests_test_accs_dla_LDADD = libarmci.la tests_test_puts_LDADD = libarmci.la tests_test_puts_gets_LDADD = libarmci.la tests_test_puts_gets_dla_LDADD = libarmci.la tests_test_putv_LDADD = libarmci.la tests_test_assert_LDADD = libarmci.la tests_test_igop_LDADD = libarmci.la tests_test_rmw_fadd_LDADD = libarmci.la tests_test_parmci_LDADD = libarmci.la tests_test_parmci_SOURCES = tests/test_parmci.c tests/test_parmci_lib.c include tests/mpi/Makefile.mk include tests/ctree/Makefile.mk include tests/contrib/Makefile.mk armci-mpi/tests/test_puts_gets_dla.c0000644000175000017500000000533012662706250017415 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define XDIM 5 #define YDIM 98 #define ITERATIONS 10 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double *src_buf, *dst_buf; double **shr_bvec, **src_bvec, **dst_bvec; int count[2], src_stride, trg_stride, stride_level; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); shr_bvec = (double **) malloc(sizeof(double *) * nranks); src_bvec = (double **) malloc(sizeof(double *) * nranks); dst_bvec = (double **) malloc(sizeof(double *) * nranks); bufsize = XDIM * YDIM * sizeof(double); ARMCI_Malloc((void **) shr_bvec, bufsize); ARMCI_Malloc((void **) src_bvec, bufsize); ARMCI_Malloc((void **) dst_bvec, bufsize); src_buf = src_bvec[rank]; dst_buf = dst_bvec[rank]; if (rank == 0) printf("ARMCI Strided DLA Put Test:\n"); src_stride = XDIM * sizeof(double); trg_stride = XDIM * sizeof(double); stride_level = 1; count[1] = YDIM; count[0] = XDIM * sizeof(double); ARMCI_Barrier(); peer = (rank+1) % nranks; for (i = 0; i < ITERATIONS; i++) { ARMCI_Access_begin(src_buf); for (j = 0; j < XDIM*YDIM; j++) { *(src_buf + j) = rank + i; } ARMCI_Access_end(src_buf); ARMCI_PutS( src_buf, &src_stride, (void *) shr_bvec[peer], &trg_stride, count, stride_level, peer); ARMCI_GetS( (void *) shr_bvec[peer], &trg_stride, dst_buf, &src_stride, count, stride_level, peer); } ARMCI_Barrier(); ARMCI_Access_begin(shr_bvec[rank]); for (i = errors = 0; i < XDIM; i++) { for (j = 0; j < YDIM; j++) { const double actual = *(shr_bvec[rank] + i + j*XDIM); const double expected = (1.0 + rank) + (1.0 + ((rank+nranks-1)%nranks)) + (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } ARMCI_Access_end(shr_bvec[rank]); ARMCI_Free((void *) shr_bvec[rank]); ARMCI_Free((void *) src_bvec[rank]); ARMCI_Free((void *) dst_bvec[rank]); free(shr_bvec); free(src_bvec); free(dst_bvec); ARMCI_Finalize(); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/test_rmw_fadd.c0000644000175000017500000000453012663426407016350 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ /** ARMCI RMW-FADD test -- James Dinan * * All processes allocate one shared integer counter per process. All * processes perform NINC atomic fetch-and-add operations on every counter. */ #include #include #include #include #include #define NINC 100 int main(int argc, char ** argv) { int errors = 0; int rank, nproc, i, j; void **base_ptrs; int ival; long lval; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI RMW-FADD test with %d processes\n", nproc); /* TYPE = INT */ base_ptrs = malloc(sizeof(void*)*nproc); ARMCI_Malloc(base_ptrs, sizeof(int)); ARMCI_Access_begin(base_ptrs[rank]); *(int*) base_ptrs[rank] = 0; ARMCI_Access_end(base_ptrs[rank]); ARMCI_Barrier(); for (i = 0; i < NINC; i++) { for (j = 0; j < nproc; j++) { ARMCI_Rmw(ARMCI_FETCH_AND_ADD, &ival, base_ptrs[j], 1, j); } } ARMCI_Barrier(); ARMCI_Access_begin(base_ptrs[rank]); if (*(int*) base_ptrs[rank] != NINC*nproc) { errors++; printf("%3d -- Got %d, expected %d\n", rank, *(int*) base_ptrs[rank], NINC*nproc); } ARMCI_Access_end(base_ptrs[rank]); armci_msg_igop(&errors, 1, "+"); ARMCI_Free(base_ptrs[rank]); free(base_ptrs); /* TYPE = LONG */ base_ptrs = malloc(sizeof(void*)*nproc); ARMCI_Malloc(base_ptrs, sizeof(long)); ARMCI_Access_begin(base_ptrs[rank]); *(long*) base_ptrs[rank] = 0; ARMCI_Access_end(base_ptrs[rank]); ARMCI_Barrier(); for (i = 0; i < NINC; i++) { for (j = 0; j < nproc; j++) { ARMCI_Rmw(ARMCI_FETCH_AND_ADD_LONG, &lval, base_ptrs[j], 1, j); } } ARMCI_Barrier(); ARMCI_Access_begin(base_ptrs[rank]); if (*(long*) base_ptrs[rank] != NINC*nproc) { errors++; printf("%3d -- Got %ld, expected %d\n", rank, *(long*) base_ptrs[rank], NINC*nproc); } ARMCI_Access_end(base_ptrs[rank]); armci_msg_igop(&errors, 1, "+"); if (rank == 0) { if (errors == 0) printf("Test complete: PASS.\n"); else printf("Test fail: %d errors.\n", errors); } ARMCI_Free(base_ptrs[rank]); free(base_ptrs); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_malloc_group.c0000644000175000017500000000233412662706250017244 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define PART_SIZE 1 #define DATA_SZ 100*sizeof(int) int main(int argc, char **argv) { int me, nproc, grp_me, grp_nproc; ARMCI_Group g_world, g_new; void **base_ptrs; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); base_ptrs = malloc(sizeof(void*)*nproc); if (me == 0) printf("ARMCI Group test starting on %d procs\n", nproc); ARMCI_Group_get_world(&g_world); if (me == 0) printf(" + Creating odd/even groups\n"); ARMCIX_Group_split(&g_world, me%2, me, &g_new); ARMCI_Group_rank(&g_new, &grp_me); ARMCI_Group_size(&g_new, &grp_nproc); if (me == 0) printf(" + Performing group allocation\n"); ARMCI_Malloc_group(base_ptrs, DATA_SZ, &g_new); ARMCI_Barrier(); if (me == 0) printf(" + Freeing group allocation\n"); ARMCI_Free_group(base_ptrs[grp_me], &g_new); ARMCI_Barrier(); if (me == 0) printf(" + Freeing group\n"); ARMCI_Group_free(&g_new); if (me == 0) printf(" + done\n"); free(base_ptrs); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_group_split.c0000644000175000017500000000125712662706250017133 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define PART_SIZE 1 int main(int argc, char **argv) { int me, nproc; ARMCI_Group g_world, g_new; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (me == 0) printf("ARMCI Group test starting on %d procs\n", nproc); ARMCI_Group_get_world(&g_world); if (me == 0) printf(" + Creating odd/even groups\n"); ARMCIX_Group_split(&g_world, me%2, me, &g_new); ARMCI_Group_free(&g_new); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/contrib/0000755000175000017500000000000012663426407015020 5ustar mbanckmbanckarmci-mpi/tests/contrib/cg/0000755000175000017500000000000012662706250015405 5ustar mbanckmbanckarmci-mpi/tests/contrib/cg/cg_timing.c0000644000175000017500000000220012662706250017503 0ustar mbanckmbanck/** @file * Copyright (c) 1995 by PDCL Corporation. All Rights Reserved * NAME * timing.c * PURPOSE * Timing routines for calculating the execution time: * void start_timer(void); Set the timer. * double elapsed_time(void); Return the timing elapsed since * the timer has been set. * NOTES * Jialin Ju - Oct 16, 1995 Created. */ #include #include //#include //#include #include /* Timing routines that use standard Unix gettingofday() */ static struct timeval start_time; static struct timeval finish_time; /* Start measuring a time delay */ void start_timer(void) { gettimeofday( &start_time, NULL); } /* Retunrn elapsed time in milliseconds */ double elapsed_time(void) { gettimeofday( &finish_time, NULL); return(1000.0*(finish_time.tv_sec - start_time.tv_sec) + (finish_time.tv_usec - start_time.tv_usec)/1000.0 ); } /* Return the stopping time in milliseconds */ double stop_time(void) { gettimeofday( &finish_time, NULL); return(1000.0*finish_time.tv_sec + finish_time.tv_usec/1000.0); } armci-mpi/tests/contrib/cg/cg.c0000644000175000017500000001601112662706250016141 0ustar mbanckmbanck#include #include #include #include #include #include #include #include "mp3.h" #include "armci.h" #define PRINT_VEC_ int na,nz; double *bvec,*dvec,*svec,*dmvec,*m_dvec,*amat,*xvec,*axvec,*rvec,*qvec; int *ridx,*cidx; int me, nproc; int myfirstrow=0,mylastrow=0; double epsilon=1e-4; double time_get=0; static int niter; void read_and_create(int,char **); void computeminverser(double *,double *, double *); void computeminverse(double *,double *, int *,int *); void finalize_arrays(); extern void acg_matvecmul(double *,double *,double *,int *,int *); extern void acg_addvec(double *,double *,double *,double *, double *); extern void acg_2addvec(double *,double *, double *,double *, double *, double *, double *,double *, double *, double *, int *, int *); extern double acg_ddot(double *,double *); void conjugate_gradient(int nit,int dopreconditioning) { int i; double d_one=1.0,d_negone=-1.0; double delta0=0.0,deltaold=0.0,deltanew=0.0; double alpha=0.0,negalpha,beta,dtransposeq; acg_matvecmul(amat,xvec,axvec,ridx,cidx); /* compute Ax */ #ifdef PRINT_VEC acg_printvec("axvec",axvec); acg_printvec("bvec",bvec); #endif /* TODO original call had too many arguments */ /* acg_addvec(&d_one,bvec,&d_negone,axvec,rvec,ridx,cidx); */ /* r=b-Ax */ acg_addvec(&d_one,bvec,&d_negone,axvec,rvec); /* r=b-Ax */ #ifdef PRINT_VEC acg_printvec("rvec",rvec); if(me==0)for(i=0;i(epsilon*epsilon*delta0);i++){ acg_matvecmul(amat,dvec,qvec,ridx,cidx); /* q = ad */ dtransposeq=acg_ddot(dvec,qvec); /* compute d_transpose.q */ alpha = deltanew/dtransposeq; /* deltanew/(d_transpose.q) */ #if 0 if(i>0 && i%50==0){ /* compute Ax*/ acg_matvecmul(amat,xvec,axvec,ridx,cidx); /* x = x+ alpha.d*/ /* r=b-Ax*/ acg_2addvec(&d_one,xvec,&alpha,dvec,xvec,&d_one,bvec, &d_negone,axvec,rvec,ridx,cidx); } else #endif { negalpha = 0.0-alpha; /* x = x+ alpha.d*/ /* r=r-alpha.q*/ acg_2addvec(&d_one,xvec,&alpha,dvec,xvec,&d_one,rvec, &negalpha,qvec,rvec,ridx,cidx); } if(dopreconditioning) computeminverser(dmvec,rvec,svec); deltaold = deltanew; /* deltaold = deltanew*/ if(dopreconditioning) deltanew = acg_ddot(svec,rvec); /* deltanew = r_transpose.r*/ else deltanew = acg_ddot(rvec,rvec); /* deltanew = r_transpose.r*/ beta = deltanew/deltaold; /* beta = deltanew/deltaold*/ if(dopreconditioning) { /* too many aguments in function call */ /* acg_addvec(&d_one,svec,&beta,dvec,dvec,ridx,cidx); */ /* d = s + beta.d */ acg_addvec(&d_one,svec,&beta,dvec,dvec); } else { /* too many aguments in function call */ /* acg_addvec(&d_one,rvec,&beta,dvec,dvec,ridx,cidx); */ /* d = r + beta.d */ acg_addvec(&d_one,rvec,&beta,dvec,dvec); } #ifdef PRINT_VEC acg_printvec("xvec",xvec); #endif /* acg_printvec("xvec",xvec); */ } if(me==0)printf("\n\tIteration:%d\tBeta:%0.4f\tDelta:%f\n", i,beta,deltanew); niter = i; } void initialize_arrays(int dpc) { int i; for(i=0;i cg.x na nz file"); printf("\n\n where:"); printf("\n\tna is array dimention (only square arrays supported)"); printf("\n\tnz is number of non-zeros"); printf("\n\tfile is either the input file or the word random"); printf("\n\t use the word random if you to use random input"); printf("\n\t input should be in row compressed format"); printf("\n\t file should have matrix a followed by row, col & b (Ax=b)"); printf("\n\t if file also has na and nz, pass them as 0's and the"); printf("\n\t program will read them from the file"); printf("\n\nexample usages are:"); printf("\n\tmpirun -np 4 ./ga_cg.x 5000 80000 /home/me/myinput.dat"); printf("\n\tor"); printf("\n\tmpirun -np 4 ./ga_cg.x 5000 80000 random\n\n"); fflush(stdout); } ARMCI_Finalize(); MP_FINALIZE(); return 0; } read_and_create(argc,argv); if(me==0)printf("\nWarmup and initialization run"); #if 0 initialize_arrays(dopreconditioning); conjugate_gradient(1,dopreconditioning); time_get =0.0; #endif if(me==0)printf("\n\nStarting Conjugate Gradient ...."); initialize_arrays(dopreconditioning); time0=MP_TIMER(); conjugate_gradient(30000/*2*/,dopreconditioning); time1=MP_TIMER(); acg_matvecmul(amat,xvec,axvec,ridx,cidx); if(me==0)printf("\n%d:in %d iterations time to solution=%f-%f ax and b in cg_output.out\n",me,niter,(time1-time0),time_get); acg_matvecmul(amat,xvec,axvec,ridx,cidx); if(me==0){ int i; fd = fopen("cg_output.out", "w"); for(i=0;i<=na;i++) fprintf(fd,"\n%d:%s[%d]=%f %s[%d]=%f",me,"bvec",i,bvec[i],"axvec",i,axvec[i]); fflush(stdout); fclose(fd); } finalize_arrays(dopreconditioning); MP_BARRIER(); if(me==0)printf("Terminating ..\n"); ARMCI_Finalize(); MP_FINALIZE(); return 0; } armci-mpi/tests/contrib/cg/matrix_med.bin0000644000175000017500000172535012662706250020245 0ustar mbanckmbanck1 aš×Ĺ´AF1=ªHׂÀÛ›¹N¯§hÁýºzeØâ-Át'n%c’jÁ }R·ü-Áwi¹4H³Á¬ñÏ€Èv@A¢cv‹§@åyžçyÝ@œ,B=†Ùœ@Hª ö@á@ÈzéêøH˜@X媾»ü”@7ÙY;óúÀ* ŒuàÀ½ã<ªsi@)0¹¼ å@ùæ9S£%Á‡²ìvÁ¸F@]jµ@‡UÐy0—Ÿ@‘}/^ÉÓ@˜¢D§ÃÔ´@F1=ªHׂÀ—çËd‡­AoT¤ÄÏÎ-AQo"¥hÁ]·8a±ü-Aækïn_’jÁ¬ñÏ€Èv@Áðám“BªÁûïWk8–à@÷NjqÎ÷úÀ&0¹¼ åÀ¾ã<ªsi@Œd5ÀÁA{V`J:ÁúžfUà€@ wsaÀEi@˜¢D§ÃÔ´À‘}/^ÉÓ@: Èʤ@Ö— ï²[‡@€•„ÿqWÀÆ®Gnr¤@À²ÉJRÒÌ‘@))Ïj#Gn@Òqý«±½À‘Û?œu›Àm‘t_˜ñ—@¢Ò—àlû@ê!Ôë–p@aÙ]<¾¿„@Óè±Ü·o@¶`Eæ ‡@­_õ‹-q@Ö— ï²[‡@KÕ$Çqj@Æ®Gnr¤@ÀÃ%l/ÿ'ÀÓ±%z Ës@öºîaƒÕP@†Õèi‚ À)\⦵ˆ~Àéåi¨ëŸz@N]ýj«p@ž-¨øqrR@¥¢Pˆ~g@[‰Ø•„¢Q@{ur3ž¡i@} U –S@/8<)¬‘¿@x ¦à_-¡@6|]ÕÅ/R@Xµ¹x×h8@Jš± 'úÀ1ÌOšøõtÀö/¡åñ À÷BY\ xÀoó`”àl@VÔj[b$ƒÀ˜Dçü@ž±×Jú?ý8¼X˜b”ÀØáT½S{ÀXõv¶J§ÀÌ—µ.nî{ÀÛŸAù¨À¨?b Àx ¦à_-¡@Æí˯(¦@¿çåï8@~NFï#¼ @W›©ÙÜFvÀ¦³«ùlÀƒ‡þ‘”©wÀÓò»¡L½aÀÑÝô%ƒÀEUþxÍU™@è±×Jú¿˜Dçü@ å61/g}ÀÕeu?µcÀíâ›xhczÀjíwŒëžÀÇŸÆ:1@]Šñw̧À4 ZÅ“@x =4 ZÅ“À˜›Ãc—–¿x =ÝZ“U–@FExäÍiÀx ½n`Û)“ÀÜàýÊ^–AÀ–RŒñÇ@»>×9@Á»)Ïg?ÛâÀÉh¦²bmÁ¨žªÂÀƒð»Ù¹ò@á^#йX@=݃ã$@ã"’iZ@ÿÒ‡Äge@3·ÖKö6@WçD>´¦@úȃpÀ<þ¥W"ÁÜò¸À›TïÀºÏ?‰âΕÁ’ß 1þ@éáÖÍßôÀNâLÚÄÀÀ–RŒñÇ@uZ×µˆ®AVÈ€Z‡#á@Zˆæ‡Ág¥Hü²—À]×|8WCðÀ±ØÉåŃÃ@%m‚…&Ä)@K›­ÂÄõ?î¶Š-a†+@‹4±•N6@•äŒeæí@,X£ò{áÀVo¿SÐ A²%Œ²€™ÛÀ é'äÖXú@~m¬ø4ì@æZ/[^• Áe}sÄÁÄÀ i‰þذÁJýü8¯çÀ¿Ðž”A¶?Λ”ÁÂ@¬4\\ÑòÀ1¼\x€°@¹IŸª(¹ÀÖDœ²¼e@ª¦Dú|ÀÃbá_M@ÏÏ~Uü)e@+ÁCï™Ly@ç©çà"S@ß}†jN@ÇkwÜz¶<@%êMif€|ÀÓRº³¼Ã€@ñ³•ë³Á‰À´œ@¤‡‘@þ]dZéæˆÀÇcp¡@”!@°¿MjÀ¦n«Ó|ä]@>Ë@Ž»3@ÀOÜD“ÁIÀnì«PŽÀŒ&‡q‚@úQ‘ž‰À@Š‘—ž§@ˆÜ‚xœœÀË’CN wp@¹IŸª(¹À·ÆÌ!âÛ@MÚ¥¿zp|ÀLq•‘Ö`’@ÐÏ~Uü)eÀÃbá_M@ç©çà"SÀ+ÁCï™Ly@´Nƒ0`Î<@ÞbŽ#i1+@ˆqÆ*,Þ‰@ f©ÓÖ¢À4ÔÒ* H—@BÆEýµ°À$o<Ð<³ÀEôA Ôq@óÔ» ˆÀ|'úv¹IÀ-L/;Ê`@ aÇfC;@…©SrPبÀ ªæÆ„•¨@v­¢5#ÇÀpºŽÍ™°~@Áµ·Õž®À_M™<µæ·AH#q¼­*A­3¬+ãÁij ®Ÿ¼òÀ&¤·h͇ùÀk–¸Sò5àÀÀüÑùvì·Á’!ü ÁÔuGŒíApÌžßõ@ªþå-#AZX;œ˜Ý@¡ª´¼AªæbÅå@O#0±É3ôÀÅèÐÞâ/ËÀ4‹gòëæƒ@e›+Iôsi@H#q¼­*AY·#ʈקAÛ5 ø&{ÀR5ÔÂ4 nÀwÚo?¥@wÀc‹évÀ¸œ|Ã>+ä@Ý{?lCò§Áƪ6…( ÁýO-WFÉ AZX;œ˜ÝÀªþå-#AªæbÅåÀ¡ª´¼A€WhO\À˜ðœûÂcÀýö=rTi@.„2P@Ÿ±•¥@Ý9Ž€À’ÀM;Ðöx@BóÖe•ÀÈ"É犚@ÿØ ÚÇ*@¶ úÛÍ9@äm Š»SÀ\„âeÀºbÓ{1h@±{„nü˜\@þl!ÐmÆ?@XœrÀY7ADÿ=\@™(H¯ëQ]@6h+î‚ü®¿½wˆè‚tÀ<%nk@¶„rîîÀާôÔ·@g@¡•É€Fª£ÀPk#dŽP^@74p‘À\ÝJ~•,À¨fQÕ7Î`@3GÍ)óƒU@ØÙ*c»S~À+he¨¢ðš@®ßw¬(L·ÀÜ5É”@@uAZFn"@¦§‚¤ìh'AAuÆ¡û†å@$íøµ{8Á¾)Iò8Á¼õ’m2¾@ÆÇ$â‰@ö¬ö}Çæ@¤’[ý­d¹@Ó³$A÷X¬@±õöVx@—kÁêöÀIAÆIeå®ÀR…HC,Ø@-À€Lƒµ@uÂ+’Ô@0À 9ù¹@¬ü!ù¯ðÂ@Bþ4»D©@¬ü!ù¯ðÂ@Bþ4»D©@eTàŒ«_Þ@GÎbÚ¡žº@¯¿þXö8Á@Xm ¼W†@”¹ÅŒsCÑ@ ê e r®@ö)EDZû@q 7ˆuá@»åž´g#A—XîŽB AAuÆ¡û†å@©õE­õ`A©2uR&˜Á²ÿ팕KÁ~WEvpµ@@ÆìfIæ‡@¯Écƒ±À~#ªRÚ°ÀäæéÕV­¦@”iµ¬V?„@«\VM„Ù¢@-L”rˆ@›|-G–¬@Cà>‚Å ‰@#'ÉÏ{? @“'ì1“§|@Bë3^¾É@ã+žn°@’2;æLCò@ÚËXYódÛ@÷USç¿×§Aã@ÐçpÝÁë¼7R"ä…@¼™îù†°«@"U'%ú^wÀu§zˆž|À h–æÅe@Hð—'p5ì@-]:=ÞnÒ@Ÿ"‡ûÿ«ð@@´I›^Ì@äáÓÛñ!¤@¿Ro1ø@·SPØAÎÀ0ìûž¿‹@ÈäfÍ¥£À°ñàÖry@\§9ì´@Ó|'RU½X@ø0lϨÁþ›Áê¾Ro1øÀãáÓÛñ!¤@ƒPTÜO‡ç@Þbª†÷øÁ@•è˜M»ê@HÊЈ‡ÁÐ|'RU½XÀ\§9ì´@¡GX #˜Áòy‚œ•Î@ÄíydhÁY:sLQ@=í—¬É@Hã!§³>ì@s[×>ÆÀP³J­×‚@Zle¹TY@4‘4ÆQïÀyÇ‹én_Ã@Ç ¤ÍC´Àoåñ¬målÀ‰‹Ûü[^‡@½X²_äl@&NÜMeÄÀ¬“.Øz£@ÆyØo_¨Î@çÛ°]À¸AÐ{³8µ@S™ñÜ%TÀÃäŠÔU‘À›]»3]gÀs[×>ÆÀ›ˆ¢qŠò@K+†åxY@b½e311@ª3 ÿg¿@LÒ_’€òÀ†_XŽlÀ"Ÿ,Ü—±ÀÒÒƒŒl@ƒ<9 û¥Q@öeòªÊ7¢@o5ŠBpÐÀèÛ°]@ÆyØo_¨Î@S™ñÜ%T@·AÐ{³8µ@ôLòüIogÀŠþ"ø²•?À`;ëˆÍ#˜Aº.2ˆ³AI@Þ-@z'Ñ™CÀPW0•„ý—Á锢)Ä^÷Àì¹ñRéÜÀÁï§ +@òi"™æÂEÀÁJ?ö‚y Áb'KÜw2ñÀ—$£¥ýÀª;T£Ò´ÔÀ_ÄÇ1Ö÷ÀÒšä@ÓÀ?TÎ-· 0@ü…Ï” ÚUÀEüL«\õÀÎ ’û‘ÓÀ»»4é\ÇP@YV¤nMÚkÀº.2ˆ³A8ÉH©á±A®ö¡­ê¯øÀp€÷•÷A¬œ©áŸÝÆÀ²j:K“Éñ@têÆ@ÍÀ»–mÔž¸õ@RþµÌDÀ!á¬Fðk@õK¸…Ê-ÇÀ×4WAíf]H?«·@\âz ô±Á”~ >TÀñ/kf3ˆwÀ†Ñ,¦žÇEÀš¸©¡†a@Øê-¦ºÈÀº\CuÝóï@€NëcvÀaTϺ햄Àoù³EYÀ‰"ÉŒƒ"À‡ýæÔoÐLÀ;ø¦`ÀË–‹¿SÀL^˜/.èz@&.Z†ËÖËÀ‡Ì T<æ@³ûš;vg@95¦”“ÀÜ=Z·å rÀ›¸g‡°ö@(Q)r6¨Aßž ¬!ÁhëóWîâ–@fÍ™³ÌP}@ã¶°X?3¨ÁFةޘAQ÷rˆNÀóDXAF£@ò³t/h]@&+fûîfB@²àà±À=àéP~õv@ãßp‘AkÿæÈð@¦§ó§ŒpÀr ;÷û˜@ê)?¥Àäy?ó®˜@÷2öËÀ;!!YC»@諽ë#Ñ A_4e´)õ@ßž ¬!Áiº›ñÇ‘¨A(ÝÛÕÖa}@¦5W‹Ñb@âàVRªœ@Á͸lS¨Áæ¦ö7ï@¡”Ë;‚Á qpzB@…ÇŠ^ '@Žv®P‰Ù@×^Z 3ôÀ SÅnû„@èou2s‡\@¯iÄÇ›á@Êñ<º'– ÁÌDh[aø@•Ñ|M‰?Á_¦cÆ}FAmÍÅÜ|Ô/Á²¢‰ñ@‚6DwB×b@¯ž¢Ç¼¦A˜®r\âÀ70´9·Zz@?E. !J@þÿļ¦Áôp4ÁÑâ@ÑשutTOÀ&nÆ’&eB@ý ®;^@Ù¬™-¦¹G@ÖÚ“µ¾r@í°¹Pl. @ò‹ôë…ÀÄS»Æ,@‰× Á©1‘@h å­Y/8@"J–¥s™À×s#BÀ˜®r\âÀötA‘õ °AßË?¬*J@ŠZãkñ@ä°…Ì%аÁµú=¥‚wÁ@iV2¥lAñÀôNàæ­K¶@ #ú0‘}ìÀ€¸ÁGI=@Çj¸ËÖ?O ’¨Ä@<–UX.úÀç\—Qa@ÙRƒçB@ÆC±ÄQÆ@mI=ºàöÀ[¡Ò®)Â@ú^ÙаW‚À8¡À¶m/˜À$>;ìñ@nyø%&¸Àå¥Рâu@ðE›ƒFõÀÛ‰}?MÀ®k¦ce'ÀBÝ£FØ´fÀðX1·N@f‡Âv%@Àú^ÙаW‚À”çÍä Å@2=¦ó>8@ùeo½¡ÀQ1DÓÍÿ@Å«·»À5Ì£ÇÔÀYJ‚¨ˆZ€ÀG¨C¹Ê4@WùÕ8ÏÀe‡Âv%@@ðX1·N@®ö¡­ê¯øÀÕâTëEÐ@y^B¢(~@"c‚+À@ùèá¼Ñ•À†k*­'@†˜ÂèkRÀÅBï—F=±@T±ŒŸÍáZ@QHsüΪ@Å–C%/foÀ¦ÏñJJ.@UÄèÅ}VÀÐáR±,(@“ÈÞPa €À+à5¹h©ÀI)IËÊø@AØÚ3'{À“[ëã\Î¿Žž#¸#A„À^ÎŒ ^UÀFƒyp›)@(vÊñŠPÀÉx“2«àÀò»G]ÚR•@0‚¢Kóµ@Uâ–\¶gÀݧ´zÓ,@£V’&GÀp€÷•÷Ay^B¢(~@½s²¬ ~Ì@ùèá¼Ñ•@"c‚+À@œ>í¶aüFÀüMg€áq@M±ŒŸÍáZÀÅBï—F=±@Ä–C%/fo@PHsüΪ@Lu°9 hMÀ¿Îq‰ÖÕu@¢!k0øLGÀýMlã +Ÿ@¢ðÐ×aÀl©‰EÁÀ×´9ŽàÀSâ–\¶g@0‚¢Kóµ@¤ í=üKÀQg‹é¾@o–ªTÂ’@Äb–F3£@Tt^%„@ù—¼X>ÃÀdÙ3ëk”Àˆ”t(@ÏÙ©ã×?À½ñŠÙuÀ³i­R]`@o–ªTÂ’@2V~ñ؆³@‚t^%„ÀÃb–F3£@˜ÿ¤`ˆ2”À`’<ЩâºÀ‘«Ó¡Í?À *ô¡U@ oys_`@>ÁWw4„Àt7õ¢›•@J¼(qjjÀŒ¢F  @g×â–œÄ$ÀŽÆØ_ÿZaÀ10¥4Pgc@Œ`á­f•Àâ²Þ =@<ú h­™^@Ä¿½tÙ¾B@J¼(qjjÀDèúp×'Ÿ@^£æc$©$Àئ ¾@@V~ñýê8c@_í¼R‚À4]FÄR=@S¿‚ ±–À r3_¸dC@lìR²Â'@Ói*ò!Ï¥Ax®n¨ ý@$xH ÁŽXJÝâÀ© ݬmíø@…ò§ŠlÃÀêŸt#}@x†¶Þ @­x7Y’~@ßV(q„ @+Ùš¦!]@ïBåÔkÙ@Œ„TÈįv@¡à;¡ÊÐ@o97í!¬&ÁgzæÌb­óÀ¾ÓæÞ¬¥ÁCr/—ÁÙU¬ÿÌÀ¢ûï}@¦ËF$@h==M4ÁÙrû:vÊÀ¯†Èaf@õç-vLá?x®n¨ ý@ÂQ\ù}J®AØtNÑ|«ÃÀŠ~õúùöÀ…ò§ŠlÃ@© ݬmíø@h†¶Þ ÀêŸt#}@æV(q„ À­x7Y’~@òBåÔkÙÀ*Ùš¦!]@§à;¡ÊÐÀŒ„TÈįv@Õ”¹1Â~Á2Kܹ¶øAªeG¨IsÀ*¸ÓÙ¯·Àï÷­’žþÛÀa8Ðp¶u Aù CšÁyô÷É”E"Aü)5À5$AFFOu%è°ÁªYOíAMÇÀ[ <‘2zå@nκ³þ¶ßÀï³ÎÓ4äü@lg5äòìÀÎ 1Q‰ AF—úìçÐóÀM4èËèæ!AÓÄ“jòòÀþGÇ’î!A„¶sG+?_À¤¼é¬ÚmÀÐo9°3H@Ô¿\ëyð?c 9pEqÀP ç´ôR8Àç-vLá¿®†Èaf@ÉY¯Öô-©@ù R•ñØ\@CÕlëŸt@|? e'”@@Óû}zï’@Hš¯vû?ÛÞDVg˜@C|K5Ze@ !+L_Àûçó¦Ù¦É¿ófÓÆgR@€Tr"xiÀÕñLàI{ ÀÐ=›‚…U@zï0 k–Àqk´yv=cÀw·_S5¥À3ijú‡ÛnÀù R•ñØ\@ŽÓÖR¡@(&ó¦4A@Ò:JáDª @÷Gš¯vû¿Óû}zï’@ÜHxØL\d@Á?i=ÃÐ1@ ©¼h@;Ð^ÀTr"xi@ófÓÆgR@W¼Â;åôR@³ÏÛ ѦÀqk´yv=cÀjë–”7ƒ0À°³ÜJÿmÀF›ë)ÕW{Àë¼7R"ä…@™B O/hR@ƒ§G§¬¨AnŸÒÿèì§Áº8ó ´~„@)¹ë7ÜñV@ÃXæœV Á)¹ë7ÜñVÀ!„âôÝ‘Á‹Œc<¹ªrÀæë)h V @Ê÷6ÑZ!l@Ð.µ(÷±AÚå’íó±ÁmÛ¶m[ÌA´i¦F<°@ùÌ}[ˆÇà@B!„€ß@iÖ9t<¥@—•mµËÀ›@Ê™ý N¢@DQEQ`A˃ šž“@~ýôׯ@€À# [´@¡éö³×@Ià¬æU›@£K?Üe@R!÷fð?1kv5°úgÀgBs#mð?%jûÌ@$„B:@'2Ï€]À$„B:ÀB˜ëx%Q@¼™îù†°«@"U'%ú^w@S÷æƒú»Ae`¾v©Ê@B ¨F©çêÀÒ>Yó…‚©ÀáqU5{Ý@гJ—ÉvÀ#îùÎÈ#±@køÆ|æš}@+ü¬¤4ýÀðLŸÉÀ¢ÀÎ~ˆŸûðÀ˜‘êFQžÀ4þn¡Á@4þn¡‘@‹—›øÜÀä+Ž‹~éÀÕ\¿=Ñ@»s!6c’ÀoódŸææ Á1G‹2Û¸¨À"U'%ú^wÀ¼™îù†°«@e`¾v©Ê@ßÉ9þØbA$x‹˜‹§ÀaifÊ SfÀгJ—Év@áqU5{Ý@køÆ|æš}À#îùÎÈ#±@T¿Èg„™Àù¿n3póÀˆå$º@°ÀÙÍ3¢/ÜÀ4þn¡‘À4þn¡Á@tüÄRš ¦À׋³·3(Ù@»s!6c’@Õ\¿=Ñ@­[{¯Ò´Ào}%ö÷ÁB ¨F©çêÀ$x‹˜‹§ÀøêšgƒØ—Aª–2+EŽ@þÿÿÿƒ×—Áõq»Ì@µ ËΔ‹@MØS:Ɇ¶@6¶‹Ž·@ó¢pù< u@f¸¼DìÇ@[oëâI„‰@Ò>Yó…‚©ÀaifÊ SfÀª–2+EŽ@ëoÍr„×§A¢cv‹§@C«|€ZÇ—@mÛ¶m[ÌAÕ‹Oòì§Á—Sðr îÓ@©ªªªª Ú@¨EÈ_³›ð@) þ¤Üù¨@ÃÙ©ñ¢@,zVרµ@æ¾ø!½@¨tdçþ@KFÁÅ“·@]tÑE¾ë@ DpìÒ8Ð@ͱF" n´@æ?.®´@¨tdçî@™Óà΋²@…ļ!©ø@™X'£=‹@}Aˆ±&J@'Þ‘{Ä[u@Þ*¨ÙUv@,æ‰,4@ŠFÑz®†@ù¬Í“1H@Ë~pžQ^ä@´¡ƒ|É+@~œ}!"€@WÁ›&³3F@foFé1.z@õ³¸QAá:@¾%svÂ6§ÀØVË0LSS@%ïÀš£L†@*¨ò}¥%8@BüË ûµÀã(Ò8ñP@©7û±<ƒ@Xðèb_RÀÜ"\9˜°À–&3 'hÀLNÇHÐÀíåƒ$h@!—‚Ÿe8@^1iyÀIN’Î…?žÀR]‰É2^@kÛ”ØCC@¦In—¦wÀéÔ|PK¹ÀaI" :,iÀ uO'Š˜½@À°¨ç?[ÀûΕ’®ž@†ÓçÌ;m@¢váœÉÀÛa¨o0@5´ÆÞzN¥À$xH ÁØtNÑ|«ÃÀCÕlëŸt@(&ó¦4A@oýF^[–A ÚèÍ@¥Æ‡©KP@ªÃú$ªocÀ6û(§‹¬“@ÏÛC2ú6a@3ðÈ8Áü•Á ÙªeAaY±Ö¥@<;_«±tmÀ•OMÿ@áÁ}ðŒK®äÀ¸‘º=jÓÁ‡’Vj?ÏåÀC¢–5I]ùÀ 6õžqÐÀn`5=V±¢@ɨ{ná$À1‘%°!'@tJðÆ\À|ìBvìßÁ²N§À³æàÀYLBJ݉@ÎbÔù ¡V@-ÂŽâKáø@_yƒd@°ãàÅœ0@Ž^ºÖWb@ºx .@8™\ M‚Á&³îÈÎÀŽXJÝâÀŠ~õúùöÀ|? e'”@@Ò:JáDª @ ÚèÍ@U‰—mþ£Adzj3ÀÀâ`"—@hðL¢_@;R®+@€ÙNmîµ@&£ø¥Á<;_«±tm@aY±Ö¥@_ µÂÞâ@ÓâÌÕ˜Á¸åo*¾ËÀþ#íö@´ Ÿ\ñþòÀµ™èœ®AvÝ@Êmä@ _`-šÁÍ„†hº÷½À Ä$îdØ@j8±IÎÀPêDÍöö@IiuÕÀéx)ëVvÿ@? ØÿÌ@IxoöööÀ2ƒa§bÉÀã%×/ñò@ͨ{ná$@n`5=V±¢@_R Œˆ[À¾¦–c’‘@sí¿”Þ@J0Wî¢ÁP br'T@&Ê„¢!@A«JcÃ@µà¥«Š[/@¯ž§K®âù?A»´½/–,@®ô A5h÷?URöëóÇÀ‡ðPù|þâ@‡ñPî:Ë@" øi‚Á_ïàa¡ÀÀ󶬵7é@·?Õ×§Aɧ]é²ûÀþÿÿÿƒ×§Á5GQñ+û@ ¦Ègf @ÿÊñ|êtÀÝ3g„ùÑÀJý"¢‘@«¬ð=2·@óL^¦q‘ö?ɧ]é²ûÀ!Ì_m÷±A­U—ojì±ÁÿÊñ|êt@ ¦Ègf @]&(ržû@-¯Ž ¯F&Á!L^¦q‘ö¿«¬ð=2·@õ }-Þ·A)³¬iåQ@»Íð6ÃKÆ@$ˆ #ŒÛ·Á ¯X;æií@;»tBW Ö@ÍQÌÂ@ìÊ‘‰O¥@•ª)²—~@—)âƒGkk@¹J`DßmÁ!¼Ä­=ãÀ°ÍN£Ž¥Y@춦“G@ÜÄŒ!.¯òÀÌN<Àµ¬ÔÀ)³¬iåQ@¥¹²Òä§A ¯X;æiíÀÌZ©)Þ§Át®¿PÂá`@‰$”8ãBN@lÛA7úâ@þÿ8ÜWÁï­B"N<@ ª*É‘~)@M‰µ|¡¤Ô@Ö ?AЫòÀ´yd€/ó@lÿJ‡à“@7C¥}[H‡@Á‚Ï`ÉE@,@#¢ã¿ÚÀã=ÝnáÀ¨† —zïÕÀø–˜%¤é'ÀnzíŒÜv@o3ýæÝÿ9—¤«~s…@1Ë&TC@ ¹6Ì¢À;=ðì.P,À©èg ú”@¬Z½ö?mû¶n´Œ@³×ç"%'XÀMì_oEµÀ, W¢5Y@˶v‰å±À0 ô+ø¿½Ÿ¤qR½…@Ù.óV_ W@±{ÿÖ0Æ„@ôò¼¡»ôÃÀ]@_˜wÀÎg„àzk@Xž°9)7ÀûLŒîĵÀHmÜ[– ÀeˆeÄìŠ@f›‘Ù‰W@-\ý}(@cY_@¼Â?ôM¾ÀìYGEñWaÀlÿJ‡à“@e?b«ð@±é¹ÓIF@ü¬]Nó]t@Ù1®r¦À¤.Àý± ÑÀ¼Àžb@0j ߘÚÕÀÛn3ýæÝÃ?ozíŒÜv@!}«jR@êá´—@š¾Ð]…Y3À;ÿ~Ó À1¬Z½ö¿©èg ú”@³×ç"%'X@mû¶n´Œ@þÖ ÊYÀ“ M/µÀŒÚ2’¡É¿r¯üGÑ ±ÀI’$Ž„bR@XÜ5¶~#@µ*鯅‘Q@&ú{iyÀs‡Ù8Tr¹ÀXž°9)7@Îg„àzk@ìQƒHd_NÀóMÏØÐ³Àža7ÎYV@ìªjúç#@ùÝ¿ø¨X@ç诂*@fˆ/ZIùgÀ”7 œwÓ·Àp¶È“»×—AtŽ.Þ“}@þÿÿÿƒ×—Áb­¹ó˜ ƒ@0ÈQ ³ÀÉ s½Àrq£E^"†@xðGJ œW@tŽ.Þ“}@¤K®ÃSûO@¡Ä¥=Ô[T@$­)œNG„À”dLVÑáRÀ°Voé'W@ö©£;!)@»>×9@ÁVÈ€Z‡#á@ÎVµ×—AüÑTÂdÀìÅ>¶&s@ØÛ$ñ! @¥`¬Ò›Ú—Á@L® &Çä@ëk·z»¿@9RŽ\þ¢@»j\Jj2@ äþU“ÞA£Eo¶™óâÀlÓÈwñ&v@§&‚?þ³@»)Ïg?ÛâÀZˆæ‡ÁüÑTÂdÀ±U§¨×§AØÛ$ñ! ÀìÅ>¶&s@þÿÿÿƒ×§Á¾j\Jj2À9RŽ\þ¢@£Eo¶™óâ@ äþU“ÞA«&‚?þ³ÀkÓÈwñ&v@«¿¢;‹×§A±ºÞ:Àh r+Ç-(ÀLÑ5¸Å@þÿÿÿƒ×§ÁØ;êY¤§ÅÀy®)Èc"^@›H½ª† ß?~»)èÐdÀ’ÀDNå5À…"Ê$ÿB#@òª0xÔ¥:À ð~ Û^Àᡪ#·i_@tÝ5®{Àõ¼ð6P²ÏG@çòÕR6ôTÀ` &SKwÀB.îû⿱ºÞ:À.Ó\’×—Aé,±q³"@@É»›ýÜÀþÿÿÿƒ×—Á©7$šçÜ@»H½ª† ß¿y®)Èc"^@_pÏÝ5Ày`n eWÀñ‹bSµ9ÀL‡Ìø~ÈQ@VwOÜß_@-ä½…2qÀohƒS¶¢¿ #NþzÀfÂÎ=gUÀ¿òµî–Õb@€ªíÎÜ?‰]]ôHFwÀ$íøµ{8Á©2uR&˜Á!¢ ° ³XAòBý)AÁ­ð´Ò¶@Gs ø:@!ß’ÕÉ› Á´!`îòÖÀºÍð6ÃKæ@Lš4iÒ¸Á ¯€¾ž@ÖþÞZx@j|ìiÆ1Ú@6^uNÉcÀº\×Qy@œOàß 7ÀžS½0´@&q¬˜ÒŒÀ©±¥O™›â@êBvjšñõÀBЮpÉ-ÓÀ­7`@ųh %Û?PX8?`“c@'õgÏa‡ÀõU½2§@;.lÄÛNgÀáð‘öÀ'káÚ™§ÖÀ”þÕÀ{zt)—e@Ë©¢JˆÀŸ»ýƒïÀ¼¨ ÒÖÉÀl¼Õ¦& Á |Ÿ›ËÁ+9å ¾MÁ1FXÁ¾)Iò8Á²ÿ팕KÁòBý)AÚ7 šr´ÐÀèVhwv3ÀÀA¹*¾ú×ÁÑx±Æ5öÀC Bx÷òÀéNz aAHÁ´¡ƒ|É+@")Ž Dá@ÚêWÿ bÀÍ…S:P`@ú×2P®–À´žðu@<"‡µ–¿ôµ­ ÿœ@V•žN„,@<ϧ\Á@WäÀÙVÝ À°Æˆ#‚@™2ÆåAkSÀë#û²À?I’ëyO@ßEuž=‘@£Gma]ÀҽߖJÄÀˆ\xu˜ƒÀѾóÝ¥S@=ÞúƒÀ‹É›SŸ Àtãÿ¸´NÀO·oÉ1cÅÀôš‹Ö&²@ ôoòGš…À[ÆÑÇâQ@‘æQ–éˆÀaô´Ú°ÛÈÀa§”Š¡ÍjÀ~œ}!"€@ÚêWÿ bÀÚåa¡¸Öá@6£É’Àc·Ij@ÕÉ@ê"‡µ–?´žðu@N•žN„,Àôµ­ ÿœ@VäÀÙVÝ @<ϧ\Á@™2ÆåAkS@°Æˆ#‚@YýõY:C@7-šµð7´À£Gma]@ßEuž=‘@?@I"¹eŒÀíüí»U¬À×~¥»ü†Àšw(ûR¶@õcŽ>ñ3@zÔ£LÍžÀ‚v Qyë¬@ke;€qêÀXÇi2G¹@0ÅZ&Ïí„À§’G¬©&½@ÀÊ%-qÀŸ!ºÎÛ_ÄÀ”ûÌš–@Gƒ {X<@=Ñ—´®²’À[÷¦;U&‘ÀñIÇp³[@-äÓK‹…À“Ý$ö>vÀ—…Á!>_‡@Gƒ {X<@8£=ÕЖ@[÷¦;U&‘Àüœn¸šuÀc‹+ ÛyÀÛÓ°&¤@´à¤+ƒ}@Ô1ûl$¥§À¬ªªªª ê@`ÕoËZ³?´RÂJÇ›­@Ð 1–¦î•@¹S´p„Û@Š΀Pr¿@-¯Ýâ<,öÀfŸµ‡qrÃÀmÞ§¸d°@NàÒ! ¯”@l¥7¦õm@`ÕoËZ³?w aHº ê@>°F–‰E‘@G¦Žm–y@+†¾Á À@{â"KX¢@X7–ƒÐZÅÀ ã¡ù uëÀ¢ÔØÃ, “@[ËüŒ!x@~ KöyUb@P³J­×‚@K+†åxY@8C™¥%«@LÝ® A°‚Àúôi“ÀiÉ“ðñA|@#µÔ‘Ê@¦Àö‚£ãÅU@¸ò"4*@:Žé× DÀZle¹TY@b½e311@LÝ® A°‚ÀÊ¿˜’µ@8È|¾³Û€@ÌzD")¦À'?0›€ÃÛ¿ (¦Àï&s )EÀ 9âø0`@1ËqÇחAp­)8T:æÀþÿÿÿƒ×—Áßè"X:æ@‹¡ %)‚À¤!@lR—-ÀoÓLYEu@Ÿ!@lR—-@p­)8T:æÀðöà§Aáxè ܧÁc›zÁF-æ@É 0®;$ÁÂ$^íZ@-CÊ6~(@²E9"(Aí‡8´^²óÀ¤Ô(cxz@¬äƦý•Àç›9+ÄÀbI¿ 5„¦À °r¼Á¬X"i¶ºô@t÷¼Zt@ííØÐÈÑ?í‡8´^²óÀ·"–3¾"A‹oÏí–À_B\g$í±@yqçÄ`¥ÀÀå«K À»ÿâi·ô@#Jì=Ô"ÁwííØÐÈÑ¿t÷¼Zt@(sxL£á±AŸŠ :PBÀ®È¢–·˜@B!„€ß@¨EÈ_³›ð@ üZÓ?±@Û¹v`NÜ@ºŠ<ºæ±Á÷Ö”f±@ÊLï·w¤@>#[©vmµ@P–“pÍ»@jVpøBšÔ@Ö†æ–@ái«€É@ýÞqoÎÎ@ÃyP«Ä“@e €³“@c! YÈ:õ@߸®¡É@˜tj,Ø@a¶V~´òTÀaÚîÎN@7YA{I@ÅÔ(]™¢7ÀŸŠ :PBÀK˜qn…×§Aþÿÿÿƒ×§ÁHqÅþ'N@ ±… 0pÀRÍs‰¯7ÀÌésaS@‡ˆì“×@{dqßE9¼Àñ-ðkÀÚ:ÀÈ;„@w°$oEµB@¸‹þ^ÀKÂ}¬nÅÀï<©'•@Û%˜}ÅÆÀ?sM wŒ@Q$QyUª0ÀŽzmyc“@^qîýH’ÀÊÄ7¢w,”@%%Íþí‚À°À ?‹z@âmÐé-ôQ@A(Næ}{ÀäÈòäǪ™À>X±ÿ1.–@íëd ÑŸ@oÀ†sw@{dqßE9¼ÀY5Tßó@Œyhi ø’@9³Òc[v«Àl7Û¢ËZÀ»J 7Ô†u@& …¶×›@&^ÒïÔÀ”Ö“Þƒ –@Uæ 3aÓÀeüPó#`@MÚ³ ®ÂÀ¦#«×In@`ÏÀ‰ßrfúÓ÷ÀW,Ò¦á±A±é«¨¡XÀku¤e:¨@ÃÙ©ñ¢@ÊLï·w¤@‰ií?Nâ±Á…·X3±@úNF‰@³@k œ*Kn‘@¤¥HÄ@åyžçyÍ@NФÌÉÀ‚µþ¼X@,ƒÐíÌc@"‡±(ÎÝ¿±é«¨¡XÀ›—È•“‘@˜ 8ƒÚƒX@;½óI¤”Àú†±(ÎÝ?,ƒÐíÌc@ÛŸx»5ª@?´h¥T?@**¿öT@û%ºb·µB@jæŸf¨À°iÙþÓߥ¿]5‹ÕG³@—•mµËÀ›@,zVרµ@>#[©vmµ@…·X3±@UmMã—Á2ëhóô@aÙqcQ£”@ËOz~ÀL @lÛ¶mÛæ›@ÅqÇq ë@F®:™Ø@Ö†æ–@!à_[¾O˜@ÁFîrÖ¡@qžÞÇ9úKÀLpB¹°‚@Ç]9¼AóPÀopnBºZ¯À¢'P@É®æ´`v@OÌìÔóþ¿ aïú–L@›Nöùh|@qžÞÇ9úK@ÂFîrÖ¡@Ç]9¼AóP@LpB¹°‚@\ˆ ´ÕÛfÀšp5踫À9ÌìÔóþ?žÉ®æ´`v@¥Æ‡©KP@dzj3À0aœ~àõ×@‡¹©êw‚ÀŠm¤« t@ÇÀYJßJ@…ƒâY‡¥@½–Dmû¿M@EU×¾øè›@%ŽŸo§½@§¬Ï‡âÃÀhB{[]€@Y‚èÏ!TL@uØî÷¯tÀ$ÞÀÇŠ@íLš¸,ùa@ß7u "µµÀµl§Š-€@R†MZ/öÅÀ%â£Õ^uŠÀ„¹0ðëDÀ™”ö?HBdÀ…ÖÅð?]TÿÝ$Àu²˜Ãv¼u@ø.Þ,öLc@ªÃú$ªocÀÀâ`"—@‡¹©êw‚ÀZ2==-Þ@¿YìÑAA@pŽ…Ý @ÄáC·ÛFÀ.TÀj!~@Üað.©h@”ºk?˜PK@h‹6­ÿŽ@ãZÆ:?ÍÀqA¼Xw†xÀó^¿»îè¡@¿©ŸèÄ W@ËË®;'ï.@DòÓD܃hÀ9-ª/¯zÃÀl¢_V»tÀÓ™‹zšðÀÀ;Âú±^Â{@<¿áä¡ÀMŒL´ûSÀЂ3ŒoÛˆ@°£ëŠ´B@„`ûŸû›0@Óû}zï’@÷Gš¯vû¿{{þž×§Ah0÷pìgÀþÿÿÿƒ×§Á86™DsZ@€ôÁÖθ$ÀcÉUÒš”²Àµ‰×åN³f@òŠQ›»9Ø¿…ëÎÓ3 -@Hš¯vû?Óû}zï’@h0÷pìgÀøþBNÝ×—Aþÿÿÿƒ×—ÁôÁÖθ$@86™DsZ@Úíîp½c@žkó~ê ¹À…ëÎÓ3 -@iƒ}l‚À8» ­„×—As˜÷ zÀþÿÿÿƒ×—Áw¯Œ]•IÀ8\ç5ž~@[Î&1 @¢ÀŒÕ†fRÀs˜÷ zÀ©·%G£×§ADQEQ`A¨tdçþ@ƃٹ_•¢@…ļ!©È@jVpøBšÔ@§yZ’?–@aÙqcQ£”@SV.ýOâš@gI "ä§Á–WÈ1`º@´¯má¬Î­@;»tBW Ö@â?HÕ—@[lp±ÁÕé@‹*ù¶~@e ¯’a²À«Ö饤RÀ'ªgŽÀ†@"Uœô :„@oÇQL@ÕrBIlÀv=*7¹@•PÂW3@ è ŒÄ@ŠÑÿ+Ž€À÷4’6WÁAÀŠB5‚A0*@¢d®:O@÷4’6WÁA@ÕrBI|@znÓ‘O@²Yñù¼c@!D7Ð&Û‡ÀAóÙ3¾3@þ½«E½>@V7@æ;@{5ú°Ê4@²Yñù¼cÀcQ ðì¢n@‘Zˆö“À@Ÿ ;/{À¾/ƒib§À:Æó”8@efuƒæB@¸ïýY”^À>CZº½“'@¦åy'žRÀ259°ƒ´ÀnÔ`"'T@Ÿ ;/{À‹‘˜üàÄ@$¦+ŠÄ„@Ç(I¸À—ðkÖÎçkÀVð’Ô’†@àr3ÁƒÖQÀÂZ ñ+|@(á ý@P@?9H#^9¶ÀhëóWîâ–@(ÝÛÕÖa}@øUÀç¼.AÔ[c @W¥…Âé@ws5©’B!À`¨¸É@§Õ‘÷Û0ÀpIoÊŠU-À1$›Þ×hF@g|ƸŸhbÀš–“ÅÅ¥)@òYˆtDF@F 9(+@Ù•¦No7½À4:ôiM™¢ÀVçê†ã`À à<ꂈ4ã4<À¬j¦¯ûV@BXÙª'À2•ªT,bqÀ€„.ÁfÍ™³ÌP}@¦5W‹Ñb@Ô[c @˜Õª´Š>Av,p~h=!À4ƒ¡»ÐJ<@€„.A†ƒ‡ÅD3ÀêYZJ@‰ŠêÑH@ÿÚ;W¤ZbÀqÁÓ’Ÿ)@“±W0z'gÀ>‹ÿk.+@?ø%y“@¢v;죗¢ÀCñãÖ«‡À[yš2›ìÀ¿­ÓDn Ö`ÀëÄ­Ž¥ùV@·„ïs¸rÀwƒ$Ç*_qÀבW„ÇãcÀÿÿÿÿXãFÁWÁ›&³3F@ —z‘2A·}DÈÀ*›ñþ“T1ÁVYxéÚÚ@«ƒGA@RˆÆ» RdÀè0€·ŒlßÀD§½XŠ ÄÀÌÙId.ÏÀ òæD~µÀÞѧ÷oÌ@ú Ä{?ž@ èÇ&d­@ÉÔsZ‡ƒ@-Þ,XO´éÀ&TŒiœÀ¿Š+Ô:lj@'ùÑzq@Û=pÔ“f@=œ d–tÀfoFé1.z@·}DÈÀptìÕybAAµ8ÖÏ@Z;pOAÁ{•D½Kê¦ÀÊÏ'ίòÊ@0ôÒÝìÁ@VW¬ÞÀ\%Í7y:¶@V‚¼Í0ÞÏÀú Ä{?žÀÞѧ÷oÌ@ÉÔsZ‡ƒÀ èÇ&d­@&TŒiœ@Øá¬MéÀguQ9r@~ËÅ¥ï¶X@vm™çðÍÀÓ÷EܯÚ@puOåôï@œ»ÁØÖ´À]É>ìŸêÀCNbÅÀ@DÒ™U¹ØÀ‹¬ß4Ö±À‡‹dbƒ¿@#^yÅDh¡@ùƒQF9·¸@J}ª$©ÉƒÀœ»ÁØÖ´À©HùÅâ±Aœ,B=†Ùœ@˃ šž“@KFÁÅ“·@E6xnRÒ@²~ CV¬@Ö†æ–@¯ËÀ„sä±ÁwÄqcÜ@uŒâ\ÇHÑ@˜tj,ø@üß\~o”@ ¹¸cã @ÎCuÂI¡@õf¾OG»@?t 8eñÀ9¼†‚?±Àäú¡+àÃÀr$(Á&M¡@]`(ƒ@K}ª$©Éƒ@ùƒQF9·¸@ü®…ßÙ§A]‘a׺Áþÿÿÿƒ×§ÁeIv›×A_4tî9ù›Àqoj.F~’@m.|‹.ÞîÀKë§;Ê@]‘a׺ÁªD€¬<²AX媾»ü”@æ?.®´@ð|zÜ\Ç@_"*IÅ5§@e €³“@˜tj,ø@A_ÐôµÖ@¯ùiZÈ@ÜR¢3 ²Á/'Üòy–‘@¼ Õ6樛@Ù¿¨–°Oœ@i¦n-væ@8(H³>†ÁmÇ7QÕAIy].^DÁ%Ê›õpD¨AxCÝ|ÑÀ¶N »TT$@¡#¾š™eÀê“$d6@õ´‡g(vÀækjÔ{vÀÜo ñ“t ÁÝ1•jàÀ½éþ >Vý@ö®oŠOÏÈ@+†T!@D2´ ìÕaÀÃ.®™0¨Áq•§!œÚÀYZZZšA´´´´´Šå@M­µyí¢zÀê¨i”!Áœ¥°]ËÒàÀÁ ž¦A©£¬ô*oä@VCÿÛ¦è$Á°ôH›ùúãÀfE³D¾Aß5Aëåâ@xCÝ|ÑÀk½Œ1ײA¶N »TTdÀ¡#¾š™¥@Ú{Þ±ìuÀ0áÔ®:²µ@ýÞR5µ¶@ö•I…\Ûà@jª}rÒó Áö®oŠOÏÈÀ½éþ >Vý@+†TaÀD2´ ìÕ¡@q•§!œÚ@‡a)q ²Á´´´´´ŠåÀYZZZšAM­µyí¢º@ ‘óà§‚á@ÍÕƒ+X"Á©£¬ô*oäÀÁ ž¦Awžò­øã@UlàJæ$Áß5AëåâÀfE³D¾AÔƒRÔÁ×§AùmǶ<Áþÿÿÿƒ×§Á*ÃȰ³CAKª‘fñ]øÀÍùØAŒ•½ÀÖ<›@Pƒ„ÀGw®*Gr@ÙŠìb P@E¾t0Z@§ÿ8R”ö@ˆÓÂ®Ž»@ùmǶ<Áq¼ê õ±Aég·ûDë±ÁÏÌÐnA“xõ‹!Á²ÐSä@‘bÑ*+Á#E¾t0ZÀÙŠìb P@…ÓÂ®Ž»À¦ÿ8R”ö@/Rý°ß·@0½–ÏÙm9´_ÀIô±íM°@W¶=1RÀÎ3ZªaçpÀ¢K‹R h”ÀŧUkþŠ@ç=±”˼7@,3 ykÀ~1i«„²À\vô“‡#пIÊaɼ=@`†3öì#qÀ0½)¦ñ@GÞ¸@+vÀ¥V d@›cÄÑ`æ€ÀqÂM."MÀ>ñr;E@á߀©  @¯/ðú2}@3ôòN½À¿þzÙˆfÀZW¸™@p+=ÍMÔh‚²À*qç;lÀ‰f…E @áqU5{Ý@гJ—Év@¹5 %tð@ÃóúÀYÒÀ`)ÛXÀÇ­mÐKÊÀB¢¾q.%´@¥ÖŽ…¬Í@$8,]£G¼À [ Ì)@¯¡ѽŒjÀù?ót8ŽîÀ ùà´VDÔ@£™Œ¸ë@öZÈÀÖ;Íè>ÕÒ@84õ¡oÀa‘Ç@g7ûÀlFÑKŸ%Ë@гJ—ÉvÀáqU5{Ý@ÃóúÀYÒÀŠU=JÙ¼ AÃU†bKÒÀ@[r/ácFž@žƒþ¿ÖéÀ%8,]£G¼@¦ÖŽ…¬Í@ìéÔ%ÊhÀ^iÛf>ƒ©@ FšÄ¸ÂÀ؃z¤‘óÀöZÈ@¤™Œ¸ë@84õ¡o@Ö;Íè>ÕÒ@)]ÎT3ï¸@õ~8¸ÅÊ Á"c‚+À@ùèá¼Ñ•@Ú8ÁªŒ@óBüLÀ®3ý¾zŸò@¡€ýod·”@sÉYœ½I@_}VÇ-’ À2+ªÎ0~c@ff§*$À×;¬2jy@§QoF<:ÀÃ_4Ïì"9@¡{ãÕ€òù¿Ú8Áª\@óBüÀ9Ýœ yu@ šWצBÀËd±Üpž0@ º*O®'ñ¿éñâ›ìæW@D+‡O¬À55w¥¼:d@qGbýÊá$ÀÎó²¤6g@´E²Áõ'À5ømý b@³ï¾³¶"À”c³(KÎ @`¹êÆYá¿›{uݲR@ˆ³GMÀ˜‡Ò 2@3ÆÅ§:ó¿~áÖÞy@oíÕè9ÀRsô¾@£Vü@ðÝ¿½p†í@£|áciÜÝ¿©Nœ ò½À3ÌiëQ§k@œ!kDưg@X·òit(ÀÏt´W(õ¦@Ä™u"|@:Äuy¢@Â/y›©‚_@ƒ³JbÖÀr> –½ŸÀB‘l&s­@r´î7#(v@:(Ð6j;ôÀ°.¹‹ø,†À–‹{fòÏ@‘ÒATÐAƒÀùèá¼Ñ•À"c‚+À@óBüL@Ú8ÁªŒ@¡€ýod·”@³[[*Ù§A_}VÇ-’ @sÉYœ½I@ff§*$@2+ªÎ0~c@§QoF<:@×;¬2jy@¡{ãÕ€òù?Ã_4Ïì"9@óBü@Ú8Áª\@ šWצB@9Ýœ yu@ º*O®'ñ?Ëd±Üpž0@D+‡O¬@éñâ›ìæW@qGbýÊá$@55w¥¼:d@´E²Áõ'@Îó²¤6g@³ï¾³¶"@5ømý b@`¹êÆYá?”c³(KÎ @ˆ³GM@›{uݲR@3ÆÅ§:ó?˜‡Ò 2@oíÕè9@~áÖÞy@£Vü@ðÝ?Rsô¾@£|áciÜÝ?½p†í@ÝÏelÀNó“–½ÀX·òit(@·›ó„‚×§ÁÄ™u"|ÀÏt´W(õ¦@Ã/y›©‚_À:Äuy¢@‚OÖÁ Ÿ@uB“Å:ÖÀr´î7#(vÀB‘l&s­@êišLXžÀ¹%‰íÀ’ÒATÐAƒ@–‹{fòÏ@¶N »TT$@¶N »TTdÀPÍ9åË×—AÚVLí¸òíÀþÿÿÿƒ×—ÁéÙN`œí@‡u$·âo´@¼€·Ã"¿\@ƒ_& #ÃÀ¦Ž¦g/@FO6d(@)¼°Oú\ÀøK=#f£uÀúîºx†’IÀ£3K Tn’@¡#¾š™eÀ¡#¾š™¥@ÚVLí¸òíÀôµMœŽ¨Açž*Ìó§Á`à9açu@¥ï=®MÏ@V BT(õÞ@Lï‹ÞzÁ;´yš”ê]ÀŸëÇ«ôÉž@· q…œý¶@9ÊÉáÜ@ü0õ¬FÁÛÞDVg˜@ÜHxØL\d@6û(§‹¬“@hðL¢_@Ä4„D×äã@ŠVžî¡@G F!>nÀ³œèþ¼$€@Wèj“Œ-ç?;ëS*¯CXÀ{­?òzé@§¶ß©,¦¶@¾r[1cóÀQZ¶9î¾À†™S7œÁ—À‡Jýa«´bÀ +îÌÀ#‚} kjÀC|K5Ze@Á?i=ÃÐ1@ÏÛC2ú6a@;R®+@ŠVžî¡@Ê1þn–Õ@[g,GïÀ‘Ï. tVÀàK±‘Ç@£+„jµ@ýÐÊ%*ƒ@ŽzѽÀÞÿlôÑqÃÀ‡Jýa«´bÀÒ†56u-À2?Õ·ŽÀÞœ²Oô·ÀáúÄ\{ü§Aë8}åe@Hª ö@á@~ýôׯ@]tÑE¾ë@wÄqc Aë%]H¨@JÉp3¯¦@ái«€É@ËOz~ÀL @ÿ÷rÞ–g¦@–WÈ1`º@wÄqcÜ@ n¹Dø§Á}ß6›Ð§á@Ž»G7¼¹@) þ¤ÜùØ@A_ÐôµÖ@?Ë⟼Æ@ßàžœ@’Õ­K@‘®¢ ¸@E.b%zÉ@Æþs<*P@%ÑOñÄ@J°¤ÒQÀU±±y+•¹@®•ís¨xÀƒ#zVå’#ÁM†”œútáÀë8}åe@9áú¤ó±A}ß6›Ð§áÀj)ê±ÁÅþs<*PÀE.b%zÉ@J°¤ÒQ@œ%ÑOñÄ@®•ís¨x@U±±y+•¹@ wÚ™øtá@°³r@ã’#ÁFE]”2 ˜AVbÊÂ`É@ŽS¿ÉÌñ—Á;·ñÊeÁVbÊÂ`ÉÀVbÊÂ`É@Oo€’×§A|h¬éØ@k œ*Kn‘@lÛ¶mÛæ›@TÇ* W›@VbÊÂ`ÉÀ_ï¥&Ù§ÁÒ–ý¯Ðý¦@‘ &ð;Þ@ŽIéAȦ¦@€ê¼É='žÞÀÁÿ1ðX„®@hihp.¸Ë?Áÿ1ðX„®À‘fhp.¸Ë¿hihp.¸Ë?(ýZ;~®@hihp.¸Ë¿+—ú9|®ÀQ„EȳڧA«4å:Áþÿÿÿƒ×§Á˜†ífyàAnXzèÔX@ã]I‹;@NÇÊòt’Àf€ˆ¡Óºh@´C†¶8†@¡3áùwh@É›"gùÀ3[è¤NÃ@«4å:ÁˆhúVL@¸A‰ öâ ¸ÁЬЄô@—.¬ºc­¥@ЬЄô@ º,Á«4å:AÙÉ­!ñúIÁê“$d6@Ú{Þ±ìuÀuÄ‹e·ß@ЍY·tqxÀ Zñ†À»?;]ʈÕÀ õoÖwu@CæÇ2ú7ƒÀnB?¸ÂÀ[VÖrEl®@…¬S âJ@›ža]Àøb²ÃFR@øb²ÃF’À—ðyŸµL»@Ážän“ÓqÀÝA8!}ÑÃÀˆgµlq@+ÛcØ(î @êE”i¨Àõ´‡g(vÀ0áÔ®:²µ@ЍY·tqxÀs EÜΈã@;qÖÆÛÈÅ@¿â hÄ;uÀ[tTÍÝÚÀ Ï{ƹžÄ@s ~©@õÅ/ƒj—òÀoÆ9}Ö׌ÀÁ³a=ÓÐ@»Š¢ì›“À»Š¢ì›Ó@Ážän“Óq@—ðyŸµL»@L½ BäöqÀ(}µŒÃÀF”i¨@+ÛcØ(î @ñ.LjÛ@§íÆÄ åŽ@l ÄÎ-<@±wŠ´æÉH@Ä¡üY¡Õg@õ¼î)UÜÀQ¸BD¶ªC@™ô&rÃKA@ñ.Lzû@§íÆÄ åŽ@l ÄÎ-<@±wŠ´æÉH@õ‹"¹OFäÀÄ¡üY¡Õg@8õÌ@r8ñÀQ¸BD¶ªC@™ô&rÃKA@Éh¦²bmÁg¥Hü²—ÀìÅ>¶&s@ØÛ$ñ! ÀÈU]:ö˜A_Œ†ÄBê@ŸŸ‘Äú—ÁPlåì²ÿÀ(ѯ½¿ÊÀc%‘Ѧë)@þÇXXÀR­`qÆ‚@|¢…pð¹l@È7¹~½r@?ÖÚÜ™\@ų“k_,@·q—5WîCÀˆ W´ ÁÜ(3!ÑxÀoû))ÖUÀ;úü8y ÁÃÈDÝÀ“Ø­c§}@B·2ðœê!Àß¶‹ÊãÌñ@@ plÕŒÂÀø—ñBa@pn}!ŽmJ@Am~w¢LQ@fmÀkՉѿ¨žªÂÀ]×|8WCðÀØÛ$ñ! @ìÅ>¶&s@_Œ†ÄBê@¸‘š¤š×—AÊ R+%êÀþÿÿÿƒ×—ÁÇÂE#^PQÀw0õ¨á«eÀ1'æÆ)XÀ¯j«¨x†@ÍPkÌã¼CÀ·Œ«Tk”r@·Xÿf@pRÀ‡–;·gÀî…R¶*[„@÷Âë#ìÚT@ÁÛ›¹N¯§hÁoT¤ÄÏÎ-AÎ]ÎE´a>A¸°7 0¤@¾&7.A½Ï+ÃwâbA¾&7.Á³N>¸6™@àJ«Uå 3À—Õ ³(Â@ÓÉö®  @=«ÆbW³ã@=] ûÅ@à~ ­ü|µÀmwu—`¤ŸÀýºzeØâ-ÁQo"¥hÁ¸°7 0¤@KÖ­à8>A½¾&7.A¾&7.AÏ+ÃwâbAµéÝ´ê3À 8=›RmI@ÓÉö®  À—Õ ³(Â@=] ûÅÀ<«ÆbW³ã@OZ Ãù€À“ŸÓÑ'rrÀt'n%c’jÁ]·8a±ü-A¾&7.A½óZ¾:÷ûFA¦£8Þ¼Äè?Ï+ÃwâbA¾&7.Á"Ìt«ÒŒ^@=Ì`ul¯?—Õ ³(Â@ÓÉö®  @=«ÆbW³ã@=] ûÅ@H'íà¢ÕÀ¸ÐÐÝÕ´À }R·ü-Áækïn_’jÁ½¾&7.A¦£8Þ¼Äè?ž|ñðûFA¾&7.AÏ+ÃwâbA\ÿË`ul¯¿"Ìt«ÒŒ^@ÓÉö®  À—Õ ³(Â@=] ûÅÀ<«ÆbW³ã@aØ•¤¾Ô´@ÉÀ.¯¢ÕÀ*›ñþ“T1Áµ8ÖÏ@w'îÒáF0ACeÞnÞÀ©=ßuÀ^9xC J{@†w-›'Û@‰\êzÂ@—Æ…E>*ˆ@HGúR¤lî?¨7=Ýs@2_¸Nf@¥4ö öÌ@@òˆ:4þ´@€ÈøÄÜ@ì¯ Ÿ©±uÀ;ß×$¨ÀÍ„Ž‚þãeÀVYxéÚÚ@Z;pOAÁCeÞnÞÀ(NšNà@A’¨ªö"¨@„ƒë7ÎÀ‰\êzÂÀ†w-›'Û@]GúR¤lî¿—Æ…E>*ˆ@® ÎÇ=If@?-Ïâ%Y@Aòˆ:4þ´À¥4ö öÌ@ì¯ Ÿ©±u@€ÈøÄÜ@ˆÊÄ­ 6Í@]_*úI&ÝÀÆ7²Zäç@<`l>£1·À\öÊrfÞÚÀ8æS"Ÿ@9}‘Rþ®@TKð£1·ÀÙÛ>ê›ñ@Z+º¶“£@ù¨››†”áÀüSKðÜ÷11~À–ë—½ÀÙ=asyT@{™—)a€@ÖŽˆÜ7V@,£Y'YÀ—¢¬…‡úSÀn·±"j@5Cg\PÀü^yÉB@i ³ˆ­K@D‡'šÎbÀ,£Y'YÀêÄñL„s@N—–‡j@÷wd@À-˜–Ç•B@ÖwebÀR§2[™bÀâ7íÒã‹w@wi¹4H³Á¬ñÏ€Èv@ÁHª ö@á@ÈzéêøH˜@Ï+ÃwâbA¾&7.AÏ+ÃwâbA¾&7.A™1j‡Üã±A³óå[ˆ@Iùì{Íi§À·›ƒÝÀ\.Ü´ñ?“7þކjð?{~µÊ9”@rlaˆn—ç?ò½³6ð?S™Ëd@Û··´œÀr*q§ÅMñÀänöÝ*@ÐS0ˆ²;¨Àü/žß”À„Š „E†@¶ßõÏ¥µä?×ÐŒ+â2å?W?jU h@®l*°1ö@'ú=&%Ý@!Sx^øAå±³A¬ñÏ€Èv@Aðám“BªÁ¢cv‹§@œ,B=†Ùœ@X媾»ü”@¾&7.ÁÏ+ÃwâbA¾&7.ÁÏ+ÃwâbAú¤„×§A£ÎV”}§?˧’—w @w²‹¿´·§ÀÃ@Oõñ?DB•*\»?:ø‘êÞ¹é?¢aÙMGÂ@~{ºI_¬¸?œÔ ¸â¶²?¾.¿2•Å?S>Tî¾ÆÌ?Û\¨Ý‚‡@í¥òy<áœÀA‡Ô×Ù#À‡‡~à?ÍܤðúPã?B/¸D•ý”À²VìÆY(ÿ?@E`¥ÌÁ?E×N°?ËVü¨°°?7Æ8»ž\@'ú=&%ÝÀ®l*°1ö@å±³Á!Sx^øA®È¢–·˜@Ø“Úi&@ku¤e:¨@ í>‹ÕG³@sÉYœ½I@_}VÇ-’ @M!п@`!MøÁU#@×@ClF»@u˜Û e@²DàÈúÃá?ªø 9@d®‰Ð©˜ÀhÏŒ¬Ñ?f€`¸¨À+ùàÑ›J³À.Õ¡"Ž1-@Hã¿o‘$@àYoߪaÀ?Ð$KÆ>ü?Â’»Ò„§À­¥É­Ò¿ÀM1F¥¦E¼?Pbš]2¼?Ð!ü¹øUÀ_}VÇ-’ À†: zó¡â?‡ UNê @C«|€ZÇ—@Ø“Úi&@þÿÿÿƒ×—Á_}VÇ-’ ÀsÉYœ½I@|h¬éØ@£ÎV”}§?Íö![„×—A¢Õ~S¦@û`ò7èÝ—À –òkaøã?~)ðèü?÷*ÂIbé@Õ¸dí`Ð?3åÚÐ8ø?œ|zá…@^Ï&p@Ùßñ~‘á @8)ih„+É?OþޱƒÂü?¼4#uñØÀ"⧪ûf@¤‰C“™£Àþ]‡¼ÆÀdÈÀ…æ?C§Á(’B´ÀQmD|Ü«#@ƒAceòi%@ff§*$@gŸÂ3Lô×ÀÁí§äâó?D—Ûi›À8c›vË›?_r\‚ðsœ?M™Ë. ÔâÀÁí§äâó¿Üɋܥ @Vg¤bnÿ Aá­ìsHÊA¢cv‹§@þÿÿÿƒ×—Á¨EÈ_³›ð@Ÿõ‰8!V@ÃÙ©ñ¢@,zVרµ@×;¬2jy@§QoF<:@]tÑE¾ë@ DpìÒ8Ð@ͱF" n´@Iùì{Íi§Àu˜Û e@–—QuF@ÇÈá‰×—AˆjC0ra@Áœbæ ý?à'á·Ä9@H‰¤<Ê¥ðÀ€š<af@¸Î§mqÙ¢À›¤ëšÂŵÀ;“†¦RF@RàjÃ_À#øÎï9˜2@_ªažkáëÀä¤ ½O›@ûØY”7ÐÀ¨%Ÿ÷mb´À ¢ä-@Ý“/5 …À§QoF<:À£fÛ‡@g"@P­½}g¦ð?r6IJ ñ?ÄØblÊêC@mÛ¶m[ÌAÕ‹Oòì§ÁWVõ”¾W@) þ¤Üù¨@¨tdçþ@KFÁÅ“·@æ?.®´@§QoF<:À×;¬2jy@w²‹¿´·§Àû`ò7èÝ—À•0ckôÁhš5 ’¨A‘®uÌ>ÔÀ•zÚË×? éአ%ÚÀÀŽ× ¯³ðÀØÉÎHö¹ÀÜÎ(ÿ£À~Õ*ãëµÀ~d&éÀ<½ÀIK{9Á!ˆ¬‹Û©ÇÀrO¸o6ïëÀ-«pe\ý?õýT¶5IÐÀVkئm´À vë&¶-ÄÀ§QoF<:@èìèýwïÀsðpå( @.ß‚±2²Àù‹¥G\Ì?[SÒÍ?Øð“âÊËøÀsðpå( ÀDÄe„$@åyžçyÝ@þÿÿÿƒ×§Á üZÓ?±@¤k¬)ã@Ã_4Ïì"9@¡{ãÕ€òù?wÄqc A0N¡¡oƒ @Á!Â!ÔÊ@·›ƒÝÀ²DàÈúÃá?+Äâݯ=@ˆjC0ra@•sˆ×§A†¹f*@s[.Pª‹!@«qÚ'È+±À–«ÈÒ?“Ã0ýZí?4/@—Íà‚_$@å¾’|1@’Ù‘<ËP@•6ÅW… Á‡KƶZ{Æ?{ƒ­ßk Àš°Œ¼ÊÀÂ7cFˆ·J@²œû¶ð®,À¡{ãÕ€òù¿éí#^å?áìVª‡ @]äÍæŽp@ÞðžÉC©0@´i¦F<°@—Sðr îÓ@5GQñ+û@­U—ojì±Á¤k¬)ã@ƃٹ_•¢@E6xnRÒ@ð|zÜ\Ç@¡{ãÕ€òù¿Ã_4Ïì"9@Ã@Oõñ? –òkaøã?øój™Ž'°À‘®uÌ>ÔÀ§’4¥á±AšÒgø’ð? Õ„ŸHk@öêžá³3@2ͼÇì?éïz£;ñ?g+ÑaÛ@)ˆ6ŒÉS@ 0s jf¢À®Ìn(«XÒÀ‘Îæ1?€À…´¤— ½?yµÿ ’@æS1½$3@/5l p]ÇÀ¡{ãÕ€òù?…é- '{?Àgáùu(Îð?!„\2Áã?}íNž8ä?›-ä•8@5GQñ+ûÀ§]«.ë%Aþÿÿÿƒ×—Áë%]H¨@&®yyšÙ”@\.Ü´ñ?nÉY­í×?Áœbæ ý?†¹f*@j>)›„×—Aø–4þã×¶?‹ íÒÚ?–~¥Iýi°?éCÞøÆ¶?PLÖfÊ?[[šXaïï?+"Y§ ¨Àøû} ÄGÉ?†[3èÌÚ”À¯šì£¡‹æ?„ã¯<Ü×?ÞV˜Š¼ƒÀë¦E5É!>ÀkŽõÑÇ8È?²~ CV¬@_"*IÅ5§@elÐæ3@DB•*\»?Y³HèQ§?•zÚË×?šÒgø’ð?EÐ.xmQ@¥ž×2·?V|ðS[¬À÷ó¸M4@êÁ´9Ï2ð?"cQ•6§À¯OD¯~´´?‚É*¨:7ÀÓÇì>\g@¬%Ç3ÿ†ÀÓÇì>\gÀ©ßQfd„@’nPV±€&@¥`¬Ò›Ú—ÁÜ>Ú¤´Ý—AhíõgöÙÌ?Cl ÎäÀGîWýd°ú?XŸ{Ôõ?rõ«ÜEó¿À_SÚ™ÀXŸ{Ôõ?_†vé-+õ?š*)>@_SÚ™@þÿÿÿƒ×§ÁŽßQ„×§AbÝ\úøå¿þÿÿÿƒ×§Áþÿÿÿƒ×§Aþÿÿÿƒ×—Á»È„×—AÕ-N»ÈÀþÿÿÿƒ×—ÁÛ¹v`NÜ@6æ‹ys8@Ú8Áª\@óBü@JÉp3¯¦@<°öå¤@“7þކjð?ªø 9@’L…‡@à'á·Ä9@s[.Pª‹!@ø–4þã×¶?YSÖ„×—AÙwV¨ÀfÜÀÂû ¸1oû?ÄĦÊÿ @X ‹)@8[zñœ#@`%܇!@¶Š¬&ìõ÷?( Ä諭¦À»9¬1½â?DIÛyÁÕ¤Àù7¢¿çô?ÄJáõÚÌó?’+ ÿfÀóBüÀ $Îð:@µä˜ÅW:«?­2õ"ÿÞ«?d£°7d&@ùÌ}[ˆÇà@©ªªªª Ú@ßè"X:æ@áxè ܧÁ$€!5:@@ÆVó\Ç@…ļ!©È@óBüÀÚ8Áª\@:ø‘êÞ¹é?~)ðèü?(‰i[ÕàÀ éአ%ÚÀ Õ„ŸHk@5Oë…„×§A›€yœú>@¾ôkyL‘ÇÀñÉ4Iü @åP¬Ø:Ã@õ´Æ¬+ @±Öš˜Ï•ÈÀ¹û—@ä'@2îŠîÎã5@¡w/*j8à?óМš1@ ÆéYÒxù?k?&Í•ù?óBü@úîÿ]÷'fÀê&HSmmë?@ ò’­zÀ9EìiI@ßè"X:æÀWŽã¡“Aê&HSmmë¿¢™K|Î]@ºŠ<ºæ±ÁõëT…g^@ÊLï·w¤@>#[©vmµ@9Ýœ yu@ šWצB@ái«€É@ýÞqoÎÎ@ÃyP«Ä“@{~µÊ9”@d®‰Ð©˜ÀMR"˜ßÀH‰¤<Ê¥ðÀ«qÚ'È+±À‹ íÒÚ?ÙwV¨ÀfÜÀÚSôJÖë±AQ¸}ʱÀmõkÉr´Àÿ?…/blÅÀÆWþ¸»À¸’@°¦ÔÀÇüå–À¼Ù_dܨÙÀ/)ýŒæ@\ñh½YÙÞÀ“›ºqíÅ£À— c»³“À>óËŒõÀ šWצBÀ2"Öé<·ÉÀÈHh)R¯Î?š×v4áhÏ?W¯T |;ØÀB!„€ß@¨EÈ_³›ð@þÿÿÿƒ×§Áì'N~a@÷Ö”f±@jVpøBšÔ@Ö†æ–@e €³“@ šWצBÀ9Ýœ yu@¢aÙMGÂ@÷*ÂIbé@F`©÷$ßÀÀŽ× ¯³ðÀöêžá³3@¥ž×2·?›€yœú>@‰ÞÊ…×§Aß,w~ÿ°Àø;¯ -@3¢ t&:@.ÌHx…Œ?@ÎUÚ=á‰ÔÀ*6¾³ÀÕ–ÀeË$ í¡I@j”úo+@¢ƒ‰·•ˆP@ŠÅ  ²@ÕH}v¤“À šWצB@Ñ:fæì7ŽÀâBÙäQå!@6°œóþÉGÀTÀ½÷@¦«?S Oó}M¬?:Úi‡© \@âBÙäQå!Àã ô"ê/=@÷Ö”f±@†¬Å ñ @þÿÿÿƒ×—ÁËd±Üpž0@ º*O®'ñ?hÏŒ¬Ñ?`O…¸5þ?€š<af@–«ÈÒ?Âû ¸1oû?Q¸}ʱÀí®„×—AGW‘ðß?$äÙ­~ì?Þ5÷~Ùëð?Ø(ð»=¸÷?á[È$†¹?ÍÓæÄãàë?ôØóó3³?´žùpÕm@K?ܚ铵?ÂÉîUƒµ?“ æê;À º*O®'ñ¿BéðnWJâ?z„A·Üü?iÖ9t<¥@) þ¤Üù¨@†¬Å ñ @TÞ: â±Á§yZ’?–@ º*O®'ñ¿Ëd±Üpž0@~{ºI_¬¸?Õ¸dí`Ð?ÊOµNÙµÀØÉÎHö¹À2ͼÇì?¾ôkyL‘ÇÀß,w~ÿ°ÀÈ K}â±A?“ž˜˜Ý?®¼¥³ì?_î‚-ñ?– ƒW:¦ÀíßßR¤¬Ð?vòdë9@ôØóó3³?zŸNÖϼ@YÃóx#É?\á”ÉÈ? º*O®'ñ?‰‰#¯šm¤À"Ä;†­Ë?ªë>™ÀÊLï·w¤@£-]Ð4@‰ií?Nâ±Á…·X3±@éñâ›ìæW@D+‡O¬@¤¥HÄ@f€`¸¨Àj¹v+N@¸Î§mqÙ¢À“Ã0ýZí?ÄĦÊÿ @mõkÉr´ÀGW‘ðß?Ur™ùâ±AU$½Ní3ÁÀÝØKok0³ÀÛ´üv@ŽTZÏ¥ÓÍ?åéFG­@N¯ 2m‘ÀÁ`{“óMÔÀ×äšVø¼É?Ão÷À)«É?,hk|hÍÀD+‡O¬À….í½lé?@z¤9G@ÃÙ©ñ¢@£-]Ð4@D+‡O¬Àéñâ›ìæW@k œ*Kn‘@œÔ ¸â¶²?3åÚÐ8ø?îóÆÉŠÄ@ÜÎ(ÿ£Àéïz£;ñ?ñÉ4Iü @ø;¯ -@?“ž˜˜Ý? B6á^@Øä±´ø @Ñë }Á@žÄ´]Ò¶@ÚËÔÈTÒÕ?dðš:}á@åüC ›o‘ÀÊþˆ‚ØP!@c¶K VÝÒ?]Ƈ¯Ö?DZµÒ?D+‡O¬@™ ܬõeÀø®s÷¡¼?cîýß[@KPÕÈ 75AÌÊy³E§Àæ8ŽãX15Á‹Ÿ7(E§@é—]•Ë–À´Ž€K“¿ÌÊy³E§À·ùºLå5A]©B€yˆ5ÁÌÊy³E§@?x§ä5×À>#[©vmµ@3ã5XA@…·X3±@UmMã—Á55w¥¼:d@qGbýÊá$@ËOz~ÀL @ÅqÇq ë@rlaˆn—ç?+ùàÑ›J³ÀÂÄRm¢›À›¤ëšÂŵÀ4/@–~¥Iýi°?X ‹)@ÿ?…/blÅÀ$äÙ­~ì?U$½Ní3ÁÀß=îï—A_”8ƒñôÀ•í3-‰”À £70îBð?yºyS°Àçþë›ÀÉô=]2ûÀ>ÿ×ndì?Ò{CÐê?9ÏÙçØÀqGbýÊá$À]¨É¬ßæ–À•ùl†£?_£3Ö¤?^ó½OJ.˜À—•mµËÀ›@,zVרµ@œ$È&¹£B@aÙqcQ£”@qGbýÊá$À55w¥¼:d@lÛ¶mÛæ›@¾.¿2•Å?œ|zá…@å«5mc››À~Õ*ãëµÀg+ÑaÛ@åP¬Ø:Ã@3¢ t&:@®¼¥³ì?Øä±´ø @`啜¦{G@2‹zE@âŠÍz”À˜Jå8€æ?+˜dä9t@çÌ9 ¸è›À‘á¸Hâ?qGbýÊá$@‹ª˜¾¤rÀ}׎Yúï?BÆ©æÀÞAeuúï,@}׎Yúï¿Å2b˜Å @P–“pÍ»@ÇÙ¹H6D@úNF‰@³@2ëhóô@þÿÿÿƒ×§ÁÎó²¤6g@´E²Áõ'@ÿ÷rÞ–g¦@sssssï÷@ò½³6ð?.Õ¡"Ž1-@ È¨þ'0@;“†¦RF@—Íà‚_$@éCÞøÆ¶?8[zñœ#@ÆWþ¸»ÀÞ5÷~Ùëð?ÝØKok0³À_”8ƒñôÀÌbŒ>†×§Aö2`g¿*@0‘O};õ?ÕóY.oj¦À¢”úª÷@U‹¦¦øÀK— þdò?ƒïÔbÙOñ?¼êÖ²ùpÀ´E²Áõ'À˜aä@$o%Qcäª?´i2䇫?ÈÛ+ú0@Ê™ý N¢@æ¾ø!½@±PYiE@þÿÿÿƒ×—ÁSV.ýOâš@´E²Áõ'ÀÎó²¤6g@TÇ* W›@S>Tî¾ÆÌ?^Ï&p@uÕ4AH7¢À~d&éÀ<½À)ˆ6ŒÉS@õ´Æ¬+ @.ÌHx…Œ?@_î‚-ñ?Ñë }Á@2‹zE@%P]I‡×—A7©|l+°šÀ ÷øFpë?þ<ј÷@ô]“ •X›À½û˜”eÀj)!üêæ?í/aÚÕUá?%±æ?´E²Áõ'@}9^MiuÀ¯Mœuºò?6§­qvyÀ]˜¸³Ý1@¯Mœuºò¿ÕÆõˆ‹@jVpøBšÔ@?Àü6’?@aÙqcQ£”@þÿÿÿƒ×—Á5ømý b@³ï¾³¶"@–WÈ1`º@´¯má¬Î­@S™Ëd@Hã¿o‘$@i §•½©~ÀRàjÃ_Àå¾’|1@PLÖfÊ?`%܇!@¸’@°¦ÔÀØ(ð»=¸÷?Û´üv@•í3-‰”Àö2`g¿*@’ï8×—Ažüâ¶Ë‰@žÛ\¡xzºÀd•GJé?Ðæ¸~†À­À¯ÇÚ`ý@ºâ¡ª¹@ßHoÀ³ï¾³¶"À%–AKÂ@@¹”f­œ¨¿?è°LŸ4À?'(ÿºÛ/ÀDQEQ`A¨tdçþ@kZ‚+Ú@@§yZ’?–@gI "ä§Á³ï¾³¶"À5ømý b@Û\¨Ý‚‡@Ùßñ~‘á @}·ÀñKsÁIK{9Á 0s jf¢À±Öš˜Ï•ÈÀÎUÚ=á‰ÔÀ– ƒW:¦ÀžÄ´]Ò¶@âŠÍz”À7©|l+°šÀ~T'BÒð§As0«žêÚ#@óktºÀƒ+ 7•ñä?Fð‹Gá—­ÀTÛ|a*€@e5T@³ï¾³¶"@K;à¾íIÖÀ4 pߣð?# ä—À€[tŠžØéÀ4 pߣð¿,R¦# @œ,B=†Ùœ@Ö†æ–@·Px`Dý?”c³(KÎ @`¹êÆYá?wÄqcÜ@uŒâ\ÇHÑ@Û··´œÀàYoߪaÀ?-No1Ÿ²@#øÎï9˜2@’Ù‘<ËP@[[šXaïï?¶Š¬&ìõ÷?Çüå–Àá[È$†¹?ŽTZÏ¥ÓÍ? £70îBð?0‘O};õ?žüâ¶Ë‰@‰Ù62^l@A¶Œ†ÜÀG+LQLj£?-?>îªU@ Ñ¥LÑÀÈYµéagÀ;Žb‰l%À`¹êÆYá¿K×J™žÈ?ò[®rß?HÁ·ºÑ¾ß?,ä* O@˃ šž“@KFÁÅ“·@·Px`Dý?¯ËÀ„sä±Á˜tj,ø@`¹êÆYá¿”c³(KÎ @ÍQÒ³¥é?í¥òy<áœÀ8)ih„+É?>¤‰C“™£À!ˆ¬‹Û©ÇÀ®Ìn(«XÒÀV|ðS[¬À¹û—@ä'@*6¾³ÀÕ–ÀíßßR¤¬Ð?ÚËÔÈTÒÕ?˜Jå8€æ? ÷øFpë?s0«žêÚ#@cqŽFç±Aã]è%jÜÀG+LQLj£?­Ž(`*þ?ŘøuVOÑÀ/!E$õ<Á`¹êÆYá?ì*U}¸¡”À¯3 ’®8Ó?oƒÄóç Àxê‘ ¦@8£fHI‡¡ÀªËXÅÝ@xê‘ ¦Àv›ØQ•G:@Hª ö@á@ái«€É@¬ H0@ËOz~ÀL @›{uݲR@ˆ³GM@ n¹Dø§Á}ß6›Ð§áÀŽ»G7¼¹@) þ¤ÜùØ@r*q§ÅMñÀÐ$KÆ>ü?7ËÀ–ðÆÀ_ªažkáëÀ•6ÅW… Á+"Y§ ¨À( Ä諭¦À¼Ù_dܨÙÀÍÓæÄãàë?åéFG­@yºyS°ÀÕóY.oj¦ÀžÛ\¡xzºÀA¶Œ†ÜÀwähuô§AZ7–(£ â?òä‹p¯.ÉÀ1MðÀ@ éÀþ©ßÞvÐÖÀ !:ÇÀˆ³GMÀˆIŒ¨÷Ëÿ?ÄçübËÀœÀ|=ù¼¬nÀ£0`‡$¸Àx!<ÔNQ"A}ß6›Ð§á@~ýôׯ@]tÑE¾ë@¬ H0@–WÈ1`º@wÄqcÜ@A_ÐôµÖ@ˆ³GMÀ›{uݲR@}ß6›Ð§á@j)ê±Á­ì¥ºå?A‡Ô×Ù#ÀOþޱƒÂü?þ]‡¼ÆÀrO¸o6ïëÀ‘Îæ1?€À÷ó¸M4@2îŠîÎã5@eË$ í¡I@vòdë9@dðš:}á@+˜dä9t@þ<ј÷@óktºÀã]è%jÜÀ )•¥á±A$`T‹šÕ?£¯ª£+1@æœüè†òþ¿Os}€Ã¸ÖÀˆ³GM@:k±ªð!“ÀCÇu @fξMÄ@é¿jíß$@T(Ü/–õ?˜†ífyàA‰ öâ ¸Á§íÆÄ åŽ@À(òd¼Ü·A¬KN-@§?ž`uT @spÙôÀjÃ~¡›¥ÀõPï7ÕôÀ]@Làôy@fξMÄ@ôež,ŸA˜†ífyàÁÙÍò$òaHAƒð»Ù¹ò@±ØÉåŃÃ@¼æ£µV G@@L® &Çä@oÇQL@l ÄÎ-<@ŸŸ‘Äú—ÁÊ R+%êÀCl ÎäÀFprø*&@ÝËš/…×—AiVháÕ-@¹VÂf=|@ã0±PiÀ8ÏjöQß.ÀÆ--“9ÀƒsÜ×—î¿„ È£‚î¿ U6WX0À:JjÀp QÁzÿ@O ip˜Ê@ó=yJæÔú?„ È£‚î?xåv'T]@8ÏjöQß.@¸né_hÐA"WO¨Ó@ A”3²|;<Ý@¬ñ‡ª'@:Jj@}¥œÕ»Ó@znÓ‘O@l ÄÎ-<@þÿÿÿƒ×—ÁÕ-N»ÈÀ¬KN-@&€å„×—AÍ9¿þ¿Ì@xE™8h+ÀýA|üÛ£Í?ÏNÈ1“jó?©Ši™>À`†hÆ÷Ðç?:Jj@OÕšZ¥Å/ÀÍ9¿þ¿ÌÀzOòò[R@:JjÀ¬ñ‡ª'@ýÞqoÎÎ@xóÕgÚU@¤¥HÄ@ÅqÇq ë@~áÖÞy@oíÕè9@Ž»G7¼¹@Ó{³Â¹é—ÁänöÝ*@­¥É­Ò¿ÀxÑé±ÞT´ÀûØY”7ÐÀ{ƒ­ßk Àøû} ÄGÉ?DIÛyÁÕ¤À\ñh½YÙÞÀ´žùpÕm@Á`{“óMÔÀÉô=]2ûÀU‹¦¦øÀÐæ¸~†À­À-?>îªU@òä‹p¯.ÉÀ¥þvµ §Àht™Lü—A&»fc@¥þý¥-@ø ‰óùîÀoíÕè9Àöµ¦!­ÀoÊ•.÷!¾?nj$j/ؾ?|zk^±À€À# [´@ DpìÒ8Ð@E37H'W@´¯má¬Î­@oíÕè9À~áÖÞy@Ò–ý¯Ðý¦@þÿÿÿƒ×§Á‡‡~à?"⧪ûf@C§Á(’B´ÀõýT¶5IÐÀyµÿ ’@óМš1@¢ƒ‰·•ˆP@zŸNÖϼ@Êþˆ‚ØP!@‘áÿ×ndì?K— þdò?¯ÇÚ`ý@ Ñ¥LÑÀ1MðÀ@ éÀRkš@ÈÀ ?&»fc@¶³Hä±A$²Õõ]ÈÀ¸ÏAË‘À£Vü@ðÝ¿–•E^í?Å?°¹·‚úÝ?[â$§Ë¯Þ?Rj6WÄ@Æñ+RÒ AÏ%´BãÖ@ͱF" n´@•%î Aù?uŒâ\ÇHÑ@¯ùiZÈ@£Vü@ðÝ¿Rsô¾@Ï%´BãÖ@úÆŠd1Þ§ÁÍܤðúPã?íÊV A$ˆ #ŒÛ·Á ¯X;æiíÀ;»tBW Ö@SYõÓNÆÀÂNŸ)îØ·A®c”Ã;æÀˆ3Án#ì.@Ç,y®ÙÎÂÀ¨é!Ü&K¥Àø¢…ç·JAüä•ã@H7Ë{uœò@æ7¹¬ ¨Ô@ ¯X;æií@ÌZ©)Þ§Á2{˜‘«Ùô¿ùͦ„×§A˜@]iÜaÀ}!`¤ý¿žó|Z ³¿üä•ãÀø¢…ç·JAæ7¹¬ ¨ÔÀH7Ë{uœò@;»tBW Ö@:ÇNàâì§Á3‰™öxëÀMš4iÒ¸ð@¤­/45@–ð÷bž”ÍÀ®c”Ã;æÀ§AÏ9Gß§A¶ñpN„ÆÁÍ©-‚¬µÀ—x>SÊA:ÒŠc¼¶@Ya,óK|ÍÀå´ð2ÞRA\­­ !Ö@ËÌ™AK›$âþoÛ@C£4¢XOÀ˜@]iÜaÀ©}VK•yL@™ŠËátGÀÏhÍãcªÓ¿j_F‡æÂÀMš4iÒ¸ð@9zúðå§ÁÇ“k¬¸`ÞÀÛ[ Ÿ^¹$@ˆ3Án#ì.@¶ñpN„ÆÁÅ…{²ò§A¸ ¸_@Î3Ee´#Á‘ &ð;Þ@›68Ñ&û@‹ÍËZþ—ÁM…• r—@]Ƈ¯Ö?ÅÏ0ø°á?í/aÚÕUá?”5ÝéEÞÀ„Bý¡Þ'í?™ŠËátGÀ qêÆ—×—A5Ãs€¹ì?€S½Ñë}òÀaþft96A7ÆõfÊQáÀÛ¦Ìñ/ˆAX媾»ü”@e €³“@Î)xCM0ù?þÿÿÿƒ×§Á½p†í@£|áciÜÝ?A_ÐôµÖ@¯ùiZÈ@ü/žß”ÀPbš]2¼?Ó&˜ 3 @ ¢ä-@Â7cFˆ·J@¯šì£¡‹æ?ÄJáõÚÌó?— c»³“ÀÂÉîUƒµ?Ão÷À)«É?Ò{CÐê?ƒïÔbÙOñ?ºâ¡ª¹@ÈYµéagÀþ©ßÞvÐÖÀÊ$¶Ì­µ ?¥þý¥-@$²Õõ]ÈÀã㮣…×§A_¦rˆð"À£|áciÜÝ¿Í*æø.Å?4®$ªrBÛ?}¼feÍÙ?2ž§ýò›@æ?.®´@Î)xCM0ù?˜tj,ø@eIv›×AÜR¢3 ²Á£|áciÜÝ¿½p†í@ȽN å?B/¸D•ý”À)ufÿ‘Å?ƒAceòi%@ vë&¶-ÄÀ/5l p]ÇÀ"cQ•6§Àk?&Í•ù?ÕH}v¤“À\á”ÉÈ?DZµÒ?üšC>¸Hâ?%±æ?e5T@/!E$õ<ÁOs}€Ã¸ÖÀÊ$¶Ì­µ ?+µjaïø?ÿG9až[ÈÀ(ÿЗæ±A£|áciÜÝ?ÏZÒ\“À‘ÀŸàäbÎ?æÌ š¬›Àí=EêÓF@4ÈꯜÀ1V!ñq@í=EêÓFÀ_½ì˜„5@ÄRk÷CàåÀ)ˆaÐ9¶A¾&7ÁÏ+ÃwâBAÍQÌÂ@þÿÿÿƒ×§ÁÆËs¼<§µ@UóV@ÿþ?Ç,y®ÙÎÂÀÍ©-‚¬µÀ¸ ¸_@-,„×§AE¯JfÈñ?*ÃȰ³CAég·ûDë±Á}!`¤ý¿ÏhÍãcªÓ¿^ò(£á±A™Ž*éFÁ*VýÜAHÒx³öãÀcªD™…íAc! YÈ:õ@q žšÀóBüL@åyžçyÍ@F®:™Ø@©Nœ ò½ÀÝÏelÀ?Ë⟼Æ@þÿÿÿ„î@¼ˆŸÆ)¢‘@„Š „E†@Ð!ü¹øUÀ_}VÇ-’ @†|Â3º[pÀff§*$@Ý“/5 …À§QoF<:@²œû¶ð®,À¡{ãÕ€òù?„ã¯<Ü×?’+ ÿfÀóBü@>óËŒõÀ šWצB@“ æê;À º*O®'ñ?,hk|hÍÀD+‡O¬@9ÏÙçØÀqGbýÊá$@¼êÖ²ùpÀ´E²Áõ'@ßHoÀ³ï¾³¶"@;Žb‰l%À`¹êÆYá? !:ÇÀˆ³GM@투Y½@À3ÆÅ§:ó?ø ‰óùîÀoíÕè9@¸ÏAË‘À£Vü@ðÝ?_¦rˆð"À£|áciÜÝ?H³ ³ïƒÌ@u`VD¸@Ú¾Ì5,@çic’JË?œ¸Àä›ïË?~vUQtçtÀX·òit(@¡éö³×@¨tdçî@óBüLÀÒΕœÀuÅ!EN5¤@;»tBW Ö@üß\~o”@/'Üòy–‘@3ÌiëQ§k@Nó“–½ÀŽIéAȦ¦@²VìÆY(ÿ?_}VÇ-’ À'ô’éKWÀff§*$ÀgŸÂ3Lô×À§QoF<:ÀèìèýwïÀ¡{ãÕ€òù¿…é- '{?À¯OD¯~´´?óBüÀúîÿ]÷'fÀ šWצBÀÑ:fæì7ŽÀ º*O®'ñ¿‰‰#¯šm¤ÀD+‡O¬À™ ܬõeÀqGbýÊá$À‹ª˜¾¤rÀ´E²Áõ'À}9^MiuÀ³ï¾³¶"ÀK;à¾íIÖÀ`¹êÆYá¿ì*U}¸¡”Àˆ³GMÀ:k±ª’ #x @~6›z—@÷˜èÑ€Z`ÀGNAåñ&@¥Ç¥ãMIÀ>ó/,@”УÞ@ù&UvV†CÀ«í8v E@}T6SgøR@Ç©Fùø#@#›Ï-CLkÀa»bþãau@ÌŸ`b#H;@­|‘Å6ä$@Å>?Üe@!D7Ð&Û‡À±wŠ´æÉH@§?ž`uT @xE™8h+À’º š&ÀN.{œ@»]2øÌÜ-Àöœàob`SÀ1pY«A^QÀjôJýKÁú?­|‘Å6ä$@õ[®EEVÀ’º š&@|ßµJ=ΊÀ­|‘Å6ä$ÀÌŸ`b#H;@ T”…y7@v=*7¹@XŸ{Ôõ?¾àÏn¬ŠQÀ¹VÂf=|@>’ #x @6c<#ÝÉ@µ†j„I@@ÉD‹ûXÀþ7[7×…ÀoÈN¦#™@ÑæPÑãÀ•G?Fòï¿v=3l]À2»€vEªÀAxhÝFü?•G?Fòï?1ucAYòM@þ7[7×…@­î|7%¸ÉÀ€ï¼‚é@2»€vEª@R!÷fð?AóÙ3¾3@ЬЄô@õ‹"¹OFäÀspÙôÀýA|üÛ£Í?~6›z—@»]2øÌÜ-Àµ†j„I@-ŠÔ›Œäã@öÕè5â?ƒÉ‘õÚ+Ë@'} þ·Ô?2»€vEª@ñÙhßÖÀ~6›z—ÀêNKþ@µ†j„IÀû†všÙ‰ÉÀ2»€vEªÀ‚é@¤ÙèÓiÀëk·z»¿@•PÂW3@Ä¡üY¡Õg@rõ«ÜEó¿ÀpÕ? ”¦ Àã0±PiÀ÷˜èÑ€Z`À@ÉD‹ûXÀ-Þåô Mµ@K áêÖr@ß3[V £sÀYý7xD!aÀa×GµŒzÀíå~É|-@ù± ([!!@a×GµŒz@¡”YHÀ¬À“¶‡öÚrÀM~âÒ'ÖPÀ1kv5°úgÀþ½«E½>@—.¬ºc­¥@Ä¡üY¡Õg@_SÚ™ÀbÝ\úøå¿T(Ü/–õ¿jÃ~¡›¥À8ÏjöQß.ÀÏNÈ1“jó?GNAåñ&@öœàob`SÀþ7[7×…ÀöÕè5â?K áêÖr@®%¨˜Ûv™@þ7[7×…À$Bn3bjÀ‡M°E­ÀºßF Š À¶!Þ¸  @®è§òufÀßi!3è –Àüiót5À؃$Ï@@Ð+ï æ@‰TÊc¾T³À¶";BGõåÀµ®Laß¶Â@Ê1Bþl“@< P–Ѧ¬ÀßWÄÓœzt@O*°fÙg‹ÀõÊà“Ò¢@QíÑ;=À†ä ƒw1³ÀÓCÝ‚MÀ‰TÊc¾T³Àì/…Á ï@=—íÏáÃ@EŠMèv%óÀ"öZ~Êî«Àqh*TË@S¨Ç9[W“À¼™4oâ©@míÑ;=@õÊà“Ò¢@‚\£ÖhDÀÁf>¸²À-vÅ|žúÁŠ»‹ü¦XeÀ—x>SÊAº*"/>½¡@¬q“¤í8?@ãMÕýv@¨Œ……O@1cU/D|@0êRS@£UŸöì¶Àr5%hôˆÀ:ÒŠc¼¶@¬q“¤í8?@R·+õŠ@)Ö™  "@‡ÁNxÁõ?b ÅG##@h9‹+*ú?ìÊ‘‰O¥@ÛiÄ÷èÍ@ÛÚLì· A$“X½Eªò@M͘?°Z@«yyê@¨é!Ü&K¥ÀYa,óK|ÍÀÎ3Ee´#Á€S½Ñë}òÀE¯JfÈñ?â¾ÒD­fà@5)v?Bv}ÀAçG!úaäÀ<üï•eVœÀ2Oïâ¦A@\iTÛÝ{@g²w¯G2@ªg¥U¤@Â9Ù¦Â@=üï•eVœ@ëÞ;ÑÝT@N_Ó_7&,@4ùK¶Ø€}@’-$]·IM@æBÿ¾Ý:@áV0uÙoÀ·d!‘EÄ…À›‘›»ÕVÀI•7t“u‚@zÕ6wÁžó|Z ³¿j_F‡æÂÀaþft96A5)v?Bv}ÀíãAåŠLá@+.Øài˜À‡¢¬ »ßÀv8ÛÉp@É2:”^/ï?üî¯QF@±“ÂÎî?HÉû¹¤i˜@Ê›RUŒr@õ¾^–µ+@´g㸱°@>f¿pØ–S@X’`¢=r#@€þm²\À>Cà r›@êÁ]Û%[ÀɃ¾4­MÀ*ß»J‚y7@ è ŒÄ@õ¼î)UÜÀXŸ{Ôõ?…žê>ð!“ÀÆ--“9À¥Ç¥ãMIÀoÈN¦#™@ß3[V £sÀþ7[7×…À4Ü2^PçÝ@A%% ?žGÀUM#*6ýï¿f˜yð®ÂFÀÌ#çvë°À'?;7å!ü?UM#*6ýï?1ucAYòM@þ7[7×…@kÚ0†<@Ì#çvë°@gBs#mð?V7@æ;@ЬЄô@8õÌ@r8ñÀõPï7ÕôÀ©Ši™>À>ó/,@1pY«A^QÀƒÉ‘õÚ+Ë@$Bn3bjÀB´$’wì@,Üè»®sEÀÌ#çvë°@GNí›»›FÀ>ó/,Ààø é˜@Ì#çvë°ÀkÚ0†<@߸®¡É@2ÇsE×W@Ö†æ–@/µ ­@†: zó¡â?8L³°@Áí§äâó?£fÛ‡@g"@sðpå( @éí#^å? $Îð:@ê&HSmmë?2"Öé<·ÉÀâBÙäQå!@BéðnWJâ?….í½lé?]¨É¬ßæ–À}׎Yúï?˜aä@¯Mœuºò?%–AKÂ@@4 pߣð?K×J™žÈ?ˆIŒ¨÷Ëÿ?99©VÐ[Á?öµ¦!­ÀY#Ñ&õH@–•E^í?Å?Í*æø.Å?Ú¾Ì5,@Ú,jOÖ¼a@†c£lÛÀݚŋ½~ @éMîÚFõ?X1{’ûgÀᤔU¦ƒ@ze$1x2J@%óJ3ÅeÀIà¬æU›@™Óà΋²@ìv—mdL‡Àâ?HÕ—@@E`¥ÌÁ?¸]Uø±?D—Ûi›À.ß‚±2²Àgáùu(Îð?@ ò’­zÀ6°œóþÉGÀ"Ä;†­Ë?ø®s÷¡¼?BÆ©æÀ6§­qvyÀ# ä—À¯3 ’®8Ó?8$ÈOm@‘6j+ÀoO~+áÎ?ŸàäbÎ?]Ë4i˜ @†c£lÛÀáiò(ÔX¥@’ yIkø¿sçØBU2‡@޲ ¦ý¢À³ÖX÷\eÀk/šëÏÀ@ÞZáEh:@ŠÑÿ+Ž€ÀQ¸BD¶ªC@_†vé-+õ?CÇu @ƒsÜ×—УÞ@ÑæPÑãÀYý7xD!aÀ‡M°E­ÀA%% ?žGÀ27u;¾è†@ÎwÁfPG@åÖ.éÊ:JÀËüíÚŒ• ÀÛeÚ §]Àx0EXGÀÚ|'oÎN@‡M°E­@—Â0i0¨5@ËüíÚŒ• @%jûÌ@÷4’6WÁAÀQ¸BD¶ªC@]@Làôy@„ È£‚î¿`†hÆ÷Ðç?jôJýKÁú?•G?Fòï¿'} þ·Ô?a×GµŒzÀºßF Š ÀUM#*6ýï¿,Üè»®sEÀÎwÁfPG@aˆsõHÇF@¾ß¢µkû@¹Ú^®­>ÀÀ¤¼x9Åö>BÀËüíÚŒ• À—Â0i0¨5@ßàžœ@¶ßõÏ¥µä?´¶îAkË?P­½}g¦ð?áìVª‡ @ÞV˜Š¼ƒÀµä˜ÅW:«?ÈHh)R¯Î?•ùl†£?$o%Qcäª?¹”f­œ¨¿?ò[®rß?ÄçübËÀœÀoÊ•.÷!¾?°¹·‚úÝ?4®$ªrBÛ?çic’JË?7°ÁÏÒ@Ô*ç$êÀ@+S0M‰”¡?¿÷Þ¼?1Y‰ž_ÓÀIà—QÉÁÀ‰Û<‚@íîa_ºt@ ¹¸cã @¼ Õ6樛@ÌìË-ç‹qÀE×N°?8c›vË›?ù‹¥G\Ì?!„\2Áã?‚É*¨:7ÀTÀ½÷@¦«?oƒÄóç ÀrÁóSÅð?¬«Ù²tNã?æÌ š¬›Àêsßo­¨?Ô*ç$êÀ@·˜6W´¹Ï@O‹]¹$ëC@Xé{±ôÛÁÀWÂoø5ÆÏÀ~З’>~@žàÅh0q@’Õ­K@¸/Áh<:À÷ŸrPT^@×ÐŒ+â2å?¼–lÌ?r6IJ ñ?]äÍæŽp@ë¦E5É!>ÀÓÇì>\g@­2õ"ÿÞ«?š×v4áhÏ?_£3Ö¤?´i2䇫?è°LŸ4À?HÁ·ºÑ¾ß?xê‘ ¦@|=ù¼¬nÀE6°`@nj$j/ؾ?[â$§Ë¯Þ?}¼feÍÙ?í=EêÓF@œ¸Àä›ïË?+S0M‰”¡?I3sÙuÑ@Oxrm,ÀÀ¯`ˆŽ½?à«Û OPÒÀÜópÁ»¿@šŒâ”@.ÀS’uÀÎCuÂI¡@Ù¿¨–°Oœ@.™Áí.š€ÀËVü¨°°?_r\‚ðsœ?[SÒÍ?}íNž8ä?¬%Ç3ÿ†ÀS Oó}M¬?8£fHI‡¡À[iðÒî7ÀFz\¢BÃã?4ÈꯜÀ‚,޳B©?O‹]¹$ëC@Oxrm,ÀÀ?Cíhæ@ ƃ½)À@ßw›\jeæÀ.ÀS’u@šŒâ”@˜tj,Ø@j°ÖÚ D@!à_[¾O˜@œ!kDưg@X·òit(@‘®¢ ¸@Ç™ßöSh±@W?jU h@‡ UNê @ÐÍóݪyó?ÄØblÊêC@ÞðžÉC©0@kŽõÑÇ8È?d£°7d&@W¯T |;ØÀz„A·Üü?@z¤9G@^ó½OJ.˜ÀÈÛ+ú0@'(ÿºÛ/À,ä* O@£0`‡$¸À• ö1:ð?|zk^±ÀRj6WÄ@2ž§ýò›@~vUQtçtÀX·òit(Àݚŋ½~ @¿÷Þ¼?¯`ˆŽ½?V½¼ö$úR@£K™Àcîýß[@ÞAeuúï,@]˜¸³Ý1@€[tŠžØéÀªËXÅÝ@ òA™C"Q@–6=+o^ë?Ø`eC@3`Sx£v@1V!ñq@X·òit(@U3¢æpÀéMîÚFõ?’ yIkø¿w»“…×§AéMîÚFõ¿|<|O/Y@"ÚÌzehWÀ$„B:@ŠB5‚A0*@™ô&rÃKA@fξMÄ@ U6WX0À:Jj@ù&UvV†CÀ­|‘Å6ä$@v=3l]À2»€vEª@íå~É|-@f˜yð®ÂFÀÌ#çvë°@åÖ.éÊ:JÀ¾ß¢µkû@WGøš@p_*CΞ?î’‹Sù't@›i!@1&à2Jã›ÀíŒêA¤¼MÀ$„B:À'2Ï€]À{5ú°Ê4@™ô&rÃKA@fξMÄ@:JjÀOÕšZ¥Å/À«í8v E@õ[®EEVÀ2»€vEªÀñÙhßÖÀ¶!Þ¸  @Ì#çvë°ÀGNí›»›FÀËüíÚŒ• À¹Ú^®­>Àp_*CΞ?6Ch[iš@Xèó ˆ£Àœm¿3Ës@ƒó­€½-Àæí*‘1½6@LCÿ5÷©M@tU ûÃá›À !+L_À ©¼ÁFîrÖ¡@qžÞÇ9úK@;·ñÊeÁ€ê¼üS¿ÉHAØ·ÈiÐÕÈ@ðïó¦Ù¦É? ¸»6¦@Z¸Ïÿ:pÀ-5¥_aÑÀ¾/)r·-c@4Ÿkh›@¯Î&á!«A@ûçó¦Ù¦É¿h@;Ð^ÀqžÞÇ9úKÀÂFîrÖ¡@VbÊÂ`ÉÀÉ='žÞÀVbÊÂ`É@ðïó¦Ù¦É?©–YŠdÔÈ@[¸Ïÿ:p@ ¸»6¦@nÚ´¨ eÀæj!0ôÐÀ±Î&á!«AÀ4Ÿkh›@•ª)²—~@t®¿PÂá`@…¦÷B“œ@Ç\ôRë†À#©Ò-£À¨ÝYø§Âw@Ú±ÏGo@wCU¬›,\@&ÿúý‡ˆ‘À°8ÒãP¡RÀ½™Lw0Pn@cáÖÅ&@@±ï*%Ù]…@xUT'\@IøìuÌQ@Чód @@¹hæ D@u¥œÎ/@—)âƒGkk@‰$”8ãBN@Ç\ôRë†À±»Ô$¨@†Èr÷1{r@6—ɧÀ{^' \@žéeˆi@I@ÿˆ¥QdwÀÊóÜBtÀ ÇÞu×I[@oÒK^¬Ô@VêG™ í¶aüFÀÖŒ=¯Î ¶@&Ö!"”ÀÑ<›+ü?—ËgæôÔ$ÀݲQÙ:ö?Û›&j^¼MÀš›Ýq! À‚÷ÙNùOÇ@Þ+Pnu·÷?õsú¸ö¤À¯p)領À ¥¢ƒl¡@^Øn[`e@÷'^I3À3]÷7³ú?ý3¨ESÀ²j:K“Éñ@†˜ÂèkRÀüMg€áq@&Ö!"”À-é ‘?ËÁ@ØwÓ%À¡$7O‹4P@A±yóJ!ÀžÉpý¶!w@Ëj$¶I@¼H˜}ó$òÀÊ-´s"ÀÍ,ì¦ÖG@8÷|EÞ @ZÆ'5—ÆÀ>Wï²ØÀ`wå6"¨@ë9Í<Å$ÀB7_LΖ@@è|!iïäæ@UjÍ´³ÀøÈ93kÅ`À ̯g†@¿R,Ì@Yán°û£@B ž5ÖíÀ'ð#.=Í›@UjÍ´³ÀµÁÖÜ÷dò@ù.ä€÷‡@ ¿°»M¯Àøzyš·ù¢@äý®Ú {@é› àäœ@‹çN?%ƒñÀ`¨¸É@†ƒ‡ÅD3À ºÝX|@»ïºv0ÀaÔ¶H¶ø@‚‡â‘5?@>б]¨@À$¦Ì—$:X@ Ý0aäQÀuó/§+6À‡~§‘~ÀÃýîÆëžQÀ§Õ‘÷Û0ÀêYZJ@vMé/r+ÀÃaa P…F@‚‡â‘5?@"7•šò{@ÐÐ^ ÆÆV@1GpÀuó/§+6ÀàX×{ ÀºV Ÿâ QÀ®–0 *qÀQ*?•{L¹@%ÈÀ³7‡@“/¹R$ÏÀäÿ^@:®À.­zbÙ°˜@6ž£c©ØE@ƒ!„íÕÇ@…”»¡=«@Ý•¥”c@u‰~z“H@R÷'ŸâÀd@§À =@”ífÅ“²À5.b))~À%ÈÀ³7‡@éÉyxÊ£@8ª'}_¥ÀQX @ÜÀi¤@Nq@bÚƒa @ò1^+)µ @ðïý /ƒ@Âë.á@s;@yå[Þ:!@¦]¼(=@[Ž5¶]@‹»½ô}Ài¹¿+ÈŸÀpIoÊŠU-À‰ŠêÑH@z¾kÖïtWÀ¦Ìº#k@>б]¨@ÀÐÐ^ ÆÆV@·K…Ml¢U@"8À/UWfÀ"ÑòuÇ¢K@¿ðû*fÀ1$›Þ×hF@ÿÚ;W¤ZbÀ1B­Ç0‚@AçG!úaäÀ+.Øài˜À@æ tïë@Í=·5„°®@ò˸¸;ÎÀka¯ ê0¢À–Ï?ßµC'@Uj‘¬ÙÚBÀ<üï•eVœÀ‡¢¬ »ßÀÍ=·5„°®@$HÝDPˆá@ø«kZÖ  Àúå¬5¬ÀtíäÄžNÀ¨ {üÐh@4‘4ÆQïÀª3 ÿg¿@P#Ò\îùø@‘éw~‰ÁÀkµoóŠÔâÀÙu/Ñ[@yÇ‹én_Ã@LÒ_’€òÀ‘éw~‰ÁÀN#lsºêû@óe#_ÀrönÔâÀ¤Ô(cxz@‹oÏí–À“/¹R$ÏÀ8ª'}_¥À:”o[Ó1AøÉ}vÿ{Ý@']êTSðÀ1[‘i–Àá¦UݸÅ4@Lâ*ï¢ÞœÀéÅüxÀ‘Ÿö4–a@IŠ‘à<9@u§zˆž|ÀT#ð_š´Ò@õ³¸QAá:@.­zbÙ°˜@i¤@Nq@']êTSðÀHœ½•.ÐÀ´é9·ÑLÀ@?9c=iÀ[w[Âär@‰ø †D­?—9våX]o@ë\Ê¥j¡„?@•2S’ë@na^ñÜ‚Ï@^ ƒ%v¦†@‰ÿcÅml@.ýiĈ@ bd} Î`@qÄTÄ@GïÍœS8À¤Q5m›Kb@†HqÉ:©?Y̬¯â z@ö¦²f¬/í¿êd†ªn#"@7/Æ3u}UÀ墪{ò—$@3ü]ÙfWÀ†S7rÆi@ƒA¶‘ä.À—A¬û€ÒÀ&чK,©@V²ÿ—µ#<À (5³Ìb@]@°§4ìç? h–æÅe@ÂÁö>Á¾%svÂ6§À6ž£c©ØE@bÚƒa @1[‘i–À×­ ~kzÍÀ?9c=iÀÕÿdÒ{Î@¬ö †D­¿[w[Âär@"^Ê¥j¡„¿–9våX]o@Tè©3Ve˜@… y‡á{@1²Vˆt 4@~*( W'@ ðù¿=5@gّټ @GïÍœS8@qÄTÄ@¼HqÉ:©¿¥Q5m›Kb@覲f¬/í?Y̬¯â z@x,^PƒQÀ }ë›À¿„@…*)ê'âSÀ:S]¡D˜†@ƒA¶‘ä.@†S7rÆi@9ÚÔ‹£ÝAkäõNØ6ÀK{:N+k@f@°§4ì翟(5³Ìb@‹¡ %)‚Àc›zÁF-æ@ßè"X:æÀ)oе¦–@3èX@Îѱ -v@„<9ÂŒ0À_]xPIÝ‹ÀiÌs%íŸT@Ÿžwy^2@ ÂYŽmðLÀ¤!@lR—-ÀÉ 0®;$ÁWŽã¡“A3èX@:da”@¹q°j]À鑲OÿÊw@<ï—Q+:|@­Ž„h£¥Àó†ŸÉ>øyÀªP†PaÍ”@Ç ¤ÍC´À†_XŽlÀÎѱ -v@¹q°j]À,2K/‘¸@,â@6%r@ßEQºÙÀ’À¥°pi'v@̧Ov;W@¼6l¿›rÀoåñ¬målÀ"Ÿ,Ü—±À„<9ÂŒ0À鑲OÿÊw@,â@6%r@€[òø›8µ@íM4…0p@2´äÞ©µ¡À™©üj'ÊrÀÑò Ž@‰‹Ûü[^‡@ÒÒƒŒl@oÓLYEu@Â$^íZ@_]xPIÝ‹À<ï—Q+:|@ßEQºÙÀ’ÀíM4…0p@\Â*ûJBÁ@à…Cþ$£Àѽò?B.@lCwˆ#t@ê:u:MÖª@äcÑɺ@”Ù,NÇÈÀûþ©8Î,@½X²_äl@ƒ<9 û¥Q@Ÿ!@lR—-@-CÊ6~(@iÌs%íŸT@­Ž„h£¥À¥°pi'v@2´äÞ©µ¡Àà…Cþ$£Àöv•A˜Ñ@^‡?:3t@8a$u4$Y@"’ówÀ@a‹w©ât@í±§@w@öå ÃYÊÀhÀNœoˆ¿@`©ž@HzSA’»ÀæÃƒAÀI¥Fr±À€&‰»#\@`©ž@ãf!Äâµ@¾¨}î{‰À4¬Äв±ÀÆG…%\À†©ì°À© ݬmíø@…ò§ŠlÃ@3ðÈ8Áü•Á€ÙNmîµ@Šm¤« t@¿YìÑAA@2Oïâ¦A@v8ÛÉp@‰ß’ •Aö]¯ÖÖÿÁîß–“Žig@+žºÔÿˆD@tF§w@÷ÉwLCZ@&Õ#Aò}uÙæä@p®:Oß“~ÀJg¼§‡\@·Û¾­dgÍÀwW˜´Ú‰ŒÀKCDÏZ(f@«³<"æ½=@nƯzÓ@A;W䱸æ@GeWsaî™ÀÇ&ÎTŒÀ®ðÿœ3{™@vCÕáfº@„íJ0=À#2¸$Ïe@\YxŒî-@=C[wC‰@‡·t 8ª…ÀO|¸¾`@›ïûGâø@.´.ÁbçÏ@lâAp¹ “ÀhçÖ=5XÀÒ³wµg@C€¤ð¬D@ZIåú$¿@ØåU`›z•@­‹ç?öûQ@ãÇ9M+ð?@Y®µ‡Š'x@°ùGâgúG@)6ª•¹yA¥´*_˜æà@< •O:ÀôzÂEÊÛT@dm°öAÒ”Z×î|Î@0–IKŽzyÀµEøI@…ò§ŠlÃÀ© ݬmíø@ ÙªeA&£ø¥ÁÇÀYJßJ@pŽ…Ý @\iTÛÝ{@É2:”^/ï?ö]¯ÖÖÿÁËmK:&¨AÔr°,‘_?@g#Ž„@ëH‹þÏñN@¼o‹^˜1@ò}uÙæäÀ&Õ#AY–ñÚêÍ@Bmˆ„øÀÿDp§»ªô@3Yò ÁŸxU6%±=@5CL™pí@;W䱸æÀnƯzÓ@AsB2áP¿@Ò´ˆ"^bÛÀãìV“M@„_]1–Br@ýŽ_BÑÐ@{Vã–9ùÀcÆ%œé@ŒÁ,# ©è?z[™Ï48×@Ù sÊñxÁ.´.ÁbçÏÀ›ïûGâø@ó²&ÒË@Ð6žUõÀ%ýo¤=@§$Y@ž ç)§_•@í®>‰{m@”‘=”v(@@ɧ—+f@ÞÓ%@P@»E$tæ@¥´*_˜æàÀ)6ª•¹yA"ïnbžÊ@è ±.åÀÒ”Z×î|ÎÀdm°öArX\ÌúYÂ@$nb&iÈëÀ«ƒGA@{•D½Kê¦À©=ßuÀ’¨ªö"¨@óíFë+À@DóʆÀ¬¯„?„ž@ÙˆËRÃÀSÀÊêÄòÇÀÅGÌ{e‡@æŠz§@¥I‡x ÀàÞ}a%E@B%—gÙRÀRˆÆ» RdÀÊÏ'ίòÊ@^9xC J{@„ƒë7ÎÀDóʆÀ®·Çé)ˆÆ@ÖˆËRÃÀS@¬¯„?„ž@º"É ÌÍ@Ýô£ÍÀœI‡x @æŠz§@þc(DÞhÀW–úàG*v@…ƒâY‡¥@ÄáC·ÛFÀîß–“Žig@Ôr°,‘_?@–‡et™P£@ðÐ!/dÀAþ6øßJ@Š>Y‡r@$7D@ßè&SÞûT@]qq—ûªÀ”{Ò¥E"tÀòªXÓâ²À½H+Æ3‰@²¥¢ ‚`i@ 0É‘ˆV@½–Dmû¿M@.TÀj!~@+žºÔÿˆD@g#Ž„@ðÐ!/dÀÔ¢[þvµ@X¥I{ž”l@d½2n@P@¯4·sl[@øôz ¶g2@Ól—÷­zÀäÊõߥ˜À¥$òŸ‹@îÓÀõ²±À4ú’W$BF@ÐÅ=3©Ã3@·BŽ¡} À@…ç™?šÀM¯ž·’þÇÀáR‚’n&@¢Ò~Oº•@ã1·9òNsÀ4=ȈÎ,–@Åj‰¢F¶sÀ!8%ΈE‰@ã!Y’ŠJÀK…Ñ‚ïç£@ >¿gÀ‡]ÀqµÕÀôy!AQ—¤@Nž NÛ™@hæk4ö¡ÀÃ)R7M‹@Œ±WuÒ J@ê:—„ºé¥@MhsµA‡yÀ-.ꫤ@÷Óé'™€ÀÕWÊšgß–@ÛÑ™8òÅgÀ9÷|<$§@Fð W¿g@K…Ñ‚ïç£@*R;9Ðn•À~G|nƒÀ×Àhæk4ö¡@Nž NÛ™@Œ±WuÒ JÀÃ)R7M‹@LhsµA‡y@ê:—„ºé¥@öÓé'™€@..ꫤ@ÝÑ™8òÅg@ÕWÊšgß–@Gð W@ÉT"¼¥XÀnäw?±0@Š,½ ¤XÀÚ:ÀÈ;„@9³Òc[v«ÀóÍù@õÀÇî×%dΰ@£ð~‚ˆ2Š@~Vä›…¾­ÀÝëð3]Àå°ô¬æ…@Á^‚aÀe Ò?‰@«ÇŸVýÀmþÕÚ“v@.±ªm¢¨!À»]}ýlÈv@Àã_fбHÀ‘žØ÷Pçc@ žTâ³XÀ ^!ƒÍs@Y–b’‰èGÀ¯ÜΊ¥q@ØVË0LSS@M¯ž·’þÇÀÿš­·cÐp@…Ãê$z‘õ@1nW™%°‘À烻ZþÅÀÖ±Rö&_”@Ú¸ MÇÀ/ªzTŠ•@”aûþ¥¹¶À„h†¬¼q@÷‘·ÝCK@ÿk»™sÀq”ØÔÙÓÀÔF‘÷e:@=÷ƒXC@¦«0¿]*mÀ8À6‰e@b„ìÏŸ€ÀIOQs·À¶Ä>yx½€À€Ñ¹†_ô¼@çà¶÷Hq¡@Ø7$ÞÀR·nW[¯¯ÀˆŠt¬s•@i/¦cÇÊa@%ïÀš£L†@áR‚’n&@‡›?baÏÀ1nW™%°‘À6]ûo<÷@^ðë£ä¹“ÀìY R6öÇÀØ_ }¤Š•À÷}ñseÇÀs=šßÃk@u”Cç2¼ÀÌ2Áú~sÀ1ç2‚¡@¥¾t^õJ‚@Që¡æ ès@k‚¡@jY‡r@d½2n@P@À_A*”g‘@<ä’R¼@ã·\2fÀ/¬ÇõeÕ£À$–^]%‰q@éqW³‰G@jd€@;€¡ÀôœÁ¼R³ÀÒ«9w\@é C.¯FI@aY±Ö¥@<;_«±tm@’or~ t¦Àã·\2fÀjgj÷Â@ãý€<ÔõpÀ%=í×ÌÀ±»KŒJ€À^Ýú¥7q˜@L Ì{@ójÿÊæ«@öÜÖq@<;_«±tmÀaY±Ö¥@rŒŸ‡:UÀ/¬ÇõeÕ£Àãý€<ÔõpÀÝÞ¤Æ@ù軺±i€@ËW‚j!ÓÌÀ¢=}]möu@žÍí"úX@÷ÜÖqÀójÿÊæ«@êŸt#}@h†¶Þ À•OMÿ@áÁ_ µÂÞâ@&Õ#Aò}uÙæäÀ%=í×ÌÀù軺±i€@üź×zá@´§>oñ°dÀC[Ó–_¶ž@{¶'ó?¥ä¢ÍF}@dÓºð²»9@AÖ©¼NNª@ý½²”Q@&ðo˜ÐÀ)Ÿ[EQÀíºÖ¤Ê–@¹‰¦u@ Ï0î-;˜@\ªÊÉác@qEFê+†@úÖûN¼üÀx†¶Þ @êŸt#}@}ðŒK®äÀÓâÌÕ˜Áò}uÙæä@&Õ#A±»KŒJ€ÀËW‚j!ÓÌÀ´§>oñ°dÀy$ðÑw×á@¡¶'ó¿C[Ó–_¶ž@eÓºð²»9À¤ä¢ÍF}@šÞ‡0r u@Èüù @‹“ºŒmÀ[¬àBÇÀ¾‰¦uÀíºÖ¤Ê–@MÙó$‹bc@ÇC4C©Ï/@öÖûN¼ü@qEFê+†@§‹}.–p†@«¬%À50@&F‚7wyÀE–v´G0À.Þ‰?À`𼽇Žl(n@ =Ýr}Òš?«¬%À50@—šÒ˜ö„@Ëã/.“'0Àéþ½FƒvÀd4FdÊ¿ÿrA7">ÀúEÝr}Òš¿½‡Žl(n@¸åo*¾ËÀp®:Oß“~ÀY–ñÚêÍ@gtžvî¡@¤—Åä¼£n@mu9þˆ@飋ðCŸg@SÑKݺ'@˪’ÛøIQÀ= [*Ò·ò?æ Û~CyÀá˜mª˜ê@Qe¤ÿä_,Àz I = @7 ¸Í¦3ÀN†}V~µÿ?0Õ©õ­©'ÀÇÅ›”1‹¤ÀØ öPyÀˆï`ëý?A‰´KºÀÈSZcÆô?’‡:O@;Àþ#íö@Jg¼§‡\@Bmˆ„øÀ¤—Åä¼£n@wuQ»M4’@m3‹[Ìe@ýÉåì™D@·# [SÀd¤Í–74|@ˆà_{ ‰ÀíæÙ6Û8@:|ZPÞÛ.À+ÝC¼æ$W@²Ã…ßf5À_ê›r`@ÐbÆØ&Ý)À© TÔMS@*œñ]á¡wÀI²ëãŒÀª'íƒ/g(ÀŒþ{u–ZC@ç¯Jò ÀC%ÀjqyI@§¬Ï‡âÃÀh‹6­ÿŽ@cµ×ˆm·@CÅïý¢À—×NÛ( wÀ鼨G·a @{rÜ×áš@sd-lÀ>£[^ @Á =zýRÀFADz¯Q@~€ÊÀµrÀîP±ýG„@šýÆâyX@—Ã¥Sg):@Qß"jcÀhB{[]€@ãZÆ:?ÍÀCÅïý¢Àæ/”®«Ô@ñ"”n»¡@‡8â&7 ÈÀsd-l@{rÜ×áš@Á =zýR@?£[^ @IzOyÕÓyÀ¬;5oŽS›@šýÆâyXÀîP±ýG„@j†fûÝcÀ¤¡ÝéZŒ@Y‚èÏ!TL@qA¼Xw†xÀmu9þˆ@m3‹[Ìe@—×NÛ( wÀñ"”n»¡@™¢Ø™AŠ¢@]Ôp/BÝ«À¼ˆ¦  ¥À"®üQñÙ@Þ‰Ö4âTÀÇi>£¶þ~@uØî÷¯tÀó^¿»îè¡@飋ðCŸg@ýÉåì™D@鼨G·a @‡8â&7 ÈÀ]Ôp/BÝ«À(.äÓ@Õü;)~Z’@»{=J½ÀÒÎù¢³R{@5T5>°F¤Àw°$oEµB@l7Û¢ËZÀø§ŸLcŽ•À£ð~‚ˆ2Š@9Ýsç•@àà¯=ÐŒÀ”X«©?ÉMÀCå5 ßg@¸‹þ^À»J 7Ô†u@ù_®M@~Vä›…¾­Ààà¯=ÐŒÀø I5¸Ø¯@wI‡Êäg@|"¼Ó2&ƒÀã¶°X?3¨ÁâàVRªœ@½{EP¨AqÀ‡ÒöA½½§õA[@É÷G¼À…„ÀFˆtç3ûƒ@ìCeÕKøò¿8žNLÓyF@k–á*—aÀå)Ì–ñA@¨éKkÀn ’yØÁ'ç26Ã+ðÀsLöÇã®N@Z&FÍì)wÀl©fi8e@ÊpT-VË€ÀàÕÌ "·@ÄêÓœF}›À&pñj!ÁØ]„.NõÀFةޘAÁ͸lS¨ÁqÀ‡ÒöA…ýEÈÓ¨AW …–õîÀATHA AþCeÕKøò?Eˆtç3ûƒ@âêr]õ>ÙÀÎ Ù¡)Âó@ry„f´ƒlÀ­©"›;ç•@Úᨛ“À窣a®À?â|;áÀ·Œö AÀ Ð—$µ÷À¢a'ä5ÝAn’omæÁÄ“ü –à.Aœ-Ï@Dc˜À‡9*ÑËš²Àã(Ò8ñP@lÌÆ³pW Apö ýêÖ@•í²ý*3ÏÀ Äá=DxÀýÐän¨ÒÀÓÆ‹†uÀ$»œ–‡Äb@þulWFŠÀÞp‘Ø¢iÔÀ•fsQ&· ÀphØÜ§×Às%KH[y§ÀúŽV;WŠ@ÄshÀ;è@QsK–ÌÜÀϘ•÷ ±ÀtÔfŽN˜ÓÀÍ—@ «À’Çò?2áÀ¤K>·À¯ñÇ{çÀ„<̉>¦Àí§ØüÆ<®@èœÀwêdÀ©7û±<ƒ@pö ýêÖ@—ž’óæ@>±A G¶¡À(0fRKÀ×ÎxîM¡Àß-O{x]§À]t•ÛAÀè¢7~Á¶@–³—\¢À霕‚—±ÀQ\†¤ÀG\¤i›Š¼À²shÀ;èÀúŽV;WŠ@€öÁ°Å«ÀàNÎNÙ·À”ÓQúø§ÀUJ¾º‡€ÀW ôdàØ®À‚ïÿ6½ÀèÉàÞªœÀÊ m{ƒÞÀÍ’þð€À²yèÊ‘6·@o $l\üÀð2Ç$¼ÒÀÕcjÄ^zû@ŽÖbW_²Ò@ #¨zWE¯ÀÑäKö˜åE@aE ƒ’¤@hçºÜh@ÿÐÜQ‰’­@Š–“c»4%À9_i+ÓÀ"·1“Ô–©ÀŽÖbW_²Ò@?PûÏbܬ@|þ ÔY¡6@ÞºÐÇk°Àû}ƒóH|@)ØÀ\øï?†–“c»4%@ÿÐÜQ‰’­@ÅBï—F=±@M±ŒŸÍáZÀÏt´W(õ¦@Ä™u"|À•í²ý*3ÏÀ>±A G¶¡ÀV®„Zh‰®@ŒSM$ÀÌgÀöD!Èâ ’@8•cþæÝ3@2*ü§Ü “@Aè3ÑÍ]ÀÜ#¹F·¼š@dÊ“Y-ßn@EËÐ…_—@Z/¬º%p@û ãŽ'ËÇÀ*0pÄ@ÂDÞÙü—@ϲ nl@(ù(Ÿ'*–@½í¼k’n@´ÒDF%¥@@Z9eïž@n¶ú·‡<Ÿ@:žÑQ©]À‹,ôÐ „¬@ñcÄl#G„@T±ŒŸÍáZ@ÅBï—F=±@Ä™u"|@Ït´W(õ¦@ Äá=DxÀ(0fRKÀŒSM$ÀÌgÀ½å­“ÐD¨@Ýúá'3<@®ËÓRgçÞ?@è3ÑÍ]@2*ü§Ü “@V8þªËD@kbê@ÅHÛÙv-B@ÅšÔ=@{ðå4uÀ¬È l‹ÊÀíŸß¬7¨B@üÙgó@®úæB;=A@[ÕËA7Ç@2àÄ4rP@רui+@<žÑQ©]@m¶ú·‡<Ÿ@PÍö¾Î-V@1©‹/@Xðèb_RÀ—9våX]o@"^Ê¥j¡„¿oOj*9x@‡ä´÷²9­?ýÐän¨ÒÀ×ÎxîM¡ÀöD!Èâ ’@Ýúá'3<@-çðïÕº@<&ÅET@39‹,›@¾Aä]0o@†xkC}œ—@µ«)O1Pp@ŸvU§¼œ’@µä³Ìšš”·Ñ@ð½—§®|ÛÀl­ë/T›ÐÀÌ'‹Á£É~ÀMà#iª½¦@­3¬+ãÁÛ5 ø&{Àáyv¿æÀð½—§®|ÛÀÜöì"ç@Ùu]÷ËÛ@µ¸¯™/µa@ÿ‚f‚‰F@oïRÂA¼ëCDD¾m@hZ뺮SL@e0€-B\@˜ì7_ß 3@ij ®Ÿ¼òÀR5ÔÂ4 nÀð½—§®|ÛÀl­ë/T›ÐÀÙu]÷ËÛ@å‘ÔÆÐ@‰,ÿ“£¥S@˜Û¡Ó[9@ÇÚ&Zð—ò@yk‘€`@i9Úm?@‘b;nZO@>Å$áÚ!%@¿R,Ì@øzyš·ù¢@!8%ΈE‰@ ã!Y’ŠJ@”aûþ¥¹¶Às=šßÃk@úç• ™œ‚@ªÙ¡“`øVÀã²þ‚@ã*/ÓtWÀÇ@^t¨Ó@kôCr|ÀåUŒ(PàÀØ cÄ• À"ñ_Clã@Xs¾,%/#À苾¥õv@k¨]="G@?G,ª±”@LN“~`@Yán°û£@äý®Ú {@ã!Y’ŠJÀ!8%ΈE‰@„h†¬¼q@u”Cç2¼À©Ù¡“`øV@úç• ™œ‚@ã*/ÓtW@ã²þ‚@kôCr|À82(§Ö@)ÏeJ(Œ¡À=WÈ%°ÔÀPs¾,%/#@"ñ_Clã@k¨]="GÀ苾¥õv@KN“~`À?G,ª±”@r:o[Ï@‡lTPzr¡@ ˜½éõ¾Àòý÷éñ‰ÀÄx¶ÃÍ2¿À±Ózµ–À‡lTPzr¡@ ýuäP¾@V‘[».¬‰Àñå/|¶C³ÀdûBÝ–À§•å¦À ˜½éõ¾ÀV‘[».¬‰À몎ÐÕ@zÀæ*‡³¥@QÓÂßœ©@Ýå髉@‹^Ê>×À×›`6c´À! ®é.»@а<Ï£@òý÷éñ‰Àñå/|¶C³ÀzÀæ*‡³¥@ÿ›÷†Ì@òý÷éñ‰@{m9 ½7j@"ä ´]´À?᜙¢÷ÄÀÊ-=š£@ð î@©zj–.A;’Ý>ÔæÀ)¿1çÁ‹@@F{€3µÀ-a;Ž£gþÀäê·yj Ì@ŒÞŸ9ï0ÐÀ€z`‚×wâ@;’Ý>ÔæÀ0fyÄ A†‹ù8J¦œÀ•Ji$•âÅ@Ómpæ}ÐÁ@ë_ЈHÁúë½µQEã@É9ú &´õÀç›9+ÄÀyqçÄ`¥Àѽò?B.@^‡?:3t@h¡„ÅP¦@ŽUƒÓÂ%g@CÕsú#šÁ@©¾Wµ¤@ت÷ñ@²Ð¥7’t@O´À¥ÂÓªÀ; ŠÌ]}‡ÀbI¿ 5„¦ÀÀå«K ÀlCwˆ#t@8a$u4$Y@ŽUƒÓÂ%g@4EAº¢@‡&_®×¥@®‡¯N²‰@ßÛ:+3‰t@ Ï$WnšY@Y¹ˆ8m‡Àq¡1¦“ÀÊ—ˆ¹]å@Ò[ J8’À,á·Ä5ƒ×ÀAtðGÃ'Àô³wL=8ÓÀ…j9Ò­K @Ò[ J8’À2rîÍè@&s|è3gÀ>P3‹ÒÀ}gC65¡@ˆ ¦Š!ƒÝÀ,á·Ä5ƒ×À&s|è3gÀ”ã׬—ÙÐ@ô¯Ê-Hg…@ÌãfÇEʾ@`¨*ë3M@Áµ›Ÿ5Àž” ™s's@AtðGÃ'À>P3‹ÒÀô¯Ê-Hg…@nåÂ!*,É@`¨*ë3MÀÌãfÇEʾ@ž” ™s's@w}…ËÖ›À¿Î ãf@Ü £I¸ì4@¿Î ãfÀÜ £I¸ì4ÀÜ £I¸ì4@à/§pÒ±Ú?Ü £I¸ì4Àà/§pÒ±Ú¿QHsüΪ@Ä–C%/fo@:Äuy¢@Ã/y›©‚_À2*ü§Ü “@@è3ÑÍ]@¿Î ãfÀÜ £I¸ì4À¾ÄÈã:§@Ê5˜»È¼UÀ'¬Ç2ó{1Àš´BrÀÑd@Ø’^ÄÀKߟ3ÌwÀ—ãœ.P]˜@Þ­´5¯N@Å–C%/foÀPHsüΪ@Â/y›©‚_@:Äuy¢@Aè3ÑÍ]À2*ü§Ü “@Ü £I¸ì4Àà/§pÒ±Ú¿Ê5˜»È¼UÀ^o+˜Qí£@ó`Ú¨µØd@ëv9´Ò˜ÀºKëqÚn@ေCdÂÀÝ­´5¯NÀ˜ãœ.P]˜@xgéUs{r@èåÔ§ßÅ À³ò¤c@ϯ˜ü£ü¿µ2tZ‡bwÀÅ/ëÏì˜÷?nÚ¸7ácRÀ‰gõ*Ò}!@èåÔ§ßÅ ÀêK¬Ùàs@ϯ˜ü£ü?²ò¤c@ñN‡‹èšú¿‹7vYwÀɹ²9ˆ– @_V²µ+XÀ_ ]_Ü@P:÷.Û¡?” 2ÐK\@Ì…-x·jt@Q¿ÿ>¥æÀÀ¶c1ƒÀ€a:AEÖÀ€ôO‰ÐŒ”¿ÜlÁ7•@ÔL§«Ò÷q@P:÷.Û¡?vÇ*å4_Ü@ì‰æ¬‘xZ@`€‰åZ„@@KÑãvfnÀ€íÔ0A¦¸À ZP‰ÐŒ”¿¨ç€`+EÖÀa,/F¶)a@Le¸þh=@&¤·h͇ùÀwÚo?¥@wÀµ¸¯™/µa@‰,ÿ“£¥S@íŽÕ&ßÃ@²K{•`ƒ{@ jåW1ù@†ùYI[f@å‹gÿJE@‹âñn—=U@,}»í¡,@nK˜ð¤ÁÀ­-¨BuiÀk–¸Sò5àÀc‹évÀÿ‚f‚‰F@˜Û¡Ó[9@²K{•`ƒ{@'Ê2»!Á@}Ï© à@¬ªšÏ.tL@Þ÷='Q+@²”0’;@4ˆò€8@G‰º•UiÀ´æ@õɆÀÀ$»œ–‡Äb@]t•ÛAÀ –ûÜ®"Aܤ¡Vül¾@Ñ EQÜ âÀ‚f` É @]5³¨@¯cGäaºaÀ)Há. â@>ìQF0ÓšÀÛ †òBõüÀ¶ÊÓ¤ë:¦ÀZW¨· z@b²µs£À£ö§ãŠed@­á~üï'‹À°FâNÒ@%xSêþ£‹ÀþulWFŠÀè¢7~Á¶@ܤ¡Vül¾@âzçåõ@Ú¹Û:»»ª@L\Z®r¡çÀ®cGäaºa@]5³¨@lË¡A` ©À‘X91ÇÂ@ˆˆ×ÛßO³ÀÒîþ3Å÷À¿Öu¶<¢À¼Œ,Ën³Ê@}ŒQØ(ŽŒÀ’7¿0[³@&xSêþ£‹@°FâNÒ@¾/ƒib§À$¦+ŠÄ„@“U©I‹ž@(ÏŸUOŒÀ<ÏPIÀ"]ìu@s|ª^˜@ô¶Ê”2îÀ\¡ÿâ ¼?@† ZÍÎÂYÀ:Æó”8@Ç(I¸À(ÏŸUOŒÀå|˜î(¸@L‰£¹4|@¡M&oÈÀï¶Ê”2î@s|ª^˜@)!+WÄ«YÀ§Øø|ºÖt@efuƒæB@—ðkÖÎçkÀ<ÏPIÀL‰£¹4|@õ(ŽaF‹@ädŸ™yöyÀ@`ÝËWWvÀšß¯é™jg@¸ïýY”^ÀVð’Ô’†@"]ìu@¡M&oÈÀädŸ™yöyÀ€Þ­ÓV @y?›;^g@*ðïÅeUŒÀ #¨zWE¯À|þ ÔY¡6@ž[^=)3ó@)ÊX4»\ÔÀl”¨t‘\@§þó(„ÀªDæ%@òÀ õF_øÔ@ÑäKö˜åE@ÞºÐÇk°À)ÊX4»\ÔÀXB ¶PÀÙ,-wÐ>x@!V о_•Àe±:³lÜÀ¿îH’§NÀOGDïÖOh@ÍnzRIEÀ3•g- p@-ïáû”@^Æp«`j@ó»ølްP@À¡³Ê?ÔjÀ[M`B—À©4§}§’bÀ /Ö ¬lŠÀ‹Züel¨b@ê ôÏïfŒ@ãàŸkpÝ@^Æp«`j@b¦žØJÆ@´"®rüjÀ[u°…@-dOë}ÓaÀ¡ž Œ$aÀ\ѯ¯WËb@N'›'”À*áŸkpÝÀê ôÏïfŒ@Ú9·ºòÑá@V¬X¦ ^Å@6¹ Ø2@ª¸,÷FLÀ”[v3áÀ¡'¤ž…ÄÀ§KRJèE—À:äýÜd…wÀV¬X¦ ^Å@"ÅNÚW!ª@þ¬Mi^cMÀg$¿þó g@¸¾iïŠÄÀCK帾¥¨À#þ³+ÑvÀ^rKë­awÀB ž5ÖíÀé› àäœ@÷‘·ÝCK@Ì2Áú~sÀùØ–ÊVW@Ì'‹Á£É~ÀåUŒ(PàÀ)ÏeJ(Œ¡À1‡8bð ÷@amVdËÄ’@'ð#.=Í›@‹çN?%ƒñÀÿk»™sÀ1ç2]ŽçÀòYˆtDF@>‹ÿk.+@)C¡óQeÐÀ4 }ßñ@"ÑòuÇ¢K@/&zÛ/­fÀÃuPLWÀ$ß^D‹š4À6¹ Ø2@þ¬Mi^cMÀ:‰£Ð@§¼U_F³ÀÄ8_×ðiÀnâj„@Ib&/e8ZÀÍ/+ìì?ÀìZaÈC@ ­ B.H'@F 9(+@?ø%y“@óÐØ+‹À±@›eËnòBÝÀ¿ðû*fÀö£´b>0‚@ÐÄY•†4ÀÕ»I‰ç2?Àª¸,÷FLÀg$¿þó g@§¼U_F³À!ØØìÞ@hÞ_Y„@š)aa‡ À#h¥ûä?ÀÅ'ØuÉj#À¸~6M8'@­‚üQ @­x7Y’~@æV(q„ À¸‘º=jÓÁvÝ@Êmä@ß7u "µµÀDòÓD܃hÀnƯzÓ@A;W䱸æÀC[Ó–_¶ž@¡¶'ó¿{rÜ×áš@sd-l@¦w©º7¸@ñõ ŸŠÀ£¬ßn»·~@OÔÙ©O³:@WBP|¡3”@Ø"öÕÄ|^@7‰7zkx@‚Â1¶\@Ý‚ |b8À4Jušätn@ȯȨé—@šž tä@ð¾àC‡@DeUÀï ÀßV(q„ @­x7Y’~@‡’Vj?ÏåÀ _`-šÁµl§Š-€@9-ª/¯zÃÀ;W䱸æ@nƯzÓ@A{¶'ó?C[Ó–_¶ž@sd-lÀ{rÜ×áš@ñõ ŸŠÀ¿O±—ìÑ@MÔÙ©O³:À£¬ßn»·~@Ø"öÕÄ|^ÀWBP|¡3”@ƒÂ1¶\À7‰7zkx@V—´@Y@s@ú5üIî§ÀŸž täÀȯȨé—@MeUÀï @ð¾àC‡@2(!Äêq@‹Ÿ¼ßÛjÀkã,HÂ?À»8ŒõZY@U‹°ØÖSq@9•l6© Ò?¨r£R=¡€ÀçÑÝ­·Z@‹Ÿ¼ßÛjÀÌLiç/‹@ëèT` ÛX@Œ&W ¥ØsÀz•l6© Ò¿U‹°ØÖSq@ÂÂZ%X[@ã>e>¨î‰ÀKª‘fñ]øÀÏÌÐnA™Ž*éFÁ•¢µ¿Û\A˶—ðê!2ÁÐ- §+šN@ÊÐ7®mÀ|/1Gµy\Áû Ó5 2AÍùØAŒ•½À“xõ‹!Á*VýÜA˶—ðê!2Á^UgLÅ/cAÜŠx¬±ZhÀ¿ò{2‡@‰ófRC@2A«ÐµcÁæ8ŽãX15Á%kNö15A™z̪ˮH@ÔG¦cÀ™z̪ˮHÀ‹Ÿ7(E§@]©B€yˆ5Á™z̪ˮH@Æbdh15A‹Ÿ7(E§À0sq‚<ÉÕ@™z̪ˮHÀísB©/ÀœTs`Bâ@X'F5ý·e@®B<êZàÀœ 0GxhuÀÙô˜+¡" @XÒ¸êûFu@ß …âO·À@àYØqeÀX'F5ý·e@·>j;EÃá@œÓÏcuÀÝêž̾ÞÀÌ›vƒu@Êmö8¥^L@ÌUõ­`÷eÀé‚OW³ÀÞp‘Ø¢iÔÀ–³—\¢ÀÜ#¹F·¼š@V8þªËD@39‹,›@¢"¸ÿš=@Ñ EQÜ âÀÚ¹Û:»»ª@ÄHß³ëé@Srfõ—áÀ}mi¡@çÅ%?Zx@!Ø£ÍR@)çýzÀù.4)Õ¼àÀBâuÄÉ[À@§ÐSPƒ @³¾gÇÆv@)ƒ8®¯@÷/÷fAŠ@€îâ|ˆlÕ@ðŒmÎÞ>®@‘îV½Ñ£@Wmĉ3tÑ@‹Ap26"¥@×xõ®9¬@•fsQ&· À霕‚—±ÀdÊ“Y-ßn@kbê@¾Aä]0o@þ@Øþ@‚f` É @L\Z®r¡çÀSrfõ—áÀ@»´êD ADQ¸t@g.•hÔÇK@Ã.¡ÛyÀŸaÀõç÷¡@kæÉLÂ@7š ]½ïÀîO§s@le]ºqLJ@›6Hz0‚@[xWËP^@Ý ›®@õö»%Ÿš…@oY{Ô…Ï@,Kµ¢?ËõÀÀ!®æ¤¬´@¯Ùy“hÓÀHzSA’»À¾¨}î{‰ÀÄx¶ÃÍ2¿ÀdûBÝ–ÀQÓÂßœ©@òý÷éñ‰@.o+(d˜Ç@]éLÁ"Æ—@g„èi.œÀ—‰2mÀmà4“ÆM‰@&‰»#\ÀŒh^øXt‡@ ‚u1m@æÃƒAÀ4¬Äв±À±Ózµ–À§•å¦ÀÝå髉@{m9 ½7j@]éLÁ"Æ—@œÄ„N¹:¼@r<±ÁðlÀ**tp„‘À€&‰»#\@mà4“ÆM‰@r<±Áðl@ÊmlÄR@g„èi.œÀr<±ÁðlÀZáÊ4™„¨@¯CYøw@„@M>­ÿê”Àj§ˆl zÀ—‰2mÀ**tp„‘À¯CYøw@„@]sI®;ˆ“@“„¦m«çyÀéuŸö'`Àùü ìçÔ@Ûb3Õí¹@Œl1›F¥Àž(A2nÑ„ÀÙ˜:Ãèv_@.Ž¥C}9@e|ðRb‘âÀ±š0è9ÒÇÀÊî¶3¡ÄÒ@'U®…7¸@Ûb3Õí¹@6Ý[U¥@Œ]2ñ_…À×"è2%ˆÀ;‹=áìC@T¯’# @úY*^—¬ÇÀô I_®À´!…Ǥï·@úö£âž@û©mZ¢²À@Ö=[ÜûjÀ©–¤’#’@¬¥[^+hv@ˆ9Ö@#tu}Á¹@SˆßvÞÀj¢0kxP½À%ãÑ ­‘Àâsµ8ˆ@Ö=[ÜûjÀÆíT’äÁ@¨Û„1pwv@wû¬ÔrÁ[@ˆŒK¥X»@ŸÎ.‚kçŸ@P÷Óì¾ÀqÌRÑ¿Àæ×ð%xˆ@£­-ŸvCªÀQ÷rˆNÀæ¦ö7ï@I¥Fr±ÀÆG…%\À½½§õA[@W …–õîÀmà4“ÆM‰@€&‰»#\@r+žêÒÜ™@à =ÛøCR 0@ÑY=MIÀí<'&ç5@Až[T‰`À€Ýgñ"N@FÆÖÂúgÀŠ}Óc¼Ji@Cµj‚€ŸƒÀóDXAF£@¡”Ë;‚Á€&‰»#\@†©ì°ÀÉ÷G¼À…„ÀATHA A&‰»#\Àmà4“ÆM‰@à =r+žêÒà™@ÚUéžÜ(XÀÛÅlƒèr@ «„`©}`À#CãP'æˆ@iÓìý¯vÀ¿/´i ’@ðˆX³ß “À …µšuŒ­@&NÜMeÄÀöeòªÊ7¢@ «Ýr-â@Ÿqpw/ŠuÀ./Í>¨óÙÀ²‘ xP ŸÀ¬“.Øz£@o5ŠBpÐÀŸqpw/ŠuÀÔ0²„ŠGâ@y…@éÁÈ À‚Ô³ØöÔÀ°ÍN£Ž¥Y@ï­B"N<@Ú±ÏGo@{^' \@^ûRöf’À1ý{ÄŽ8~ÀÅÌbü-÷Â@T ±ñä¨@=ÎL‹¹ZÁÀŒÊv°6¦À춦“G@ ª*É‘~)@wCU¬›,\@žéeˆi@I@Òþ¦QzÀŽÖÓèFnÀT ±ñä¨@Ü$¨Tyt‘@FÏJ¨òá¦Àe·ˆ\,JÀ&F‚7wyÀËã/.“'0Àó»ølްP@´"®rüjÀæ–!Dz›@ ãåX qÀ‘²#'–ÀiÅfäo@E–v´G0Àéþ½FƒvÀÀ¡³Ê?ÔjÀ[u°…@ ãåX qÀû¦Âäë£@c- …¨{@§Ø'±Àˆ¦ÀŒÊ…ņž@yO´pƒ@ŒÊ…ņŽÀyO´psÀŒÊ…ņŽÀyO´psÀyO´pƒ@ÿ£—¨Âh@yO´psÀÿ£—¨ÂXÀyO´psÀÿ£—¨ÂXÀÍ„†hº÷½ÀGeWsaî™ÀsB2áP¿@= [*Ò·ò?ˆà_{ ‰ÀPú‰ìíR@XÁ šÊ-CÀAŒo} ÓADáo&±–@GÀÌV¹Á}CÕáfºÀ ÏXYõûô?Ž6ðyÀ 2VxUý?ôô†½Ì%Àç¸^l–ñ?íüæÝ?ÀñEØð?Y= £LR À>š‰¼Â ç?:F²ëžRÀ Ä$îdØ@Ç&ÎTŒÀÒ´ˆ"^bÛÀæ Û~CyÀíæÙ6Û8@TüæNm5À@”PïR9_@Dáo&±–@â>;Š:©A’êØà¼NÀùßek¤ÁÈ>âßÀ,Þ"ÓOŸ9@‡†_i†±À[zÚUÓ¾A@ü- ¢ ÀÂ÷[à^5@tCßÓ Àhuzm%@MöƒÂÀ¯€€yº3,@®ðÿœ3{™@ãìV“M@ŒÊ…ņŽÀyO´psÀGÀÌV¹Á’êØà¼NÀ‚ÒfM«Aù4÷()m@ŒÊ…ņn@yO´pS@vCÕáfº@„_]1–Br@yO´psÀÿ£—¨ÂXÀ}CÕáfºÀùßek¤Áù4÷()m@¢Õü¡AyO´pS@ÿ£—¨Â8@K…Ñ‚ïç£@ >¿g@q”ØÔÙÓÀ ð}”à€@¡ Š¢`@"Š­¶öqÀ`2¦zû@Ûì¯ìúkqÀ"ñ_Clã@Ps¾,%/#@÷¹€:y»@:ô_Rú†”Àžj¿Ñ’c@쟺&[ÀTÖHB71pÀ&ömÕF˜@Êk]îëù,@ø$ŽùHÙTÀ_M¤Ó<’@ê×´»q„c@F>P¢›¯@ÊR>|@ >¿gÀK…Ñ‚ïç£@ÔF‘÷e:@FíÆË¼°×À"Š­¶öq@¡ Š¢`@Ûì¯ìúkq@`2¦zû@Xs¾,%/#À"ñ_Clã@:ô_Rú†”ÀË@°ÊÌ@WMÉIÀúVwÔ ¶@pšÃñi˜@NL`–¡LÂÀ@±Š×UÀP\n@é×´»q„cÀ`M¤Ó<’@ÊR>|ÀG>P¢›¯@têÆ@ÍÀ¦ÏñJJ.@Lu°9 hMÀÑ<›+ü?ØwÓ%Àžj¿Ñ’c@WMÉIÀ?or³ë@†÷KØ~ÁÀ‹ÐøMÎÍëÀ'c’ ÝÄ@@oˆpü?¸xô“gSÀ©iz|j–ZÀ@SBUp›Í@8švWþ?ª[J0š#ÀÝR;X>a@ËWYЈÀGlŒ&@fî¨DHÀ»–mÔž¸õ@UÄèÅ}VÀ¿Îq‰ÖÕu@—ËgæôÔ$À¡$7O‹4P@쟺&[ÀúVwÔ ¶@†÷KØ~ÁÀ}¿R ‹›ú@\ÂE¼ëÄ@Mc‡ýÀ„Tþ%À¿fû™T?|@÷÷gî†b@¢0]ÛöÀ§"˜‡&ÀêzÛhHM@TLüX„݉ÀØÎ Cœ²@Àט—á\)Àã…—âBD@=÷ƒXC@ ™²ë1mÀTÖHB71pÀpšÃñi˜@‹ÐøMÎÍëÀ\ÂE¼ëÄ@í2ì@§bŒÜ¨ÉÀô ‰ºo×gÀvBWf'‘@¦«0¿]*mÀ¤JÑL–@&ömÕF˜@NL`–¡LÂÀ'c’ ÝÄ@Mc‡ýÀ§bŒÜ¨ÉÀ±G´ÚvSAJ{»±½‘@ c:x‡¹Àá^#йX@%m‚…&Ä)@þÿÿÿƒ×—ÁPlåì²ÿÀÇÂE#^PQÀÓ!{@P_Æç‹R@p QÁzÿ@B?H„Ø—A`å$'€ÀاHî°¤@E  r¿)L@Ú%W€aÛ’À´âpB›qlÀm°?ªro@€dmË;l9@]SpÆti@("AëÚ9@ä‚69¶À«@—•w‹WdÀBÀš?lÕÀñžãf ó†@$}O3f@0­êéýq@à°ö§ãLC@=݃ã$@K›­ÂÄõ?éÙN`œí@çž*Ìó§Á(ѯ½¿ÊÀw0õ¨á«eÀ…à—ØæxB@ê§W›;A@O ip˜Ê@`å$'€Àn¼ï=اAßOˆ×,l@‹AˆµÃ,@9$`£}À7jáe<¬@ÒÉÿ7åh5@+ø±C#O@w† ôT1@6U ~š@¥S(Ø(ßÀ NÀ@®A˜•w‹Wd@ä‚69¶À«@:¿®0Ü@ŽÑž±üçÝÀ„~³uèÜÀm¶ýæÐA"£l8‹Á2@õýTðœf>@U…ON@†É{Ó@Kî?ÌZ·¡ÀÑjýXd‘x@P£¢¼îp@`í5¦Û+…ÀfèòôZ+™ÀSyÎR8|@ÔKÅÀ3£a@ KóÁbКÀ”6ÙÕU±À2ÇsE×WÀÁí§äâó¿sðpå( Àê&HSmmë¿âBÙäQå!À}׎Yú￯Mœuºò¿4 pߣð¿Y#Ñ&õHÀX1{’ûgÀsçØBU2‡@éMîÚFõ¿, ‹n›•¢@-Ç‘˜úˆÀÏO6Ñt£Àôl¿t\T@a»¾{w÷r@ÀäÔðs'W@p‚ìps@Üɋܥ @DÄe„$@¢™K|Î]@ã ô"ê/=@Å2b˜Å @ÕÆõˆ‹@,R¦# @Y¹»Š @ᤔU¦ƒ@޲ ¦ý¢À|<|O/Y@-Ç‘˜úˆÀÍ _RB²@k÷РgÑS@Ôš£3R¥À—IÃ@ÊÒV@äE ¶ÁÜ;@ze$1x2J@³ÖX÷\eÀÑjýXd‘x@C£Ñbl@<ÀÄUé‘À%Ø5¼aÀ%óJ3ÅeÀk/šëÏÀ@P£Ñbl@±d˜§ £@J3¬`ÀçüsÛÜ-‡Àj8±IÎÀ„íJ0=ÀýŽ_BÑÐ@á˜mª˜ê@:|ZPÞÛ.À†&âßÀäAëïg:c@ž†ò©¬DÀÕÏ¡GJj @†ê¡ß6ÀµXÚÕ!Æ@ÃЇ*ÀøÌ²i”åbÀü O)°=8@ÓÄh#Å@e¼ =³™ÀŠR®FJ÷?e¬àvœ!ÀPêDÍöö@#2¸$Ïe@{Vã–9ùÀQe¤ÿä_,À+ÝC¼æ$W@ä\ ­ÀóSÀ»x±«¹}@Ž6ðyÀ,Þ"ÓOŸ9@ž†ò©¬DÀ³Ç Ì·"x@ß[¹µ·6À‹äo¹ç…`@…ÇÀ2©*ÀV’ÜßMåS@ü O)°=8@³&Bæ×rÀ<§/µ')ÀLÍÈmFóC@ç}ëµw!À—Q²jBJ@ìÛë¦K8u@êÐÖÍïŽÀ²ExœÑgÀö§N"¹DZ@&r_3ûžbÀ^<Æ„^¨‹@êÐÖÍïŽÀº.JdÕ¦·@ÂKd6Z@„–ÓÆèˆÀ§«L©‹@‹.°Š´À²ExœÑgÀÂKd6Z@ép0h;Ü‹@4̃N™ÀLƒû“§1@«(Ì›8ZÀh?o¢UÀèûmü +@X"ÃÛ¶b†À^×Á᪙@ö§N"¹DZ@„–ÓÆèˆÀ4̃N™À‰ª¹ L®@ö§N"¹DZÀ½ÃNÀОFV…˜À$Eý6ÿX@_€Ä>Ÿ@ÐЭžƒr@@Ú³^CÞœ@ï´»ès@E´vwHŠ«@:–c<ó†@x¶µ!ñ‘²@ÈG…n)iŠ@z'Ñ™CÀ!á¬Fðk@s%KH[y§ÀG\¤i›Š¼ÀZ/¬º%p@ÅšÔ=@µ«)O1Pp@o¶A¦à@çÅ%?Zx@g.•hÔÇK@+ÿRÌ>ÃNÀņ³E´Á@»µ—¬£Z@µ ë.Š À~%©A÷•u@6ž|øJ•I@?hDòs@÷†U5‚K@Ü…ŽËƒ@ĉíý¶_@IÄxX©‰@ x"Y?b@®B<êZàÀœÓÏcuÀŸ~êß@bP¾³Ð‡@ùuZ‚g)n@|JåH/@Al4í.µÀÛ(dWÈgÀÓuŒó œ@DU‘B pÀÙÐÍHèu@pp¦Ñ[¨I@Ç×Ç ®@¦¢Çפ–Àœ 0GxhuÀÝêž̾ÞÀbP¾³Ð‡@œ÷K#W°Û@|JåH/ÀúuZ‚g)n@U?d+£S‚ÀåÎéŒô¨ÀDU‘B p@ÓuŒó œ@pp¦Ñ[¨IÀÙÐÍHèu@x£Çפ–@Ç×Ç ®@Fˆtç3ûƒ@þCeÕKøò?÷Ïp_ÈÖ@ð24œ&å¤@ÆÈ¬ êÔÀ´oÉašÀÒ¤› ãh@_ …º†Àý+_H›¥À:}n›pÀìCeÕKøò¿Eˆtç3ûƒ@ð24œ&å¤@Xg÷^"=¾@š¯æ7=“À@qñÈ\pÆÀž»´HBª’ÀÊãLê°@a…^“>XpÀaÕcÙü“ÀŒl1›F¥ÀŒ]2ñ_…ÀK_™f‡‡–@èÇ|áÏl@Å Pc3ËlÀÓêÜÏF@̮̊x—@qõÄ{ï}@uèXÂ1E#@-Å[­\>Àž(A2nÑ„À×"è2%ˆÀèÇ|áÏl@äe‘QÕ‡@€KÔ@_òIÙŽoÀ»¤Î¸}@îL£4þób@ˆZR¡ÉGÀÄ¢Ú½b@k.µDz%ƒ@ cÜà:DoÀ§µpd¶F@¹ö§/ÑjÀ°„Õæl@„0ê_ˆÀ2e„»]£‡Ày2“~¡ê“@Ö1ê,ä«_ÀMø1o¿>À cÜà:DoÀ葪@·FP×ÕœTÀiãñzVx@þE§@†yÀ1Å][–@°iªˆ@Kƒ'qAª¤À{p!>ÀÁ¥ :÷UÀþÿļ¦Áé—]•Ë–ÀÌÊy³E§@.Þ‰?Àd4FdÊ¿‹Ÿ7(E§ÀÌ‹p‹Ô¼¦AÊl eêÝ(ÀoùiˆäÈD@˜ºOµ¿Z¼ÔB§`Àt€©î(@ôp4ÁÑâ@ä°…Ì%аÁ´Ž€K“¿?x§ä5×À`ð¼ÿrA7">À0sq‚<ÉÕ@Êl eêÝ(Àc‰óˆ¨œ±A ˜ºOµ?oùiˆäÈD@©>Á‚l½(@Ïtƒ©eÀ÷SŸ›l>ÂÀSU\Fò@WBdÕ9·À/¼ý€¾í@_ölW´ÅÀDçr\ÉÈû@Žo¨V·ÇÀ|HÇváâ÷@#@çzµÆ@+Þ-÷Ÿ›@¬Š{L¦‘@žybÊQnv@؃X èéÈÀ›¨mÅ´ À+Þ-÷Ÿ›@ËÆF©º@¹6¨,‘v@K¬¸V£®\@íõ|+¢ ÀòªA{~wºÀ”[v3áÀ¸¾iïŠÄÀ`¨_ÁSOâ@Í(LºÃ@˜áÒÕî­Àp)½…–™è¹3•@ýÎÈåNz@¡'¤ž…ÄÀCK帾¥¨ÀÍ(LºÃ@Á“Œëκ@‰a¹§±¿ƒ²BŒ}î­À…}Eqy@0ŽÅ4_@‰,ÎÞùð@ f„úÿåÅ?SÃÌÇÑàæÀ ¹R:†@+ŸëC¾ÒÀŸ¼”e¡:†À f„úÿåÅ?Õƒz¼îð@„ðì‚7;†ÀBû½àæÀ5Hí"Ù9†@å/ÍÁ+¾ÒÀõK¸…Ê-ÇÀÐáR±,(@¢!k0øLGÀݲQÙ:ö?A±yóJ!À©–¤’#’@¨Û„1pwv@@oˆpü?„Tþ%ÀU¿vÙÓ[ØÀ£ß<˜bΑÀf=(âã@@y®Ê‚@¨@ÝÉd•2!ÅÀö”q¼Ç@¹úµ{“½@AÒÔz²@¡@CFÌÊ› ø?þî&ñfÀž’­’vp@["Y.»ŠÀšý°ÈÀ¥qËçÁ«ÀÜ™sû?Ó7 µ žÀ×4WA“ÈÞPa €ÀýMlã +Ÿ@Û›&j^¼MÀžÉpý¶!w@¬¥[^+hv@wû¬ÔrÁ[@¸xô“gSÀ¿fû™T?|@w5§:¿µg@6›¶ÔÀ@y®Ê‚@¨@¯Ó lº×@þ=5ÈïÀâÁªÌâ‹ÁÍØZßûD¢@DR?/{P…@˜­Ð[PÀŒ>ÈÄÆt@0ÃQȱŠÀEÔóŽŽ¥@ ð![™ŠªÀÁúûìlk–À¹ß†¾RÀÜ(Hœêl@PW0•„ý—Áíf]H?«·@+à5¹h©À¢ðÐ×aÀš›Ýq! ÀËj$¶I@©iz|j–ZÀ÷÷gî†b@4œE…²@zà6Îr–@ÝÉd•2!ÅÀþ=5ÈïÀs*ýµ Ø—A@.Ž¥C}9@T¯’# @ÓêÜÏF@_òIÙŽoÀT,Aƒ¾jSÀ@‹Œ‹Âà’@6ô3—®G@i.­¶åŽÀe|ðRb‘âÀúY*^—¬ÇÀ̮̊x—@»¤Î¸}@sWûô¦Ð Aò àImÑ@ 'Cvi Áqî± ²À4,"kšm|@a<\S^–À±š0è9ÒÇÀô I_®ÀqõÄ{ï}@îL£4þób@ò àImÑ@K÷$º0µAôµ)©›m²ÀÒéí ËÁ¯my$–À—{ÎæU±@g²w¯G2@üî¯QF@\YxŒî-@cÆ%œé@oùiˆäÈD@ ˜ºOµ?Z<†b¹W@\“*2@væD^Àç¦Y[Ê߯¿¼€Pü°A@•—jn°Ý@¶³·"“i@©®êTÕÔ8@rkkÒÃqÀI–SÒZDÀªg¥U¤@±“ÂÎî?=C[wC‰@ŒÁ,# ©è?˜ºOµ¿oùiˆäÈD@\“*2@F8ÙZìOT@¦˜ºOµ?|²8TR^À¼êÒtké%@p˜œ7ý?Qp|P6ûN@ËwòQÁ@…ÐQÖ¿VÀšrì/ûv)ÀÛ%˜}ÅÆÀ”Ö“Þƒ –@C¦5PÍÝG@Á^‚aÀ9goa@Õ§§‰À®÷Ïl(äŽ@$\Dy‰f@\(6¬Æ@dØÜÿÎú”@¿çÙž¿=@ħéáãyÀÙa{L¯$@=æ¬Ò¯zÀÅ)Œÿ¹ìL@£¢é!PgÀò¼½øL@³ÚÏBb«tÀYÃ5¤„@04Íi@ª¶É×ãÀM¡4xˆÀ?sM wŒ@Uæ 3aÓÀüùì qÀe Ò?‰@|ػ̔C‰À]⌙¯ò²@³Ë©6”5—@—±>¢¼îp@dØÜÿÎú”@Nárìl¹@þPUœm@ÀGPÕ°—£@F¹‡,ŽNÀ„ûVäÿµ£@ñûØyf]uÀe85˜G8‘@xƒ]C¯tÀƒ„(шž@Ƹ[u@|SYi’bs@ËŠe6@„@6:Ø^E,K@Zµ?±/Š„À7YA{I@RÍs‰¯7ÀgC­…È™À“–œ¥­â¿;ž ÷OÀ6:Ø^E,K@Tµ©f>j @5H€Å=ÀÅÔ(]™¢7ÀÌésaS@ÜÞ†^Ç¥?–ÿnè™À<ÿúš®J@Zµ?±/Š„À5H€Å=À ‡ã#¡@ò³t/h]@ qpzB@Ö<›@Pƒ„À²ÐSä@HÒx³öãÀÐ- §+šN@ÜŠx¬±ZhÀ3tØy{†@J–ú{LMÀßBwæ8“lÀ—å Õ(:FÀ&+fûîfB@…ÇŠ^ '@Gw®*Gr@‘bÑ*+ÁcªD™…íAÊÐ7®mÀ¿ò{2‡@J–ú{LMÀp]?÷ Œ@ñ;zECÀÐm·)F[ÀÇßY–;®@%ye“Žpœ@w³g<Ð@e,ƒ{°@·á€ÙÛÒÀO±ù‡u´Àí\Z ’Àž×)‰À¤x7?SÁž@Ñ…²¯,•Àe,ƒ{°@ݯ©\»@úÈû·FŒ¶ÀKy-AL´ÀJ4-ùyÀzÕ²:3Z|Àƒ!„íÕÇ@ò1^+)µ @á¦UÝTÀ­_o82÷@4¦GJü|@Ê{Âcc¼UÀ&ÿ«ùɉoÀói"™æÂE@ßè• )€j@ÝPŸaº P@v±,®o©\@ä3M"(4@:Ì]Oþ W@Yiqš²¶2@„ÈÝŒKžT@𵯺r*3@ì¹ñRéÜÀñ/kf3ˆwÀªô”ÎIÍÜ@Ê{Âcc¼UÀâ(˜ïùi†@LÜXjÒ¼E@HG`(…«wÀèU17ÕsP@žòôo¥4@™3SËA@ºý ÷@aªG^•œ<@Îâ]s<@û,â™9@q xR,Ì@‹^Ê>×À"ä ´]´À¬ùáwñµå@¢Ë¸Žæ½@CheÑ-ÔÀUâ¯å£À×›`6c´À?᜙¢÷ÄÀ¢Ë¸Žæ½@ÆÕþ`1³Ø@U_°°£À߃PnÌÀ)¿1çÁ‹@†‹ù8J¦œÀQøÙúÞñÄ@Ψ µ¶À7ÔN¼¬ÀØ\ëê‘T’@Œ5 ±Ù™@ʤßÿcõ¿ »†÷áÂÀ+èUùÝ›¸@@F{€3µÀ•Ji$•âÅ@Ψ µ¶ÀŽ˜Ïr“{å@EüpŸ’@'Uv*›cÄÀ¥ßÿcõ?Œ5 ±Ù™@aÒ ë6HÃ@ØÛŒã#ªæÀ3;vr´„´À`í5¦Û+…ÀSÃÌÇÑàæÀ„ðì‚7;†À_0] ­ã@úQ"ÝÌço@VÀlÌ¢@Ó!çmcz@ÔhÉ*ŠÂ@¹R:†@oá“ ¾„ÀfèòôZ+™À ¹R:†@Bû½àæÀúQ"ÝÌço@/°06vþâ@ã™–¨/ˆy@ŠTЉ R@¹R:†ÀÔhÉ*ŠÂ@l”¨t‘\@+ °ÑÝ/†ÀÄUövíî @0Ÿ~à&8@‘£§6§„˜ÀÖkDÁQ…PÀz"93†À¯ ô%€‡@§þó(„À §§Šë¯@0Ÿ~à&8@‚ßš¦‹Ÿ@‰ðøœìQÀ;(Û[ŽZ’À¾A™Ü7˜…@-AÃ}FA³ÀsëubÁc@ I؉۳:@.¦lDu@§¸Ú@±GÀâ±›1¦Jy@b¥´š› l@Þ̺)øÈŠÀ]‚Ê<³á*Ëì¿ÎÐ ø…\X@öû¬ãÀÁ«~¥!j@"4E‚*>@툲ÕýŒj@27âO<@woV®r$:@9<­¶L@§¸Ú@±GÀ(>š•D¿‚@ð¬,UQ@&&ÎÚù8C@ÅaÝŸSÀÄm,^p{ÀwcÚĈí?ԃعtm@ów?J›&À&õcF¡T@ygœÏ"@»ŠI¥K’šÀfÙü+DõT@×X LÈ@˜Ì>á*Ëì?Y¼(á P@ôû¬ã@ÍÐ ø…\X@$4E‚*>ÀÁ«~¥!j@ 27âO<À툲ÕýŒj@I{÷ÞÁj@€ àèºB@â±›1¦Jy@ð¬,UQ@1 ußnu«@\~òÓ@îcÛ6–ªÀ%zÊ(jÀ1$ÓæªÒ†À¥ÝsŠ`Às#ëÚ½¬]@j2>¸Å4@b¥´š› l@&&ÎÚù8C@\~òÓ@æ¨Ýcõ @fZl•j"”ÀCdJœJý™ÀÓV[|Nh`ÀHlˆíë¶ÀR÷'ŸâÀd@¦]¼(=@$® …½ÀLâ*ï¢ÞœÀ.ýiĈ@ ðù¿=5@$Ú2éè,·@Nùðåw|š@áƒr Í S@Ë_Ê5å7@Þ̺)øÈŠÀÅaÝŸSÀîcÛ6–ªÀfZl•j"”À±‰´Yö³±@¾f Õ–@%‚U “@î%š„1ÀÐ*Ð0u@ ‰jä?§À =@[Ž5¶]@ö®úîFx•ÀéÅüxÀ bd} Î`@gّټ @ÿ p 9@HÂíSŠr@n…ÓAR§*@(ù¨ º@]‚Ê<³ÙÀÛøCR 0@ÚUéžÜ(XÀ30<Í2À@|U­÷í¤@ç%{æ~"@!Ÿ»ÂÞDKÀ§B)«ÑØ8@9ðŽþKÅSÀv³SâÚT@ß*¨<.pÀ=àéP~õv@×^Z 3ôÀ4:ôiM™¢ÀCñãÖ«‡Àk–á*—aÀÎ Ù¡)Âó@ÑY=MIÀÛÅlƒèr@|U­÷í¤@ 4ç"@bÕE<À 2s€We@Ûšm9rSÀŒ ¸âUòn@ÿ;çjRpÀ¡þû]ÀS‰@ý¹Nn°¡®@ð°|‹F8“@ÁpáÚ+ù@ï5œY¶@wº^-ÕÀyÆ*?ˤÀ=|Œè&±@í‚æ§ºF†@Ž.µ~ìõÀê+ºýµŠ³Àì¡ÏrŸÕ†@t ‚þ®§l@ï5œY¶@ß©Pðñ@jEã¡€°¡Àêç€iÃÀŠÂÚ"‰m‰@Èà ›`@ò˜ù@Á‰³Àz Ÿ¾3ïÀÆyØo_¨Î@èÛ°]@kµoóŠÔâÀóe#_ÀŸƒgü’Àdô¨·´Æ¿ågk5¦„×@0ª@W_Õ?çÛ°]ÀÆyØo_¨Î@Ùu/Ñ[@rönÔâÀºû¨·´Æ¿à_0ù’À0ª@W_Õ?—,çÙS„×@Áï§ +@†Ñ,¦žÇEÀ%%Íþí‚À§ÍmØôŠ@ÈCÆ=1@Àã_fбHÀ‚è_~µH@aîˆrÀÅ)Œÿ¹ìL@ñûØyf]uÀæ~ü7@¸ëO ´bÀ §ÖßRâ @ æ‰Q$GcÀ&ÿ«ùɉoÀLÜXjÒ¼E@3tL_h°…@R™«n×P@w»õãí:4@£Ž^Ý]Àòi"™æÂEÀš¸©¡†a@°À ?‹z@NûU]üb®ÀîãCêÊKÀ‘žØ÷Pçc@¼÷päGêcÀ™s©Ökß@£¢é!PgÀe85˜G8‘@åYÞ«jæÀ¤Ô,8&~@£¬¾Ë(À(Jp‹X@ói"™æÂE@HG`(…«wÀR™«n×P@rêf,,@n¹»¼)NPÀM6›Üx@˜xЕÜVµÀ&Ûvª}À-a;Ž£gþÀÓmpæ}ÐÁ@ÂÅùiLMNAï?i¤«}@ìÄNìXMÁ¹½Qß„#B±@T hŸÐÁÀh¸íhª}À )qÝQ¦Àäê·yj Ì@ë_ЈHÁï?i¤«}@®×R5HNAµ;±³¿;±»XMÁäê·yj ÌÀ‰4)ŽóÜ@7ÔN¼¬ÀEüpŸ’@Ճعtm@wcÚĈí?ì‘çUÃ@̡йŠÀÿ©'‚'@U|¤ËWS@¥Ï ÍÀ«ùÞ¦ûœw@â+¶Ã@š­@Ò†#´“ø€À=—ŠÔ¯z@ƺ׿ˆCÀu¸b“PIY@=¢y©äPƒÀâ€ØD„@Z •ÛH-8Àø:«l^¹•@¡lbAB²i@ÈRjK–@åÃÓ}>h@Ø\ëê‘T’@'Uv*›cÄÀcÚĈí¿ÔƒØ¹tm@̡йŠÀÎ;Ü^ªÌ@U|¤ËWSÀÿ©'‚'@ªs¶z¹Bd@ñÐŽ¡¸ ÐÀÒ†#´“ø€@ã+¶Ã@š­@¾º×¿ˆC@=—ŠÔ¯z@pÎÓ¦‚À-­·}¬@Y •ÛH-8@â€ØD„@¡lbAB²iÀø:«l^¹•@åÃÓ}>hÀÇRjK–@Øê-¦ºÈÀFƒyp›)@–‘«éÛHÀÞ+Pnu·÷?Ê-´s"À8švWþ?§"˜‡&ÀCFÌÊ› ø?˜­Ð[PÀá uTí±6ÀNÊÓCk É@ìÄNìXMÁµ;±³¿à‡²†XMAóï­*"’0À)68&àü?ÁÁ¸ù(Àº\CuÝóï@(vÊñŠPÀÇãÙ.lp@õsú¸ö¤ÀÍ,ì¦ÖG@ª[J0š#ÀêzÛhHM@þî&ñfÀŒ>ÈÄÆt@óI| S]@ï6.ðÀ¹½;±»XMÁóï­*"’0À§ß>0XMAk¬Æ` §"À7n’ÙËÌ=@&õcF¡T@ów?J›&Àÿ©'‚'@U|¤ËWSÀ^A/áâÛ@ýƒÙò‰Žh@]‹Hޏ°À/÷K¾˜)z@{Šý1uM”@2KN,wÀ+c@[U§b@+Û˜“6Àì¯Ë:l@NUyú ;DÀ'z¿C¨À;)  ¾TÀ¢»;ù @Ñ4°/Ô @Kêi¼Ÿ@¡Ó/Èÿœ)@7¯²€@â³I>h%ý¿ów?J›&@&õcF¡T@U|¤ËWS@ÿ©'‚'@ýƒÙò‰Žh@Bc×%5*•@Ñmšðm„ÀѦЯ­À2KN,w@{Šý1uM”@+Û˜“6@+c@[U§b@OUyú ;D@ë¯Ë:l@Átm:iŒLÀGâ€õ¶¦À×4°/Ô À¢»;ù @»Ó/Èÿœ)ÀKêi¼Ÿ@(´I>h%ý?7¯²€@>CZº½“'@àr3ÁƒÖQÀƒ_Ž|©Ï@ËIi®í³@]5³¨@®cGäaºa@Œ5 ±Ù™@¥ßÿcõ?<’ òžš—ÀygœÏ"@%‚U “@Àa)y31À¥Ï ÍÀªs¶z¹Bd@]‹Hޏ°ÀÑmšðm„Àç‡þ ä€ó@PljYlzÀ¾|ô[fàÀÈ"soA©@3æJoöV¦Àäú88‚ÔV@€yÓ¶À ðBçt¡{@„g•¢ÿˆk@àAó¹…Q@€9Šç ÉÙÀì ®Œð·À­3ÂW-OÇÀÚcÄž À¦åy'žRÀÂZ ñ+|@ ægÅs|´@¯"¹<’à™@¯cGäaºaÀ]5³¨@ʤßÿcõ¿Œ5 ±Ù™@þ ñalJ@»ŠI¥K’šÀî%š„1Àƒ¯¬è¾åX@«ùÞ¦ûœw@ñÐŽ¡¸ ÐÀ/÷K¾˜)z@ѦЯ­ÀPljYlzÀG«ªëD|ô@¾£ùwW©À¿9•¥ÈfàÀv 9‘Ó5X@dÑu«À‚~l“g‘@jIgVÂÀ¹½¶†œwQ@xñ\N$;6@:ºâ›ÞϪÀª/ŒŒÉÀ <ý-)GÀןœ4‡¾À–&3 'hÀqÄTÄ@GïÍœS8@Ä^ôdl–@ZÁêìB@ŸvU§¼œ’@¶ä³Ìš6@|]Ò$ª@zöŠÔçî@LNÇHÐÀGïÍœS8ÀqÄTÄ@YÁêìBÀÅ^ôdl–@µä³Ìš6À›˜¼O†@{öŠÔçîÀ|]Ò$ª@Z¼ÔB§`À©>Á‚l½(@væD^À¦˜ºOµ?,\÷Gå±o@x ›V*“(Àt€©î(@Ïtƒ©eÀç¦Y[Ê߯¿|²8TR^Àx ›V*“(ÀèFÇòr@§KRJèE—À#þ³+ÑvÀÄ8_×ðiÀhÞ_Y„@…–™è¹3•@…}Eqy@êðk6%Au@ÐWfü§…À:äýÜd…wÀ^rKë­awÀnâj„@š)aa‡ ÀýÎÈåNz@0ŽÅ4_@ÐWfü§…À9D\Àóô¡@259°ƒ´À(á ý@P@s|ª^˜@ï¶Ê”2î@X¼(á P@˜Ì>á*Ëì?=—ŠÔ¯z@¾º×¿ˆC@+c@[U§b@+Û˜“6@3æJoöV¦Àv 9‘Ó5X@kgŒ¼¢$@‘_E ä-aÀ,±ÒçmÆ®@¿ñÃt­tdÀALt0f@h^óÅ0ÀÅ”·Ÿw@O~†²æM@4yÑ6*x@Ÿ~Ê YL@nÔ`"'T@?9H#^9¶Àô¶Ê”2îÀs|ª^˜@¨Ì>á*Ëì¿Y¼(á P@ƺ׿ˆCÀ=—ŠÔ¯z@+Û˜“6À+c@[U§b@äú88‚ÔV@dÑu«À’_E ä-a@kgŒ¼¢$@¿ñÃt­tdÀ·¹F>³@h^óÅ0@ALt0f@O~†²æMÀÅ”·Ÿw@ ~Ê YLÀ4yÑ6*x@ŽÆØ_ÿZaÀV~ñýê8c@–Ï?ßµC'@tíäÄžNÀ ïÂ|ÖGÀÓŸ£çúS@Žòò1'c@|­GU tZÀK–¼w=5@šÌßqo¤PÀ10¥4Pgc@_í¼R‚ÀUj‘¬ÙÚBÀ¨ {üÐh@)23Î)L@‹ θrÀ|­GU tZÀ„b¿Ó|@Ï–GW QÀì×ÊÖj@‡]ÀqµÕÀ*R;9Ðn•À8À6‰e@ކŒ#["†À!Ø£ÍR@Ã.¡ÛyÀ¯ªi”Ð@•WãŒpµ@V¿Õûˆ¶AÈgE²ÊßœÀEª:ÃÍÀ«2CÆÙ‰ž@ùR«½55R@Á©ws¥˜{Àl‹[Ðö™@«ýÈf@P õb@o«†ÈÂMˆÀ™ÏÅýqÒÀwj›ÐͶŸ@…WªÀ¢×ÓÀE½/ó£@#çæI×jL@¡3ö“[xÀÈ !*ÃÀ–¨ÎõŽ}}@ |½VlqÖÀ;ÿ–ª^hœ@cQ:SoµêÀ§:×À_óÀÀôy!AQ—¤@~G|nƒÀ×Àb„ìÏŸ€À+ÏÁy¡@)çýzÀŸaÀõç÷¡@àê{†H…´@ÖãO³`\›@ÈgE²ÊßœÀÃAŒ@A ŸïÀ†žÀÐ)e5ô6ÍÀÞ¡“î&¾zÀªàË€D¤@¬ýÈfÀl‹[Ðö™@_^t•ŠÀ¹°bžq±@ÄÄyy„ø„@"á5 ÚÀ%hý€À]e[’(äÛÀ剿»~À3âPÃéWª@ XŠ÷ÎäQ@iw;6âÅÀH:ûäåƒ@2}ô.éÜÀUºÐêáŸÀUôj)ãÀíåƒ$h@Nž NÛ™@hæk4ö¡@Eª:ÃÍÀ ŸïÀ†žÀ[H°±NÌ@žøEËmv…@c.!Î9š@Kzdº@@@°ÿËRÉÀ¨þ'àõÀLã‡IOí™@BØÐo@€ÂcZÙ˜@›AZ®c@–sßù"ðŠ@Å_}GX;b@°! ÌfY›@¥êŲ±5q@ÑàiN~À¤@ÞùFÀ·ëˆ@!—‚Ÿe8@hæk4ö¡ÀNž NÛ™@«2CÆÙ‰ž@Ð)e5ô6ÍÀžøEËmv…@f£O^}Á@Tz¼z€j@§"ßãç@æ¡âœoŒÀIí?F±ÀBØÐoÀKã‡IOí™@›AZ®cÀ€ÂcZÙ˜@Å_}GX;bÀ–sßù"ðŠ@¥êŲ±5qÀ°! ÌfY›@ÞùFÀ·ëˆÀÑàiN~À¤@ Ý0aäQÀuó/§+6ÀµÌCŸt~@-«£6@mÕ?SûyÀ@Üa@TLüX„݉Àô ‰ºo×gÀJ{»±½‘@x$A= Aßè• )€j@èU17ÕsP@w'bì@_Uí)PÀA.*Ôp@w—ÂîœG@ ÔÑ´ñk@QUÆ®„ùE@C…›u6h@ïâ°vpF@b'KÜw2ñÀaTϺ햄Àø$ŽùHÙTÀP\n@ËWYЈÀØÎ Cœ²@vBWf'‘@ c:x‡¹À‚·8ñ@ÝPŸaº P@žòôo¥4@_Uí)PÀc3Zž"@5”Ú%U@¯Y©¾ -@ŠebQúP@\¶ËSy“+@Î8ÒÏüaN@Ãüž >,@Ã)R7M‹@Œ±WuÒ JÀ‚Þͯ¿>@ žTâ³XÀIOQs·À8Ûs%ùˆ@õÁ %íƒ@£ Œ?ZfÀ‹ö¿òôƒ@‹+îïzÑfÀ”X«©?ÉMÀwI‡Êäg@苾¥õv@k¨]="GÀ_M¤Ó<’@é×´»q„cÀžm6ò˜øŠ@®[9¸/–iÀÒÂ*È•@~Û(ûö?ÀŒ±WuÒ J@Ã)R7M‹@ÉT"¼¥XÀ ^!ƒÍs@¶Ä>yx½€ÀÐ'U#“j¸À£ Œ?Zf@öÁ %íƒ@‹+îïzÑf@‹ö¿òôƒ@Cå5 ßg@|"¼Ó2&ƒÀk¨]="G@苾¥õv@ê×´»q„c@`M¤Ó<’@®[9¸/–iÀ€x9E˜Ó–@‡Û(ûö?@ÓÂ*È•@” 2ÐK\@ì‰æ¬‘xZ@h\4$@´}Zq<À7ÀjœO[ÀûXÈ/~y<@!Èñª5ŸÀV_84 giÀÙ ç€Z»|@¿4Š»ˆUX@Ì…-x·jt@`€‰åZ„@@´}Zq<À7Ö˜Fm#‚@ûXÈ/~y<@zËOƒÙógÀmûáýa}À.–$ E|ÀÙÉäXía@~©ô ^>@kã,HÂ?ÀëèT` ÛX@p'^4”ï1@ø^!è¡LÀöw'â¤+@±kuVEÀ»8ŒõZY@Œ&W ¥ØsÀø^!è¡LÀì¶q©úf@~ˆïFÀhÇ]"Ù`@†`‡c@)·FÎÚ÷yÀF‹¸S@­xÔ²gÓnÀ÷x=µÆžhÀoþ‡'ȃ@gê&07@ÀÂbãOF=@)·FÎÚ÷yÀò[ÑŽs”@T]—¢ƒ£nÀœðî*¶ˆ@£d®aRƒ@ÉO+F ŸÀjä¬Ì&E@ÉÔ:š?\À¯p)領À8÷|EÞ @õ¼p ‹}@¼9sµ1SÀùR«½55R@Þ¡“î&¾zÀÔ’<ï¾@YÂÅÌv¬À™º& /§ÀТ§î¡@ ¥¢ƒl¡@ZÆ'5—ÆÀ½9sµ1S@ö¼p ‹}@Á©ws¥˜{ÀªàË€D¤@YÂÅÌv¬À‚›XxKÕ@sñÌÓ ×›@JöÏøÅüÉÀÉx“2«àÀ mäGFË•Àƒ³JbÖÀ‚OÖÁ Ÿ@û ãŽ'ËÇÀ{ðå4uÀØ’^ÄÀºKëqÚn@£ 0Ý÷@kÌ™4%xÀè]7L)@/(Ô¯ÕeÀ~D<ƒ §ÑÀëyPLŠs@ò»G]ÚR•@U>´9ŽàÀr> –½ŸÀuB“Å:ÖÀ*0pÄ@¬È l‹ÊÀKߟ3ÌwÀေCdÂÀkÌ™4%xÀ™õƒ}Jø@–ÿ÷p?!EÀ1­JMâš@!EqÝ£áx@ƒCmm•ÕÀå)Ì–ñA@ry„f´ƒlÀž²Üò†@Qy ½voÀ²>Nø|öFÀJƒŠ$)b@R‘éx…¢†ÀŸb®‘cçt@¨éKkÀ­©"›;ç•@Qy ½voÀå¥õeîâ›@WLõ¸%*b@%±dí;»|À)÷‚*qnt@T<_áL¥ÀŒ`á­f•À4]FÄR=@K–¼w=5@Ï–GW QÀˆsq—@é˜øéÈS@:0¨@dÀë¡rÍ„$À5Ëy±/@ĹrymÀ™Ú%/\@ÏÓþãÀFÏ*¤çé@¥pú;*Àâ²Þ =@S¿‚ ±–ÀšÌßqo¤PÀì×ÊÖj@é˜øéÈS@owºdý“@Ô>9ëó$À’Û¥hF`À-š¡kÀ改X’5@¼KƒšÀíÂxwÍ59@ãQ3+œ+ÀM,LPDDE@ÀüÑùvì·Á¸œ|Ã>+ä@oïRÂAÇÚ&Zð—ò@ jåW1ù@}Ï© à@·Í­ò€ò·AXìvÇ•ˆ@V.u2…°ÁÝ¡`á%öÀ\‰}TaÁÝñ"Ó˜éÜÀär´]8N@ǾgŽ2@L$nP÷Á6˜s]ùÚåÀØÒ¡!ô@g¯†ÍáË@’!ü ÁÝ{?lCò§ÁXìvÇ•ˆ@—µúZb ¨A sr….Øÿ@¡wš¾ !Á²5ñ “éÜ@Žök›OaÁ ;€U˜‹2@B|ï¶@ ¥K!Æå@æM­¡aïÁÔuGŒíAƪ6…( Á¼ëCDD¾m@yk‘€`@†ùYI[f@¬ªšÏ.tL@V.u2…°Á sr….Øÿ@L÷z[ ”Ã@›ß ‹@ù'Α2@=ñ¹ÚΔRÀNÚñÁžÎŠ@«ŽÏ!]K@æ’¯Öa@ÂÀÆ |¼š¶…@õ5;?m2Àe,z?»ÿ@òyáõ7¾ÐÀqY8`{s@îm²Á[/鿜2Dc•¾À{Ù<þ\@qþöv“¦À®R϶‰v@uÆêƒ>$N@>âAo'¨¢À&žlÎýÀH³u q¥Ñ@¶W“ªFc@Yju¶œ À¼ídˆq\@–|IjÜ­à?÷eÆ¢â?¡å!~«ÝÀéOQÕAjñ?ûÚ6K&ÀÖØ"—yó?áÄði*#À&nÆ’&eB@iV2¥lAñÀIN’Î…?žÀ†HqÉ:©?¥Q5m›Kb@ë¢f«iE¡?nœæjBl@…pJR|¬?ÜØ_’Ïtg@SU\Fò@õ5;?m2@Æ |¼š¶…@òyáõ7¾ÐÀBElÎAým²Á[/é?pY8`{s@{Ù<þ\@Q»ÊÄCËÍÀ®R϶‰v@xõáø¶ÀÚÃŒ§ØP{ÀµÓ¼cèÐ@§¾=`š³Ï@º@”\_<ÁWju¶œ @¶W“ªFc@Ž|Ijܭ࿼ídˆq\@\&UKUeÀ“¡üŽG@Ñ1×0!À`{Ç›V@¸æ+|¼È"Àl¹á£9ëR@¸AÐ{³8µ@S™ñÜ%T@ê:u:MÖª@"’ówÀ@ت÷ñ@ßÛ:+3‰t@./Í>¨óÙÀy…@éÁÈ ÀÍ,îΦèÞ@œ£„=ß´@®¬¼kèKÍÀÐyUÛD²ÀS™ñÜ%TÀ·AÐ{³8µ@äcÑɺ@a‹w©ât@²Ð¥7’t@ Ï$WnšY@²‘ xP ŸÀ‚Ô³ØöÔÀœ£„=ß´@@EÕ¸ Ï@ãŒkDC²Àðy ,ùÅ–ÀIiuÕÀëÞ;ÑÝT@õ¾^–µ+@‡·t 8ª…Àz[™Ï48×@z I = @²Ã…ßf5Àñ_îX=s2@³UoâZÀ 2VxUý?‡†_i†±ÀÕÏ¡GJj @ß[¹µ·6À¼€Pü°A@¼êÒtké%@ô虩:“@6äx=¶]@¸l<>e§@ä¦þàe2À,QöžŒ@§ÂDX\@îé®ìB@Y8–MÌr"À§R©šž ™À““!ùÖgÀéx)ëVvÿ@N_Ó_7&,@´g㸱°@O|¸¾`@Ù sÊñxÁ7 ¸Í¦3À_ê›r`@bª¾õ£[ÀV¯b/¨"„@ôô†½Ì%À[zÚUÓ¾A@†ê¡ß6À‹äo¹ç…`@•—jn°Ý@p˜œ7ý?6äx=¶]@§‘Ìá€@Û¾äøv2À¹[@Û>µ6iBc@¿ŽÕ.l3@F4ˆýk1À#À¡[¢K@dƒMÏNlÀþÐrÀ¬¯„?„ž@ÖˆËRÃÀS@ò ™«ƒô¤@Çšôçè[ÀúíyýqqÀ?¾3)…WF@ýzÏX1¸ÀŒ¹™¯í»TÀâµÇ.œ´œ@¾§Ç­Æ¼Q@ÙˆËRÃÀSÀ¬¯„?„ž@Çšôçè[ÀEká—ã©@Øsqóã8F@9Ü»5–€À8Dºýÿ$k@ä18ÙZ¬¹À¼§Ç­Æ¼QÀâµÇ.œ´œ@Vçê†ã`À[yš2›ìÀ¿úíyýqqÀØsqóã8F@ZœØ¬FÅz@°õxt¢6@<ñ”Ä’ 9À0 çÔ {k@j•ÎÉB@2;™9¾Ìv@<Ó1…Ï‘2À)ò +f@TÑZ~Ý$ÀïBåÔkÙ@*Ùš¦!]@ 6õžqÐÀIxoöööÀköp1ÖÀ#%é‰ß±gÀ\­­ !Ö@¨Œ……O@‡ÁNxÁõ?.´.ÁbçÏ@›ïûGâø@dÓºð²»9@¤ä¢ÍF}@OÔÙ©O³:@£¬ßn»·~@'î¶0ÀE|¥tŸ‘ÀÈi‚©³A@×Üäç¹Ý–@]£[^ @Á =zýR@ÒCéRúK&@LÝJh«>PÀøcßék°Àl"µ͇wÀWBP|¡3”@Ø"öÕÄ|^Àç¸^l–ñ?ü- ¢ ÀµXÚÕ!Æ@…ÇÀ2©*À¸l<>e§@Û¾äøv2À¯/+†‚Û@Ÿ¨!®@5¦ž ?ü€@ÊëÔ6¿4ZÀ)±_x@FúÚ!‹+€ÀÐêë§© ÀØ"öÕÄ|^@WBP|¡3”@íüæÝ?ÀÂ÷[à^5@ÃЇ*ÀV’ÜßMåS@ä¦þàe2À¹[@Ÿ¨!®@G< n›FÈ@ªíÌÿvÀ­YØú{•@-º—Ò¾â¿)±_Ÿo&—@»êæPïô\À&©×Àèc?Û{À´4-Ù*Î@Æü#©‡`@‡#1WØz”@$¿òD;â@ɨ{ná$Àn`5=V±¢@öÜÖq@ójÿÊæ«@)Ÿ[EQÀ[¬àBÇÀpeêÇÏ €ÀY´íµY½ÀãÁ0Õ¯—@ÑšLÌU Í@»êæPïô\@eZ>Ÿo&—@h}[kÌoÀAÊòBO‡ÓÀÊü#©‡`Àµ4-Ù*Î@¿òD;âÀ†#1WØz”@è0€·ŒlßÀ0ôÒÝìÁ@†w-›'Û@‰\êzÂÀÉB8Ó—Ñ·@œ,MÙщ@åOæT›ˆ@ú8&$®l À¦&µ‚ú‡@&MИœópÀTìö<¡©ÀSü’­Þœœ@D§½XŠ ÄÀVW¬ÞÀ‰\êzÂ@†w-›'Û@œ,MÙщ@,+³ö`\¯@ÝðËÓ&YÀ<Æl‰Æº@&MИœóp@¦&µ‚ú‡@Öjô˜ªP‡@w¼„TvÀÀÒ¤› ãh@ž»´HBª’ÀØô“·ÉƒÀUS ¥@Hj ‘Ýà@Ù¿èZ¿–˜Àw&/M§àÀ Ÿ2»“÷¿_ …º†ÀÊãLê°@D£^Îî¡@Š å¹K™ÃÀÙ¿èZ¿–˜À3orÜ€pã@øA=ÎϱI§àÀãßp‘A SÅnû„@n ’yØÁÚᨛ“Àý+_H›¥Àa…^“>XpÀÈyaG1€”@ M× —Uk@e…oÂÇ¿¹@hèM•ånr@W©ää,t @.vÉ·´t@kÿæÈð@èou2s‡\@'ç26Ã+ðÀ窣a®À:}n›pÀaÕcÙü“ÀÈÈ9dÎk@0Û{íÞ_B@hèM•ånr@üèÙíû'³@° ˜:_v@X.}ßK'L@¼¼u‡„@jÛô’}r@=ÎL‹¹ZÁÀFÏJ¨òá¦À£Hàm+À@“ P¤@(JŒžhÒ1Às\Û  À6³vLüFj@§eV‹ùªW@ŒÊv°6¦Àe·ˆ\,JÀ“ P¤@Ü–%¹)kŠ@s\Û  ÀWX¹ü¿—$£¥ýÀoù³EYÀúŽV;WŠ@²shÀ;èÀОFV…˜À»µ—¬£Z@yŒŽ®uý@v±,®o©\@™3SËA@A.*Ôp@5”Ú%U@&zF¸JÀ‹@“ÚÊÍdÀIÉ!\ÝC]@³õý^MÄ7@ˆëÅ/Z@tÃãNW8@ª;T£Ò´ÔÀ‰"ÉŒƒ"ÀÄshÀ;è@úŽV;WŠ@$Eý6ÿX@µ ë.Š ÀMÖÔünªÔ@ä3M"(4@ºý ÷@w—ÂîœG@¯Y©¾ -@“ÚÊÍdÀnŸ'Ä_œ@Cá·|‡4@LXCµ¬@ÚpÑ^2@bh-W7@ŒÞŸ9ï0ÐÀúë½µQEã@ »†÷áÂÀaÒ ë6HÃ@Qß„#B±@äê·yj ÌÀu¸b“PIY@pÎÓ¦‚À‰Êˆ#8Õ@èHËççÉàÀ€z`‚×wâ@É9ú &´õÀ+èUùÝ›¸@ØÛŒã#ªæÀT hŸÐÁÀ‰4)ŽóÜ@=¢y©äPƒÀ-­·}¬@èHËççÉàÀ ¿½Ã•èø@QsK–ÌÜÀ€öÁ°Å«ÀÂDÞÙü—@íŸß¬7¨B@Ú«¬ï;˜@¿ŽuÕŽ:@)Há. â@lË¡A` ©Àù.4)Õ¼àÀkæÉLÂ@_€Ä>Ÿ@~%©A÷•u@P õb@_^t•ŠÀtseÀ ð@ÆùM˜Â¶ÀLpÉ5¡@>‹Éë-ot@(È…ÿBD¬@!|ïÔ7އ@BÖäRAµ@ ±XKð¢Àf$cìNÒÀÔÊÀ3³@Ϙ•÷ ±ÀàNÎNÙ·Àϲ nl@üÙgó@Eœ¿4иl@7–ªày@>ìQF0ÓšÀ‘X91ÇÂ@BâuÄÉ[À@7š ]½ïÀÐЭžƒr@6ž|øJ•I@o«†ÈÂMˆÀ¹°bžq±@ÆùM˜Â¶À·™†‘Îõ@‚U*wðŽq@\úµ’ê7H@€Ý³'À€@Ñ*qÖìê[@Æþ:ŒŽÀ¸ô«c¢‰Ã@CAÔw®¬@­ûjÂäÀS‰ÖœÀŸ.~¼–@a»¾{w÷r@—IÃ@ÊÒV@<ÀÄUé‘ÀJ3¬`Àž’­’vp@0ÃQȱŠÀéeþ½¹Õ¢@(õÀ}£;€À{x†î½,–@·ŠHõ\·ÀÀäÔðs'W@äE ¶ÁÜ;@%Ø5¼aÀçüsÛÜ-‡À["Y.»ŠÀEÔóŽŽ¥@(õÀ}£;€Àþ…R¬º®@ Vdt:ŠóÀîØJOImØÀ·á€ÙÛÒÀúÈû·FŒ¶ÀЯ8îÜ"ø@¯&C¾w±Ý@"©0æS~@Kœ½2¸w@8²©Óü¾ØÀï÷¼rqï¾ÀO±ù‡u´ÀKy-AL´À¯&C¾w±Ý@v|OËZÉ@Dî׉se@bU.øÆ`@tÔfŽN˜ÓÀ”ÓQúø§À(ù(Ÿ'*–@®úæB;=A@ýÃprd–@ÂÈäÒ!Š8@§ÐSPƒ @îO§s@@Ú³^CÞœ@?hDòs@‘£§6§„˜À‰ðøœìQÀLpÉ5¡@‚U*wðŽq@I:Æ¿‡²@Ue'ÚÖ…@~fVÓPª@¾ªrîÃ…@‹¦`¤…œ±@-ç¥Ç ‰@ F::•œt@ëm1óhÿ?Í—@ «ÀUJ¾º‡€À½í¼k’n@[ÕËA7Ç@È]¤KÒân@»âþAì@³¾gÇÆv@le]ºqLJ@ï´»ès@÷†U5‚K@ÖkDÁQ…PÀ;(Û[ŽZ’À>‹Éë-ot@\úµ’ê7H@Ue'ÚÖ…@T„Õ·u±@À‘@‚@rU•k^@¯í¦Jˆ@fÔöá&Fa@æm1óhÿ¿ F::•œt@Ò³wµg@%ýo¤=@ÇÅ›”1‹¤À*œñ]á¡wÀFADz¯Q@IzOyÕÓyÀ¼ˆ¦  ¥ÀÕü;)~Z’@ÖkƒŽ>ð³@& Ôz!kÀ‰kë³6}@@ì–wyhÀC€¤ð¬D@§$Y@Ø öPyÀI²ëãŒÀ~€ÊÀµrÀ¬;5oŽS›@"®üQñÙ@»{=J½À& Ôz!kÀ&EÅÌe϶@~§¥à1raÀÜ®‡æŸä‰@ꂈ4ã4<ÀëÄ­Ž¥ùV@‡~§‘~ÀºV Ÿâ QÀ®ÇÚßÔ@¦³…|s5À¬j¦¯ûV@·„ïs¸rÀÃýîÆëžQÀ®–0 *qÀ¦³…|s5À]p–‘ðì@øÌ²i”åbÀü O)°=8@h?o¢UÀˆVÿ0 +@ö1oóê.c@xÓÚãBÀü O)°=8@³&Bæ×rÀèûmü +@Ð)Ç^õöSÀxÓÚãBÀÉÆ–+w@Hð—'p5ì@úôi“À8È|¾³Û€@ „(9ŸÜ”@va…°Á–xÀ@Út@?@2ç;é>gÀX›µ„º¹C@T‡jÈ @ók‡Íµ ìÀéAÊkŸ‚_Àß!cê]@8½pb9@½ºÔ+¿Œ€@bJ=aÈG]@ÎþÜ×ÌÆF@ü]Òl.@-]:=ÞnÒ@iÉ“ðñA|@ÌzD")¦Àva…°Á–xÀ¬{ÛV£@3ÍÊ«jçÔ {k@]ñ¹ÚΔR@¤þ1–à…@"ì67bÀØVN7Äõ@@ž,‚RzýZÀ1Ìú´Lq@ÈY{ôÕB@d¢mlmx\@”yÙ{ÐvÀZX;œ˜Ý@ªþå-#Ar ;÷û˜@Êñ<º'– ÁZ&FÍì)wÀ·Œö AAž[T‰`À#CãP'æˆ@!Ÿ»ÂÞDKÀ 2s€We@Ýñ"Ó˜éÜÀŽök›OaÁ=ñ¹ÚΔRÀù'Α2@"ì67bÀ™)î÷@¨UKÿ~›iÀ½–Ѐ3`„@ÇY{ôÕBÀ0Ìú´Lq@ÂÑ—€H~…À'§II­ @Êî¶3¡ÄÒ@´!…Ǥï·@¬Š{L¦‘@¹6¨,‘v@ 'Cvi Áôµ)©›m²À—øˆ}(A'|ñKÊV§À¤Qñ«tÀU-ü9“@'U®…7¸@úö£âž@žybÊQnv@K¬¸V£®\@qî± ²ÀÒéí ËÁ'|ñKÊV§ÀrÕ D.Aý$±¶’@DN*˵“´À^Øn[`e@>Wï²ØÀê:—„ºé¥@LhsµA‡y@™ÏÅýqÒÀÄÄyy„ø„@Lã‡IOí™@BØÐoÀ™º& /§ÀsñÌÓ ×›@ÒâÛ¶@ã Z½Šc¤ÀAw©»k¤@¯™ç±aÀÕLœET_–@h$ÈÀ•6@3=£Jk¬¦@éöCú<&@d<§…’±@/Â[)»ƒ@÷'^I3À`wå6"¨@MhsµA‡yÀê:—„ºé¥@wj›ÐͶŸ@"á5 ÚÀBØÐo@Kã‡IOí™@Т§î¡@JöÏøÅüÉÀã Z½Šc¤À‘ÖjÔ@¯™ç±a@Aw©»k¤@k$ÈÀ•6ÀÕLœET_–@ÛöCú<&À2=£Jk¬¦@.Â[)»ƒÀd<§…’±@½‡Žl(n@úEÝr}Òš¿ /Ö ¬lŠÀ\ѯ¯WËb@‘²#'–Àc- …¨{@s"Þfj@XÅåü5bP@ibþìKœ@£PÄ8 }†À =Ýr}Òš?½‡Žl(n@‹Züel¨b@N'›'”ÀiÅfäo@§Ø'±Àˆ¦À‹Œ·@ TP@‚lÚC4@£PÄ8 }†À§ƒ%ñ„®@_ÄÇ1Ö÷À‡ýæÔoÐLÀ:æcÈ2¯÷@:Ì]Oþ W@aªG^•œ<@ ÔÑ´ñk@ŠebQúP@IÉ!\ÝC]@Cá·|‡4@¡|\"Ö‹h@Tæ7y­|€À†sŠÐ•TÀ´f=V |@‘Æz²b U@|sëb¶‘3@Òšä@ÓÀ;ø¦`ÀbÇ‚P <Ó@Yiqš²¶2@Îâ]s<@QUÆ®„ùE@\¶ËSy“+@³õý^MÄ7@LXCµ¬@Tæ7y­|€À¨øîB4ݦ@ÃGÜ\ƒ{@°•òuJ¾¢Àš•Õ1@)¯ÌüÈ@DŸ<6ËÀyK?g°—³À’Çò?2áÀW ôdàØ®À´ÒDF%¥@2àÄ4rP@êxf:»\¥@nZŒX!iG@)ƒ8®¯@›6Hz0‚@E´vwHŠ«@Ü…ŽËƒ@(È…ÿBD¬@€Ý³'À€@~fVÓPª@À‘@‚@uïËÔ@yK?g°—³@yêÍÀ@bΛo#å—@yK?g°—³À)êž—6œÀ¤K>·À‚ïÿ6½À@Z9eïž@רui+@ºª°FÍ@öttF‚#@÷/÷fAŠ@[xWËP^@:–c<ó†@ĉíý¶_@!|ïÔ7އ@Ñ*qÖìê[@¾ªrîÃ…@rU•k^@yK?g°—³@â4nœ†À@ڕʆ…œ@Q¬‡és@-.ꫤ@öÓé'™€@…WªÀ¢×ÓÀ%hý€À€ÂcZÙ˜@›AZ®cÀAw©»k¤@¯™ç±a@Ò$VîÍÃ@§;$˜ Àu §3F ³À#ä—Ì @ÑΆÃö?•@¯ÁcåyW@GEÄö›Œ¥@r¸jZˆÌc@3Ÿ/.”°@3j^ªë‰@÷Óé'™€À..ꫤ@E½/ó£@]e[’(äÛÀ›AZ®c@€ÂcZÙ˜@¯™ç±aÀAw©»k¤@§;$˜ ÀM2YøwaÙ@ã7(.á7’@nÙ"Æ©ÖÈÀ¯ÁcåyWÀÑΆÃö?•@r¸jZˆÌcÀGEÄö›Œ¥@4j^ªë‰À4Ÿ/.”°@?TÎ-· 0@Ë–‹¿SÀ#çæI×jL@剿»~Àè]7L)@–ÿ÷p?!EÀ†sŠÐ•TÀÃGÜ\ƒ{@u §3F ³Àã7(.á7’@}üï4Û¬·@µõ•sСÀØQºßi’ÀEðB)ŸQ@ü…Ï” ÚUÀL^˜/.èz@¡3ö“[xÀ3âPÃéWª@/(Ô¯ÕeÀ1­JMâš@´f=V |@°•òuJ¾¢À#ä—Ì @nÙ"Æ©ÖÈÀµõ•sСÀŠ—,Ž«®Ê@Xôlcoi@»ùùo1æ®À0‚¢Kóµ@Sâ–\¶g@B‘l&s­@r´î7#(vÀn¶ú·‡<Ÿ@<žÑQ©]@—ãœ.P]˜@Ý­´5¯NÀ~D<ƒ §ÑÀ!EqÝ£áx@ØQºßi’ÀXôlcoi@¯œND•¥¸@tñz³¥­~ÀUâ–\¶gÀ0‚¢Kóµ@r´î7#(v@B‘l&s­@:žÑQ©]Àm¶ú·‡<Ÿ@Þ­´5¯N@˜ãœ.P]˜@ëyPLŠs@ƒCmm•ÕÀEðB)ŸQ@»ùùo1æ®Àtñz³¥­~ÀLš*ÇrÉ@Û †òBõüÀˆˆ×ÛßO³À€îâ|ˆlÕ@Ý ›®@ÎÐ ø…\X@ôû¬ã@â€ØD„@Y •ÛH-8@ì¯Ë:l@OUyú ;D@€yÓ¶À‚~l“g‘@ã¾r÷˜@£òºÆdÀALt0f@h^óÅ0@íæ›CpxA#gjRŒ’@Ê2PEÓÞ@¶ÉøZ@«Ú7oéÀlDC›mÿ“À¶ÊÓ¤ë:¦ÀÒîþ3Å÷ÀðŒmÎÞ>®@õö»%Ÿš…@öû¬ãÀÍÐ ø…\X@Z •ÛH-8Àâ€ØD„@NUyú ;DÀë¯Ë:l@ ðBçt¡{@jIgVÂÀ£òºÆd@ã¾r÷˜@h^óÅ0ÀALt0f@#gjRŒ’@«ŸŽÑ\A·ÉøZÀË2PEÓÞ@Éìȶ¢¤À$,òTOãÀIb&/e8ZÀ#h¥ûä?À¢ûT~±cq@»LN1ñ‹Q@6M»˜L†À"rµ½^UÀ}¡“ó±åv@òRf2þV@91)Å«=@‰ yT@ßD_ö°€1@Í/+ìì?ÀÅ'ØuÉj#À»LN1ñ‹Q@–5‰Q@í­úºs_iÀV{JqRÀφÿ.<í[@(‡Ë <@¾ÂQú"@Œ–F¶Cø8@Ó©¿«ãX@t÷¼Zt@wííØÐÈÑ¿Ÿžwy^2@ó†ŸÉ>øyÀ̧Ov;W@™©üj'ÊrÀ”Ù,NÇÈÀí±§@w@O´À¥ÂÓªÀY¹ˆ8m‡À®¬¼kèKÍÀãŒkDC²À \º &—Ý@yš]‰¶@ííØÐÈÑ?t÷¼Zt@ ÂYŽmðLÀªP†PaÍ”@¼6l¿›rÀÑò Ž@ûþ©8Î,@öå ÃYÊÀ; ŠÌ]}‡Àq¡1¦“ÀÐyUÛD²Àðy ,ùÅ–Àyš]‰¶@†SnÚH‰Ê@ê)?¥ÀÌDh[aø@ÙŠìb P@#E¾t0ZÀl©fi8e@À Ð—$µ÷À€Ýgñ"N@iÓìý¯vÀßBwæ8“lÀñ;zECÀ§B)«ÑØ8@Ûšm9rSÀØVN7Äõ@@¨UKÿ~›iÀÒÿæ ‘´¡@Æ«'“Rvw@@“9õ•s@.ÁÝjªcŽÀäy?ó®˜@•Ñ|M‰?ÁE¾t0Z@ÙŠìb P@ÊpT-VË€À¢a'ä5ÝAFÆÖÂúgÀ¿/´i ’@—å Õ(:FÀÐm·)F[À9ðŽþKÅSÀŒ ¸âUòn@ž,‚RzýZÀ½–Ѐ3`„@Æ«'“Rvw@üsôéJ—’@÷hƒ’*ÀxœU‰E.¨@<ñ”Ä’ 9ÀêM£Y ´¡¿é{.Âë+U@5H‚LÖ«2@3"އMÀ5H‚LÖ«2À0 <Ü•~§„9À5H‚LÖ«2@Ò¨~0ÙC@@5H‚LÖ«2Àž¡q~œÀÕWÊšgß–@ÝÑ™8òÅg@Áµ›Ÿ5Àž” ™s's@È !*ÃÀ XŠ÷ÎäQ@–sßù"ðŠ@Å_}GX;bÀÕLœET_–@k$ÈÀ•6ÀÑΆÃö?•@¯ÁcåyWÀFsœ‘ þœ@ãÞ`MçõÀÈãï´i—@•Ý9Í1ÀÔ›`'W¢@GÒï‰fKr@ÛÑ™8òÅgÀÕWÊšgß–@ž” ™s's@w}…ËÖ›À–¨ÎõŽ}}@iw;6âÅÀÅ_}GX;b@–sßù"ðŠ@h$ÈÀ•6@ÕLœET_–@¯ÁcåyW@ÑΆÃö?•@ãÞ`MçõÀ¶ºÖb‘¯@Ý9Í1@Èãï´i—@GÒï‰fKrÀÔ›`'W¢@7ÀjœO[ÀûXÈ/~y<@ gm>8˜]@‘»ZÄÑãLÀJ7½¢ÞD"À ®¸E=@ûXÈ/~y<@zËOƒÙógÀ‘»ZÄÑãLÀ+[2êq@&íX%N=@A€ÂÁyWÀ„¹0ðëDÀ;Âú±^Â{@òªXÓâ²À¥$òŸ‹@îP±ýG„@šýÆâyXÀ7‰7zkx@ƒÂ1¶\À5¦ž ?ü€@ªíÌÿvÀKCiÆh¡@2ûVS¯n‡À™”ö?HBdÀ<¿áä¡À½H+Æ3‰@îÓÀõ²±ÀšýÆâyX@îP±ýG„@‚Â1¶\@7‰7zkx@ÊëÔ6¿4ZÀ­YØú{•@2ûVS¯n‡ÀßýÕP!±@Œh^øXt‡@r<±Áðl@M>­ÿê”À“„¦m«çyÀF‹¸S@T]—¢ƒ£nÀŽ=ýk»@:Ëz“jr@¾2µÍÄn¯À:}€Ø¥&À•t5ø[@Àq$èàåóm@Ûhê°8(£À™_OÄó‘ZÀ ‚u1m@ÊmlÄR@j§ˆl zÀéuŸö'`À­xÔ²gÓnÀœðî*¶ˆ@:Ëz“jr@c„8¼@€Ù¼Ô{pe¨õ­ÀÍx‹Qóm@3Ô_§œÀ<ö,ZÀýOüò]» Àœ2Dc•¾À{Ù<þ\@¾2µÍÄn¯À€Ù¼C¼6ɬÐâ@GÔ¬ªÏCÀˆÅå_9ÚÀ€2¡b?Ø¿{Ù<þ\@Q»ÊÄCËÍÀ:}€Ø¥&ÀÔ{pe¨õ­ÀGÔ¬ªÏCÀòµ¹Bæ@z2¡b?Ø¿øðÞP˜ ÚÀâmÐé-ôQ@YëÖ€zÀê ôÏïfŒ@*áŸkpÝÀ¾ÿ%s<ßÀ=êÓ¡Ê—Àwº^-ÕÀjEã¡€°¡À¨¨âá(ó@21v ¦½@@l'8FàÀ÷Üñ›),ªÀÀïTBv½@çPh2:½á?A(Næ}{À0¥æÀÀKÑãvfnÀ§µpd¶F@·FP×ÕœTÀ!Èñª5ŸÀmûáýa}À†ª`ô¶^É@ø“DÜy(‘@~>€úô‹`@9ÍKS®|Àè uáDt¤À 283’Žc@¶c1ƒÀ€íÔ0A¦¸À¹ö§/ÑjÀiãñzVx@V_84 giÀ.–$ E|Àø“DÜy(‘@Ë6ö½@vb(È}‰ƒÀÝÝ6 î @–¢#Jüw@±ÌÊdM©À<ú h­™^@ r3_¸dC@:0¨@dÀÔ>9ëó$Àär´]8N@ ;€U˜‹2@;gÞ{ Kp@mÛÖ+ÛÁaÀ œ2ÑZÀU:m"cz%@j潡ðÂ.À±¢Éæ…H@fvNÅ dÀΠ t—÷A@Ä¿½tÙ¾B@lìR²Â'@ë¡rÍ„$À’Û¥hF`ÀǾgŽ2@B|ï¶@mÛÖ+ÛÁaÀŸÍz[§â„@/I± 9Î#@·q„ÿžaÀ±Íü*gH@ðºs9tcÀç˜a FÎB@mêé‹ß‡pÀ¡ª´¼AªæbÅåÀ5Ëy±/@-š¡kÀL$nP÷Á ¥K!Æå@NÚñÁžÎŠ@Œ«ŽÏ!]KÀ1Ìú´Lq@ÇY{ôÕBÀ œ2ÑZÀ/I± 9Î#@«€0î Š@3û H&X@,`׆M ÿ?O–«Î\ÄÀyäî @ƒ¯†V’ä$ÀªæbÅå@¡ª´¼AĹrymÀ改X’5@6˜s]ùÚåÀæM­¡aïÁ«ŽÏ!]K@NÚñÁžÎŠ@ÈY{ôÕB@0Ìú´Lq@U:m"cz%@·q„ÿžaÀ3û H&X@Cd÷èæ@`²xr¼YÀ‚‰Ý84@ÔD¬%&À•S~®A@ÔG¦cÀ™z̪ˮHÀ™Ú%/\@¼KƒšÀj潡ðÂ.À±Íü*gH@,`׆M ÿ?`²xr¼YÀ¥¶cCò„d@¬À ÍØ,;@à˜\«n9@O¼žÂ_þ(À™z̪ˮHÀísB©/ÀÏÓþãÀíÂxwÍ59@±¢Éæ…H@ðºs9tcÀO–«Î\ÄÀ‚‰Ý84@¬À ÍØ,;@Ê%¿·zÍU@¬œÂ&câ)ÀNn±ìûïC@'z¿C¨ÀÁtm:iŒLÀ„g•¢ÿˆk@¹½¶†œwQ@NÁœeÍÒ@ûQa*®Àãgnvÿ÷ÏÀÆb…b®@;)  ¾TÀGâ€õ¶¦ÀàAó¹…Q@xñ\N$;6@ûQa*®À…6l|*Ý@Iz¡À$D®@:VÞbYÚÀZIåú$¿@ž ç)§_•@ú ä*ýáÀ!V о_•ÀÓ`ÏÛuÀ£f!Xnve@)±_‰{m@ÖåU`›z•Àe±:³lÜÀüapeGRe@'dàg,ÔŸÀ)º—Ò¾â?)±_ÀBÌxÍí#†ÀPü]†‹p@3*í#ËPÀZGòÈ%É࿚WÇN¬ß>@©ª-q“@kÀ“:\A@ a;eç^@,3z×’~D@7<Ÿ×£ÔdÀ,3z×’~DÀ3*í#ËPÀË#õ¤`£@jû›JÑB@@’P¥šèÀ“:\A@¼ô¹#zÀ¯Ò‚;ÓC@Ä÷kñ)@ÑÉ]-—CÀïÏ,èhwMÀ1‘%°!'@_R Œˆ[À…ÖÅð?MŒL´ûSÀÝ‚ |b8ÀV—´@Y@s@ZGòÈ%Éà¿jû›JÑB@@¥“Là Œ@m)=ŒZÀËÃ0šŒ½‹ÀmÕ>…í™FÀtJðÆ\À¾¦–c’‘@]TÿÝ$ÀЂ3ŒoÛˆ@4Jušätn@ú5üIî§ÀšWÇN¬ß>@’P¥šèÀm)=ŒZÀ`ø8ªäª@šÕ5ãFÀcQ:µ« |ÀSˆßvÞÀP÷Óì¾ÀÌè¨dyœ@Øí©1m@šý°ÈÀ ð![™ŠªÀ ]_ýL@Öß`DXf7@np"î†×ÁÖ-(k&÷À´‹ààQAéäoFåù@u)¶tØ(d@mÝ”-€Àj¢0kxP½ÀqÌRÑ¿Àìv“v¸\@û~'t‡e@¥qËçÁ«ÀÁúûìlk–À&.`dµUs@SÂG™è@‘«3²G÷À~眑ú(ÛÀéäoFåù@OuÁðBá@"d8¾NF€Àƒmlvìš@T›|°l‰¥Àû}ƒóH|ÀaE ƒ’¤@û}ƒóH|@%ãÑ ­‘Àæ×ð%xˆ@1Ä®±tÐÀ ƒÅŽ廿u)¶tØ(d@"d8¾NF€ÀÏâ /Ñ@Ì9–Å_oÀhçºÜhÀ@ÀÇ"_ÀhçºÜh@)ØÀ\øï?âsµ8ˆ@£­-ŸvCªÀ0HÅŽ廿=›ÏPHÐÀmÝ”-€Àƒmlvìš@Ì9–Å_oÀÝ÷¾îñäÑ@‡u$·âo´@`à9açu@­qù³_@fTV e«5@]SpÆti@w† ôT1@qþöv“¦À®R϶‰v@Én¢Þ,ˆ@z¿yäs0@g¼!Å'›Àf‹óèY[ÀˆÅå_9ÚÀz2¡b?Ø¿o˜Ì^R@Ù$ý!$´@Ÿ2N‡Oê@d¿–Æ@ïSÀX˜c„­ÜÀ5z”9Ý<ƒÀiuðÕÏw@²©‹@@¼€·Ã"¿\@¥ï=®MÏ@ØÆ’)0@Gˆ'DX@("AëÚ9@6U ~š@®R϶‰v@xõáø¶Àôún·ßX@Öõvèµ@âh1ΦjÀq3·? RÀ€2¡b?Ø¿øðÞP˜ ÚÀ”¶“‚¨"@:& T+î?d¿–Æ@ïSÀnü\$»³å@:Ì6ê!ÂwÀ´¤Ä—Ä™ÇÀ ¸a/H@*ó 1]@ƒ_& #ÃÀV BT(õÞ@¥S(Ø(ßÀX˜c„­ÜÀ:Ì6ê!ÂwÀ×`–â„ã@åÇwŸ‡@md33kV"@´šfæÑ{cÀ¦Ž¦g/@Lï‹ÞzÁ NÀ@®A5z”9Ý<ƒÀ´¤Ä—Ä™ÇÀåÇwŸ‡@!Y8®Ð@ a3saÀ3—fjÐ-¢@•t5ø[@ÀÍx‹Qóm@ÖJ4Sܰ@ñƒ¯—ÉòmÀ3kZ|N¼°À`-½q$èàåóm@3Ô_§œÀñƒ¯—ÉòmÀȰOa½·@ðГġ¿ó5©1¼°ÀäÈòäǪ™Àeû€ù®˜@näw?±0@Y–b’‰èGÀÿƲ2ìG@?æñqÀÙ ‘SÁ@Ž.߃3¾¥@ò¼½øL@xƒ]C¯tÀ¤†ôYƒÿ?]R[s˜bÀʯÀ׿î @A(wÁªbÀ=|Œè&±@ŠÂÚ"‰m‰@w»õãí:4@n¹»¼)NPÀ@l'8FàÀÚÐqÄ¡²Àé´r5Õ@A½cW]˃@>X±ÿ1.–@V)]dd$ÅÀŠ,½ ¤XÀ¯ÜΊ¥q@6èÀú*¨qÀQ\!x@|š@_t`£d¡–@2º(ð#f|@³ÚÏBb«tÀƒ„(шž@Â{4¶‘ö&Àž»Š@vï{îâZ5ÀòœB‹@í‚æ§ºF†@Èà ›`@£Ž^Ý]ÀM6›Üx@÷Üñ›),ªÀÜßÔLŸŠÊÀA½cW]˃@€4EÑ@¯ñÇ{çÀèÉàÞªœÀ‹,ôÐ „¬@PÍö¾Î-V@O?*Ϭ@ñ”: :’O@ZW¨· z@¿Öu¶<¢À‘îV½Ñ£@oY{Ô…Ï@x¶µ!ñ‘²@IÄxX©‰@BÖäRAµ@Æþ:ŒŽÀ‹¦`¤…œ±@¯í¦Jˆ@yêÍÀ@ڕʆ…œ@ÀH`bÌ@±f^r#ÃÊÀ›êí¬d@C„‹›öªŠÀ„<̉>¦ÀÊ m{ƒÞÀñcÄl#G„@1©‹/@O,‚•w|„@BÃy\s&@b²µs£À¼Œ,Ën³Ê@Wmĉ3tÑ@,Kµ¢?ËõÀÈG…n)iŠ@ x"Y?b@ ±XKð¢À¸ô«c¢‰Ã@-ç¥Ç ‰@fÔöá&Fa@bΛo#å—@Q¬‡és@±f^r#ÃÊÀ‡ƒqñEö@¼’ÉaTÀh%ûO†³@9÷|<$§@Gð W£¶þ~@5T5>°F¤Àì–wyhÀÜ®‡æŸä‰@“:\A@¼ô¹#zÀ¶È*McqfÀðfÛü“@ÿÐÜQ‰’­@†–“c»4%@ªDæ%@òÀ9%kVGÕ@z"93†À¾A™Ü7˜…@ F::•œt@æm1óhÿ¿ bW¹5kñ@ËïÅ$áÚ!%@,}»í¡,@4ˆò€8@† ZÍÎÂYÀ§Øø|ºÖt@šß¯é™jg@*ðïÅeUŒÀ¥ÝsŠ`ÀHlˆíë¶À ‰jä?Ð*Ð0u@@Ü<Ô­¼eùyÀg¯†ÍáË@Nø|öFÀWLõ¸%*b@⤀~•@IƒŠ$)bÀì2P˜ËÆ”ÀtËÑ(‹ ¿JƒŠ$)b@%±dí;»|ÀIƒŠ$)bÀPµ:Ð,õ›@½‰h‚’`Æ”À-ìQø(&ÁŒzpÄHÁÁ«~¥!j@$4E‚*>Àø:«l^¹•@¡lbAB²iÀ¢»;ù @×4°/Ô À€9Šç ÉÙÀ:ºâ›ÞϪÀD’œ#°©@W‘·Y/‘ŽÀÅ”·Ÿw@O~†²æMÀÊ2PEÓÞ@·ÉøZÀ6[Í»&AóIŒAràA?O Ü÷“@½äNF~*À‘Ëìæ’LÁq }enCÁ"4E‚*>@Á«~¥!j@¡lbAB²i@ø:«l^¹•@Ñ4°/Ô @¢»;ù @ì ®Œð·Àª/ŒŒÉÀW‘·Y/‘Ž@C’œ#°©@O~†²æM@Å”·Ÿw@¶ÉøZ@Ë2PEÓÞ@óIŒAràAÄ"þHt–A´äNF~*@?O Ü÷“@EüL«\õÀ³ûš;vg@€Ñ¹†_ô¼@=Â*š] @¾µæ81õ@„ÈÝŒKžT@û,â™9@C…›u6h@Î8ÒÏüaN@ˆëÅ/Z@ÚpÑ^2@‘Æz²b U@š•Õ1@?¶Tâ@mºÂ᥺@$Æ›^àæÀFø#%ÂÀÎ ’û‘ÓÀ95¦”“Àçà¶÷Hq¡@¬x¸¨¶·ƒ@R¶„H³Ó@𵯺r*3@q xR,Ì@ïâ°vpF@Ãüž >,@tÃãNW8@bh-W7@|sëb¶‘3@)¯ÌüÈ@mºÂ᥺@­ÇnÞ\AÑ@¦§£d'ÂÀ76¥‡µÐÀ»»4é\ÇP@Ü=Z·å rÀg;EÔ§@’h€ü\ÀØ7$ÞÀV€"¸<˜nÀñb-Ä´'¡@B~ÖEëÀIø™>‚¡@¦¾t^õJ‚À?G,ª±”@KN“~`ÀF>P¢›¯@ÊR>|ÀÒÂ*È•@‡Û(ûö?@$Æ›^àæÀ¦§£d'ÂÀwþ°fî@îÀ,\èÎÆ@YV¤nMÚkÀ›¸g‡°ö@h€ü\@f;EÔ§@R·nW[¯¯À4@<½®ØÀB~ÖEë@ñb-Ä´'¡@¥¾t^õJ‚@Iø™>‚¡@LN“~`@?G,ª±”@ÊR>|@G>P¢›¯@~Û(ûö?ÀÓÂ*È•@Fø#%ÂÀ76¥‡µÐÀîÀ,\èÎÆ@<~ÐLãÙ@¼®žJ²@/tÉ8@ϸmXÃíÀ”WãŒpµÀcQ:SoµêÀUºÐêáŸÀÑàiN~À¤@ÞùFÀ·ëˆÀd<§…’±@.Â[)»ƒÀ3Ÿ/.”°@4j^ªë‰ÀÔ›`'W¢@GÒï‰fKrÀܳZ'¢Ž²@Þbî^EB„ÀœßJi§“ö@RåIË€Å@JtÉ8À¼®žJ²@žCnn…´À,*cŽæÀ§:×À_óÀÀUôj)ãÀÞùFÀ·ëˆ@ÑàiN~À¤@/Â[)»ƒ@d<§…’±@3j^ªë‰@4Ÿ/.”°@GÒï‰fKr@Ô›`'W¢@Þbî^EB„@ܳZ'¢Ž²@RåIË€Å@KÒH½î@! ®é.»@Ê-=š£@uèXÂ1E#@ˆZR¡ÉGÀYñ<à)À‰À6ô3—®G@CheÑ-ÔÀU_°°£ÀuÆêƒ>$N@ÚÃŒ§ØP{Àw&/M§àÀøA=3kZ|N¼°ÀðГġ¿ì2P˜ËÆ”À½þ{ƒ³JÃë@ÕcãíPÀtTí|Üò¤ÀÁïÒ|@@а<Ï£@ð î@-Å[­\>ÀÄ¢Ú½b@1Å[­\>@i.­¶åŽÀUâ¯å£À߃PnÌÀ>âAo'¨¢ÀµÓ¼cèÐ@ Ÿ2»“÷¿ÎϱI§àÀ`-½ó5©1¼°ÀtËÑ(‹ ¿‰h‚’`Æ”ÀÕcãíPÀ›)ˆd*í@áËέ©2£@WZ z`ÖÀ&žlÎýÀ§¾=`š³Ï@tTí|Üò¤ÀáËέ©2£@ÉPe°ý@KrÁþr"ÒÀH³u q¥Ñ@º@”\_<ÁÁïÒ|@@WZ z`ÖÀKrÁþr"ÒÀ4ØÄ nA—Æ…E>*ˆ@]GúR¤lî¿¥vz9â¡£@bÞŒÕy@ÊêÄòÇÀº"É ÌÍ@ýzÏX1¸À8Dºýÿ$k@fxé¼m'@#è1)ÒPÀL®ìØŸÛ@+ Å®[*“À´Ã9ÅËÊÀ4Ôjž%Z@æñG”4j‚@솈…9ÿ?HGúR¤lî?—Æ…E>*ˆ@bÞŒÕyÀ¥vz9â¡£@ÅGÌ{e‡@Ýô£ÍÀŒ¹™¯í»TÀä18ÙZ¬¹ÀÈ+¹ÂÄPÀ(T6m‚ux@+ Å®[*“À/úÎM'à@e jG@â¤4ÙÖÏÀ‡ˆ…9ÿ¿æñG”4j‚@4‹gòëæƒ@ýö=rTi@nK˜ð¤ÁÀG‰º•UiÀKêi¼Ÿ@»Ó/Èÿœ)Àãgnvÿ÷ÏÀIz¡À$D®@«~)Žþ>Ö@vö’Uí*®Àe›+Iôsi@.„2P@­-¨BuiÀ´æ@õɆÀÀ¡Ó/Èÿœ)@Kêi¼Ÿ@Æb…b®@:VÞbYÚÀvö’Uí*®À]˜`Nà@u²˜Ãv¼u@°£ëŠ´B@­‹ç?öûQ@”‘=”v(@²¥¢ ‚`i@4ú’W$BF@ýÅs»y@Ò«9w\@Àr˜Zh@ÁÃ&i@@|„ކÊÅ—ÀÊÀƒ}¸iÀ×tÞ7qƒ@N¨¨#j²"@VõÑãÀsÀ1:]òaFÀø.Þ,öLc@„`ûŸû›0@ãÇ9M+ð?@@ɧ—+f@ 0É‘ˆV@ÐÅ=3©Ã3@*ö:Y½9f@é C.¯FI@ùÏü³lSU@ØÉ™4 ,@Ö9 €¡ÀíÇMHã®}ÀN¨¨#j²"@›œÿ;ƃ@RÒwðzkEÀÐRæ8,ømÀ÷2öËÀ_¦cÆ}FABXÙª'Àwƒ$Ç*_qÀàÕÌ "·@n’omæÁŠ}Óc¼Ji@ðˆX³ß “Àv³SâÚT@ÿ;çjRpÀd¢mlmx\@ÂÑ—€H~…À@“9õ•s@÷hƒ’*ÀŸÜÿмHË@»Qpñ\R¥À;!!YC»@mÍÅÜ|Ô/Á2•ªT,bqÀבW„ÇãcÀÄêÓœF}›ÀÄ“ü –à.ACµj‚€ŸƒÀ …µšuŒ­@ß*¨<.pÀ¡þû]ÀS‰@”yÙ{ÐvÀ'§II­ @.ÁÝjªcŽÀxœU‰E.¨@»Qpñ\R¥Àò£Õ@&ÿúý‡ˆ‘Àÿˆ¥QdwÀr%1‘ÍD@~í=Æó5WÀä‚69¶À«@˜•w‹Wd@¾ÚÓí!lŸ@àýšÂã]@®x‡^¯Yï@È‹êNѾ@‰•ׇˆgÑÀó°¬hâ}Àƒ³¥ çÀ Y½‹å°µÀ;:ãÈ£À¥¦2¼ÒF‹À³u(µœR@ÉKÿm«cÀYÀEÕï “ÀÃCä5Ñ|À°8ÒãP¡RÀÊóÜBtÀ4H—áWÀr‰$ö–Èi@—•w‹WdÀä‚69¶À«@àýšÂã]À¿ÚÓí!lŸ@È‹êNѾ@´üñtܳÓ@SîEvˆŽÀ,GšÿåpÄÀÉ9‚!(¶ÀžéÙ!²$ÌÀÂKó‡pÀ„ã‹üøN†À:Kûð7¨dÀôÀÃ{¯Ôu@SEEÏ“–gÀI/…=Á_À$Výï`‰@é@1W]@·‰iQ)3@ç èÝ9(@Ÿº’gèÓ@­`ü(c@âb–‘*¥@ÃäŠÔU‘ÀôLòüIogÀ#µÔ‘Ê@¦À'?0›€ÃÛ¿@Út@?@3ÍÊ«jgÀ-¤Gʘł@©’ r@îV› [­¡@諽ë#Ñ A²¢‰ñ@&pñj!Áœ-Ï@Dc˜ÀR‘éx…¢†À)÷‚*qnt@W©ää,t @° ˜:_v@Ã|ß½½º@–€9½ë‡TÀ_4e´)õ@‚6DwB×b@Ø]„.NõÀ‡9*ÑËš²ÀŸb®‘cçt@T<_áL¥À.vÉ·´t@X.}ßK'L@–€9½ë‡TÀ4ˆ¹Ê‰q¼@±ï*%Ù]…@VêG™ f¿pØ–S@Y®µ‡Š'x@ÞÓ%@P@¶³·"“i@Qp|P6ûN@,QöžŒ@Û>µ6iBc@uZ,;mÄ@BèòÄR@y_>ºñB8ÀYÓâ‚r‡x@:/òD;ÈÀ|= /¾VŠÀ’-$]·IM@X’`¢=r#@°ùGâgúG@»E$tæ@©®êTÕÔ8@ËwòQÁ@§ÂDX\@¿ŽÕ.l3@BèòÄR@ZI· ƒÇ@½­ZÔÃm@n¼*ß®Àö`±æWÀ+hדf¿ÀŒ„TÈįv@§à;¡ÊÐÀ|ìBvìßÁsí¿”Þ@sw¹¸JÀ=¬oë|á@7ÆõfÊQáÀæBÿ¾Ý:@€þm²\À)6ª•¹yA¥´*_˜æàÀíºÖ¤Ê–@¾‰¦uÀȯȨé—@Ÿž täÀ2;™9¾Ìv@<Ó1…Ï‘2@y_>ºñB8À½­ZÔÃm@¾c Ìú¡@™·DºsÀÈú[ò2C@€òªCvqÀʬü¥}3@µÓ黲¡cÀ¡à;¡ÊÐ@Œ„TÈįv@²N§À³æàÀJ0Wî¢ÁÛv¯]–Ó~@Þ{ÖH»ÁÛ¦Ìñ/ˆAáV0uÙoÀ>Cà r›@¥´*_˜æà@)6ª•¹yA¹‰¦u@íºÖ¤Ê–@šž tä@ȯȨé—@<Ó1…Ï‘2À2;™9¾Ìv@YÓâ‚r‡x@n¼*ß®À™·DºsÀï‘§µ“¶@‚òªCvq@Èú[ò2C@*gàF ´sÀÀ:Ïð Ù£@€„.Á€„.Á€„>AÿÿÿÿXãFÁÿÿÿÿw„>Án @ÈSAíëd ÑŸ@ªóGC6u@+rtýÞ§ÀªóGC6uÀ+ŸëC¾ÒÀ5Hí"Ù9†@ÔhÉ*ŠÂ@¹R:†ÀŽ.µ~ìõÀò˜ù@Á‰³ÀÀïTBv½@cMh2:½á¿’@Ã&¹ö@`± 9г@oÀ†sw@?«³ÀDgO@±WÉåwÀDj>]ŽçÀŸ¼”e¡:†Àå/ÍÁ+¾ÒÀ¹R:†@ÔhÉ*ŠÂ@ê+ºýµŠ³Àz Ÿ¾3ïÀçPh2:½á?ÀïTBv½@`± 9г@Ðw˜æŠfð@{ds”@ ýtð÷ŸŸÀ5Ðò7sа@?÷eá’@o×?C6%´ÀÚF¥ÙŠÀ^Ýœé|ÀG×ü"o š@ ýtð÷ŸŸÀaóûÕÄu¿@óµ 2–’@BÞæ ‰Þt@#iWBŠÀ>€Ã¢ÀªëΚ@®‹Œf¸|·ÀÁ­ð´Ò¶@\s ø:ÀúîðpMÁ@¼õIJe@1sÓ37€²ÀIÞEý©íÀBŒ¯vÃÀQQLjÀGs ø:@Á­ð´Ò¶@¼õIJe@m9AP3¬@BŽlù‘À>Ô‘¬ gšÀôj^á ‰ÀÉÁõ|Q¾À¼õ’m2¾@Âr‘=ÖZû@%d¤’´>ÒÀˆÓ,íªüÀšÌ h~À9_¾¯oá@ŠÇÑ1¬Õ±@íÂn:¶tÀA×E)žú‘Àð‘y®izÅ@ݵ-¶÷e¹@.´ÂQ9‘…@Ås{iÍöÀêPO\À ‘±=øÐ@0NÉ^œ@ ‘±=øÐ@0NÉ^œ@GV‘‡ÜÎ@4#¿ªª”@(ªgÙïö`@Ubû¤¤î—ÀÆÇ$â‰@%d¤’´>ÒÀ˜R«ægA;Ñ3~Zœr@¤!ÝX•:ýÀùˆÌ!;²@ØÔð ƒ@I›|[M§@úS‹v‹Ã@ ÙÊle÷Àå”wÅ…@pšFz|R@.H›ÚGdŸÀ"ÕL:òÀòbf0E@àù‡•Ph@òbf0E@àù‡•Ph@†n3†ásš@-6I’(a@lŸ”ÔÍ“ÀΚ9yìÊ@I-E¢âe£@†Prl¹ƒ@{&Õ°×ã@G«ehëOx@þù.©{ÀcûìæUÀèÓH¯²é§À‹¢5¿w$À†Prl¹ƒ@~¢ñ‹ÿ0@ç½W·¹Èx@ðÀ8cåb@˜_ÒMO˜[Àãòa hÀ‡ãd¿ªŒÀùÎÑZ²ÀÖDœ²¼e@MÚ¥¿zp|À…ŠgälêeAP+);POÁ£7è}ÃâÀÄÐk®Ðï@ý¾Ã‡Ôo×Àïí‡â@¿ð@´« =€SË@ÈúÉzu¾àÀ€ã²úCnâÀ Áì ùñ@¹².™£•Æ@’Ö(v@Zщ‡ýë³@TrÎøHÀÊx#hŸ ÁÌ3T‡¨Ax‡É–hÇÀ¿Ó²æå@Ôc"L{c@rlˆªæ~À}DŽ1éÒ@Á_û¡tÔåÀ®¯mƒSaeÁOÀŠKAª¦Dú|ÀLq•‘Ö`’@P+);POÁáœE>uAxPÉ)Ôò@ âRz& Á–¹Ç3n±í@J’”òR ÁÆ€Ø- ~äÀ+ø.8°ù@FI;˜1¦ô@š4<Ò Á˜Ö(vÀ¹².™£•Æ@'TrÎøH@Zщ‡ýë³@‰™ØÒëåA ugk40Á>/5.çbá@QvïIDÁ ×c[€ÀüDUlé™@»fUÊ]ëÀЇ|yW_AÊ( &\KAžJŒýq¾sÁ£7è}ÃâÀxPÉ)Ôò@d7Z^ã@Ë8rhÛ‘¢ÀPź§ß£Ò@ú›€‡®G@B 4øåw@ÜÃ÷ , ”Ààu™nB@8ã}Æ,N–À°¢âîú˜æÀùÖåÍ<—¢@|‘÷š ¢@RJy¸Àd3¹Sâ`l@r„EЊÀzkõÕ@›ÐwðÀÄÐk®Ðï@ âRz& ÁË8rhÛ‘¢ÀE/-Ñõéå@Ýù›€‡®GÀPź§ß£Ò@·ì|‰øÀ*Á £½!©@º‘-ª¸¤•Àóœíøù«@B¤ßÕÔŒ¢@çØõ×$éÀ$żJ¢¶À1\¦c\-Î@|ˆŠpËÀ›É/Ϧ @Ug!Nd‰ëÀ ™: §APź§ß£Ò@Ýù›€‡®GÀÙ@™\AØu& á@˸4ê5¶u@¥œäøÛ¿Pªv‹åª@¸D¯U.(@³VÒ ’Áí¸Yc" áÀ +ÒõçºÀ®=ãu pe@²ØAÚÝ}@¬v·O¿ëfÀú›€‡®G@Pź§ß£Ò@Øu& á@Â~NC“ð@¦œäøÛ?ʸ4ê5¶u@~D¯U.(ÀPªv‹åª@ÖklõáÀí•ÕÍx˜ôÀ1¤•‘«weÀå> ÑgæºÀ¬v·O¿ëf@²ØAÚÝ}@MW—?p¼@[ù<É'Ï@w¿]pí¡À[ù<É'ÏÀqSŒƒ&¶Àɾ"Àdc‰@ÌW'g…@0l…žÀ™›À[ù<É'Ï@žúa8«@[ù<É'ÏÀª«pÉxÀIY5Pj­…@à¶vCW¨¼ÀS)¹ I¾™À+ÍŸðÿ˜°@Ãbá_M@ÐÏ~Uü)eÀw¿]pí¡À[ù<É'ÏÀ‹´¢ÜTÀ@ÈÊå%Àȸ¬¬Ö¡@[d7°-ÏD@‚µÜoDÂÀ• K"x™@ÏÏ~Uü)e@Ãbá_M@[ù<É'ÏÀª«pÉxÀÈÊå%ÀöðO{BîÅ@[d7°-ÏDÀȸ¬¬Ö¡@ßA¿¬À{•@„“dz‘ËÀ+ÁCï™Ly@ç©çà"SÀý¾Ã‡Ôo×À–¹Ç3n±í@B 4øåw@·ì|‰øÀȸ¬¬Ö¡@[d7°-ÏDÀÎ*1$¼@xx²ˆP§À­.`·Pz@_ß°TïÞÀ¿{qÙL›@*ý ;3²ÀRIKçÙve@Ц?„Àk7‹‚òµÀ1¤‹ƒ@ïϳό›Ð@å·7SéèÀç©çà"S@+ÁCï™Ly@ïí‡â@¿ð@J’”òR ÁÜÃ÷ , ”À*Á £½!©@[d7°-ÏD@ȸ¬¬Ö¡@xx²ˆP§À¨„PRˆÏ@ÎQo=ä•ÀH¡¶6K¬@Ôn~qä¶ÀÇ“¨ì…Î@ÑvHc©ÿÀü´†ÈôÖ @6–3N©x@Àè½ÖPÓ»À :'4ÚëÀŠ+@§ãA?XÍÈ8Ô@Þ$¤\z-iÀµÎÝȱ¼À&G4·¨±@ãwšÑÀ¯JOã òg@5ävt±³@Ùæ’:_ü1@¢ñtÞãî À–5’±ÊŸŒ@I÷@ºÞB@ç‰bþà/fÀ}Ô„‹@j €xŸ­À|/Œ*ÿZ@™…Úu?U}À/ÍDXÃX@<ÏéézÛoÀ5f¶`“q@fE•‚v{‡ÀÞ$¤\z-iÀøvlH&ÌÔ@ƒµmúŒ¨@;ò÷é°ÐÀâUBø¡ûgÀd›É­ÕÑÀ®æ’:_ü1À6ävt±³@Rÿ³S¼ñ‚@ì¤,Hb²ÀÎd‰P÷Š^ÀÃÅØd²ô@ÁKˆŸÀnÕmbõÁ@§ ”Þ+ÙuÀòì› 2½—@ e$>¯tlÀkƒìøÒM‚@N½ @V2„À— z¾èûš@M9D ™t@Ÿö¥!ŠìƒÀ`¶ß>ïjÀ:k9Äœ@?™j­Áß@ô¯ÿ†S"@­{ œ€ƒÀ‡eIÎAP@Ÿö¥!ŠìƒÀ²ZA…a›@ÈJH(hš@”lŒ‚š—Àô¯ÿ†S"À?™j­Áß@¸TŽ€ÛT@Ùûß”a¬ˆÀB®ˆdGªÌ@¡s§Ö¦°À:ìwnª·Á@Oëšå}nÀâªÁ-lÀÌÛ²qJªš@T§´´'c±@¥›–3ޤ ÀÜo"ÃSÆ@'ZÃ)£NrÀÛµ;ò@T·HZ„À'­ìóøöÀíڗ·@àgpÞ»Á@ıC‚š<“ÀU³Ã_Ý@ŽÍ=’ŠÀ§aÀtÅ@™5éS‡tÀ¡s§Ö¦°À'Ü'6eæ@Jëšå}n@;ìwnª·Á@©3‡±(aš@Þ4©löÈÀ£›–3ޤ @U§´´'c±@'ZÃ)£Nr@Üo"ÃSÆ@T·HZ„@Ûµ;ò@YÉ_Ù¯ÀjòÙ úgûÀıC‚š<“@àgpÞ»Á@ŽÍ=’Š@U³Ã_Ý@™5éS‡t@¦aÀtÅ@OÖÂykÁ©@¬3cêŒÀ²Ži¶×d\@PÀi°#DfÀCè½Y&¨Ànú˯ k†@ ”lÌÃñsÀŒâV°}6@¬3cêŒÀ±VÊ¢†÷­@™1®–fÀœdk©3¶q@íã7qh†@æÍªâ„­ÀÕ,}áa?9@×.üÂÿTuÀ®A$&.×@¯,~_fÄ­@9¢Ü.=™@"7–[—7À&N èÚi×ÀGÞ|õ±À9"Ðf’q±@`oFëÖ‚Ÿ@otȸyª@0‚ªJM/*@‹°CpÂÀÄÖˆ•W²”À¯,~_fÄ­@ï81  Ê@"7–[—7@8¢Ü.=™@œßv¬ÛhÀÐCsDÞÑÀ`oFëÖ‚ŸÀ9"Ðf’q±@>‚ªJM/*Àotȸyª@ßñt™ÀùG†lÀ²ÀFN“ÎÐÒ@`’L†*À›ƒ–6wÞFÀ[áÔn¸€1ÀrÆ®o³OFÀu+¡ð û?kOw- C?Àš¿•´AL@Ç»_Ç{kŒÀ©¾µã.@1w$Š;ÀÈúfÛGt@¥±,c;€Àev¥fKqR@0*A¨rgÀî¦*¬»aÒÀ¦ ¤—´<™@`’L†*ÀŽ.©ƒ#Ò@[áÔn¸€1À#6Š¥ÊÀu+¡ð û?ö.Çu4VÀ¯@‰¶0L@%äå|NYÀ¢¹­@¸«G´í:ÀTÊc(²ªH@oÁFýð5•À¦Ù<,ñù @Ìf°×ÌIsÀÏ1bÐ…ˆ@$Û23dš@xØdi—ØÀŸ"‡ûÿ«ð@X›µ„º¹C@°¸!u„Ç)@Wž£ÇØè¤@mÆûût?z@Ë´Í n´À~b4µ®J;À/뻸r"@@¯s¤&“ [ÀN6I0øðÀ ŘÚoÀA’5[1‹À@äWð…D@bb•>®a@r€ÕRæ>@KÅEÎýæƒ@>Y$ë…V@xšr;7ìJ@c­OPÝú1@kË€ýÀ¨f;Ø?YÀ>œ¯ÀDÌE@àOL©ñrÀ_ÂÄÚüþ8@¶Ÿ«@]À@´I›^Ì@T‡jÈ @×)WÈï@mÆûût?z@œ@ ²­“@Óצ²?,À"Ï·£—ŽÀ%“ÖäÑ[ÀS*ΤÒQw@™&¢o¨ßÌÀ»©\¼rcÀ~Î?, @xF°p†ZÀѬ¤× >@&>·@‚ÇFPîW@ª:ÛZ#{h@Gœˆr è&@ÿÔ¹m˜@qö¯´[À‘UÝ’{bÀàOL©ñr@>œ¯ÀDÌE@¦—ª^ºUÀoØ‘1L+y@À5CyD§@ åF´æ‚@è@ceˆ¦À€Î1 ³xÀš—u’T½‚@¸mÙ½±ÎH@ÀÜaMaÀ Q ò6åÀ´èî³uõ0@Ó<éðÒ})x@vÛYɵ´@@º‘¦Á ÀÔyJÝ@P@ƒ¦T])t7@ß}†jN@´Nƒ0`Î<@ë>´¤"“@@2¢æk<@ÄëÓZ}@Ú̸ _áfÀ“,èÊW›Àì?ôî½jn@‚?À«œ‰ÀEû*§ h[À”²òÀÑG@&Ñ.¼b À„VI Gœf@2úŠÜÅ?ÇkwÜz¶<@ÞbŽ#i1+@@2¢æk<@Ù–ÞWe’@Ú̸ _áf@ÄëÓZ}@Z« žFQaÀÏ6:þ$®œÀ‹Vëj[Ào9¶Ú÷ƒÀ&Ñ.¼b @”²òÀÑG@yúŠÜÅ¿„VI Gœf@}o„ßü¼@ùï_³ƒ@Æ0•^βÀúº ‰f@mk!7þV@m;÷QA¼zÀÈÖ˜Wò¥Àa4^‹òwÀùï_³ƒ@E›w¢˜±@X"seh@'%ާöåµÀÍzÁ fŽzÀôc]áž@Ïs?ˆ yÀTÈg»P‹À—¢¬…‡úSÀN—–‡j@ÌãVÁó…©@ÆJ±{Á“À³ô”Õ µ@¨åj³~j3ÀŽ·_+7¸„@Ñü(Všò¿7ìÕ#®À<­¨Š•Ð@n·±"j@÷wd@ÀÆJ±{Á“ÀgŒgf⺷@¢nÞ?0k3ÀyOûÄbI@Üü(Všò?·_+7¸„@TƒúÅÉ@#ÉŽc¸ÀR!jN Ë@ ÷Ñ/²@,ÝH~}ÖÀJ{Y7?¾ÀB³*cE¤@œ3gžÒ@“S/Ç-MÆ@ML$’±@jðî¢@À5´@µ+Џaf@÷¡á^.%Q@b~C2­ÀÀâÌ¥Ëþ«ÀþÂpê Q‘@ÿJ¨Ý{•{@ ÷Ñ/²@JNŸ'n?¯@JÀ×£&¿ÀÇ"Š;dÿ³À9Ǻ—’Ä@*Nc'Õ{@²tÎ’cݰ@‘=Š(“š@’M¹¢Œ@[å^B¯Æj@ɦÏììP@µˆÝ]î9@Ù¿‰Ê «Àî/ÝÁ+f–À»Ɉ³0z@Í/Üd@,ÝH~}ÖÀJÀ×£&¿ÀUö‹ÚAàá3øWZô@KÔp·ØaÁúL#ÇŠðÀŒÝE(wÚÀu²‚Êq±À¦Œé¸Ho™@,ƒéÉ]p@£øfI…Y@oš7‚Ñ@Ù³`Ý!m@w]QmašÀÛ5ó(BƒÀNŠeª*hž@Ãõ B'‰@ç´½»±ÃÀÔð“®)¬ÀAЋB#cD@œŽk=Ò¿%=äj7@®²;aòMÀJ{Y7?¾ÀÇ"Š;dÿ³Ààá3øWZô@œR³?\ný@HœÞj¢ïÀ(lïýÀ·7k²YS¾ÀoV!­À'ÀÀÏ‘‰÷Èw@½ï¦ÿœN@Ž™Æf7@æ³`Ý!mÀoš7‚Ñ@Ƙ‚">”‚ÀÌ·{¯0sÀilͳˆþ†@|³}%}s@ä<žRGªÀ&†•‘ý®¡ÀÑk=Ò?AЋB#cD@Ô#z²XúLÀT­ÆjÈÌb@B³*cE¤@9Ǻ—’Ä@-Ö>GœÈ@%š½B1/¥@Õ —¢ñÄÀî,“­e˜ÀׯA¦äx‡@oÿ8‘cÆÀ§í7oU¨À±ÛÆë;_¸@ï±¾ŸÚ‹@œ3gžÒ@*Nc'Õ{@%š½B1/¥@Eš=“¶@,‚ RУÀíhÙ„Ç@’ÀÞÆq•@e@oÖäè ¦ÀËœ±¾ý³Àt—pßLè•@;öm| i@u;ü»@~˜$©VÀQ%çô;%˜@샯%Ń@žã\´Ìx@*GÑ}–²¥À{zîd'ÒµÀãw+’º)“ÀS$½äû«À~³@œY«@~˜$©VÀû;I-3£¼@í[‘·äƒ@|«Ú¾ßIp@úcv…+ðÀ{—Ç&2º@ØFˆnœG“À¡è©Ô9¨Àf¤C?¯™@†WËâ¼ÞÅÀ“S/Ç-MÆ@²tÎ’cݰ@KÔp·ØaÁHœÞj¢ïÀQ%çô;%˜@í[‘·äƒ@gÇuAéö®cyê@‘,ç…Ì@ž †N¬ª@ÅÆ]p!éÝÀdãd­Ž-‹ÀÝÒùG?Ü@Ó ÑÔy@·;"æº@MzǤ@ML$’±@‘=Š(“š@úL#ÇŠðÀ(lïýÀ샯%Ń@|«Ú¾ßIp@éö®cyê@5XßÞƒÿAÖ¶y¶@­ipà•@¶Õ3¹ûxÀã.ФݧÜÀØ™Kõ[‘z@øŽ' Zd@b„/®)ޤ@ï{f_@äáÓÛñ!¤@ê¾Ro1øÀ#îùÎÈ#±@køÆ|æš}ÀC¡Ñš˜ÔÎ@ ” é~ŒÀEm™>íÖÕÀ Ö6¾n´@²É—²×à¸@z¿•RÇZ@‘]ÙŒ”@žïVi¿À…êü²3k@¿Ro1ø@ãáÓÛñ!¤@køÆ|æš}@#îùÎÈ#±@ ” é~ŒÀ(œùÅ‚q×@±´°õž!r@“ÁçÛÀu¿•RÇZÀ²É—²×à¸@|¸Â:2pb@¡öKéY@P¡%ÕÁÀö¬ö}Çæ@~WEvpµ@!ß’ÕÉ› Á  mpLçÀÒç9“ÂXA-‡5Ci±Í@^éŠÈ^ÁëÅØšO|ÏÀÚ•óÂb¶ª@‚3Ç›³Ù‡@sߛ₃Ë@P#pþ€äž@Òª£Î44¦@ˆAü{´ËŒ@n”,FÖ°@K‡äSƒ@Ñ_žp§#£@BÞ3và€@0ƵÌSÎ@pë~ú,[³@aÅçZBƒõ@Ô-Äq"à@¤’[ý­d¹@@ÆìfIæ‡@´!`îòÖÀ´mƒ”ÜÄæÀ-‡5Ci±Í@´Ÿ®Óx‡AOJ8=éÏÀÞ:*1ÁšÝk[Ç}@HáÄ[–Z@ò‡ê$Y@ç#‘eÞyp@=¥º~Àx@%k¶Ñ `@Ï“OåÄ‚@y÷‹?s`@²ýyÑèUu@t¦Šž@ÐR@è7ã‚úæ @ªõ,kÍ“…@ñ#a=ûÇ@ÀôÚnü±@c½»`Ô–@b¿Î®jBŸÀÿ>òîiÀ]0g8—AŸ@s/uÝ"´“Àj¬»óÌ¿b¿Î®jBŸÀ•ŠÛÅÔ@b¿Î®jBŸ@;~@ƒþˆÓÀ ñ¼6гËñ«“ÀµÎÝȱ¼ÀƒµmúŒ¨@»OH®AÖŽ¥-¼ÔÀÉÛ›@Ó·ÿLgxiÀ$L Õ„@oàmt¶MRÀñx+âþyw@ÚAç8‹ða@1e¿×±ã ÁC¿4¾Àfâ}À;@ì@îctúÑ@¦Øñ”éÊ@‘’Š‹Ò·‹À@Ö”\S¹›Àüuо¾(—@¸¡Á‰w¸ÀGÛ µ½¾@&G4·¨±@;ò÷é°ÐÀÖŽ¥-¼ÔÀP6°vè AÒ·ÿLgxi@ÉÛ›@oàmt¶MR@$L Õ„@gÕ¾ ¢?b@vYóB«ãK@¦Ð5UuöÂÀ {«zˆëÁD1ãSÔÉ@RÉ ¡M<¯@­‹#.½j‚@(5޳j¹@J©ÿݧ¡@He»ÀB~»;bÃ@꛹úŽÝÀ“9}þ+×@¯ Ücóݰ@OõÓͳ9×À˦Y ³Àxúnè¶ÂÀIÃF‚ÊÀÖ2_c&Ì©@Ÿë0Ý2ÀzJ‰œ1Z·@:•xš@¯ Ücóݰ@ž Æí˜Â@}æ,í³ÀJo 5Ý®½À(Ûé5a‘ÀBÛLê:¶À›ë0Ý2@Ö2_c&Ì©@ø‘ùM7š@œš\¿â}@üäÿ~ Û©@C[6ɯDg@ä+ n­{@ž¦R˜™š@ô¦ÊòUgx@¢@~Ô$.ºÀ‘Ç߃šÀó‘¦Ã¹gš@…°Þô:…@C[6ɯDg@,|¾•üA¶@z´JF3-¤Ààe2íÜ…@ÙËçËd@2ûõ±˜ÀYFÚš{Ä«À¶ù«Zð³…@gt'sq@;JÓȉ!A—ºË’ÔRâ@XµeéNÁ°»Ä,j¶ÔÀ6sMÔüsð@3Γ¦™u¼@X;„¬OÃÁ¬Jþ0³ ×Àä+ n­{@z´JF3-¤À—ºË’ÔRâ@cèyÏ# A>^\¶ÔÀ#qC†­ Áyb}¿üßÀ@íÌßi0@ä+ n­{Àø^çÏÄ@['K_ØÀ\›¼ýÿ£§ÀˆÓ,íªüÀ;Ñ3~Zœr@{CÖ¯A—7V/¨Ô@8õ»dçÁ<Î8¶ÑÀ+ž•š‡ÕÌ@•€M>Ï™@úŸ ûM¤p@øÓjº×¸¢Àû7?ï[5q@úkt앤ÀšÌ h~À¤!ÝX•:ýÀ—7V/¨Ô@è¦ÑZ:A—µ`@ÒÀ¥S£§ÙçÀ-°!=wž@z}N˃îj@ô ²64ŸÀ¸&Ä>JÑ@{DK0" À:%­\ÒÒ@9¢Ü.=™@"7–[—7@oÑüà/dØ@q°ŠœŸó®@ïlUÓÌÔÀT,EÒR«ÀºT¸¬´ÀOx‡ „~À"7–[—7À8¢Ü.=™@q°ŠœŸó®@YFÓPÌ@é H]ŽR«ÀA7·?^ÈÀÓ»I{À w g¬À­äÂâ€É@>¿ÃÃ:@Ñ?D£f©vw@j¹²²ŽÀÐé#—uv@é ТÐ'a@ÓüZ’N{@*wD %&žÀ;ÈÌ-þƒÈÀÆíPžHׯ@Ÿù¯J®p@íy°¡>’ÀÖÏŒHažÀ …¼¨…º`À>¿ÃÃ:@Ñ?)³ˆ0€É@ú‹›dâ1ŽÀäCp1À£@V¼ÑáAa@ŒCÅ·à[J@&©謑‘À`Æë.f³@biøˆ°¹¥@&`¨¾tÕÀò½6`w…ÀÁßó‘z§@Xû"B>²aÀ{Êÿ÷z•™Àü?rÐAØ]@JK-aº‹Àü?rÐAØ]ÀJK-aº‹@JK-aº‹ÀavMïù@JK-aº‹@U“yï¹À]X¥ã¯&AŽ'VBD…×@’ ¨ÌÄ@hŒ6£ãtÁ¼ˆð5ÙÀ G΢§"Õ@ò¼û‚W¡@æ]SÙ`PÁ@?ÃýÀç€PÀ>]ÜwáÀD'Pf(v ÀŽ'VBD…×@¡R‰ö.AL¹œÆ|™@¹ rôÐÚÀ»é(ÿíÁ^¼†È}¡@r‘?(´l@@ÃýÀç€P@ç]SÙ`PÁ@² á«æ@Ûì€: váÀ²Ži¶×d\@™1®–fÀãÀÜ‘‰@?ë‹Ú3ar@:TNXîsÀ±ã땊eiÀ-ðÏó yÀ^A†mT@]ƒE”J@l–ˆç*â@@k¤hc×5@0‹ƒ–``À\¯ÿ›´ÌqÀ:¹¾bð›Y@PÀi°#DfÀœdk©3¶q@?ë‹Ú3ar@b€,‰ÂC@'‘˜QngÀÖÇ´@/Û]À°¯¦—²tY@¶¾qú¦þ|ÀÑXG bã@@È1÷)­ƒ5@[%ýñVLÀÍÜdWëÊt@y7ÿ¬À“Ê\DÒJÀ¿ •ˆt¼×@Ózì‰àá´@ ÍjQ°°âÀ¸ãŽð{\ÁÀH¨îÐn©@óòxîe@z¼w×Ó‡À•wNÖ€[¶@ü«¸²!z™@ÕRX™°ƒœÀ]Ó®ÙvÓ‡@§õÊ4ô%º@v† ª;â@Ózì‰àá´@«Œë¾½¦@|e(Ñâ£ÁÀ¾f×DËb ÀÈBøøvŸ‡@ á`ì‡Àͨj_þ©@S ÔHõ•@jZ!A¸ x@ á`ì‡@úßí wp³ÀÝþ@œã­˜@޵%×q4|@††Jí@P>iXj¬@Ó6T7Òßc@E±ü\ÖK{ÀK,—¸…èÀ%ªiXj¬@+n—·\~è@çÕpšÜ…ÀÿÂâÿžž@þÁ»î ™@…RR.@NìÀ§#W ^ä˜ÀÈÕ`m‚[¾ÀØ zÜi©À7‰ywº(Ç@œ~32+s@+¸ŠÁ‡(œ@³€;KÀ@Lõ•t–¡@ þv¸öªÀáôF(éÀƒm2Ê;‚@Ÿ Òçë™é?ÐD’­³ü´ÀÖö˜à;šÀLõ•t–¡@¬¬„&›@£él»OêÀ·—©^ƒú›À! Òçë™é¿ƒm2Ê;‚@†¯·Ž4šÀ´ÍrÊØ`€ÀãwšÑÀâUBø¡ûgÀÉÛ›@Ò·ÿLgxi@ì6Ì?(ç@x?Kþ±Ð?.ƒ\ÃãÀËËaü ÀJ½îSNz@~_(„@ºž° =‹»@wztàSØ @¯JOã òg@d›É­ÕÑÀÓ·ÿLgxiÀÉÛ›@x?Kþ±Ð?jñnñŒç@€Øn¹ Àp€o”¤àÀ„_(„ÀJ½îSNz@±øó²Ý @ RÍ´f „@Jš± 'úÀW›©ÙÜFvÀÒSƒX «nÀØZÌi7ÔNÀAÉ+hã<ƒ@¤ÿb@ò\ø@תZ@·²^UþC@maäÏ«]@LÊõ±>ãC@­ìàÆ=Ée@a,ýÁž©P@£ÚˆeÊs@ÙÁDgç]@1ÌOšøõtÀ¦³«ùlÀ°N÷ý3OÀÜ1Êæ_œTÀ¤ÿb@Sï¶ËÔŸk@(¬kiHB@é§=“³i+@R>øc›WD@4 E+@ŸùÇyeßM@²£¾ÎíØ6@ÿ»$5"[@ª‚2Þv€D@°½ÞW¯-AÁçN¸í@;Š „†öÀô©‰Ñê)Áûƒ–îœCëÀ¢ÄŠÕÜñ¡@G^Ãy%õ@;=ppðœ@‚3³hÀh½ö^@îÀjšÿäqø²ÀÁçN¸í@Q}æ»AJIE[ÀÀóóhŒ*¤ÅÀÙ.4µÓ3çÀF$8ØqÁP^Ãy%õÀ¢ÄŠÕÜñ¡@‚3³h@;=ppðœ@|*õs(´Àþ˜Uº¬vËÀ+ü¬¤4ýÀT¿Èg„™Àõq»Ì@™X'£=‹@E.b%zÉ@Åþs<*PÀ;Š „†öÀJIE[ÀÀ×òés A4ݽ׹6…@Ç·ÓyhÎ@Ð/—Qðââ@’Ú^ÎD|Àؘ³î@ >³ÜĽ@TŠ“!Ñ×@ÓŽOŒ˜À“_5Ek©Áb /õÀàSô„ÌÏ@ßôC1@'öu›Y%à@) Jè8¡@GKD™y?¼@”cª:Ї@ðLŸÉÀ¢Àù¿n3póÀµ ËΔ‹@}Aˆ±&J@Æþs<*P@E.b%zÉ@óóhŒ*¤ÅÀ4ݽ׹6…@ùßÑÏA8Å?Ë1@Ú^ÎD|@Ð/—Qðââ@ÓŽOŒ˜@TŠ“!Ñ×@_ä~þõ³À¢Æ·F>þÀ 憎@nzCGUL@¯†¹4Ÿ@{ë茈`@ ¦Ègf @ÿÊñ|êt@è@ceˆ¦ÀG³x«æv‡À§ó²ƒDy·@}j‡–ô‹@™¹&¼ÀqŠ„tš†Àx¡~ u@Ó¯îÓ²Y^@V^9»^£@ãolJx@qþšcÉŠÀ>"‘»þ’pÀÿÊñ|êtÀ ¦Ègf @€Î1 ³xÀûvþ2¾†ƒÀ}j‡–ô‹@6¬¼À® ª@•“¹—S¢z@š‚P$ ¼À<¯9S,Z@·s¡lÍB@ãolJxÀV^9»^£@ùø=¢ŠàaÀK(‡ÂµeÀÝ3g„ùÑÀ]&(ržû@5GQñ+ûÀš—u’T½‚@p§ÕZ˜7g@™¹&¼À•“¹—S¢z@2l^ê@_×ç/q•@cjÔãÝ¡@Cx?:I¤x@ˆÀdÈ?ÞÀó}^˜.á¦À|e/ÜMs@YN¿%Û[@Jý"¢‘@-¯Ž ¯F&Á§]«.ë%AqŠ„tš†Àš‚P$ ¼À_×ç/q•@!Hc?"zæ@ 6{ÊÑv@‹Ñ¢†¤yO@½2ÝDæ À³§ðë•ÎÀ‚³ÉÚÐAµ@PÙDÉŸš?Çù}í3‹@®BéI,«Õ¿Zu¢Åøê©ÀÒdMÄH•@ñ…fêëv@=ó¬…ïH•À—êå0½«À°Nki­uÑ?PÙDÉŸš?ŽºA€’Aµ@¹BéI,«Õ?Çù}í3‹@q{°"ó¡@®¡þ^SÀÀq{°"ó¡ÀqG‚Kàµ@îÜ2Þ(U׿T/åÐT¼«ÀÜÄŒ!.¯òÀM‰µ|¡¤Ô@H7Ë{uœò@æ7¹¬ ¨ÔÀárñ-<]@þEKøÅ¿ÄëÓZ}@Ú̸ _áf@SrdMÁ³×@Y`Õµaõ°@~ѬðXKÚÀ΀h’²À4¼yxÄw@•¦·ƒYfá?UO€ð&è•@nÍ|˜F‘n@ÌN<Àµ¬ÔÀÖ ?AЫòÀæ7¹¬ ¨Ô@H7Ë{uœò@ÇýEKøÅ?árñ-<]@Ú̸ _áfÀÄëÓZ}@Y`Õµaõ°@‡îQ‘¹ Ã@zéòð1r®Àó—vïíSÈÀœ¦·ƒYfá¿5¼yxÄw@mÍ|˜F‘nÀUO€ð&è•@“,èÊW›ÀZ« žFQaÀ~ѬðXKÚÀzéòð1r®À›]æ.BDÞ@É¥•ö b°@}Ö¿ô;@'Ìܳ#$@ÄŠÃAe@¤ÀÞ<€=¢¿è38²Ï@‚ÀÐË¥k¼ÀO·7*žÀ'¿š.“WdÀì?ôî½jn@Ï6:þ$®œÀ΀h’²Àó—vïíSÈÀÉ¥•ö b°@ÿ‹÷ëïQÐ@ò4V^@ÿh4L@SÂÞ<€=¢?ÄŠÃAe@¤)L³ÖCÀÛãU|<€ÀâÕ’¤Åu@vFÛ?q±@¨7=Ýs@® ÎÇ=If@•Ä|ìîLŠ@Û½–üviÀþÇPWXLq@!wM¤.Ú?ö\o==UÀÜÞ2Ã'Cj@¡ŸQykŒ‹À8œ_gÀ2_¸Nf@?-Ïâ%Y@Û½–üviÀ½-Øèñ ‘@vM¤.Ú¿þÇPWXLq@»+év¿Xj@˜bëjø[‰ÀWäÝæc#gÀÂ7ÂD¶}„ÀºÍð6ÃKæ@¥g–žYºýÀîw©Y:eAè*Ê&J°éÀ˜äF, ,Á4¾Üe¥aÐ@Yd*¬˜ÁU6$ =ALš4iÒ¸Á¼Íð6ÃKAè*Ê&J°éÀðÃç\#A†G}Ì@êFBÁ¥¬›ÃcA‡©ª‘(Áog&#üÖ@êwçHvËÀ79  3T§À²Kj>ýW§@§qÁŽ{eÀ.¢Wdwx@ïÓ$~„@™Ûä2°:@Hñ0Çñ÷@ªG"Å«òL@~[Ý´_©ÀRµçrƒ*˜@Nô1HÚ¿ÀuÁ ¼@ 3NfÀœ_E:ã€@³TødÅÀÞuø[°š@i¹!©g2@Ù›E¾òKÀ90ƒã[i@§ÉUÆ9ÿsÀêwçHvËÀ…˜ÎAº„ð@ç¤êûwÁÈÀÄÔøÃÀz€@£é©4Ñ·™ÀœÛä2°:ÀïÓ$~„@–oÀà­l@¥rOò‰v(@f5{YâÝ•@°ŸÞ¼~ÂÀÈüm¿‘Ä@fœHuÚÀù¯e‡@o! ¨¤¡À¥"Ë‚A’@+¨ÿ<[ÏÀOŸè]¦ýKÀ@î–@e@ˆ¹'šmg{À‡Í¿œ…@7C¥}[H‡@±é¹ÓIF@79  3T§À‚ÖºÖÞ»@÷òþC>@LùhzÊ&‡ÀøEË›¦^ÀI›d×Ε}@³4ËFL:@q¼‡Ò@ÐæFì/]HÀlY³`Α@GôŽR^ÀçQ°Ò¹›¡ÀùÞI¥5ÏS@ÎÖD)œQ'@‰üS× ¿UÀ‹p" $¦—ÀœÿN•êy@8]EhÇ›ÀÁø‚¶T`ÀŸëu1C-nÀ¢–<øT@nbæAÀ±Œ æ¨%aÀÁ‚Ï`ÉE@ü¬]Nó]t@ækjÔ{vÀýÞR5µ¶@ Zñ†À;qÖÆÛÈÅ@²Kj>ýW§@ç¤êûwÁÈÀ÷òþC>@1b~èÝÏÜ@ý Çm¯ @œúj™äãÀx„ùÃ[Àm"Ë^u@EráN‘wÀ!Ðí3œ@Z¢Î"…H˜À›T2Ú=ª@øEË›¦^À3(” r3ÀZëNe(H@‰&Fè#p@Öàñ(ïdÀæ–¶šãö@Ï&nK1RˆÀBíC©Ç¬@“QÌÕyHÀun°§±¼r@GôŽR^@lY³`Α@¯:å“WtdÀ”çÅH,À¢-CÅYVÀ?Š·ƒ „@‹¾í[xq@VÀïH ²À"p¹ÂÞbÀX]$)sÀ“QÌÕyH@ÈÖ¾ê‡À˜gøÜ.j@s…”­¸C@Üo ñ“t Áö•I…\Ûà@»?;]ʈÕÀ¿â hÄ;uÀý Çm¯ @iÛ“™‘TØ@¹b…£ä•ÀÁÛ(¹* A='þçÇ‚àÀòaOƒu„§@ù™{+åÀÄÚz.ø«@;Xhˆ%ÀÝ1•jàÀjª}rÒó Á õoÖwu@[tTÍÝÚÀœúj™äãÀ¹b…£ä•ÀŠÑõÞÐô@='þçÇ‚à@ÁÛ(¹* Aš{+å@ñaOƒu„§@>Xhˆ%@ÄÚz.ø«@«äx”S É@Ë.?vÝþ©@n¼»®dĨÀS†LH,À¢³¬¬À^s Ë4™ÀžVñB¾tÀÀ6/-9¤ˆÀ’ tþà”ƒ@߆:*1'[@î4g_ÊQœ@¬@¹1æ?Ë.?vÝþ©@³éžñÚ²@¨Šr?'FÀ3ÿæÛYŠÀCTíM•ÀÐA©º‚À>º«Â»’ÀÞÔ[‡µ„´À IÑ?¯Pq@qXDë§H@\@¹1æ¿î4g_ÊQœ@¨Bs‡Œ¹@~î—7¹º}@Åχu·ºˆ@vPöv}¬ëÀx¼ÄþŒÀÀ¯®ÿ”µÀ9d¯âsÀuŽéà£À~î—7¹º}ÀÏ®:Y/E¤@¢±ì¢£[r@@¹¤?¦@TP¡ás@%C(Fó'Ú@œ†žÂì´@¿·ˆ#¶yž@aÒˆgªk@ŠéÿTòsÅ@·ËzÌD˜”@AK„zÇ@ß`$ÓâT@~î—7¹º}@ÛQü¿²ª@Ó8bÇF?ˆÀTP¡ás@À~bàSµÀ~î—7¹º}À¨É4v,WÀTP¡ásÀ@¹¤?¦@Åχu·ºˆ@†}Ecf+å@“*…#»–@¡ˆ/(ç?îÀ7`aogÀÀƒÖJŧ×Àlâ «oÑ‘@e&$Ae&$AiyÅ¡)Áš:+wÁêMua¬¤@8‡¹r@3m¿­Ú@ý fIWµ@I  |tºµ@:€¤Éöa‘@äTñÛŸ@E|~?7l@.FP@5í¹-ú`@¾¾J’àB@~b4µ®J;À"Ï·£—ŽÀÄÄcYjkÀ|…á§_@ç¿ÙGWÀh¹—Õ¥Àϙū¯gi@¾Ð®›‹ÑR@.‡Bó @@òÕ¸¨>P@YjJ ,øO@ ¶&hþ“2@Tk±IB±C@oIrqå%@·SPØAÎÀƒPTÜO‡ç@Î~ˆŸûðÀˆå$º@°ÀMØS:Ɇ¶@'Þ‘{Ä[u@êd†ªn#"@x,^PƒQÀEm™>íÖÕÀ±´°õž!r@Ç·ÓyhÎ@8Å?Ë1@48’ÏUÂú@e ÑØ …@—ë@ܧ:@æÅIz§ŽmÀ|¥¢Ñ5æÀýƒà2_¦À"U'%ú^çÀ`öüª´¤@R›+c1@A²Ävlâ@Ÿ˜EÅQÀ”: ­î¸@豞{ãv@ÀÛ œQÉ@wû!·‹@0ìûž¿‹@Þbª†÷øÁ˜‘êFQžÀÙÍ3¢/ÜÀ7/Æ3u}UÀ }ë›À¿„@ Ö6¾n´@“ÁçÛÀe ÑØ …@>a»ù@L{Ò9ÑnÀ%#fk‚¡@1Á²ÆÛpÀ!«ì8Í-àÀ¼™îù†°A–R›+c1Àaöüª´¤@ºô.b ´QÀMHOå …@\öÊrfÞÚÀZ+º¶“£@ì ›®àÍà@‡„Ô@ì‰FÔ9•@fFɱt@@=·>A@uWÆß“£À6ðÒú°1ÁÀzŽ\Ðð“”À8æS"Ÿ@ù¨››†”áÀ‡„Ô@nù†ô’_Þ@ýê(fgw@Ì»&JV@¯¥ù?"ŸÀ¯Qa•©Á@Mú@ $h•Àï¯C톰ÀìZaÈC@¸~6M8'@6M»˜L†Àí­úºs_iÀ©s@‚4|Æ@ƒó˜è½Àˆ@³â96Á‘ÇÀŠAPììÖ{Àä··Õ8Û–À &VYàtÀ"ÞEÂY–Àó‘°ÕªpÀd©:-£+¡@ô¤Hàän@Z×ÏöG¾@!ÞWø;Éh@ ­ B.H'@­‚üQ @"rµ½^UÀV{JqRÀƒó˜è½Àˆ@²·#ĺ@VòCüÜNÀaªUÒ]…ÃÀaÑæŒ:PÀ–©Æ°¡|ÀlŸûEbÀgÕÕ}eògÀô¤HàänÀd©:-£+¡@!ÞWø;ÉhÀZ×ÏöG¾@}¡“ó±åv@φÿ.<í[@³â96Á‘ÇÀVòCüÜNÀË/¥âB×@\Šû]ï”{@ÞŒLˆ@Ç’Oso@KÞŠYäs…@|)â $Wb@›Ïå:¢UºÀÁ-ç¶4{ÀßÛ7›D²ºÀKYt {ÀŠAPììÖ{ÀaªUÒ]…ÃÀ\Šû]ï”{@æ b㥧Ò@ºƒwiUÎQ@‹³ÿ½è³À §$0_ÆPÀ…¢ñxD±À:TNXîsÀ'‘˜QngÀ‚¢ÛÑ}@_4”xeHh@Né®$DgP@Ñ ý+ìêD@ÕÝÓ/[ø‘À03¥|ò<@=¡ÿh@X8ã™^B\Àw‹îA~q@j—"‰ w&@’ÏWúäæA@"ŒÒ‰HÁ¿“¨ dNO@ ë4² 8@±ã땊eiÀÖÇ´@/Û]À_4”xeHh@Ü©Þ)r@€ ìçD@WЂˆ³§:@൶C×eÀŸŠ¶rnçÀU8ã™^B\@=¡ÿh@h—"‰ w&Àw‹îA~q@"ŒÒ‰HÁ?‘ÏWúäæA@`ÐöÖOòC@Þš)à¾.@u%õ¨ž¢Ê@&…¡7ù"£@üX'> 4¹@(Ê ‰Å¥@RJâjQmÑÀF«÷Ó‹§²ÀW+­@ˆ¦À¬›ñ)Û£@_>ýwq@bŒ×-‚’ÀîQˆç‰ˆv@Ü]€ßÝšÀ&…¡7ù"£@¤žßysÀ@šW&£è£@¬-óŸ2—@ñ‰RXp²ÀvxÂ:¿À•¯èH˜—@ÔmhÉ·%ÃÀN„>y‰ÀÀ0"ר«@'W‚Ñ{Àþ¢Ìù[¦³@¡w*ÖÎïø@`‡O°hOíÀ´îôPƒùÀÏN©•]è@X–SO>Ì@^½>i@™²â\>¢ÇÀŽúåbÃ@`‡O°hOíÀ6¥àR2¨Aûä|—kè@Çóú&v.Áe½>iÀX–SO>Ì@Î}&©óÃ@?Kè K—ãÀHRá¬êÄ@WIÉ8À*ذÔWæš@ÔU•X"·v@?”ñ ÷Š¡ÀW€)Ô;²}ÀßbV¼5žÍÀ‚ÔÓ0q‹@Eµ¶¯Kt³@á÷¡üö>‘@WIÉ8ÀýÃ^§®Ò@¥žðv@>Ç;d_S@E9·ë}À9©r‡SYÀcy.¢µëŒ@5ö­0;ãÒÀq%•´@£¤9¼Dm@<>³fA"Sö› ³À@4ç„ØÀ¢ãôÚpfÊ@Ö2l@‡M‘i^‚ÀŠN–ŒBu¬@þU§ÀÃÀP(÷ÈôÜÁ‡ày•rÂÀ{Mˆ†Å{@ÂáËέ‚ŸÀ"Sö› ³À@6^…a›þAÙ`‹É×@šæ,†E÷À»fÅ>@“ÀÛ)U䙩@cÄ\G—mÓÀް¶ê@©øÅ€EÂÀ–GF’YÑýÀùoÄ®õ¢ÀG0ËEƒÅ@áÉE\}‚”@žeîK^rp@4];'“ÀÞ® ErpÀ‰Ž³š¿`ÀøíV­M;À.Ž»•¾ÎF@’ Ï ;@žeîK^rp@'á»{Ç‹@àOk–qpÀ>òà ‰ÀåçëÚæ:ÀRËT`Z¤YÀþ‹²Ý\Ú:@ÃGSÒµÖ/@Mé9óÉ=Ä@VîN––›@¶ÆÉÉÀ™ ÜôÊ ÀÐ23rü£@­1Nýw@VîN––›@rýh“Ír@×H“l ¡ÀÍKò†QãvÀÿ 9 z@i9%Î/YP@ÀEuV2ø’@ßjNÒõk@ã/ñ¶OE@Îý,‡.}]ÀË–oÔ//h@{í\¶ƒcQ@yy§lë„ÀhkyóÁZnÀ Œ[¿eˆÀæÄ¦ ©áP@ßjNÒõk@B7ˆž8<…@NE¼â¼]À·Mü “t@~ØlâœQ@ *_A¯R9@IÓôX.]nÀß x¹fVÀgF%çñP@<aÒ<†À¯®ÿ”µÀTP¡ás@°$Ȱ"°Æ@"Jȇ96…À±šB±L¸ÀVJÞļŒv@9d¯âsÀÀ~bàSµÀ"Jȇ96…ÀŒ1#ìdÌ@¯fzß@'@›D˜ÛÁÀ»AÍÈ,Ê´@)kò¡žP@gÛ±+b@h¡]m”‹…Àù–"§ÀÒ·CfߎÀý@ïãê}«ÀüWq&•@+Ûœ&Í@Ov¡p@)kò¡žP@˜©=0ŠÁ¹@,DNÄ…À°†ÿ ©@;ñÙÌ@‘ÀÞɲŒK'wÀ…s£øï”@‘"ü”™ÂÀ`¤õÜÙTw@¨ö1òX@4ç„ØÀÙ`‹É×@“€—5á]+A&øFZ˜ôÁÝHï}ÀŠ@©š€ò­À™¡/thÇÀ£Ê|ãÑ@õœjÏ}w)Á„[<à&AýŠ“ØîÎ@ÉÆ<:“F@Aœ.€0®m@¯]$³NƒÀ­ökƒ¶¤äÀFå±P(xð@¢ãôÚpfÊ@šæ,†E÷À&øFZ˜ôÁ·KW¨å=Atº€gZ®À×äÍ’IâÐ@ :ë¬ç«Ó@ 0æ9ìÀ˜æ %>A÷;÷s^8Á³Æ<:“FÀýŠ“ØîÎ@ŒÌµZ†UƒÀG8Ìn'™@4`£ ¬|ç@€n‚ò{ó Á(ÏT¼wàœ@Á!ÎY-”À;"äP’ÀpyF]WQ†@æþ*À}@KlDÖ …SÀ"]*Šq¼À õE£6‡@uÍ=µÃ?œ@¨f`ws‰rÀÄ=¤Š!nYÀÍQÉ—]gƒ@„ŸTY„ò¡@~òåBãÀZC}›pQs@’M¼’ $"À²ÿ>Ô™n@u\ÉV`KrÀSèú‘|H˜@‘ƒ(<8úTÀÁ!ÎY-”ÀÐKpv Ã@6’<€à…@ÇifóŒµÀKlDÖ …S@æþ*À}@Óno[Ý•hÀïeÁÀ¨f`ws‰r@uÍ=µÃ?œ@»­Ð •ƒ@Ësþ,â­À‘òåBã@„ŸTY„ò¡@M¼’ $"@YC}›pQs@J^ÏmŒ!rÀKkóÒä @ƒ(<8úT@Sèú‘|H˜@ƒÖJŧ×ÀM· qg³@Ô‹çL_¥@£ž…2ÈA>N÷¬»uðÀ0m=5ÐÀ-LJxgKó@{Õ•ä"ÞÁA]¦.§@ËGˆ*k³ìÀr÷¢)غ@)|®ðM6Ã@œê‡Þ¼/±À°/Xo‹;È@ꕼ‘êÀ&6k€¼?Ö@ZG~dœie@Ùý*K±«@´orI¯ŽÀU,=·Ú~²@i%ÂÛ¯Œ@ðË=bŽ(˜@ Wà‹ åÆÀÊÉ£AUlÃ@KÇBM4ÂÀlâ «oÑ‘@M â²ÅQÖÀ´ª¢»È%›@>N÷¬»uðÀ’ƒÅäY"AfÞFsŽñ@ÐËj°æÁ¶Uº"”3§À×U7éÝÁŽî¡ðàºÀˆºÚűìÀœê‡Þ¼/±@)|®ðM6Ã@ꕼ‘ê@°/Xo‹;È@_G~dœieÀ&6k€¼?Ö@´orI¯Ž@Ùý*K±«@f1$s‹~§@ѽ+?W8‚@™G•ï+ºÀN^ˆWyÍè@ÔRWÛí¸]ÀÑcKªÖ¥à@5Ðò7sа@óµ 2–’@F I=Týð@}³¸â\HÆ@¾ì_€>òìÀõC.PœÒÀÀgÂ[oJ¡@> ü¹¯;ƒ@õøF˜ÊÚÀ +gO½Àþ•RíɸÄ@êÿ”=­¦@?÷eá’@BÞæ ‰Þt@}³¸â\HÆ@ÊýÛHõÞ@}òûÛÀÀ8¸m9ÞÀAŽ5bsÜ‚@þP‡VKûd@–g÷{:½ÀÇtŸ*5ùŸÀýZÔ ›¦@¹EO\ý¼ˆ@вÇ_ a¨@S‘èM‹À5a9i cÇÀ^¶Ò_tÏ¡À¡JᘌÀ>°¶­ k€@ìlÎë´@g3XeR™@í%fÁ,±@4ðáå·|@S‘èM‹Àõ \FIá¶@[F"¨h¢¢ÀgwF`—W¯À¥‘+I©E@8ԖפÀÅqÖT8—@gñ–Å|@ÇüD㛓@ =ÿ:äyq@ þv¸öªÀ£él»OêÀWO¥ûßèª@Ñ…kU•ÝlÀ&pVý@b@ ‰Þöå }À eƒnÛ˜À,ȼc‘@bŠ 8gh•@û¬ÈÂz@$5c{~iT@6TsÌ-oÀáôF(éÀ·—©^ƒú›ÀÑ…kU•ÝlÀêÉpcÉ °@4•€BÁ0}À¨ùðMJ—@ÐùhвG‘@uY[VႲÀÌå6¥z@⋟OB§`@àO”$RpÀ}6œÿíˆ@EŠ#ÇU7 @½ûì?ªHs@©¼ÙY® À…Åz;§OkÀ©KkBv‘@3^Ýä_þ?ƒ]´7”À±ƒ[>ž`À»#.{]^@¡@¼û2@‘ÿÁÎ$š\@O×–H[1@½ûì?ªHs@o¤šê9¦•@vÝ@ôÚÀaÀP¹T¸U›À¢^Ýä_þ¿©KkBv‘@éú3N‘`À½»tÀ£@¼û2À»#.{]^@Q×–H[1À‘ÿÁÎ$š\@1Y‰ž_ÓÀXé{±ôÛÁÀNYH’ª'Ô@7ˤÇɦÂ@ô"ÑQP@·ã˜™bƒB@"Ø£ ‹Àö/¥ˆ­{ÀIà—QÉÁÀWÂoø5ÆÏÀ7ˤÇɦÂ@q ~·>HÐ@Ÿ®U€OŒB@Ó™ˆ– 5@× ÔX̘‚ÀÏfçÊ@†zÀòRf2þV@(‡Ë <@ä··Õ8Û–ÀaÑæŒ:PÀÞŒLˆ@_yÕÿ¬“œ@Î$fm1{@Çÿõ0‹e@ ¾LTkB@E9OÕ\ Àª{êeçƒÀpÇ£0 U„@-ùzQÉ;i@91)Å«=@¾ÂQú"@ &VYàtÀ–©Æ°¡|ÀÇ’Oso@Î$fm1{@™ñT¦M’@Î)5`ÌK@¬ÃZ¿òÃ'@ôÁièƒÀ£ŽG›û¶hÀUÕˆÛ?i@«M(UO@‰ yT@Œ–F¶Cø8@"ÞEÂY–ÀlŸûEbÀKÞŠYäs…@Çÿõ0‹e@Î)5`ÌK@ ~ï'Ú@è«9A]­@§`äªôðÀ÷º GéÈÏÀýøñãÇå@'Mš4i’È@ßD_ö°€1@Ó©¿«ãX@ó‘°ÕªpÀgÕÕ}eògÀ|)â $Wb@ ¾LTkB@¬ÃZ¿òÃ'@è«9A]­@i ¨á4Í@uRÕqØÞÏÀµÀŽžeÒÀ„ *T¨È@EŒ1bĬ@M;Ðöx@µ¼]‚¢”–À§`äªôðÀuRÕqØÞÏÀKW7€#£A°8$®'Žñ@p…°6lÁ!2pêÀBóÖe•Àw¾oÔZ³@÷º GéÈÏÀµÀŽžeÒÀ°8$®'Žñ@3Ú¢"ÄA0:íRæ~êÀ3­éËÁ´RÂJÇ›­@>°F–‰E‘@/뻸r"@@%“ÖäÑ[ÀüòÕf2*”Àç¿ÙGWÀ‡ÏýÀ¤¾µ@®ˆŽiøV–@ŸÈ¥²˜u¹@$œƒ®@Nâròi ÏÀnfH”VÖ°Àjønž*VŽ@srÅR#s@ Q¼ù¦]@Ð 1–¦î•@G¦Žm–y@¯s¤&“ [ÀS*ΤÒQw@ÀÉCˆ/bÀh¹—Õ¥À®ˆŽiøV–@a ̬K @YãgÙÛ¢@eøÞ¿Š…@ÞÜT&å[µÀFp&Î ¤À¬bóE·xv@õð7¼AZ\@ÃÀ¦ŽŠE@¹S´p„Û@+†¾Á À@ŸÈ¥²˜u¹@YãgÙÛ¢@©yœëA’´æÚkä@S7—RR8Œ@z㢵ÒÀs¬C_I¢ÀÁõ:7pÄqÀÞDÚIŒ#ÁäzV­½äéÀ—Qï'=1¼@)¿ œÉ¡@ΠÜ,s‹@Š΀Pr¿@{â"KX¢@$œƒ®@eøÞ¿Š…@’´æÚkä@,cºl%YÈ@ªz㢵Ò@T7—RR8Œ@O6Ko¥qrÀV?À!Ày—À´N°æÄqêÀrŒÐ3´—ÍÀVœ?ò" @ ÿIivS„@¢nŽÅÌân@ ¯€¾ž@×þÞZxÀ½id;Rœ÷@›eÕ(Ù¾òÀ´l„9<‚»@A»Ï”·¥À–¯qkÁ·@ oÎË´‹ÅÀ 1OGÔT÷ÀÖ¸€>‹ó@F´Z©{î¤@)–Úñ d€À{œÍåR°@„˜Äs‘ÀO¥Ë4ÙÀ]”›¬tË@ÅÛÌ5q=•@-Ç;š™‡Àà®@Ñ-•@£ÉÖ=ˆ‡ÀÖþÞZx@ ¯€¾ž@›eÕ(Ù¾òÀ‘ËFm3LAB»Ï”·¥@´l„9<‚»@Xh»{ü#ÄÀ£^÷\DÒ@‘ë¦Eqó@ݽ æT–Á)–Úñ d€@F´Z©{î¤@…˜Äs‘@{œÍåR°@#2nü6/’@„G¶æ“ áÀ-Ç;š™‡@ÅÛÌ5q=•@£ÉÖ=ˆ‡@à®@Ñ-•@j|ìiÆ1Ú@(^uNÉc@^éŠÈ^ÁOJ8=éÏÀw«t„*ÒApyÌ5üÑ@ÿHægÑÀ§}î z¡À6^uNÉcÀk|ìiÆ1Ú@ëÅØšO|ÏÀÞ:*1ÁpyÌ5üÑ@ ;›U/ AHÓÒ Û³ À? ´Ê±¡ÀkÊ7–J©Ú@Z¶g»Ý|À]Û^Ô9EZÀ¾“ 8¾Þ|@kc\ÚÀ(Z½Z¶g»Ý|ÀâE_ÄŠÜ@x  Û7Þ|@iЏйŸÀgÅÎ0Ÿ¿ól?%ýŽÚÀÈäfÍ¥£À@•è˜M»ê@墪{ò—$@…*)ê'âSÀ—ë@ܧ:@L{Ò9ÑnÀd©:-£+¡@ô¤HàänÀ›Ïå:¢UºÀºƒwiUÎQ@ ƒ6²¶@©#Ú]ºf@£w֙ΈêÀêJaÙùö @Ϧi -TÀ+‹hàꈕ@k.¹ Y‘&À°ñàÖry@HÊЈ‡Á3ü]ÙfWÀ:S]¡D˜†@æÅIz§ŽmÀ%#fk‚¡@ô¤Hàän@d©:-£+¡@Á-ç¶4{À‹³ÿ½è³À©#Ú]ºf@âj•ˆyå¯@ó‡¹Q'AÄ`413GSÀH&Õá\í†@h.¹ Y‘&@+‹hàꈕ@IøìuÌQ@(ÖY¾Ë@@;:ãÈ£ÀÂKó‡pÀbÑóUH~@ç èÝ9(@='eOX•@·€= l@€ÁfÉØœ@·¿¹}À‚ÀÕš|’”À”!…ë˜@"ÄIÈÓT@á˜:ÛÅ?@Чód @@îx²xß,@¥¦2¼ÒF‹À„ã‹üøN†ÀHiwâHk@Ÿº’gèÓ@y; ð];ƒ@½®`ŽBWY@·¿¹}À‚À¡æyŠ$¦@v4t ]×@¿EC媠¡À!›iB@ú²R¼£ ,@5a9i cÇÀ[F"¨h¢¢À0(£°Q¯AÖ-†Ïg/Ö@JpÚªä¦@÷ètàƒ@biEñ,X@Þ{ÁnýtÀ¥24ò¿Ñ¹@ÆyW_¢ÅSÀÕÕ_+¬ôÀ&G=¬=ËÀÊD$ÍÅ@èÀ”˜_@%Ô¹À^¶Ò_tÏ¡ÀgwF`—W¯ÀÖ-†Ïg/Ö@³§|â8ªí@Å‘(]pSÀR„þ§^üqÀûg,²|¾Ò?+ïåI@` â!¬D@¨ÿCk–c@Oõ›áV*Ì?$´ŠQ®9=@®÷e0ßÄJ@NæÅôŽ4@<‡Ú‹¶t@¼¸¢“Ø~`@¦Œé¸Ho™@Ï‘‰÷Èw@cjÔãÝ¡@ 6{ÊÑv@G¡ŒMæ¹ÀJ®l¼ {À o)ýÎ@)%}D=˜@3(Ö1a@ÞãÿœHJ@÷dö¾è‰@U·ì{ùU@¡!Ȭ½¢À‡±î*ânÀAQ¡&È “@®=¡›%’d@ëÇ^‰¼·ÀÇpxJÔÀœ•÷ˆÀÀ‰@-_Ü#¬`@Hb i¯‰@Ë‹ýèËÄÀ®ŽÓ¤o”ÀÛF×,r¡Ÿ@Ýl&Øíp@Cx?:I¤x@‹Ñ¢†¤yO@ý‡AI¦uÀ~‚ö¶·ŠÀ)%}D=˜@5¦èœž@Ç¡ZRÎ`@LqjÉë,@^¼zÆGÔoÀ^ÆÀ;Àp¼TÊ¢vi@ œ¯:@¡ô‚°åØŠÀÖõõ˜ãaÀþº?6a´`@~tí ¡5@t®˜—!©`@*Ô#VB+–À¼ª‰ z–Àªœ8¼e„t@Bæ×HöE@5ävt±³@®æ’:_ü1À.ƒ\ÃãÀ€Øn¹ ÀÔ/´Õ£«ê@7u“’n­·@Z]PUÒÀðÙ¬}®ÀÙæ’:_ü1@6ävt±³@ËËaü Àp€o”¤àÀ7u“’n­·@íÏæ‰æá@²DÐËt‚®Àj3¬½À7úmg>Ðä@ž™zæ¬&¡@“Úz ÐÀMsìrºûa@ÚòÌô€ÙÀûðP9F¢Àž™zæ¬&¡@ÞmSìqà@!D þaÀè#À#e ÐÀ[¥XJÌ À»³¤—XÞÐÀ%êMif€|ÀˆqÆ*,Þ‰@´« =€SË@Æ€Ø- ~äÀFÄC¸ˆ…@ „¹•LÀZðÄ&À D@Tìe»8ZÀéçrLúcÀ§Û0’—í(@ÆÑHmAR:ÀN$ü£ƒC@2E/"qYÀØlÌ‹JR@u)7qÀZR_;/m!@ó);)ÈSÀQ›^Gw+p@\ìÞµ ŒƒÀté}›˜ÌÀÝÿ$¿Då@ÓRº³¼Ã€@ f©ÓÖ¢ÀÈúÉzu¾àÀ+ø.8°ù@ „¹•LÀ½JAà ¦@ ø;ü7)ZÀTÃïãq@Öm¬h¾z@`m%úD@ÀÌå%[Á-Q@»ÿ¶ÛxYÀ’%˜ Ôšp@g´H,àgÀö&O&¢x†@j A:¿6À(:ÍW}Øh@/–™úßЃÀêbÃ@fô—@ïûî ©…á@Å™êòyúÀ#gmIŒ¢@o#=*ƒÏÀ( Ž•½ƒÀk_Çeñƒx@¿}’™„e@´Ã™¦sPÀêpi©è‚ÀOqÔ¶˜@o#=*ƒÏÀÇÐ]:ÓÊ´@+y 8DFp@Ž/iql@•À´Ã™¦sP@¿}’™„e@é¨Ð!¹¶˜@tJ쯑&°Àî~¾D˜¯°@sQ¡C‡‹‡@+Ÿôê_ÿ}ÀF@Ï“qWÀÏ$]¥×­ÀgoÞÄëÀ²k]Ÿˆ0<@¥ p;ñvUÀsQ¡C‡‹‡@ ©²‚z¡@ÙNìÙWÀ†sC¥šßkÀŸuHœ¤åÀz$˜È¡Àŧ)UUÀh‡p°U>p@M㋸Mé@ÎJÙ£B¤À¯i¬è)Ñ@;Æ­=ThÀÍϯ\ÃÀ%hÝ D@1$› ˆ íÀŒ“„„J¥@ÎJÙ£B¤ÀÈ_“¦Q›î@>Æ­=Th@¯i¬è)Ñ@´-4ö7DÀI…9Xh\ÃÀ ºÕ¨Wà¢@50 ,ñÀüX'> 4¹@šW&£è£@ÛGoõ@YNþÙsïâÀáÓSùmÎ@·Xty¶@"!è qÐ@úe‘G7®@õáö¾Ç@›­“êæ-¥@Ù-ÈÂtºÒÀ³2‰,¬¶@ž¯O!ô¯þÀƒ¼uàÅÑ@UÇMè¹@(Ê ‰Å¥@¬-óŸ2—@YNþÙsïâÀ8I™ÊdAîJ(ÊÎU¸@ó½zbî¡@ZKÙw©º@,)´UVl˜@ãÒR…«²@wûb#,‘@3ÄÑ(ä·@&ŒÄh/ÞÀáÐéCòãÂ@-b¤QóZÁ"ípÉN¥@løªdõÄ@Öc·¾Ç¿ÀÐùjƒÿp˜À›æêˆ‚,°@2™©¹DçÁÀ¬´„Úp7¯@Öc·¾Ç¿Àâ¾WUîÜ@öoŒ•a°@ðˆÎC!®ÅÀ6Ì®cSÌ®@!\\pXÒÀ©¼ÙY® ÀvÝ@ôÚÀaÀô"ÑQP@Ÿ®U€OŒB@˜È䥕Þ@‰¿þ!¶‘`@BŒß›ôàÀ6øÿò l@&= Vgu@"\gÀxê‘ ¦ÀE6°`Àí=EêÓFÀà«Û OPÒÀ ƃ½)À@²ÍÕµùÓ@pm…Û¾À£Ñ¼ÕÊœÀ}Š´ ûŸUÀŒ$2µð:`@Ge®¼B@šÓj|âz@©ßQfd„@v›ØQ•G:@ýÓ'§C6@_½ì˜„5@ÜópÁ»¿@ßw›\jeæÀpm…Û¾ÀšN”Â’æ@Y3(lãOXÀ=,hî*×—ÀMyŽ£œB@ÙìâÕ$@S7—RR8Œ@ªz㢵Ò@•Õrwyg±@4bú—/õ‹ÀÜ|2É4³¥À¤A„È‹@"üXºÒ)¤ÀÀ+½z㢵ÒÀT7—RR8Œ@4bú—/õ‹ÀTq™OÇ»@ã¶È!Œ@½D®Äá8µÀ@>®}]q¡¿ ºÉ–)¤ÀsÎ&Fè@5æ)úm·@r×ó¸ërÆÀÚÿIK$/ˆ@¶*Îgh@:R5C§ŠÀ^:ÂâÀÒ«iƒVȶÀ5æ)úm·@ÇÇ_t1_Ý@ [M‡@aÕKsxÁËÀö2jX6Ö„ÀšÒÄt…Á¦@ê“Rf·À{Ì·VÒÀs¬C_I¢ÀO6Ko¥qrÀÜ|2É4³¥Àã¶È!Œ@§;þ³@5)¤heæ‚ÀÁõ:7pÄqÀV?À!Ày—À¤A„È‹@½D®Äá8µÀ5)¤heæ‚ÀŸ‚IÙ»@§qÁŽ{eÀÄÔøÃÀz€@x„ùÃ[À‹eO›¶y@Rsú~‚‘À9 `7C@œu®µ6I]ÀWÕ-†” ,@ ±D¹PÀT¾ÿèÝåL@è4ox:_À<°õJ“é@''*´ô3À$µ/Ÿ`ñ<@¤Â„³áaÀ©âEýxÀš°ñTcE’@.¢Wdwx@£é©4Ñ·™Àm"Ë^u@Rsú~‚‘À¹âö~sêª@}þ¨).]Àã)œ4TW²@áv)ŒöðÀ7Å‘D8ÃÀGbBÁÀÏŸ5ôŸ@[.œÒ>Ì@#ðóÜ]+©@TKðW²@^É`«›…ã@Éé“_ÃÀ‹™L…ÛÀéË  ’1ž@ìÿ=6˜ÐÀqQãX„=©@`¢9ë°†@ÌÙId.ÏÀ\%Í7y:¶@¥4ö öÌ@Aòˆ:4þ´À€a:AEÖÀ ZP‰ÐŒ”¿åOæT›ˆ@ÝðËÓ&YÀá%7ÉZ»Àøê[[´zŠÀ;8C@8÷@LÕ€ÇÉÀuM—à@áÀ9¦þ*#®ÀÚùbŸÜ@9ˆ‚n©Ñ¬@ì\Ž«èåÀLSº|ׯÌ@XëCãÏÀ@ø E<œ¿‹ßeQµ¡@_<4Úlh@ òæD~µÀV‚¼Í0ÞÏÀ@òˆ:4þ´@¥4ö öÌ@€ôO‰ÐŒ”¿¨ç€`+EÖÀú8&$®l À<Æl‰Æº@“Ðé¿‘ŽÀ“o2çÎ(]ÀLÕ€ÇÉÀÜ–“îƒÖA9¦þ*#®@S:J(`@áÀ9ˆ‚n©Ñ¬ÀÚùbŸÜ@Îwm…ßÎ@ÄO[X{äÿÀpJ½ß¯Ð›0ãÏÀå :ã'€s@Á¶an»å:@aI" :,iÀÞѧ÷oÌ@ú Ä{?žÀuM—à@áÀ9¦þ*#®@ ‘qmnø0A»|Ð'Üð@ì«­ª,¼ð@«´€)3žž@£v«¤Ð1ÁË;bb°ÁñÀ uO'Š˜½@ú Ä{?ž@Þѧ÷oÌ@9¦þ*#®ÀS:J(`@áÀ»|Ð'Üð@ç„ð ^"A¨´€)3žžÀí«­ª,¼ð@ëÕ(í3îïÀÓDFH¡$Á$~¸z»ç¸@=-Q*×°‹À»õ1˜Î!³À‘ÞNMÒå‹@ÓvÀŽ@‚®Ë1w~ÀBê!èNªÀ­á­£êYÀV0·½;Ä‚@åÄ2±°r@°_qÍl>Z@=-Q*×°‹ÀÄòŽjÔ”À@5îýæF}‹@ê¯DC9d»Àd®Ë1w~@ÓvÀŽ@Û Á@1tÀ;_æ’ÚZ£À©ÏtÎ)k@q¥· Z@y‰óö;þB@OõÓͳ9×À}æ,í³Àý Ü„WŒá@øšš— 1À@T™Êwö½ÇÀÓ•»µªÀ˦Y ³ÀJo 5Ý®½Àøšš— 1À@#/Uˆ²À@²Õ.sƒªÀ #x½¨Àº\×Qy@´ó$òãœÀIîá(LqÝ@Vѱ°ßêÅÀ cûGV“ÀšÂ[’.n@Y”/þÝÀþ ,ÉŽ„Í@Èû3¾³@á8=ýÕ¡ÀœOàß 7Ào"PäªÀ@Vѱ°ßêÅÀí b=kó@šÂ[’.n@šPœ‡%¢ÀÔz2¦J¬Í@øZÎ3Ï÷ÀV:8Ï(J¢À¡Aém“Ä@°„Õæl@þE§@†yÀ~>€úô‹`@vb(È}‰ƒÀDb6¶Ø@¨²s¾•±À$A[k A&_:[,òÀ+„vJ³ÉÀ6  qÏæÎ@ ³»ëÛ@‚¶ÿ¢Y¨@S«)ùÒÜÁ&õlþJÍí@„0ê_ˆÀ1Å][–@9ÍKS®|ÀÝÝ6 î @¨²s¾•±@Db6¶Ø@&_:[,òÀb_¹¸½ºA~…€:Ð@0Ï ¦ñòïÀ€¶ÿ¢Y¨À ³»ëÛ@(¾ë4)ì@Ã,žÂ'ÁÇ2tÒ-í@rv´NsÁÀƒ¼#>s“ãÀ=¦Š%QÃ@æ‰ßá­ÔÀGg%‘€ž¬@+ÐC/ˆ@ eåÁˆx¢À»Ç*0V!‡@>ÏÑ[S¡Àrv´NsÁÀéž]5[¥ô@ÄŠÛsŸ=Ã@¢P zðÀ:GV2­@ºLdaL—ÞÀn †“‹f¢À½O þN¼@WÀÓô¡À1êtDRY»@ƒ¼#>s“ãÀÄŠÛsŸ=Ã@Ê3G‡èÝ@ 1¹“-¹ËÀú¤¦’×>Å@×2—þ´D@ê´X|@ÔU”¯‡B•ÀU›W|ö&ÀªŒ Q¶@=¦Š%QÃ@¢P zðÀ 1¹“-¹ËÀß}Ž ñ@Å2—þ´DÀû¤¦’×>Å@NÍŠáB–•Àú()²0°@èÊ¿Æ _¶@öµ²œ[ùÐÀæ‰ßá­ÔÀ:GV2­@ú¤¦’×>Å@Å2—þ´DÀë²¼íÝã@7³ZíóÃÀm.³ÅëÝÀ·ólÀpv¹@Gg%‘€ž¬@ºLdaL—ÞÀ×2—þ´D@û¤¦’×>Å@7³ZíóÃÀFÍ¥bYÈð@e„ë•[m¹@’úàH¨”çÀ«$G¥ßEä@TkÚñTÑÀõ)‹–Ah@ÆÖ¾þ¹›R@Ä×´ìô•@t'UÐë¹ÀÀó×L§º²ÀÕªÄtÀ W·s¶âÀp¢Ay Ø@TkÚñTÑÀ{6/7Ó¯ó@‘ÀÀ®˜R@‹uaˆ<@U,§q¬ÀŠ_?”2ÊÐ@Єd–âêtÀ#è²–įÀ Á˜­L#Õ@§ÖTæöÀ2¡í³o@«F]ÍÎT@“YîÌF@ù>±¶Õ cÀ” Ð`ÑÐ~ÀšŸVc"-ƒ@!ÊÕ+Àg@¸ÚF¹„ÀC8ÿ8ÈmÀa­9ÕcÑ]@«F]ÍÎT@ª»6«9×v@3’òvåÓ\ÀÈZ&ýÀÿx@‰õ‰er@)•2–ÀM7ôtÀ’~r§t’@©¼m¥vP@«§Ær“f€À{&Õ°×ã@ç½W·¹Èx@¸’A[:AÁ@ˆÖznÞh @p0Ôò‚À_@µu®ìA@Þ;•JÂÀtéÉ£ÀG«ehëOx@ðÀ8cåb@ˆÖznÞh @n:°@\[aNÆtB@ÀòMC{…À_Áô®¼£ÀÉzeE¬À@– €_f@ óW˜;ç[À÷[>ƒ›ätÀ¾·Ê×ûRÀ9¾_T@3#½C=6?@8d´ÑWEÀ óW˜;ç[@9oúÛ¦]@ß¡b‰§WF@ óW˜;ç[Àýç®gñÒz@+·ò–îRÀ’(à™§dÀâò©+?@›©wˆà'@ óW˜;ç[@áÊÂ>rÀãaìØ’GF@Æ# ‰1@ÜlÁ7•@a,/F¶)a@2e„»]£‡À°iªˆ@Ù ç€Z»|@ÙÉäXía@è uáDt¤À–¢#Jüw@+„vJ³ÉÀ~…€:Ð@9=†ðøÆ@ì)áÑ'ã¼ÀXáz7§@<ù…ݧ(ÅÀÔL§«Ò÷q@Le¸þh=@y2“~¡ê“@Kƒ'qAª¤À¿4Š»ˆUX@~©ô ^>@ 283’Žc@±ÌÊdM©À6  qÏæÎ@0Ï ¦ñòïÀì)áÑ'ã¼ÀjÓ².Œtà@*¡Œ§3ÄÀg>–YoVâ@]É>ìŸêÀõf¾OG»@:ÌžËBuï@‚§+ÓKÀ½ÀµÉ»–=ž@—(­TÀj@`Ò¼¡l©@^çé òŠ@ŸÖ^”ÕÀ•_œéËc¥À–Ý1H²@&jN‡tç›@EAë°»r›@5UpI!Ï@CNbÅÀ@?t 8eñÀ‚§+ÓKÀ½À¿AQÿÐó@¼è?¶€@êaŠ4‘M@»|<ÀŒ@Pnr%Èm@C˜¬’¶ ®À‘债p(ÅÀ³UéËØ4”@áêØe×~@«:˜¨cV~@üd›&”a@DÒ™U¹ØÀ9¼†‚?±À²Õ`L¾ð@évÑ”Å@ÿ;ùzË@g”4îÈTÀBƒ W¯êÀµÐ¼`OF¹À‹¬ß4Ö±Àäú¡+àÃÀévÑ”Å@o ¨A)Ü@f”4îÈT@ÿ;ùzË@Ö#¬íÞ¹ÀÙW‘e?ößÀÝHï}ÀŠ@tº€gZ®Àáv)ŒöðÀÉé“_ÃÀcž#ºù?ú@¢/öjÌ@ßÿÏéIÓt@ˆêß%º–Àv…ÿƒ'ãÀá‘øÄ»„@©š€ò­À×äÍ’IâÐ@7Å‘D8ÃÀ‹™L…ÛÀ¢/öjÌ@kS¿a׿@Ý¿bÿe—À0h‚>m¸@DmýŒ}‚@¿[”LˆäÀ³N>¸6™@µéÝ´ê3À"Ìt«ÒŒ^@\ÿË`ul¯¿,ƒéÉ]p@½ï¦ÿœN@Òñ¡W…À>‘(]pSÀ3(Ö1a@µG°Eد­@„Ód¾M0(ÀÏd`Ä€ÀQ¢¥|ÖVC@ÅÓ®ðL9¤À¿£«¨Mú;@'çÙ“%D€Àd–¦|2ÀàJ«Uå 3À 8=›RmI@=Ì`ul¯?"Ìt«ÒŒ^@£øfI…Y@Ž™Æf7@z[Æ€$cÀR„þ§^üqÀÞãÿœHJ@„Ód¾M0(À&=¨øqà­@ÓŸJÙYP@Ä}m•p„ÀÒøɳ®<ÀqÒµ5¤Àü=²¾À{ãèt[è~Àr×ó¸ërÆÀ [M‡@,7-—ÐÂ@Ê ±8»¡ÀØ+»pέÀäcðG¾ ™@uÖÁá+¶@]¬ªƒc¼SÀÚÿIK$/ˆ@aÕKsxÁËÀÊ ±8»¡À:q­:¿Ñ@ãh‚¥#–@^5Ý•™ÒÂÀ^¬ªƒc¼S@uÖÁá+¶@ —b˜Æ±Ah,ü}Äê@û1Géö•}ÀâÛS˜.ã©@T®òÁ(¤ÀÐ=ÞIWï ÁKÈŒå£Á·†ï AoÁéðr÷@h,ü}Äê@®TÓ ríè@âÛS˜.ã©@‡>øÀ¦ÖÀèöZ‹Œ’¿0;€ö~(¤ÀÌÅpܹÎÁy1²y5ðÀq;l÷@a W…ä@ƒ«1×ÿKÖ@U×€;*¢@‰Ó³?QÖÀ$)ºü‘½‰ÀÿœƒÕkk‚À%Ñàîí´x@· ç‹ñÃc@ôOCW2h@/c8h0ŒÀ_Êä:FˆÀÖ„z‹4TlÀJ:ѵ7j@€áÂâQ@U×€;*¢@‘;›|«áÇ@aÖó8௕À…ŸÕ n¿ÒÀ‚n.²¦@…¤îóÍbU@ƒXö×A@”°|èøŒÀV+§WYà°@ÑÇÿAÚW`Àd–ˆ9²kÀ=Ö! Í™F@øãa¤M¥-@‰Ó³?QÖÀaÖó8௕À44òýïÙ@£l7Œ!å…ÀH½.v†À|¿ñaÊˉ@k𛍧€¦ÀÎHp¯Þ@©As¤‚Š@«'~áóf@$)ºü‘½‰À…ŸÕ n¿ÒÀ£l7Œ!å…À¿ù„á@ñSà&Ö&’@š¹…%ÐÀì¼ZŽ+ù”@p¡ ^ÜcÁÀ¼æìoÀª-×Er˜¶@Øoð°qÁf@ŒÎ[¯¬³C@_žbÚµ•„Àí“Çà®@H½.v†ÀñSà&Ö&’@q† ¸FÊØ@ :Ü?ñÒØÀ•Mùïgs@{í½u'·­À¦Àâ–ö¡ÀƒÂrv´Ø@~l¸+WCÖÀõB}¶›¥@ÿœƒÕkk‚À‚n.²¦@|¿ñaÊˉ@š¹…%ÐÀ :Ü?ñÒØÀÎVnbùA&µ^öhå«À°‚ \¤[å@÷‰¸1zmÀ†,Éæ/‘@‚´äÄ}Ö@Fñžš$TÁY:ÎçeG·@Ú1¾Ç˜]ìÀ( Ž•½ƒÀ+y 8DFp@Gå/«c:Œ@g‰¡äKÀŸõîÞqwÀ´Ã™¦sP@í…’ªÝY@¾"'QçpÀ+vÀ¥V d@k_Çeñƒx@Ž/iql@•Àg‰¡äKÀßJ‘i–@´Ã™¦sPÀ ,LÆciÀQ}JyêpÀLï!V†@–ÏÙm9´_À¿}’™„e@´Ã™¦sP@ŸõîÞqwÀ´Ã™¦sPÀ¥á&qÈ›t@›cÄÑ`æ€À´Ã™¦sPÀ¿}’™„e@´Ã™¦sP@ ,LÆciÀ3¦×f•w”@ïlUÓÌÔÀé H]ŽR«ÀÐùjƒÿp˜ÀöoŒ•a°@¡#ÔÜÑÉÕ@ä3þVM–‰@yÿ¶%B@S¶Ê¬—ÀT,EÒR«ÀA7·?^ÈÀ›æêˆ‚,°@ðˆÎC!®ÅÀä3þVM–‰@ÙÄ7ÌÓ@·[EŒ×–ÀÞOøá¢U¯@c%‘Ѧë)@1'æÆ)XÀy¬ÙN´K¡@þl ·Â‡ÀíQΪÏGÀ™nžÒ¿8v@1}ÊEjž@ÎWû‚ÒLÀ“ë§2ò“_À–é"в¡ÀLÝ©Ë d…@þÇXXÀ¯j«¨x†@þl ·Â‡À .}¢`¾@ó¿õ‡ 0v@Zæmaµ¤Àu‚{)ÅxLÀ¾MòÛÍz@ÂæÕ]@î%û0ˆu@µƒ£¼&¼À%Ñàîí´x@…¤îóÍbU@SÌÒ\)A"9 A‘gªûð(ÁöÍ/¤r5 ÁRö‡1ìÒÀód°µ="¼ÀÛ±&ŽN@š?ñ<ˆd@· ç‹ñÃc@ƒXö×A@"9 AØæ®Ô¼°Al²¨áÀ/ Á®ÍdÊörÁªÓ½Ø E½ÀSi”oª¯ÀIޏq@ i@â2ôcÛlP@w¯Œ]•IÀ‹*ù¶~@Iô±íM°@qÂM."MÀmEWÐP@í-ª@„À¥ùçºsXÀq&¡º ŒEÀ­œ6/¶Y~@ë×)+!@2Q8˜SÀWG’‚%@>PAOËXÀ8\ç5ž~@e ¯’a²ÀW¶=1RÀ>ñr;E@í-ª@„À⯘¯á¸@#ã í’ýŒ@¼’'•3“y@íì‘"C²Àùw³îZTÀ0ß „B;‡@P}´½€YÀ=‚Ì¡he@áÓSùmÎ@îJ(ÊÎU¸@8MS¾|Û@ ­iT¯@ ƒl´ÄÁ²@-G‘.‘@–9 ÛDª@¿Ÿ²In)ˆ@ó|å‡ò4ÅÀ÷w¬8)†ÀýšGôÚäÀi­~Š©EÆÀ?U›ô@·Xty¶@ó½zbî¡@ ­iT¯@øé@¾ï%Ò@°˜AMJ¤›@^vRy@ÛR5‘([“@¨ž”¯Íq@û M73ŸŠÀ[xƒ^ SÁÀ-I&˜*vÈÀgh}È-ÍÈÀëJ³éÆ…@-¯Ýâ<,öÀX7–ƒÐZÅÀ¡u8ŒžK…@ϙū¯gi@Nâròi ÏÀÞÜT&å[µÀÞDÚIŒ#Á´N°æÄqêÀP%M9AÕááN’ñ@FªÉgâ ÍÀ$‰oÝŠ«±ÀÁ€Ìà67—ÀK—Rà+@š—7 BÀ™ü‡~c3@v/¥¿VÀfŸµ‡qrÃÀ ã¡ù uëÀ˜–yŒo@¾Ð®›‹ÑR@nfH”VÖ°ÀFp&Î ¤ÀäzV­½äéÀrŒÐ3´—ÍÀÕááN’ñ@—Eœ4ò@Âóè¹î|­À±ì¨îLšÀѵÚ6Õ¾À£…F•.BÀv WñKÄW@`{ȳò„IÀÅÁñm@\§9ì´@Ð|'RU½XÀ4þn¡Á@4þn¡‘ÀmÞ§¸d°@¢ÔØÃ, “@²É—²×à¸@u¿•RÇZÀ|¥¢Ñ5æÀ1Á²ÆÛpÀjønž*VŽ@¬bóE·xv@—Qï'=1¼@Vœ?ò" @FªÉgâ ÍÀÂóè¹î|­À»L†êݽÚ@6æ‹ys˜@<ÙhÝ?1u@[ èÏç`@Ó|'RU½X@\§9ì´@4þn¡‘@4þn¡Á@z¿•RÇZ@²É—²×à¸@ýƒà2_¦À!«ì8Í-àÀ6æ‹ys˜@±gEX•7É@=Ñ—´®²’À[÷¦;U&‘ÀgÛ±+b@,DNÄ…À!‚?9•@ÓSû¶÷Âx@D± TrÀ »õâe„•@[÷¦;U&‘Àüœn¸šuÀh¡]m”‹…À°†ÿ ©@ÓSû¶÷Âx@iüAuTî°@ó–„a»•@¤‘Ýbƒ¹À7ÙY;óúÀûïWk8–à@—Õ ³(Â@ÓÉö®  À—Õ ³(Â@ÓÉö®  À®l*°1ö@'ú=&%ÝÀ7âþ9Ÿ@i[Y ÄY]@´a¿q¥ÑžÀFÃ/¯¶sÀ;.¬_y@ªòFßE1@cFX;Ñ|@–霨d@* ŒuàÀ÷NjqÎ÷úÀÓÉö®  @—Õ ³(Â@ÓÉö®  @—Õ ³(Â@'ú=&%Ý@®l*°1ö@i[Y ÄY]@²™\çš@ži›é” sÀæ‚à]+“À«òFßE1À;.¬_y@ ÂPæ™»d@kAÀýÛ¹M@»õ1˜Î!³À5îýæF}‹@çF÷Éb»@Aâefð…ÀŤ#i$ÛµÀÉvdÐôr’À\HsÅ(°Š@Þ-ºªÜxõ¿Õ_=¥@5(þØù‹Ž@‘ÞNMÒå‹@ê¯DC9d»ÀAâefð…À“Ö–/7¬À@¾6¾áZ’À#‰eÄG¥À.ºªÜxõ?\HsÅ(°Š@Ô-'%Ý@[Ӛﺦu@jóÛŒlh@jóÛŒlhÀká5ÁH zÀçŲ7˜²b@ã¦DÛˆ@"R2ÂU@n߯õŽÀiâΞx¶CÀWE¥ê\@ÃdÛlÉÅð¿zÇX<ãƒt@ùÚGzj À¶=¥Ÿçí~À¶=¥Ÿçí~@÷x"ì–2|@ò»4X½ƒƒÀ"R2ÂU@rÜh?54‚@%×¼áàGÀ}¿ÙIŒÀËdÛlÉÅð?WE¥ê\@ôÚGzj @zÇX<ãƒt@éÀ{siAHG\IÇà@·dÔº¡7Ð@£h·uº@”­œÜ¥@ËkvÒ>"Ž@†[Û†íóÀÿ©,!VqàÀ¨A&&/»@€•»[¯œ@ݬÊ>„JêÀB•ÑÿÔ¿Àæß1¸´ÇÀó!Ÿ…B+”ÀAÞ µïáÀëYçå­Àf;#ÇAAµ@÷ßp~lp@™ûDä†TA@ jéé»@ë’)wêž@€…"åü¤@T@bЈ @6²šéj’À”Š"µ_AÀHG\IÇà@<ªÒœ{kî@[¸V–ª×º@/ÀDÕå¥@o¿6Á=ƒ@„ЂOšTj@¶€ê’”}àÀ•Û³t-7ËÀñ,÷ ™˜@æþ”\;y@Z‡ÎÁvÁ¿ÀNBƒqÏÙÀO¢LÛd+”À#«a)Z¹ÀÇÊjˆ°®Àž°˜ÑcÒÀtÕk’’@˜ûDä†TAÀ÷ßp~lp@=2Œœtœž@ì»Ô0ô€@¦6y>ÃV‚@Ë/®i¸l@˜ûDä†TA@iW6ÎÀ·dÔº¡7Ð@[¸V–ª×º@r‹øiËfë@ºß£¾ÀÑ øuÈÀûª÷ñ¡{§@ÓMdƒþ£îÀ+šâ«¢¿¦À7E /ê£@Ø‘Qº:s‹@£h·uº@/ÀDÕå¥@ºß£¾À±ò9¿ñ@ C0C•§¦@Ü\²ÔXÑÑÀتhŠM“¦Àê±^çÂëÀBÁ"U@i]³¬mÔv@”­œÜ¥@o¿6Á=ƒ@Ñ øuÈÀ C0C•§¦@$JªÀz\• Ï´›@›mµ‡²[‹@rŸy–©çt@ËkvÒ>"Ž@„ЂOšTj@ûª÷ñ¡{§@Ü\²ÔXÑÑÀFLJ‚¦@Ír*mbÂ@oŒ pX®À* IM™Â@‹eÃÈ@Fmc™ÈÄi@ÙåÐ@²ÀFÅ­.¿“À8–¯Iƒ@¬j‡]ßÚr@œéå¥Ð\@†[Û†íóÀ¶€ê’”}àÀÓMdƒþ£îÀتhŠM“¦À5ßÙxá<™@oŒ pX®Ày U¡mA›ëìLÌã@ÿ©,!VqàÀ•Û³t-7ËÀ+šâ«¢¿¦Àê±^çÂëÀÏÊï®À* IM™Â@›ëìLÌã@Ó‡ghêí@¨A&&/»@ñ,÷ ™˜@ãn Ùóö¡@‹eÃÈ@¼hˆNê@År饭Á@M¸ð$GüåÀQ*\èáïÄÀHÄ©Kw±@Lak"?¡@‡) ![[Š@cÇ¥ÌØ¬ÙÀ²}ƒFõšÀ»D*i“ž@Oú…à;k@€•»[¯œ@æþ”\;y@ˆ¶Ý求@Fmc™ÈÄi@År饭Á@v¤±t¬oÔ@Á>Z×áÆÀ'bÒ‹ÃÉ¥ÀûDó  -’@ë+˜ò@‹34„£mk@Ž‹ˆmá/”À6g'ïeÔÀQú…à;kÀ»D*i“ž@ݬÊ>„JêÀZ‡ÎÁvÁ¿ÀA ŸðC ð@C_V¥.øÄ@–NÒ‰(ÇÀm’¬]¤ÀB•ÑÿÔ¿ÀNBƒqÏÙÀC_V¥.øÄ@2ÄJ9]åÜ@ÿø.òº6¤À¶ÁH¨Õ­¨Àæß1¸´ÇÀO¢LÛd+”À¿²»© É@øÓn]J ’@}åŸÒÂ{‹@ÊúI¤l@ÒÞmÿ Àê#ïœ9WÀ,œf#˃@ó!Ÿ…B+”À#«a)Z¹ÀøÓn]J ’@(ÚQM¢*¾@[Àn]õîh@ÌP×øûI@«‘ê1ÜiÀû¶ %”À%AÎýôa@žS½0´@&q¬˜ÒŒ@0m=5ÐÀfÞFsŽñ@´l„9<‚»@B»Ï”·¥@yµ^­oè@…Š`¸÷Àd(jS´y±@È1Ö¸M¤Ž@»ä/A‘²@AhãB7Î@ÿÀsÝÈD»@d}v¹p$”@Æ'xîAÈÅ@ VÞœºó”@£¦Ù&Ï}íÀÇÈø'€>É@$(1ÈlQ¯@0z›ù…€ÀÏ üçb:¯@úöÌæÑy€ÀœNš^ÓÀh6Îqh³@&q¬˜ÒŒÀžS½0´@-LJxgKó@ÐËj°æÁA»Ï”·¥À´l„9<‚»@…Š`¸÷À&lªžäÕACä¥Ò‡„@²î¹×ÿa@IîB>Ð…@Ù;üY¾c@d}v¹p$”ÀÁsÝÈD»@ VÞœºó”ÀÆ'xîAÈÅ@vjBœíÑ@­xM8*Á0z›ù…€@$(1ÈlQ¯@úöÌæÑy€@Ï üçb:¯@A̓"(­@ˆ¡ãúѬåÀ˸4ê5¶u@¦œäøÛ?›ƒ–6wÞFÀ[áÔn¸€1À™ëÈ9«r@?Á£ë¾S@ñ—pŠŒ@‰<×ô‘H@B!·[ñ¡™ÀDìâµÉ1À³ÇnÑ µ_@(í+«>HÀ¥œäøۿʸ4ê5¶u@[áÔn¸€1À#6Š¥ÊÀ?Á£ë¾S@ô#$×^@b<×ô‘HÀñ—pŠŒ@oR[mNZÀ&¨¾¸.|—À(í+«>H@³ÇnÑ µ_@Ðé#—uv@V¼ÑáAa@0pú’¿[@– L¤E@n߯õŽÀ%×¼áàGÀTþS/ëª@ïNFNÀw4o((@˜uÞ¢“?ÀŠF¾ŒÀŠ+¢¼a@’‘HÀPßì)£À`räjYÊ`Àé ТÐ'a@ŒCÅ·à[J@ò%œ…ÚE@~Ö&X 1@iâΞx¶CÀ}¿ÙIŒÀïNFNÀ0û‘+qù«@M«ÆÝ?À¥œéù²—T@ AµT8W@ö…q(ŠÀìêçõ__@ñXÌb§aÀaþÔ:Wš À"!è qÐ@ZKÙw©º@ ƒl´ÄÁ²@°˜AMJ¤›@g,_E¤ŠÇ@ĺHø»š@0z#¹@–ze¢LŠ@hb'Ç££@æ)Jê¿+3ÖìêŒÇÀp‡â~U>ÀÀ­ ÅãßÀ¼ 7ËÄÀP@-¯0 @úe‘G7®@,)´UVl˜@-G‘.‘@^vRy@ĺHø»š@o;¼@xˆ³@Ë2ņd‰Š@„ÓF›§@P æ)Jê?hb'Ç££@þÈÊ+Á€À ƒÞZ<‚ÃÀ»b(C6½ÀŒld?: £Àdmo‘P©}@d_Ö@>A€iî[ †5Á¦ËoS:óÀr†žzUã@éÔç²*±@iH½…Ë ÁEÒ@¤Ø4A]²âšÓ@ôºÌ½´@€iî[ †5Á‚ Qu‚`A£{jøÓè@q—.žÈ³ÁéBÕwg”@F¹ì™D«4A[!Òæ_Á(zؾqu°@ÍB“À˜Þ‘@`¶ß>ïjÀÈJH(hš@æÒ&†@…>AÁÈï[fT$ALh$“ò6@%Îá¯ÁüMÀ€„>ÁWUUUUX$Á:k9Äœ@”lŒ‚š—ÀÁÈï[fT$A”H—I AQMqà"NÀóÿòj›c@WUUUUX$ÁÉqÇq Áñ³•ë³Á‰À4ÔÒ* H—@€ã²úCnâÀFI;˜1¦ô@àu™nB@º‘-ª¸¤•À­.`·Pz@ÎQo=ä•ÀZðÄ&À D@ ø;ü7)ZÀiËÔ ù¥Ã@¶ÌØ÷æ-Àœˆ0kûhÀ sæ*,/@2å©)u@À磫Tÿ¶£@‹ÚäpTIºÀ╸} gH@,ÑÕ–¨Ð_Àõ/#ü7u@¡V7Zâ“À2Ãt³Ê%@¼µgÍWÀ:ÔÐsƒü×@+ŸÜ–býñÀ´œ@¤‡‘@BÆEýµ°À Áì ùñ@š4<Ò Á8ã}Æ,N–Àóœíøù«@_ß°TïÞÀH¡¶6K¬@Tìe»8ZÀTÃïãq@¶ÌØ÷æ-Àˆ§v@"È@¨­t«W€@í¼×[dDÀ‰6-!ˆU@2-ÔŒ{¹À#8³«üÐ@pkó4í_À,ΚÑöÏt@߯hÖÔƒ‹À2­{†ëÈ©@ÊÅùêÌ‚<ÀÿÄ-¢3$o@ÎàóRïÀÚè6>@AŠÃ5˜ýš0A‚Nò"xåA.¤tZºª£@óÕöXàOÀùXÀ‘_0ÁáÞêã6wÁ±8)SMPÑÀù¤ÀY»À‚Nò"xåAÈ&q2>AéÕöXàO@.¤tZºª£@AyãtÁ‹56c8Áb þ,.c¼À¾n˜ïl¦À^alÞ=æ@·O®Íß”@ —Aì­ÙÀ-°þýŠ”À®0+—ÐÍÒÀ``Þ¿Á•>@·O®Íß”@•à=BC;ã@©c+F4–“ÀF´?ã¨ÓÀ¼»àáª>Àý†µÍÒÀ:ìwnª·Á@Jëšå}n@5ºä×Z@õ7ïÒ0À¢Ä9zæ A(·+yzqÀðÖ¨k*ýÀ’—O^x­À^[ÕÞ]¶@W1£ ¢a@ãb(dC½Ì@Âõ”jû)@…J¬8¸@<»ã…Àî…Z…ÁÈ5%šÈ¯}@ï0âz°äÆ@æòÚj@è“À#nñ£œ¼â@Á&ÛPsMÀSmÙ:IÎà@m»/‚à­@%ÎTç²u@=Khî rªÀ§ž™}ÒwÀÞd¶¢kñÀЙâµF›·@àüç žË@fTDOþGÀOëšå}nÀ;ìwnª·Á@Æá5Ò |ŒÀ´Z'Ia¿@(·+yzqÀj “"u Aï¡¿kíJ®À ] 1ÝôÀY1£ ¢aÀ^[ÕÞ]¶@áõ”jû)Àãb(dC½Ì@<»ã…@…J¬8¸@Ó¤ªs1Ó§À6ëþV8™ÁæòÚj@è“@ï0âz°äÆ@¬&ÛPsM@#nñ£œ¼â@m»/‚à­@±Ò4œ¬Žz@›Tz…S§À„­ÊmÜ@Šžžà›©@ø¢îZOíµ@T)ü!XþÀbTDOþG@àüç žË@½ã<ªsi@&0¹¼ åÀ¸mÙ½±ÎH@‘_àjDaÀ´a¿q¥ÑžÀži›é” sÀChÉŸ¦@õ?ìÌÚq@¹Ö cb’À1Ø ÊTd@)0¹¼ å@¾ã<ªsi@ÀÜaMaÀ‡Â>})x@FÃ/¯¶sÀæ‚à]+“Àõ?ìÌÚq@Óræ×c;¡@%ý}hZNd@!ç6µŒ˜ÀYTç«è·±@ êWø\sÀL?ÞÙñg™@õŠ—„W@C °å@:Z÷üeÀC ‚²Øª@Þœ!žKo@gKðÇìÛÀF<_J$n@4°F ;Ü¡@îîØ@9|Àì{Á侨@[$NøòU@ÝÝP¢“9¦ÀÈ#½óÅ-Uþ…º@èš­ e@óÅ-Uþ…º@èš­ e@ êWø\sÀXFtÓš·@õŠ—„WÀL?ÞÙñg™@:Z÷üe@C °å@Þœ!žKoÀC ‚²Øª@’o¦w@Àб’ÜÀîîØ@9|@4°F ;Ü¡@ù#NøòUÀì{Á侨@¦ ü]¿oò—H9¦Àëš­ eÀóÅ-Uþ…º@ëš­ eÀóÅ-Uþ…º@€•„ÿqWÀÆ®Gnr¤@Àã/ñ¶OE@NE¼â¼]À°{pmk”o@’'Ñø¤yÀê|ªñŸ]iÀ…‰aÛ“@Æ®Gnr¤@ÀÃ%l/ÿ'ÀÎý,‡.}]À·Mü “t@’'Ñø¤yÀNmð&^“@o®2ühŒ@qè—+R˜ÀPªv‹åª@~D¯U.(ÀqSŒƒ&¶ÀIY5Pj­…@ñ—pŠŒ@b<×ô‘HÀï@==[Ñ@$£«@å¸ÀÀ(€ÅJLÑÀúzcYÀ@žšÌšš“@h/>Rõg~À¸D¯U.(@Pªv‹åª@ɾ"Àdc‰@à¶vCW¨¼À‰<×ô‘H@ñ—pŠŒ@$£«@å¸ÀÀî7¤Âá@þmuN¼@ßμêàÀh/>Rõg~@žšÌšš“@E9OÕ\ ÀôÁièƒÀ&å⚣±@øÆÅ å•@Ú{ðØ>£Àü‹Bú×á‡Àª{êeçƒÀ£ŽG›û¶hÀøÆÅ å•@Ññæ‡-{@GˆÜâ‡Àþvš2¤mÀxúnè¶ÂÀ(Ûé5a‘ÀÔVä¹Ñ@V4]ÐTpÀ1C=FoÁÀŽ0ºPÓv•@IÃF‚ÊÀBÛLê:¶ÀV4]ÐTpÀ°ó9¥©Ò@ËØ“¶ß”@>ýƒ5ÊÀ.¤tZºª£@éÕöXàO@í]j‚ãvA0‹Õ„^Ál1ž´Ûo|À dAã÷ú£ÀöþgWOQÀ+A¥o`À¿-koµó-ÀAbÖ¾U†S@#”“Òáß=@ÿÿÿÿ_ãvÁdffæ„^AóÕöXàOÀ.¤tZºª£@0‹Õ„^Áñ†n‘™*AdŒRÚ<[@ð¡Ä/‡d“À„ÚÇ^&mK@cGiÅÚ£À…ÄÝKBÀ®"Ñú-‡u@¿-koµó-Àª¢ŒnÂWÀ#”“Òáß=@¨WbõÚ&@pN{Ú€.CÀ9-.¯m@ѯ$ Uÿ@ÀÅØ{ÑÃ*j@dffæ„^A233ó‡*Ál1ž´Ûo|ÀdŒRÚ<[@åöA4¤¤@crÔ¬ðuÀPG7žÅŽ@Ë­­‹·À ÿC X¢À\s·òGY@e}Ur@Z—W\ÑG@·lyJke@" Ùó;@?Œ1ôæ Š@J™$š°Àq’¬î©TÀqe¦C£@·›>¹w@^eù=ŸÀòŽ<›Z;`ÀFüߟV$l@õfoW/&>@àÑxµ8 @vVJ†¬R@ë1y–¡~@°­ªKP@%žÛG¶0r@ /*ŽP@ULF{s@y^QbŒI@ð¡Ä/‡d“ÀcrÔ¬ðuÀ>7ƒç ´·@°­­‹·@QG7žÅŽ@|:»Jl@­ë‰B5(®À³AûçkG@ìºv@¼¢^礮;@Š% `"@kl˜‡Ó`@E×­­¿~}À"oÆ3ù”ÀN ¸¥'s@qñÒN@C>xðReÀ™.•ŠÀPŽÀø™x/B@*h¾„{@göœ˜'V@ãv™Þ¢d'@;ûh Ç}S@>\ç™+Ý$@ /*ŽPÀ&žÛG¶0r@( ¾i´GI@s¿-_k‚ @&pVý@b@4•€BÁ0}ÀpÇ£0 U„@UÕˆÛ?i@Ú{ðØ>£ÀGˆÜâ‡Àâ¦ü©ý @GbKKè‚‚À Eˆ;!1†ÀDö8¡@)={Ii@F>ÇQPƒÀ ‰Þöå }À¨ùðMJ—@-ùzQÉ;i@«M(UO@ü‹Bú×á‡Àþvš2¤mÀGbKKè‚‚À{¦Uƒ'®@Ñ&Áûд¡@ð&劰ë»ÀÄ&f-„ÀOÐßiÑž@ãO^4Â@´ž(ó¦@Ç—OÑ̯@ÍH±;¢ç‘@Åã˜<úÃÀ‡ÝÝü&®ªÀ­ ç«ã§Àî?Ùóßâ„À´ž(ó¦@«áÕgAÒš@«³¿¹á—@¶‰:z@»˜ñ¸;•¬ÀuÌå “À>#0M›‡Àÿ?ôS¤¤ŒÀÖ2_c&Ì©@›ë0Ý2@1C=FoÁÀËØ“¶ß”@§S™ëÊ#º@ûO!¨¡ñ±À¼š9Cî®Àþ¼(MƒM©@Ÿë0Ý2ÀÖ2_c&Ì©@ª'T_º/iÀO€6R#œ@Ž0ºPÓv•@>ýƒ5ÊÀûO!¨¡ñ±Àåœb@+ÛÔ@ºÑ†U}œw@lÁðÕBí²Àâ]”M©@ü9”+0ÃÀÊ{¹K@ fÀ÷µƒÚWš@+ž•š‡ÕÌ@-°!=wž@l'6ÜÀ§Râf"ŸÀºÑ†U}œw@QD”ëQÒ@û8m׈Àë¯ûtåµ°Àµ·»9@•€M>Ï™@z}N˃îj@I/¾‚0S—À¾ î}ÏÀlÁðÕBí²Àû8m׈À=Àñ$Þ@`v£Q߃@YÛóJ!ÄÀÝû¡õæ·@àͰ/i›À'’õ6¿ÀQÒØç6&@¸¹ä'··ÀPÃxä<›@àͰ/i›Ài2êA‡GÃ@ÛG…׃%&@(3ð`=ÀPÃxä<›@f žb8ÃÀƒm2Ê;‚@! Òçë™é¿ eƒnÛ˜ÀÐùhвG‘@ Eˆ;!1†ÀÑ&Áûд¡@“`k•I¢@ß‹“?›´ÀT@d!zƒÀ³5´Þ À@Ÿ Òçë™é?ƒm2Ê;‚@,ȼc‘@uY[VႲÀDö8¡@ð&劰ë»Àß‹“?›´Ànélù£ÕÐ@…È´÷÷\ž@dAàd0·Àù–"§À;ñÙÌ@‘ÀL?ÞÙñg™@õŠ—„WÀá›ú¨X€¼@Šmmú8Ž@-ÞE®¸ª@B~®ÿ®qÀ®oø] åª@ݧTè¸I@+Qr.‘ÝÀÖ¿/pÌ÷™@%h¡@Ÿê&f3‚ÀÅf½é~¨@M _úVfÀ‘ú‹bŸº@Dêïð¶hkÀ‘ú‹bŸº@Dêïð¶hkÀÒ·CfߎÀÞɲŒK'wÀõŠ—„W@L?ÞÙñg™@Šmmú8Ž@…täÀ´@B~®ÿ®q@.ÞE®¸ª@ݧTè¸IÀ®oø] åª@|o¹Àï—ÀH<,ÞÀŸê&f3‚@%h¡@N _úVf@Åf½é~¨@?êïð¶hk@‘ú‹bŸº@?êïð¶hk@‘ú‹bŸº@’ ¨ÌÄ@L¹œÆ|™@ ÍjQ°°âÀ|e(Ñâ£ÁÀUD“{ô@“¯΋Ð@jMÌø¦8ÔÀÇitب“ÀaFÞ½Õ@CnhnÝzh@¯ha€·ÖÀ¦Ç˜Õ9B¡ÀfÛ†ÃÀ‘”ã$ôV§ÀM †/ îÆ@‰DuŸ2±ÀØ u³Õ“@@ëô”†o@ãŒðu™=‘À*wD %&žÀ`Æë.f³@²áä]{˜ÀºÄq‹°@0#`üÔ>ÃÀ³BF@õ5ç@…H¤€ºÉ@uWõˆEéÀ¨oîÇ+”@»&[úÂÀùpŒ<¢g‘À‘›9rY ³@nyϵA¯ñ·P×<«@jìUwç˜øÀUÙ#²±À¶ú¶PJÍÁJ;ñH$†@ãçÅkûî@Õ‡i!d@¯ñ·P×<«@6…-&WAk÷}]'o¤À1—©¦ñÀi$Æ…e.†À(Ò†gÍÁì‡i!dÀãçÅkûî@R­`qÆ‚@}Ö¿ô;@ò4V^@ÞÕ‡p^¦@§\RØPPšÀEç¬@T°Ñ‰¤v@»£ñ=^ÀשöC@ a@´ÚÒ•²À ‘»ù•@È=¶Þ¼T{@.°—ìd@|¢…pð¹l@'Ìܳ#$@ÿh4L@§\RØPPšÀ·¹knXº@!b^Ó³v@!'TsfRa@G¼œ»A"Z@q[êÈŸ£|Àùx¦'å[‰@Mc…“B\¹ÀVIèd@~L¥zP@AÞ µïáÀÇÊjˆ°®À7E /ê£@BÁ"U@Á3Òÿ£sÉÀÙåÐ@²ÀM¸ð$GüåÀÁ>Z×áÆÀ#¦úGîû@‰’Rã*Ô@ÅeéåÿÎÓÀX•aTxyÀÀM./ªjM¦Ààe•W¦¶@wuð ’—@Î3ZªaçpÀá߀©  @¥ùçºsXÀ#ã í’ýŒ@ëYçå­Àž°˜ÑcÒÀØ‘Qº:s‹@i]³¬mÔv@^mEÏ>JªÀFÅ­.¿“ÀQ*\èáïÄÀ'bÒ‹ÃÉ¥À‰’Rã*Ô@÷’i‹“à@’•Ù£¤Àh!œ(ÓÀôý3€eÛ–ÀÕ"säÉÇ—Àwuð ’—@ûÙÖcU‡x@‚õ?ÛérÀåèÞ#–¥@PÓ`T³±wÀ¶º¶gP«@[Î&1 @«Ö饤RÀ¢K‹R h”À¯/ðú2}@q&¡º ŒEÀ¼’'•3“y@f;#ÇAAµ@tÕk’’@z\• Ï´›@8–¯Iƒ@HÄ©Kw±@ûDó  -’@ÅeéåÿÎÓÀ’•Ù£¤À-·ð’õË@pðÞëE%°À¡2ÃYI™š@µHrûS„@¼]}Jl”@†ú$Øo¬Àó¸ uDKŠ@<TÍ>@Œe€=ãqÀòÀn~ÚdÀ }aw}­À¤Z&m¶@¢ÀŒÕ†fRÀ'ªgŽÀ†@ŧUkþŠ@3ôòN½À­œ6/¶Y~@íì‘"C²Àh!œ(ÓÀpðÞëE%°Àà6Rèëî@îÙ<úäa@W«31æBŽ@7«2ÈÀ‚›5ÁqÀž˜‹¬Øž¤@ÞhÜ ˜@ @Zþ` @LèëAB•×Àö/¡åñ Àƒ‡þ‘”©wÀò\ø@תZ@(¬kiHB@,K{(²ñœ@çB@…v@åÏK8–&ŸÀ—"%ó‡_yÀŠYØκw@hë0ÇGà`@¾Ä„iü”`@qÿh“:F@¶``ÈYh@mœÂŸR@;ö½qv@ËÐ.wJ¶`@÷BY\ xÀÓò»¡L½aÀ·²^UþC@é§=“³i+@çB@…v@n£kw ÍŽ@ó(æØuhyÀJV^ã BÀc¿o%ó`@KP!AÔH@Ìð>õÕÜH@Zrz)ª0@§’`qeAR@ûÅì«ì;@oNµè•`@÷’«ºÅI@–¯qkÁ·@Xh»{ü#ÄÀ²´Î$Ç×@‰Œ°´—ÈÀ²júëå`ºÀÿå4=­¸–@ ,ƒuõĸÀ9ùV¾@øú­ÛßïÕÀ”Ü×ñ†ÂÐ@¿W¼Šq¢@Í(~:l@$C‘#¦—@È|åd@—q¬é0 ƒÀŠƒrE@‘@„Ðø7–ƒ@«VJs9 Q@Eá zZ“@Eá zZ³À oÎË´‹ÅÀ£^÷\DÒ@‰Œ°´—ÈÀU ¯¶Eé@д‚j|@3”Ú³ÅÀ®ëFžœûº@ve¸$éßÀLÃR§Ô@Ü›É?èÀÍ(~:lÀ¿W¼Šq¢@È|ådÀ$C‘#¦—@7ùX$ï@·¨¾Z30©À«VJs9 QÀ„Ðø7–ƒ@°Kr4µÀ°Kr4Õ@ÐD’­³ü´À†¯·Ž4šÀbŠ 8gh•@Ìå6¥z@+ÐC/ˆ@n †“‹f¢Àm.³ÅëÝÀe„ë•[m¹@¹[Sbc¦â@zæ ki–Àå{L"Õá±Àüß½ô–ÀíÂn:¶tÀI›|[M§@Öö˜à;šÀ´ÍrÊØ`€Àû¬ÈÂz@⋟OB§`@ eåÁˆx¢À½O þN¼@·ólÀpv¹@’úàH¨”çÀzæ ki–ÀS%ò‰çÒä@VB¬i΃@°¢.PèÜ»Àüß½ô–Àe Âç[v}À¾Áé"™ærÀäU®,ᩪ@A×E)žú‘ÀúS‹v‹Ã@úŸ ûM¤p@ô ²64ŸÀVB¬i΃@Ýj]§¦ç@0†ƒç­¼À“SÅ9c@€õàKm–À8™Ý’¶2Ï@PZ¹ì f–@͆ïÀß UN”Àð‘y®izÅ@ ÙÊle÷ÀøÓjº×¸¢À¸&Ä>JÑ@°¢.PèÜ»À0†ƒç­¼À n·•ý@ý=? •À/ýrô:É@A£²w–@fˆiIÁ_@Ê8„e8'”ÀÄiì‚Ú èÀÓ³$A÷X¬@ݵ-¶÷e¹@å”wÅ…@²júëå`ºÀд‚j|@,ùú€9äë@sc ßÃ@ÎÜEýÝîèÀ¯Ý+/ïÀúÛëBçÀÏ® }©ÀÂ&-ÉDÜ¿@Fx«.¡Š@Â&-ÉDÜ¿@Fx«.¡Š@Øí¥”ø¼@ÔúIÁÊ‚@®ÿ&^É÷Ò@ZEgZö–›@ŠÌËà%\³Àd¤ +õ\XÀ±õöVx@.´ÂQ9‘…@pšFz|R@ÿå4=­¸–@3”Ú³ÅÀsc ßÃ@Xºè*×Ûë@WßÌÊrÀ½lM¢À“@ƒ0·qÖ ßÀ0‡‚[wªÀõôµ…“€ËÀÞ¹Æu’ë`À¡×s°Vy@]±áWþ ‹@×ÜwÞãœV@]±áWþ ‹@×ÜwÞãœV@ðonèà™ˆ@`ƒz‡8êO@ºw~öv@µâþ›³e@JÍ5X@–ð1S†V³Àí?(…ÆÒ@ ý§€§?ˆ çÓÀ´‹”þþ“ÀÞ䉶@ ò íàþ“@–§5 Z·´ÀàIONS¿ ý§€§?ìîytÆÒ@7q„B£“ÀÁfÑØl¿ËÀSw$£“@Ó{DÆq@&=a$ K9·´À ,ƒuõĸÀ®ëFžœûº@WßÌÊrÀÀ¿¢çýA‘ÈY- ðÀ¹D©Õ@6Íuf,Àoô°J@BbüycÀToÌ`ޤÁ\ ¯:­sí@9ùV¾@ve¸$éßÀ½lM¢À“@‘ÈY- ðÀU¹Ø¿Ô”&A j"Š£Ài[~æÑ¸±@Õ2MK lÀ25„G\V…@§j¿ë®í@ò"83È%Á 1OGÔT÷À‘ë¦Eqó@øú­ÛßïÕÀLÃR§Ô@ƒ‹ó@ݽ æT–Á”Ü×ñ†ÂÐ@Ü›É?èÀ¸Ë 8– ¥@6Íuf,Ài[~æÑ¸±@'§œö%öÀìJÄx~ A`Ü$'–\~ÀNTà$Þ»–@4ÌÐ]my³ÀÉ·nâ†Á@’ļSÓ•Ø@ÛGý7>ËÓ?Œn¨dsªÀPÏG£<‡„@ߥé׋@ˆðŧ—tm@‚¤ÿkV&¶À¨$‘@«V|»ó‚@sP[ùD™À†Å““IBÑÀ–÷CNGwÀÛGý7>ËÓ?€ âÁÚ@Fâqv¶qpÀaS3^ºÁÀ,5òt±PÀËüB†œ$ƒ@,5òt±PÀËüB†œ$ƒ@Hä<ÆÑZÀ°à Ðº!‰@Š @ìÿêg@6QeÓMI@L[~s.¢@ˆáÈ$ôLÃÀÿf1ž<œÀšË¾¹Ò²@ {•KfSÀF-Ì­á†@ z]_KÀˆ¶¡ÒôoÐÀ»'À‹vTÀ[X*%‡ ˆ@÷dö¾è‰@Ç¡ZRÎ`@Œn¨dsªÀFâqv¶qpÀ8Öo1¹@¢‚ìëï4 À6îFýèû@ÀxT“–Nt@þg&~3ÀVbˆuž˜w@ë&W†è‰@œ,õb[Àq[Öm²À¼×' u@XÎbΓ@Ýìˆëc@ø¡s5Š@VÆÁÚ—q@ܹ3!eUÀ7ù(e¡/‰Àâ«“­ðˆ@ÆC_P›@KØÍ‚Þvw@׊"+ðˆ@]€Îq%`@²AÁº w:@Ð(QÌ&oÀ#É,`߈@0£·óöY¼Àq¾+ŒÿvÀ jó£A¡ž@G@p‘ºdp@)[ÜJhÌ’@ú¤­Yˆ_?ÀU·ì{ùU@LqjÉë,@PÏG£<‡„@aS3^ºÁÀ¢‚ìëï4 ÀPÃ,'À,Þ@¬T;]ûv@d·¸ uz«Àß¹ÛeEz@ ·œV‡±±Àœ,õb[@ë&W†è‰@d–Gàm@4ùa‹½ÀÎ!tß`@g¨ÿ_å0@VÆÁÚ—qÀø¡s5Š@ý)³ÄB؈@UtW¥ˆ@è’Dã1/ÁÀKØÍ‚ÞvwÀÆC_P›@Êîo&§&U@NQâMáb+@wä”7oÀˇz_¢@ôØ iU@=á{¥+!jÀÿø4 €Ì´ÀOkUÁvúi@ËÅ3qÎÎ;@ü¤­Yˆ_?@)[ÜJhÌ’@5Cg\PÀ-˜–Ç•B@rÆ®o³OFÀu+¡ð û?³ô”Õ µ@¢nÞ?0k3À"WåV¢`Y@ë‘‚¥{2Àü^yÉB@ÖwebÀu+¡ð û?ö.Çu4VÀ¨åj³~j3ÀyOûÄbI@ë‘‚¥{2ÀÖØ”Jg@²ÉJRÒÌ‘@Ó±%z Ës@¢ñtÞãî ÀRÿ³S¼ñ‚@$L Õ„@oàmt¶MR@óòxîe@ á`ì‡ÀJ½îSNz@„_(„À.1JÒT·±@ DÖÙŠ*ÁÀÇ9_Ì媺Àó¯À˜|À5¤yÐ"<•@„/zî—Š@ø`¯èlm@KâVÏf‚@ú±óo@))Ïj#Gn@öºîaƒÕP@–5’±ÊŸŒ@ì¤,Hb²Àoàmt¶MRÀ$L Õ„@z¼w×Ó‡Àͨj_þ©@~_(„@J½îSNz@ DÖÙŠ*ÁÀû9¹~{ã@£ÿÛ.ÃQÀ“ߌ¼Õ±À¢³µ´lr@‰ôPgif@¶Äý¹I@J‚pM_@Œìô¤ìG@F;»ÏÀ@.°SÀhwáÀ-ýìba@, h [’J@+Ÿôê_ÿ}ÀÙNìÙWÀ9 `7C@}þ¨).]Àgû¶—œN@ `†®V<À¼5ÑÔÀ׊f5úUÀ¼8ÖÓf@ü¦ N3@º¤çãjw@¾L=»Ññ^@xCª¿yÀ¯=Ç=ç*]@` „@Ñ‹˜ü±&Q@F@Ï“qWÀ†sC¥šßkÀœu®µ6I]Àã)œ4Tí2Wµ^@\›JD@º²˜üF]@ÎIƒü°†ÀÑ‹˜ü±&QÀ` „@½éþ >Vý@ö®oŠOÏÈÀ¼5ÑÔÀ׊f5úU@9 À³GÁ@€óÑ£rƒ÷? 0†åXâýÀÔ¸Á3>¼È@Àk ¤Š0€@58»Ó.ò¿6 ˜ª.å›@_‚w“×g@6@ínÔw@¶fn©Ú%@0ÁÂÀÒ#v@Áÿ<)#@üËõRÀÀ:°æBpÀö®oŠOÏÈ@½éþ >Vý@׊f5úUÀwø¿»qÀ€óÑ£rƒ÷?´²ÍI+ÃÀ@¬Áwb™¼ÈÀˆhpíáýÀ@8»Ó.ò?Àk ¤Š0€@_‚w“×g@Ó¹²ýº`4@µfn©Ú%À6@ínÔw@Àÿ<)#À/ÁÂÀÒ#v@F¥ØÑH°^ÀsiŠðɳ¹À,@#¢ã¿ÚÀÙ1®r¦ÀÁÿ1ðX„®Àhihp.¸Ë¿,5òt±PÀ6îFýèû@À¬T;]ûv@¤­ì"g|Ò@"“,ø¿@-¡ ©¹³@;MAUqkJÀÓš¶"ûT"@I¨¿«ªWQÀ?gåõ8‘ƒ@:®0_Oð¿±a,¬Û‘@-†ÜæÃÀŸèbïŠ@•árrÖã¿«I^Æ@›Ó P”OÀéþ;wÑš@õ·ímqÀÓµÝk…“@«/daCÀ"+#Õ=@M/Þƒ.¦PÀx£”óߨ›@Ç×…(­R Àã=ÝnáÀ¤.Àý± ÑÀ‘fhp.¸Ë¿+—ú9|®ÀËüB†œ$ƒ@xT“–Nt@d·¸ uz«À"“,ø¿@©ÆX•¯Â@;MAUqkJÀ"‹õvŽ­µ@>ÄTE,ëUÀx_"L¼„@\®0_Oð?>gåõ8‘ƒ@.†ÜæÃ@±a,¬Û‘@TárrÖã?ŸèbïŠ@ l<øPÀÃÔMYá‚@ ¸ímq@éþ;wÑš@²/daC@ÓµÝk…“@WÔ2¹.âPÀx†~9èƒ@Ï×…(­R @x£”óߨ›@¨† —zïÕÀ¼Àžb@,5òt±PÀþg&~3Àß¹ÛeEz@-¡ ©¹³@;MAUqkJÀá,í!¹Ä@æÝæOZÀÓš¶"ûT"@I¨¿«ªWQÀ?gåõ8‘ƒ@:®0_Oð¿±a,¬Û‘@-†ÜæÃÀŸèbïŠ@•árrÖã¿«I^Æ@›Ó P”OÀéþ;wÑš@õ·ímqÀÓµÝk…“@«/daCÀ"+#Õ=@M/Þƒ.¦PÀx£”óߨ›@Ç×…(­R Àø–˜%¤é'À0j ߘÚÕÀËüB†œ$ƒ@Vbˆuž˜w@ ·œV‡±±À;MAUqkJÀ"‹õvŽ­µ@æÝæOZÀéw6“÷¨Æ@>ÄTE,ëUÀx_"L¼„@\®0_Oð?>gåõ8‘ƒ@.†ÜæÃ@±a,¬Û‘@TárrÖã?ŸèbïŠ@ l<øPÀÃÔMYá‚@ ¸ímq@éþ;wÑš@²/daC@ÓµÝk…“@WÔ2¹.âPÀx†~9èƒ@Ï×…(­R @x£”óߨ›@Ë–oÔ//h@~ØlâœQ@àÞn DÅ@A^¶ÛðÊÚÀàÔmWd“Àå}¯ó%rsÀŸâÒsF8ÃÀ z{Û@{í\¶ƒcQ@ *_A¯R9@A^¶ÛðÊÚÀЬ3™ó@õm…ÞˆdsÀ¦1=ežœ~À z{Û@Ì]œÿóÀó–Ð/¿Ù@³úÓ e¢mÀ¿7y¯Mƒ®À—h\ˆp@avNÚùÁ@«b{9u& @™”5¸@[”S„“…„@Äï”õ\HÄ@zªÜ‡f¤°@(âxÂì@ø¬ÌÄt­Î@@ûücûÀô¼×Ò³/ÖÀ0 +ƒ´@³úÓ e¢mÀ8!:P{Ú@nðâu6j@xWCº2²ÀUchD=þ¤@:ÿˆØLPƒ@3:n‰óœ@¡|°“ Šh@½U‡lA¨@Ö®›uéæ“@$£oc2Ñ@î%ˆáW²@œ¡˜Dû+ÚÀ VšŽÜÀö4Ñ.”˜@;"äP’À6’<€à…@ˬºlÀ@©uôVuä“Àhxp–SÔ…@ÛzA: TÀW™Z'>;@¬Ë±:ZÉdÀv#x+ÆÀ%§ÈL.‘@÷ú!5”c„@iÜ’'‚ï@{‚¹L{¼’@N±%ï`¾:Àâ¹4¼DSš@3ΓãèdpÀpyF]WQ†@ÇifóŒµÀ©uôVuä“À~f*CŸÏ@}˸pqWÀ`f~¸Š*“@12\tµeÀM®Åæs@"ÿž÷•ð€@6u“ÐÀvÜ’'‚ïÀ÷ú!5”c„@Q±%ï`¾:@{‚¹L{¼’@3Γãèdp@â¹4¼DSš@î ¬÷:Á@€ðDÅ+Ö¸À¡¼„ŠU`i@sµßLƒÀ„va9x=‰@ ÿ§9ù£À‰¸Ýƒ°~@sTáŠ÷F—À=B½Õ‚žÆÀé[ê –‘Ï@LZïy"šÀŠÈ׿ Ñ{@‰5áþ L•ÀrĸEÞb@¼Žœ+€ÀL‰“~À?iÆ5Ò÷“@¡ñ˜ fH@ì} Ñ|À ªªËÏW‘@ã2æÿQãÀ€ðDÅ+Ö¸À ¾¹½¿Õ@0޵ÚÜ•À3¼¢Ï˜@Iøè®wjŸÀ~‚{³Ç·@ÏKµLm“ÀYù¬@ÿ(™knËÉ@ábæ"êÂæÀ2x­jÀC°@ ØÀø¶O‘ÀÎJç,‚ª@2[‚={vÀ’äÙ~ ”@àλPg“@½ËŠ¥PX©Às‚f^^À - n‘@Uô &–¥À+·W6=™¸@õáö¾Ç@ãÒR…«²@–9 ÛDª@ÛR5‘([“@0z#¹@Ë2ņd‰Š@Ù´ƒ+yÚ@pvn4ªd†@¨Ù®·‡v§@Ü–õ64@yÞRŠÒ7ÕÀðS/ô¬†Àž>ˆ»Ì¯ÞÀhAR‚ϺÀH c<¬–@›­“êæ-¥@wûb#,‘@¿Ÿ²In)ˆ@¨ž”¯Íq@–ze¢LŠ@„ÓF›§@pvn4ªd†@Nò¼ÿo•×@ –õ64À©Ù®·‡v§@96k†Àú¥pNøSÒÀË<ëe€7²À}{îßÃÔÈÀ‰LáÛt@Òqý«±½À†Õèi‚ ÀI÷@ºÞB@Îd‰P÷Š^Àñx+âþyw@gÕ¾ ¢?b@Ç9_Ì媺À£ÿÛ.ÃQÀ¥¦'|‡©á@kŽïàμ@ yä@#p½ÀFÈ3+›åZ@¢oþ·JxÀ®+Q³×à¸À\ìJ8¦ŒÀ>º] ù°À- Péü˜—ÀÈÇ<Ö6V`@êâ‹÷"ÀÀoΈ±ÀMÉÖ×ï—À±ÇŒ>su@ÝoÍÄ e`@‘Û?œu›À)\⦵ˆ~Àç‰bþà/fÀÃÅØd²ô@ÚAç8‹ða@vYóB«ãK@ó¯À˜|À“ߌ¼Õ±ÀkŽïàμ@–Ge3+5Á@cp¶=šÀAóðg¬ÀûÊ´7&NxÀŒëCTûò•@’à=tˆ„ÀMƒ^ñvI©ÀøÑŽÀÄDÁ‰ÃˆÀåvåy^5ƒÀÌyéÞ¤@ÍÇ3ö<À¹JÕQ_‚ŠÀÝoÍÄ e`@h¶ýéýI@m‘t_˜ñ—@éåi¨ëŸz@nzíŒÜv@Ûn3ýæÝÃ? G΢§"Õ@^¼†È}¡@aFÞ½Õ@Ü]ÞÓœæÞÀ›m¤·¤À5¤yÐ"<•@¢³µ´lr@ yä@#p½Àcp¶=šÀß±ùÈ$Å@«YxòÎy@ÒÅ*XCâ‘@òö®ioÊs@'.›p»Àˆ@aç·\ër@ʼtz“‹@­$xLu@áÄÉ i q@é˜\{ð™<À¿DXõÉ%˜À]޽½ø;@o3ýæÝÿozíŒÜv@ò¼û‚W¡@r‘?(´l@CnhnÝzh@0«› ¢¦ÀløƒKð°ÀAóðg¬À«YxòÎy@fŽJõíÀ@é˜\{ð™<@áÄÉ i q@f±>2µ¨<À$¶äˆy ˜ÀÕ —¢ñÄÀ,‚ RУÀžã\´Ìx@úcv…+ðÀë&W†è‰@œ,õb[@÷:"õ@gö.±³³¯À²8&*n·ÆÀ@ŒiØ»œlÀÖIˆu6?˜@1qv„@òmñÀ3ÁœÎûûº@¾œ¼ö¥‘@ä§«‚Ö]@î,“­e˜ÀíhÙ„Ç@’À*GÑ}–²¥À{—Ç&2º@œ,õb[Àë&W†è‰@gö.±³³¯À†Â'ÓXû@¦šL.Äa‹À…+:§>p¥ÀÝ6$^„Ëu@g=žžb@'ÞzM{àÁ@œ¹ŠüÀä§«‚Ö]À¾œ¼ö¥‘@ׯA¦äx‡@ÞÆq•@e@Hä<ÆÑZÀq[Öm²Àd–Gàm@Óš¶"ûT"@>ÄTE,ëUÀÓš¶"ûT"@>ÄTE,ëUÀ²8&*n·ÆÀ¦šL.Äa‹Àÿ8¶$­Ï@´.åñq@…œ9Á`6&@—Oˆ3ZÀ}:)ŸNš¹@ý‹ ÿ¢B@‡Õín'@Ȥ% [Ày@´®æ0¼À.O[§,pÀ°à Ðº!‰@¼×' u@4ùa‹½ÀI¨¿«ªWQÀx_"L¼„@I¨¿«ªWQÀx_"L¼„@@ŒiØ»œlÀ…+:§>p¥À´.åñq@ÌvÛpTÀÇ@äQ´YqUÀceÙûȈ@QÉ[X*VÀ†?_¬["Š@ò.FŒHâTÀîÝb|*ìµÀ©KkBv‘@¢^Ýä_þ¿BŒß›ôàÀÒõ»¢õOlÀļŸò'ê@]Rl$Ê©£@BWà6–\‹@‰æ°øt‡`@Q±eáʼn@™z‘©Úë^@:•"e$'ÕÀÚÊüáà£À3^Ýä_þ?©KkBv‘@6øÿò l@{<|¥íóàÀ]Rl$Ê©£@S›,ªÓxç@‰æ°øt‡`ÀCWà6–\‹@šz‘©Úë^ÀQ±eáʼn@_",n£ÀÉ)Ð}”ÏÀÈ"É犚@ÿØ ÚÇ*À ]ØŒ=ø@¬ × u¼@œ“¬E"¼ÀýWOÉœN„@nÛ”åöÀäi›Ò@¾ÀÿØ ÚÇ*@È"É犚@¬ × u¼@¶ñ0@žò@b¹Zâ4@, Bµ ûÁÀXD-DuG¾ÀÊTÚaöÈðÀž¦R˜™š@àe2íÜ…@ÙîösNá@ÿ£øÉñEÇ@R…øàyôðÀ×^0êŸs×À.ÁÝ䉭á@´lP‰¹Ç@å=<# ¬@Íï<1ly’@q–ˆYxTÂÀ…N±ùQ1¢À­äyét@Šw¾y ¯‡@ô¦ÊòUgx@ÙËçËd@ÿ£øÉñEÇ@âÃjB©¸@Ïé)DÙÀ°ÉùIyÁÀD„Y ðWÊ@cµg'±@Óâ,Fð”@Üçs]ć{@ åXÊ.xšÀNCO¦þÉ£ÀÍš”D{@Ìç”+mºe@¡¼„ŠU`i@0޵ÚÜ•ÀR…øàyôðÀÏé)DÙÀîf÷Ÿw A m’^ä@U¨­Ilsg@:Å÷AÀÀTêˆ@“ƒ\@üt<Ί uÀ6ù SääÁu8ÓÕÐÉÀáû×EÃÀÕ”'^s@­¦ :1HxÀQ 5>ØY@m˜ÉsÀÞéISÈ@@4fê|Q ^Àƒâ¨Q«&@j 7iŽZÀܦÓp@•†¨«\‚ÀsµßLƒÀ3¼¢Ï˜@×^0êŸs×À°ÉùIyÁÀ m’^ä@Éž 0Ó´û@MÓûÕÀ ƒpXd›@©"ʯuÀ³y)är@Š ýÅç)ÍÀ©†¨MùÀHuŽòþèà?5LæÅÀà³çÎw’@þÆd¨sÀǵP*\Ž@×õ©ä†YÀÜÏà~Úv@<ï¹Ê=AÀ|V\(‰Ês@·>RÄ‚ˆÀúÕPî›@}Ô„‹@ÁKˆŸÀ1e¿×±ã Á¦Ð5UuöÂÀµÉ»–=ž@¼è?¶€@2_€Õ’Ao‘À‡±¬Ù@. 1|æUþÀgÅXzê$¥@oÐmwk¢­@­N9ãNh@ÖÔEKï¤@\²€I´ÂÀ„ ufåÀǨ%T½À–ðÀ„{@ÉíÞ³‘ÀçSQ1º@åQrnü¨“À!7ÂPþŸ@‹i Oʉ‚@j €xŸ­ÀnÕmbõÁ@C¿4¾À {«zˆëÁ—(­TÀj@êaŠ4‘M@o‘À‡±¬Ù@ìvãâ%®A5Ý1¯RÒ¾@®”§lQðÿÀb8L7z@™Åí”È[@pj£ÀÀKܽÉÞ@zå½Fw ÀÀ ÖàSô’À%ŽÒ`žÀÌå Ê[³@l’Îÿ³Àò'ÍûüÌ@£ºpGMl@Ô¿&÷2fP@œ“¬E"¼Àb¹Zâ4@dRs–@Ó?HŽÀíkæÓëYÀß]üÑ7 w@ˆçá" ì¶@*û5X~ËH@ýWOÉœN„@, Bµ ûÁÀÓ?HŽÀAÊ£¿¡7²@£µ™V´ w@˜g"»±”Àû5X~ËHÀˆçá" ì¶@¹².™£•Æ@˜Ö(vÀZ''õquç@-ëk°ÜäÌÀú:lZÔÊÀÌ“ }1Œ@¢¬)ìUëÀTQ÷ÏË@cG€üÂ@óŠžKæ@’Ö(v@¹².™£•Æ@-ëk°ÜäÌÀöQŽüûò@Ø@ fƒqh@ÊVØž@ÌÀgüL(ÊÔË@½ Eë5¦ôÀÿ‰žKæÀcG€üÂ@Í…S:P`@6£É’À¿W¼Šq¢@Í(~:lÀÎÜEýÝîèÀV\‘AµšÀ 8’c 2 A «Y…À@Ow'‰È²@ÿ`³ö‡ùH@y nâq@å…Ê}¡¢ÀÉΨ7p@¹ÑbN/ŸÀî'øÆ¾0Á³ÃB>Ô®@ ” ÖÕ§¡ÀÇgcAŸ@t\E7é9@b¤^0·qÖ ßÀ «Y…À@M’îÓ‚¯þ@ý`³ö‡ùHÀOw'‰È²@G PW#¨À›wö žÙ@TèfŒ¦À4/ðã…pÕ@=|ÂfÆ¿ª@©`¢os Á+MÆFØ@ÿs\E7é9ÀÇgcAŸ@m¤ÀúWiÅóþÛ@ïÓ$~„@œÛä2°:Àß#.Á´@ AD‘t@0³EŸ Àõ_¹ìcÀ¨Æoë@Ä6 o"%kÀÒ_Ùê,&·À‘› ({hP@5Øz“@‹øy«Íið?™Ûä2°:@ïÓ$~„@ AD‘t@Ïýo±7‹­@À´»*fÀ£zqðþº–ÀÄ6 o"%k@¨Æoë@ÄŸ¾¥Q¬xÀ$§ÊºL…´ÀBøy«Íið¿5Øz“@Hñ0Çñ÷@–oÀà­l@*ذÔWæš@¥žðv@ #ö³:Û@ϬÍ1SÉ;@ÿɶuÚÀÚ½&«ëƒÀÅ­ËÍ.¬À÷†NK…–*@ªG"Å«òL@¥rOò‰v(@ÔU•X"·v@>Ç;d_S@ϬÍ1SÉ;@  ¿¹Ú@îzöGJWÀ¥yãÙØÀàšÏ{?vÀ 6á'ÙZŸÀ~[Ý´_©Àf5{YâÝ•@EráN‘wÀWÕ-†” ,@:Ú²ðxSEÀ0³EŸ ÀÀ´»*fÀ;LŠqï°@TLW{‘Á?Ä"ëç‡h@íݵX‚zÀ›sÛ)Ì%5@2Sv)%PÀ³§‚¬‘X@e àÞÇ}Àãí`/2†@f®åëÍb@Rµçrƒ*˜@°ŸÞ¼~ÂÀ!Ðí3œ@ ±D¹PÀî'’”oi@õ_¹ìcÀ£zqðþº–ÀTLW{‘Á?A2üBï°@Ö†`ŽAÀ»^xŸ@X¨ž8YÀbÌCMAs@~Ò›5M}Àbe/7V¡@·üÆwTTf@‡KfVêB@?”ñ ÷Š¡ÀE9·ë}ÀÿɶuÚÀîzöGJWÀ†àé;õÚ@[-MðšQŠ@@OÛZ›@Y3 A\æpÀW€)Ô;²}À9©r‡SYÀÚ½&«ëƒÀ¥yãÙØÀ[-MðšQŠ@v{&\B×@X3 A\æp@@OÛZ›@Nô1HÚ¿ÀÈüm¿‘Ä@Z¢Î"…H˜ÀT¾ÿèÝåL@Î×vùeÀÄ"ëç‡h@Ö†`ŽAÀ”4®k;‘¾@âgÉ€Ó·À¶v³ËeÊU@žPûÒ¢pÀš#VkçPy@ÝeØõÀ)SFEå>@È!RvCHÀz€XKüƒÀœe¾¿ |@uÁ ¼@fœHuÚÀ›T2Ú=ª@è4ox:_À:Ô¡ ¿w@íݵX‚zÀ»^xŸ@âgÉ€Ó·À3l×I^Ñ@1÷¶DŒgÀLÖGú@›ª/ºŽ[‹ÀV~ƒÅ/°@|<`é\HÀuŽBÁ!S@$8-Ó½º@¢“B“ÀZщ‡ýë³@'TrÎøH@°¢âîú˜æÀB¤ßÕÔŒ¢@³VÒ ’ÁÖklõáÀÔ°NÙÞ˜A%¿/”ÙÓß@TrÎøHÀZщ‡ýë³@ùÖåÍ<—¢@çØõ×$éÀí¸Yc" áÀí•ÕÍx˜ôÀ%¿/”ÙÓß@xàÔ ìÿ@ñIÇp³[@c‹+ ÛyÀkE­—Üð@87 ¾\h@ÎáI@ 1®À­|¬¢œˆÀ]P'ÌâïÀéážïAÛŽ@-äÓK‹…ÀÛÓ°&¤@87 ¾\h@¯}vÜ»¾ð@Ÿ2^€·w@?·s<‰ªÀ„èyÑÅ\@ÿÖZ‹ðÀnXzèÔX@’xßQÖÍd@d.ˆ*#?@<,°KÆ,@"òœ 6Àfz ZÔ™]ÀÉ[¼%~ûq@ªÌi¤9v‚Àk‡':²é]À<Œ/§@¹4üì}óÀ´e’£…‚%8@·€»¢(ZÀ`ªÕ`ºþ@Óiü¶ì)&ÀhÈ<ÄÏw@àzª„_7Z@èT²TíDÀÏA„®×½0Àã]I‹;@d.ˆ*#?@ßœjZ4Z@T¡¼*»6À‘„ëÒA@±Ò¨"›d@}]ÐOJ}À6ý„Ð}bÀzde —VÀ½¸¶ †yÀ $(Äñ@þk^¢§WÀ‰`šv:¡l@ ‡)8CÀ¹bR‚'ªd@ÓŒ>þçÙÀ1ÐØÇ=‚1@cË>‹hZ@T××£1=@'ÐÑË0À0Å¢¼o=Àê´X|@NÍŠáB–•À„va9x=‰@Iøè®wjŸÀU¨­Ilsg@MÓûÕÀi?r¶+è@¬ðð'w¡@¯¢ \f\|@l•¶%Ô‚•À98xøQžÚÀU1OUv™@ÛÊw;«(ÙÀûpn’ÊT½@cÌÔ&˜ÀÒj ¼´y@È5ûù_®“À•…Èí±`@Æú ã}ÀÖ?Ây,ŒF@ý”bÎáyÀ{fY”ð@˜ŒgqC¢ÀÔU”¯‡B•Àú()²0°@ ÿ§9ù£À~‚{³Ç·@:Å÷AÀÀ ƒpXd›@¬ðð'w¡@Î͆Cè8å@Ï%&¸w•Àp¦6]H°@é•~¦™@:ò£ÜÞÀïI›tº@‹X *––æÀ!²?LH²@£’3@u“ÀˆøÆ/ŠË­@lääDyÀÉ‚›˜hŸ–@‹^¸ÿ6aÀŸÊÇ]—“@³yeC¨À×4r离@Ö2l@»fÅ>@“À™¡/thÇÀ :ë¬ç«Ó@ >½.`¸@‰€×^HS§À±fG´èV@‡SÐÊ%ÔxÀ¼Óõ£[Ÿ´@#r[ÌÀKxú¦Ñô„ÀB»Ê“á@7#_' „@ôg”ŸÕ¦À‡M‘i^‚ÀÛ)U䙩@£Ê|ãÑ@ 0æ9ìÀ‰€×^HS§À–J*³€!É@ºß-œ¥¶lÀØÍÙ'½&@w>k ÞÊÀÑñºy¦xâ@º’ÑŠãF›@‘šKX-r³À‘ˆÌ58šÀðË$ãÆ¿½@ì‰FÔ9•@ýê(fgw@æþ*À}@KlDÖ …S@±fG´èV@ºß-œ¥¶lÀ‰¨OøåÄ@*[Ú­Á?üOgM*óËÀ~SÛ•S؆ÀÇMf`G§@K—Äy Ь@uF”qw°‚@,×n´+w­ÀÔá3–¼€ÀTð,û='@’2@”´P@òalÚýs@1“c—ÎJ@•°¨ª¨£@ßt¸¸$(q@‚1z¶±ÀJôßï“J@fFɱt@Ì»&JV@KlDÖ …SÀæþ*À}@‡SÐÊ%ÔxÀØÍÙ'½&@*[Ú­Á?V‰ÈÖÙ\Ã@}SÛ•S؆@ÕÒÅ’SdÊÀÇMf`G§@uF”qw°‚ÀK—Äy Ь@B¡^Ä) dÀðQlk9£À’2@”´PÀTð,û='@1“c—ÎJÀòalÚýs@ßt¸¸$(qÀ•°¨ª¨£@…¿ð,õ@¹›hEgµÀÀ°¨ç?[À´žðu@ê"‡µ–? èÇ&d­@ÉÔsZ‡ƒÀ"]*Šq¼ÀÓno[Ý•hÀì«­ª,¼ð@¨´€)3žžÀhxp–SÔ…@}˸pqWÀüOgM*óËÀ}SÛ•S؆@Y)X±Ž» Aó,*d dÀ—uµƒGãäÀ®”Øý½¯@æð8z\.@æ,Çì*WÀc¯”"B%Áð­p<¼¡‹ÀLd#ظƒ@ÜæwRlÈb@pFf‚Ÿ€@Ù¶œ.áÓQÀ•n@™õ‡ÀÀvd·yX^À¶JnÅ¢¸À·ô³oÀVŒ?yæ_@Wû9,–?fV‚j“Nm@“§e¡ÎÀõΓŽqÏåÀHüÊ;¶çÀÊϪzŠ@{òð¾z‰g@&©ñ"¾‘t@Ó \;šÐJÀûΕ’®ž@<"‡µ–¿´žðu@ÉÔsZ‡ƒ@ èÇ&d­@`)ÛXÀÃU†bKÒÀ@ õE£6‡@ïeÁÀ«´€)3žž@í«­ª,¼ð@ÛzA: TÀ`f~¸Š*“@~SÛ•S؆ÀÕÒÅ’SdÊÀó,*d dÀ>[OA°LÔ±S©À,r5.›óÀ˜õ6a"WÀ‘³D-æ¦@ñã~VÁ%‹@`—E"ÁÜæwRlÈbÀLd#ظƒ@Ù¶œ.áÓQ@pFf‚Ÿ€@R}P5@r@­ÐñÁÁÀ øYÀn@`Ü a–¸À&Wû9,–¿VŒ?yæ_@.í÷©IpÀ÷Á¨j-ð@“§e¡Î@gV‚j“Nm@Bš1} ›@F(˜ªþÉåÀ{òð¾z‰gÀÊϪzŠ@Ó \;šÐJ@&©ñ"¾‘t@+†T!@+†TaÀÇ­mÐKÊÀ[r/ácFž@FO6d(@;´yš”ê]ÀuÍ=µÃ?œ@¨f`ws‰r@ÇMf`G§@—uµƒGãäÀ°LÔ±S©À±ºÓ—ùÙ@É~öFtyœÀh;‘Ü[Ë@_4^œ ¿¡@¥b5ûД@ü@96’¹o@¢º›û’@nèÒØ&¿h@fxv(rrÀ­²’=¼&šÀã¡æÙŽ|@, è_ßi@Âi„ IwÀ_Á³¸ªÂ@È!;ÄJ@æZª}jJ@'ˆ¨ZOÔÀD2´ ìÕaÀD2´ ìÕ¡@B¢¾q.%´@žƒþ¿ÖéÀ)¼°Oú\ÀŸëÇ«ôÉž@¨f`ws‰rÀuÍ=µÃ?œ@ÇMf`G§@®”Øý½¯@,r5.›óÀÉ~öFtyœÀ4’\Ãõ@_4^œ ¿¡Àh;‘Ü[Ë@ü@96’¹oÀ¥b5ûД@nèÒØ&¿hÀ¢º›û’@^>1>ãû²@=”™ñèTŒ@a sd˜ÔÀëØö(¦Ü¨À¡)Þ$/`¶@È!;ÄJÀ_Á³¸ªÂ@Y³ÁT‰À×òAªÌ@WÅö{ÊØÀpÂßðI«@@=·>A@¯¥ù?"ŸÀGbBÁÀéË  ’1ž@ßÿÏéIÓt@Ý¿bÿe—Àm_ã£]à@KHʯ ‡žÀø É6·X®@ôÁ%1.“ãÀuWÆß“£À¯Qa•©Á@ÏŸ5ôŸ@ìÿ=6˜ÐÀˆêß%º–À0h‚>m¸@KHʯ ‡žÀ|qìNgä@¶ úÛÍ9@Ž^œ)ˆSÀ3"އMÀ5H‚LÖ«2À<ê\ƒg@øˆZÍë€wÀfƒ©ø3[cÀÿ–r96Š}@äm Š»SÀQKê²Nßm@5H‚LÖ«2Àž¡q~œÀøˆZÍë€wÀÁ¼"ÿ;ù’@õÈŠ¸‹š}@;7î+Þ––À\„âeÀs¦ Ol@fƒ©ø3[cÀõÈŠ¸‹š}@W° ¿+r@LKÔ-¹ÀÏêßcç@³ü¼Ê.Àí/¬~µ›@³ ¡•³:À–Èï;ª@çt”uH¨5ÀF®ƒžAB@ò+ðJü8ÀG·“–@*†ÍÐHß-ÀKèü®3 @4‰äWO=ÀºbÓ{1h@´lô®ÇˆÀÿ–r96Š}@;7î+Þ––ÀLKÔ-¹À !5œð³œ@ê#­GóÛ)À¢nªNG@ÿ½ Li6ÀHµGá 6T@eõþW-2Àã›™ dP@Ôxj ,Ù Àþ¶ú ‰éR@¸ ¯ö)Àë'íbrœF@£8EBþ†8À|*È}/V@•wNÖ€[¶@S ÔHõ•@¯ha€·ÖÀÀÑêbS­—Àc+¨r¦J™@PL(žÖ¬î@“i½÷õ=À@R›#Šò8ëÀ•xtÃÄÀ#ÕŽFìXµ@òå—£—@f†±O-lª@â+]í|2Ž@ü«¸²!z™@jZ!A¸ x@¦Ç˜Õ9B¡ÀK[Ð^öÎÀw®¹ùÒ|@“i½÷õ=À@- ­~ŸVá@»ˆ/MˆäÄÀŸ@{oAÔÀÚä\ü—@8tz@£Ú‚Ž@Ë3&“”4q@fÛ†jÀ@_¬˜µ¸‚Àh\±çÌþ~@‡á-Ëаg@\J‰›r7@ˆéOj@ê!Ôë–p@ž-¨øqrR@ø`¯èlm@¶Äý¹I@\ìJ8¦ŒÀMƒ^ñvI©Àòö®ioÊs@òå—£—@8tz@wB{øƒ‘Àtq­Ò³N¾À_¬˜µ¸‚À6÷̹/Ä@Ô¿æo&a@,·®7J@g‡(õg c@|†»&M@åÏK8–&ŸÀó(æØuhyÀjÅ¢+ôާ@;—&—Ïì€@ÎÓs„VÏF@ŽØå¥ñ6^ÀN’:\­œ’ÀЄá³x@heüsÉ@@áY1ûïaVÀ9k‡Æ­1@‚ѼxÜFÀÛ-8Ø @ê,Ô!ãå5Àd;ÔLûE@ÈPmÙæKÀîÍM1*@(Öû»÷`Àå÷‡”l)@vùDwŒNÀ—"%ó‡_yÀJV^ã BÀ;—&—Ïì€@*iˆ+omš@vïÚÕb `À£3óÌ>u@¨ççmIu@š,¤ßÒ ¡ÀþÏù´šWÀÉRMñxo@i“}οHÀ9çÁªž`@WºŽåx¯7Àr%ÓƒÊN@o54tŸè^ÀðÉÔc@ŠGÈ#55À|0AÈÛw@󲻿æßAÀÑ!aB;ze@ßbV¼5žÍÀcy.¢µëŒ@*jüØ@DÔÌõ‡@?ÇýZÄÀ:”§IpšÀ‚ÔÓ0q‹@5ö­0;ãÒÀDÔÌõ‡@à)”nÏöÕ@fÔŽO#³™ÀD>ᚨÀÎÓs„VÏF@vïÚÕb `ÀÏ™h$óW¡@q=ëÓA@Su8l DžÀN*tØLŒ@©a¾«H‘Àõò ¿©ô@Àߥ‘2_ßO@@aÌ”?eÀ_¥ˆ“ž@@÷æ*ýç³UÀ&XŸ3iû/@ÆZ.ÑÉDÀC`›Sô€@í¸LÓº¿›MÛ%ÞT@Û ÆYå|ZÀÝù”½á¢,@ŒÌ£úžpÀ©¾ŸvÄ"8@°$ïÜ,]ÀŽØå¥ñ6^À£3óÌ>u@q=ëÓA@ã.fv’» @L©hah8‡@ è×{¹®¯À?Š^~AÀ.ˆ9,À>°[ÄeÀÿê$[j%|@lqýß¹VÀ³a¬€¿l@’«Û¡.EÀrE"l‰[@ê·LÓºÂ?B`›Sô€@©é®CY¤kÀ8ñÅ‹q@äkW÷BÀF`YBV…@yÓ´øOÀÙÆˆ!5s@Ÿ9B‡H@" +::ò_Àl:ÒÓ"q†@oà^<ËÍf@œ—ø#–E|ÀŸ`‚<ÙþS@Ç—­sÀî­À ×`À_ÑX9Á\Àa)ij¹r@oà^<ËÍf@H þÍw@%jþ~åÉP@3°ƒßƒÀÒ¬±y!Ò`ÀY%ý5ÊLÀŸö±‰¤ƒ@¡!Ȭ½¢À^¼zÆGÔoÀþþÅ_·à|@‘4|Fá›H@¶JÙÇǾ‚@ýƒçÛY@±E²±³§ƒ@Ua3Y@¢`÷ÝÕ¼P@‡±î*ânÀ^ÆÀ;À‘4|Fá›H@Zmyç—ø@$‘tzÊòO@Âu棋&@Ÿm—â¿P@M`€j©º%@¯i¬è)Ñ@>Æ­=Th@ÎáI@ 1®ÀŸ2^€·w@Ÿ¸·ó@ h–ŠžXh@çà.‡÷À5Î-zWhÀÆ3![·›§@½+ûÀ«ñÀ;Æ­=ThÀ¯i¬è)Ñ@­|¬¢œˆÀ?·s<‰ªÀ h–ŠžXh@ÛU[†ëò@Lñô©bSh@ê §~÷À¾+ûÀ«ñ@Ç3![·›§@otȸyª@>‚ªJM/*À;ÈÌ-þƒÈÀbiøˆ°¹¥@Ù‘äœÂæÃÀ•(âÏQ@¨é¸dGª¨@‹'• –@‘”ã$ôV§À…H¤€ºÉ@˜ŸñÅ`xÕ@^ó|"VÕÀ‰rÔDr@Ø u³Õ“ÀÇ2W)2¯ÀwQöŸj®@ÎýðþŒ@ÜŽ¢¼„  À0‚ªJM/*@otȸyª@ÆíPžHׯ@&`¨¾tÕÀ;‹úSª,¶@̬븨ÓÀ‹'• –À¨é¸dGª¨@M †/ îÆ@uWõˆEéÀ^ó|"VÕÀêƒf ¼÷@è"éÿ+”À–Þ:Ñ æµ@T ý|ç@G]ì³ÐÀ¢¼„  @ÎýðþŒ@“Úz ÐÀ!D þaÀÍϯ\ÃÀ´-4ö7DÀ‰DuŸ2±À¨oîÇ+”@‰rÔDr@è"éÿ+”À›ÈéÅÒ@ ÑcI⛚?Ê|}^¾éº@†¾þQüa@ƒ"ÏW“´@"hÝ D@†lûFãŠÀMsìrºûa@è#À#e ÐÀ%hÝ D@I…9Xh\ÃÀØ u³Õ“@»&[úÂÀØ u³Õ“À–Þ:Ñ æµ@ ÑcI⛚?Ádˆ´Ò@†¾þQüaÀË|}^¾éº@"hÝ DÀƒ"ÏW“´@³Smä‰ÀLùhzÊ&‡ÀøEË›¦^ÀÄ=¤Š!nYÀ»­Ð •ƒ@W™Z'>;@12\tµeÀæð8z\.@˜õ6a"WÀöëžI,‰@B*à>nÀøEË›¦^À3(” r3ÀÍQÉ—]gƒ@Ësþ,â­À¬Ë±:ZÉdÀM®Åæs@æ,Çì*WÀ‘³D-æ¦@B*à>nÀ"¶ecÜi¡@±{„nü˜\@ž§Dôµ?@!É•Ò`Œ@&Jw´}rÄçxÀ–²`8¨[À(¼þF0@åHgEMÀþl!ÐmÆ?@æÎ+{ù!@&Jw´}À‚GÍ xMÀSS-H€j@ƒ]´7”Àéú3N‘`À&= Vgu@êú3N‘`@¨¡wí‡ ‘@Îr¦ÌI@{™YÓ4tZ@~~`^=@2ÿ„ô`yÀç] —èbÀø ±´ÐA@€G WK+@Øj\F6b`@’‰c9I@±ƒ[>ž`À½»tÀ"À”ÞÛäR0ÖÀÝ–XÑ͇@"C¢ `p@Ò£àYˆÀ-°þýŠ”ÀF´?ã¨ÓÀ%»(@‚ÍÕðœá@ÊA}uÌœ>@Ä7Ávx¹@=·±Iï‘@+Ô€ˆuÚÀ>·±Iï‘À³l³ n²@†ÓçÌ;m@-Þ,XO´éÀ&TŒiœ@€ÈøÄÜ@ì¯ Ÿ©±u@†S7rÆi@ƒA¶‘ä.@Që¡æ ès@jPÝÝÎó?ö8¨\ƒÇ@­,¶¯nžƒÀ„ ²(Îc@«ýcQ·@¢váœÉÀ&TŒiœÀØá¬MéÀì¯ Ÿ©±uÀ€ÈøÄÜ@ƒA¶‘ä.À†S7rÆi@køÀ¦ÖÀž¬ç•Ñ1¨À¾FŒðsé@9È.8ä©À1ß´.ÚÀ0–CöôF¢¿ñ£à*D¤À–pÆÚ_ítÀæh&t:|À¿Y¿¬ã©@ê9µÌ3p‹@ q@÷™]@®§5F@ ¹6Ì¢Àš¾Ð]…Y3Àÿ>òîiÀb¿Î®jBŸ@æ]SÙ`PÁ@@ÃýÀç€P@?gåõ8‘ƒ@\®0_Oð??gåõ8‘ƒ@\®0_Oð?áŒ%¬zȨÀJ»“#è@.}¼´`ŽÀ¾•8ðÁáÀ ƒqúëµPÀ™¥I ¼a@]Ýᦿ7=¬1|€Z@°Ç²¡X{¸?W3Zö¡j@’ì˜;G §?ÕŽäÆÂíb@¡kŽsÖ•¿©á9„âwk@ü^¹B»õ©¿Ó㼄æÑÀl‚X§ï¬À;=ðì.P,À;ÿ~Ó À]0g8—AŸ@;~@ƒþˆÓÀ?ÃýÀç€PÀç]SÙ`PÁ@:®0_Oð¿>gåõ8‘ƒ@:®0_Oð¿>gåõ8‘ƒ@.}¼´`ŽÀLåu9ºÊë@6ÃýÀç€P@ÿZv#çÀáÀAÝá¦?™¥I ¼a@XDz¡X{¸¿7=¬1|€Z@ìì˜;G §¿X3Zö¡j@¨¡kŽsÖ•?ÕŽäÆÂíb@Å^¹B»õ©?©á9„âwk@öâE¸ À]ËÖü3ÂÀ{Õ•ä"ÞÁ¶Uº"”3§Àhb'Ç££@P æ)Jê?¨Ù®·‡v§@ –õ64À$ãðr A×YÕ'ªÀ7ˆ §å¦ÈÀZM½?ƒ9©@• tëyEÝÀkÿV„¥œ@‚¼¦ˆf8èÀpoÀ€]¼“@A]¦.§@×U7éÝÁæ)Jê¿hb'Ç££@Ü–õ64@©Ù®·‡v§@×YÕ'ªÀW4BDÃrAZM½?ƒ9©ÀL¬Ò™ÅÀ2Lyw„°ƒÀ<äÜd§¬ßÀ(̵N”°@ç19¸ÍëÀËGˆ*k³ìÀŽî¡ðàºÀd(jS´y±@Cä¥Ò‡„@«fÒP*ù@KËi_@i@“)®Ã$»À.LxÈ\§@ äCvü¹±@œÌÕ_ @(˜L*Z¡]@~¤b‰¯vÀ±ŒPч¼À6–.×·@à”ß§ê ãÀ;y+mâónÀr÷¢)غ@ˆºÚűìÀÈ1Ö¸M¤Ž@²î¹×ÿa@KËi_@i@w©'`÷@.LxÈ\§À@üžBk¾Àé^Q@©.²ø!l@}õ¹z…vÀŸ_ö1>‘@SÒàV`ÅkÀ6[d§/ÀÀÕ2”½ô»À+¯ìè>ßÕÀôµ­ ÿœ@N•žN„,À)|®ðM6Ã@œê‡Þ¼/±@7ˆ §å¦ÈÀZM½?ƒ9©À“)®Ã$»À.LxÈ\§À–Q 0p-A§"žêÆçÙÀ±<2üïÌÁEõ-sFå@“î ig@/µ1ÒáSÀÿé,)SF–@\™t@#’\¸Ö£@#„m{ sŠ@·Œ«ÕÆ´@ðE$ïþ‚ÀµºXöIßÀ •­µé¤@¿¨:‚Q®…@z@ˆ‘F†l@ã]•à§Å@ EPåC@@j§ÖM¢@Y¹CJ8ÓÀ3¯´b;™@¡§} óy@V•žN„,@ôµ­ ÿœ@œê‡Þ¼/±À)|®ðM6Ã@ZM½?ƒ9©@L¬Ò™ÅÀ.LxÈ\§@@üžBk¾À§"žêÆçÙÀ.…IÔ A¬ÇŽgç@Ñ(A‰Uý$Á:X®îYþR@ØV@tu@\™tÀÿé,)SF–@#„m{ sŠÀ#’\¸Ö£@ðE$ïþ‚@·Œ«ÕÆ´@è»´(5?•@D1 x¼%èÀz@ˆ‘F†lÀ¿¨:‚Q®…@EPåCÀã]•à§Å@ÐDQŒCàÖÀ¯§Ô\FÔA¡§} óyÀ3¯´b;™@oó`”àl@ÑÝô%ƒÀ©a¾«H‘À?Š^~AÀ,ö‘½¶p@€Ç ow?Jz\‚½@Óûá—lŒÀ¶i%í¾ºÀ¨Å/˜ÑM˜@VÔj[b$ƒÀEUþxÍU™@õò ¿©ô@À.ˆ9,À ¦ ow¿,ö‘½¶p@Óûá—lŒÀ°y(%¶™Â@SãmH(P˜@ùs™tšGÄÀ݈*Ÿ³•@Ga²É< _@;»^ÑF•À6ÚQì \P@AeÌaH{@»óó#zP(À¢w”eü|ÀÕ§Ó~Ø0fÀGa²É< _@¸@åpL2‘@ –.¾;G@Ö7üè–ÀÁóó#zP(@AeÌaH{@b$•ÚfÀ"˜ý QÀÈ7¹~½r@Eç¬@!b^Ó³v@;»^ÑF•À –.¾;G@+½í¬@½R-—4&z@š"¤'49®ÀÞT†Þ‡ŽÀ;Ÿ¨j,be@2޾œß^P@CdP¶Gk@¥ž´&âT@?ÖÚÜ™\@T°Ñ‰¤v@!'TsfRa@6ÚQì \P@Ö7üè–À½R-—4&z@„ æ¤@Wjˆ†Hj‘À¦wZJ°2•ÀLi_¹Y²Q@óf;Až;@‹­ˆD7ÑT@¼\š6ß?@1sÓ37€²ÀBŽlù‘Àå{L"Õá±Àüß½ô–Àán©®zRÀ@. 8jÇ¡@ŠhÆ·è@Ù®ùCes@IÞEý©íÀ>Ô‘¬ gšÀüß½ô–Àe Âç[v}À. 8jÇ¡@Hõl1þ @£N…s@ž^\¶ÔÀjìUwç˜øÀk÷}]'o¤ÀhÙ'MôÛAjt†3ÄØ@V¸š°tÉä@‰»‘FP2‹À°»Ä,j¶ÔÀ#qC†­ ÁUÙ#²±À1—©¦ñÀjt†3ÄØ@|,À@7NA„»‘FP2‹@V¸š°tÉä@6ðÒú°1ÁÀMú@ $h•À,×n´+w­ÀB¡^Ä) dÀLd#ظƒ@ÜæwRlÈbÀLE¤CíÅ@_ðŽëæmš@P¿A!²m†@5ɺ£%ÀzŽ\Ðð“”Àï¯C톰ÀÔá3–¼€ÀðQlk9£ÀÜæwRlÈb@Ld#ظƒ@_ðŽëæmš@ P@"U'%ú^çÀ¼™îù†°A£w֙ΈêÀó‡¹Q'AB•¥sºA²:Ǧ5Ù—ALãå’mÀD,僑@ç]áE6tÀ"A*ÞÆ­@Mn [Ž|ÎÀr(lì AMíàöÍ3tÀ6GÒ^ÁQ·Àž½ºO‹!’@…°¨¸ÚÀfýH§»tÀ·¦ûÍ©fÀã!.§›UQ@¢Ãî °8@g8bV(@å¬êØ @ìãÌ0R;TÀQŽÈܯQ‘@n¼»®dĨÀ¨Šr?'FÀMzA:g7¶@& ³ói†@æPŽé\“‚@n3åñ‰Tp@¿àrº¶x‡@ Sa®ue@¤Ç#¨ûõ²À îÍCvÀÄ*†"úŽ@‹ÞùÈðn@S†LH,À3ÿæÛYŠÀ& ³ói†@¾âþ¯®@›á Eùlp@¦2!A\á\@6¯ÃBÁt@VIH¤ÖùR@Fl¯pÞ‰=À0’-ô²°À‹ÞùÈðnÀÄ*†"úŽ@ Q ò6åÀvÛYɵ´@@x¡~ u@<¯9S,Z@cFX;Ñ|@ ÂPæ™»d@¹Ö cb’À%ý}hZNd@ÞuV¨Ø•@~ç‰w$}À´èî³uõ0@º‘¦Á ÀÓ¯îÓ²Y^@·s¡lÍB@–霨d@kAÀýÛ¹M@1Ø ÊTd@!ç6µŒ˜À~ç‰w$}ÀÌo)pîÄ£@¸F@]jµ@úžfUà€@à~ ­ü|µÀOZ Ãù€À+ïåI@ûg,²|¾Ò?Ïd`Ä€ÀÓŸJÙYP@é ÙÉMek@߇ÓWÅ+HÀŽ á`s@†bÃÁO*À‚…E×½æL@³òô»0þ¸¿‡UÐy0—Ÿ@ wsaÀEi@mwu—`¤ŸÀ“ŸÓÑ'rrÀh,²|¾Ò¿+ïåI@Q¢¥|ÖVC@Ä}m•p„À߇ÓWÅ+HÀ\刓t@ŒbÃÁO*@Ž á`s@¡òô»0þ¸?‚…E×½æL@yy§lë„ÀIÓôX.]nÀàÔmWd“Àõm…ÞˆdsÀgi2®Î§›@ápßm@@Áçïa@g]¨­ó+I@hkyóÁZnÀß x¹fVÀå}¯ó%rsÀ¦1=ežœ~Àápßm@ BçhV}@é“Úo`“I@Ì^T2@Ã.®™0¨Áq•§!œÚ@ÁÛ(¹* A='þçÇ‚à@PG7žÅŽ@°­­‹·@¼8ÖÓf@ü¦ N3À 0†åXâýÀ¬Áwb™¼ÈÀ÷ã­½F¨Aái/¨¬QÀ4ŒªpŠÁŒþš qyåÀ_Îëü¥E!A_Îëü¥Eá@ºVÇ“@ -n™LÀãñÛy„Á ÏnuäÀHÈc½„~@‹&$‡jFP@›M׆D‹$Au~ ýã@dþ®Q`‰@¤¿Ì"Áè 3WÊãÀñÜz@ìKŠ@=no~jâ[@‘¡`Åø€@•Áë&H_@*oÑ„­ €@½õë®§Nâ?q•§!œÚÀ‡a)q ²Á='þçÇ‚àÀÁÛ(¹* AË­­‹·ÀQG7žÅŽ@ü¦ N3@¼8ÖÓf@Ô¸Á3>¼È@ˆhpíáýÀái/¨¬QÀ³‚éñì²A:rÒ0¨å@¶ññ™Ú¥Á_Îëü¥EáÀ_Îëü¥E!A -n™L@ºVÇ“@ö0][)uä@Á]‘.9„ÁFC¨¶@@P@°6o\šU!@u~ ýãÀ›M׆D‹$Aøøª ([@ÎcǻŹâ@—{i@ÊóÁn)i\@ý|/ï ³-@•Áë&H_À’¡`Åø€@Ðõë®§Nâ¿*oÑ„­ €@Cè½Y&¨Àíã7qh†@-ðÏó yÀ°¯¦—²tY@Né®$DgP@€ ìçD@H9ÙE@¨@FrݱŒÀb6ƒèßbo@‚‘UVìÎö?èÙõKúaV@_”mô@A@nú˯ k†@æÍªâ„­À^A†mT@¶¾qú¦þ|ÀÑ ý+ìêD@WЂˆ³§:@FrݱŒÀ7LôãYή@q‘UVìÎö¿b6ƒèßbo@œŽäŠL@Ì÷@mÿ5@oš7‚Ñ@æ³`Ý!mÀ{zîd'ÒµÀØFˆnœG“ÀÅÆ]p!éÝÀ¶Õ3¹ûxÀ‘‹¾ bÑ@· @h #@\,ÖîCŒ@v{⸀û?Ù³`Ý!m@oš7‚Ñ@ãw+’º)“À¡è©Ô9¨Àdãd­Ž-‹Àã.ФݧÜÀ· @h #@î²)gË@]{⸀û¿\,ÖîCŒ@YZZZšA´´´´´ŠåÀ…ÄÝKBÀ ÿC X¢À|:»Jl@Àk ¤Š0€@@8»Ó.ò?4ŒªpŠÁ:rÒ0¨å@’\«L>kÁ@ŠÌŽg\rÀû™2Õ×®@ ;Íp4CÀc ˜ÃMß@õ1ÄŠýÕ@Àúûµ#•@Ñhh|¨8D@i&{hc£“@ò5·8/gB@â¨?¡•ÀÞÍLR‚€'@YïÞèÝÊ9@YYæ£~ìbÀ´´´´´Šå@YZZZšA®"Ñú-‡u@\s·òGY@­ë‰B5(®À58»Ó.ò¿Àk ¤Š0€@Œþš qyåÀ¶ññ™Ú¥ÁŠÌŽg\rÀO«º ç(Æ@†]oñ MÀÎ-‚‡Éxv@#g¬O¼IÀX€~DÏs@Ñhh|¨8DÀŽúûµ#•@ò5·8/gBÀi&{hc£“@AƒÍã“Þs@’îeÑ3žÀyM1ÚRÀJä1sé©{@‘gªûð(Ál²¨áÀ/ Áߥé׋@Š @ìÿêg@<îwm¼|(A9…$Éo A2À!Ç–>Î@õÌç82¸@3©œÞb—Àg;(*ÿLnÀöÍ/¤r5 Á®ÍdÊörÁˆðŧ—tm@6QeÓMI@9…$Éo A…°ˆÇQA¢øHï?è¸@èÆ òÿì£@±×rKëqÀöÆINÆ}À±<2üïÌÁ¬ÇŽgç@Óß ‘NAEöýÉõÀøJ 2ÐÁáb(lt¤â@Eõ-sFå@Ñ(A‰Uý$ÁEöýÉõÀ ‚Æò‰@2AE¾ˆMŒä@8BþÁšŒâ”@.ÀS’u@£Ñ¼ÕÊœÀY3(lãOXÀ{™YÓ4tZ@ÀaŸ4ÐGD@L|vøC•@œÚÂ× ¹p@Ù†‡<~’À“à ¸ÜsÀZbyz;L@À¼q›? 5@ka|u¯öi@kí™üS@.ÀS’uÀšŒâ”@}Š´ ûŸUÀ=,hî*×—À~~`^=@+g?¦Úƒ&@œÚÂ× ¹p@AÛ© Ho}@k÷1sfqÀ}›.°ËpÀº8õ»ÏW/@ƒU=@Dæ"¡ÓL@szèZ06@XœrÀ16X•j®^@Ïêßcç@ê#­GóÛ)ÀñÜð'ÖŒ@–,¡±5vM@>W½eIl„ÀYH›}ÛQÀ"›½/@¾îaS6ÀÒ”äEüß@*~í›ì1Àm±½µ l@ì *ÈÁ­4À-ÔoL]t @®!À(¹(ÀG”LÂzÑ@ÿ¶fBûA8ÀY7ADÿ=\@ “?(Ë †À³ü¼Ê.À¢nªNG@–,¡±5vM@5ó¯ŠN³†@vºF4—éQÀ {PëyÀÁÂk=6ÀЊDx ëS@Yš…±áé1ÀuFó+É'P@ød³™¤š À´°‘ÃX£R@X)(žÆ¾(À@T\Á‡HF@˜ Ï÷+8ÀãÿD„'ÝU@C °å@:Z÷üe@-ÞE®¸ª@B~®ÿ®q@Ç}ú6îÐÐ@„Þ½<&jÀñLÂÕ_N¯@xP–¹ï“„@?: ×"½À”ž]K @, ކãÀq|§Šâd©ÀN$PîV¥@ Ü+å\øqÀ‘{ ÊñѬ@8ÉU‡‰ u@TW“¿T@k¯€aˆý‡Àq‚`™¿@#.¯ÜŒ@q‚`™¿@#.¯ÜŒ@:Z÷üeÀC °å@B~®ÿ®qÀ.ÞE®¸ª@„Þ½<&jÀ÷\³óÈœÚ@yP–¹ï“„ÀñLÂÕ_N¯@ˆóA»Î @ØUÌY†aÚÀþ¿Þ¡»µ¥@RÏÐ&qâÀ Ü+å\øq@N$PîV¥@9ÉU‡‰ uÀ‘{ ÊñѬ@}**ˆÀ ÓNݼ@$.¯ÜŒÀq‚`™¿@$.¯ÜŒÀq‚`™¿@NàÒ! ¯”@[ËüŒ!x@Çù}í3‹@¹BéI,«Õ?srÅR#s@õð7¼AZ\@)¿ œÉ¡@ ÿIivS„@$‰oÝŠ«±À±ì¨îLšÀ<ÙhÝ?1u@w4o((@M«ÆÝ?À®Á‹…jÔ˜@eTÈýGZyÀá,v‰ÆšdÀþ’'<_Xl@¶¿¥„ŸHÀ›o§ŸÀ?ÑÒœ¶e@l¥7¦õm@~ KöyUb@®BéI,«Õ¿Çù}í3‹@ Q¼ù¦]@ÃÀ¦ŽŠE@ΠÜ,s‹@¢nŽÅÌân@Á€Ìà67—ÀѵÚ6Õ¾À[ èÏç`@˜uÞ¢“?À¥œéù²—T@eTÈýGZyÀÐPz†-L¥@²9è½j@'v£4XƒˆÀ†ŠƒÜ`@Jy§øj'X@ÏØÁW£À±sékXf@öq“º×áMÀ< 6NXhÀ¸æE¾õÀ”P€Ñ-Q@$å7>;²E@øîEoÒJÀ0ø‹Zd”6@öq“º×áMÀ¨‡…í\m@HÜ3?cÀl¹á=´gÀȯ2 ««E@˜Ñ®j£;@n{Ž„…6@IÓ¢9RÀâªÁ-lÀ©3‡±(aš@ãaÀ´µ@@ht™†À1 ü"‚@‘Üâý4—SÀÛÛ)O\Ÿ¼ÀÅ¢lÉh½S@¯×>P½W@Ôîù…";…ÀŠÓù‚\v—@ýys=gºö¿ÌÛ²qJªš@Þ4©löÈÀ@ht™†ÀÐVÅk(É@‘Üâý4—S@1 ü"‚@¿èËlÎTÀbõ!lT—¼ÀŽçuåË…Àwñ‡÷´@5zs=gºö?‰Óù‚\v—@–Gm¡áœ@ÅMŒ×G@™ý°˜q „ÀivàCkÀÔ²ãØ†˜ÀXêA že@>-x:DØw@²)@OAÀÅMŒ×G@ªlBªÍÉš@ivàCkÀ-£:†Ö¿QÀ¢>Û¿Y d@ÍÐ÷ôÔžŸÀÏ)@OA@?-x:DØw@ž¤~üZš(A–gÄÈÁÉí×åÙ‹@ߢLÛW½ÀÁ§®U¬ÁŸ"Ójeã@þ—:ÐM–Á,ÑÃS´ù@–gÄÈÁØáͱ>A³ÕþFÂÀbâJê§Aó@„ë'GMá@§éà¹pz(ÁïqÄ3û@ß$Ú÷®¨3Á+A¥o`À¿-koµó-À­†¶Ö@¦@ *þÃqF@AËì0ù°|ÀôA-ßLÌ=@¨WbõÚ6@#”“ÒáßMÀ¿-koµó-Àª¢ŒnÂWÀ *þÃqF@™Š1ÿõ}@ kàXÖ=@‰°“.uk€À#”“ÒáßMÀAbÖ¾U†c@Å,A§ Àö­“w«x@w+Û6Œc@™F*ŠË¬xÀ¡PU±ÿ–@É®gyȵ;@¼ÌŽ´~ŽZ@Òro $QD@€Ø™8¡À-WÛm ±yÀdOK4|@ë­oª½v@=UnxïyY@Î9ís÷óX@…ºÿeC@XöE89è@êEUi@¯“¯„9‚y@ÖõiÙw,œÀ¯“¯„9‚yÀhá‰@É®gyȵ;@¡ºî@°@:Úƒ'4XD@f½³Øÿ /@µ‡å“LgˆÀÔ£ÀÂ.tÀ¥ýåÐ¥‰e@¡¼ø³Âì`@MAÞ$V„C@ ~0–´C@¹+U€*:-@A¬FKév@—@ßÂ?hS@›ÄQ\$£@€ú•¸˜‘À‰"Tý²Àq, þK@žŽÀOÒ¥Àñ¼z˜uf@âiˆ‘j’@RÛÃÕ9¯Ù¿zeÊšùte@'UW˜rP@€ú•¸˜‘À—HzPP©³@[ÇZ¨Š?@Þö¬XJd‘Àx’4Í>@ íeýÂè³À¨ÚÃÕ9¯Ù?âiˆ‘j’@K6aß§DK@ 7üîöæ4@<,°KÆ,@T¡¼*»6À< 6NXhÀHÜ3?cÀ)ö¿[Òr@Dc–:b@놵 %†À´Ù<ÝwŠ@½zUK &@ÁÕ'/lñ0À|é!ýŽ#j@·9J_3€Àû4ª‚–U@{W¸ cwÀ¸õ¿pc.@hrû¡µÐCÀ¶t|F÷!@0%¥áK0,À"òœ 6À‘„ëÒA@¸æE¾õÀl¹á=´gÀDc–:b@Õ€¤çå€z@Ò‰Þu0y@pI'&Ï›À8Ó½;H1ÀŽ\⢒:@;þšú~tÀÏ…ëNh‰@AD}Aqí`ÀG_òV‚@uÐiÔ7ÀÖ–÷…7O@:D1ÈJ5,ÀJ±@!!6@—kÁêöÀ¯Écƒ±À©±¥O™›â@¯Écƒ±@Ås{iÍöÀ.H›ÚGdŸÀû7?ï[5q@{DK0" À$C‘#¦—@È|ådÀ“SÅ9c@ý=? •ÀúÛëBçÀ0‡‚[wªÀOw'‰È²@ý`³ö‡ùHÀé,LÖ:Aˆyd6à@Jô-Ñž°@\Üš>´{ÀõæL²´€þÀ©¢ÑxE!ÄÀaxH«¦…ýÀqò|K¢½À¼¯VÇíõÀzfs¿³¶À?ñU_®ù“@¿æÏ¼Í @IAÆIeå®À~#ªRÚ°ÀêPO\À"ÕL:òÀúkt앤À:%­\ÒÒ@È|åd@$C‘#¦—@€õàKm–À/ýrô:É@Ï® }©Àõôµ…“€ËÀÿ`³ö‡ùH@Ow'‰È²@ˆyd6à@üAÂP ATn*s‡È{@÷ìN —’°@) 12&;ÂÀ© á1µlÖÀ+Æ¡$ Ô¹À •¸·1íçÀž4mO¼Þ¹Àxr;ÒÀÌæÏ¼Í À?ñU_®ù“@.žµ½üýŽÀÓƒ½ty@œ—ø#–E|À%jþ~åÉP@9ä}°ñД@?'ó—xP€À[ ±u#÷[@vδ §îG@öÒÞ¥x@Aúª½˜ÀŸ`‚<ÙþS@3°ƒßƒÀ?'ó—xP€ÀŠÃi[¦+£@ÊxnàÚG@¼¼«%j4@´îôPƒùÀûä|—kè@‰¸Ýƒ°~@ÏKµLm“ÀTêˆ@“ƒ\@©"ʯuÀ¯¢ \f\|@Ï%&¸w•ÀçMp«¦…þ@«ÏÑ[S¡À1êtDRY»@ªŒ Q¶@öµ²œ[ùÐÀU1OUv™@:ò£ÜÞÀÞ‹›‘æw½ÀÍ÷@ãXä@DúG£S•£@Y ËJ߉@ 3NfÀù¯e‡@Öàñ(ïdÀ<°õJ“é@~UVñ2À›sÛ)Ì%5@X¨ž8YÀ¶v³ËeÊU@1÷¶DŒgÀ™ý°˜q „ÀivàCkÀ­¯oî¹6…@Îv¦äc@̵-ÇÓE@ öï_ÓiÀœ_E:ã€@o! ¨¤¡Àæ–¶šãö@''*´ô3ÀŠÒÞìL@2Sv)%PÀbÌCMAs@žPûÒ¢pÀLÖGú@ivàCkÀ-£:†Ö¿QÀÎv¦äc@¬›äÕ ßn@dJZs©`À‡Ø*s·ƒ@]ƒE”J@ÑXG bã@@ÕÝÓ/[ø‘À൶C×eÀ<“ÈéqÐ@{i_sø~@IIÖÎç*ÃÀJ”Té{±‚@¿cSZ1áo@!ÖR+`ÀÁݨá`‡¶ÀŸž&W‹À¥ôHóœzÀ¶VíOÐ,KÀl–ˆç*â@@È1÷)­ƒ5@03¥|ò<@ŸŠ¶rnçÀ{i_sø~@8ÞœŠlÐ@}Ÿ*'²·‚À…ɲâ)ÃÀÖR+`@¿cSZ1áo@¸øEhÈ´3@^‚++HµÀ'+þc;@–¶ß!8yÀÓvÀŽ@d®Ë1w~@Ť#i$ÛµÀ¾6¾áZ’À¢s°¥Ô@A––í‚À @tÐòÆRc@Œ\Yƒ.kyÀl`‚¹ w@òU¢ÙŽÀ6Ù¤„ÊV@ ÒT"~’mÀ=òî³·ÐÀ h3!ÛÀ›@¿JÛ÷“‘À‚®Ë1w~ÀÓvÀŽ@ÉvdÐôr’À#‰eÄG¥ÀA––í‚À @åùýUzÏ@»áƒsÊ6zÀj»ž%¶‡‘@–«=^ËÀÅö¥F¥@µŒJxœooÀÇvoŠe„@ŽÀQn…å†@¥7*G>ÕÀWôHÚ>¨@¢³¬¬ÀCTíM•ÀæPŽé\“‚@›á Eùlp@Øœÿ¬’f³@õÌ?2ä‰@ÝßÄ-,›’@ø>æq@Õ¬û$¨@ïeÛÜÌ•@aÐÔ ¸ÀÞ§öð•À^s Ë4™ÀÐA©º‚Àn3åñ‰Tp@¦2!A\á\@õÌ?2ä‰@œi1s‹íª@í³²Šg[€@±A Ù÷è]@;“¹|)8•@8ñÕÿž‚@)ÕÔ=M8•ÀõG|¸óº¬ÀðÖ¨k*ýÀï¡¿kíJ®À,·È{lc AÕv&¨éà½@[©ü§©Õ|@ ¸¨LøÑ°À€ÛÒ¥Ð@®s+óÃWDÀ‹Ö–ñÄ*Á¨ú,YA~@óTôfFËÑ@GŽ8¿=W@’—O^x­À ] 1ÝôÀÕv&¨éà½@ ©WœAB~n/8°À#Ï=V7ìâ@—s+óÃWD@€ÛÒ¥Ð@‘˜Ô1Æ{t@@\¥ ê°Á;Ž8¿=WÀóTôfFËÑ@"üXºÒ)¤À@>®}]q¡¿¿7y¯Mƒ®Ànðâu6j@± š{S§«@žže ªmÀ0&8î̧@ç|\È;@À+½ ºÉ–)¤À—h\ˆp@xWCº2²Àžže ªmÀ3´[ŠÊŰ@Ü|\È;À0&8î̧@?™j­Áß@ô¯ÿ†S"Àfz ZÔ™]À±Ò¨"›d@”P€Ñ-Q@ȯ2 ««E@놵 %†ÀÒ‰Þu0y@Þ¯zͪÒ@S€Öé»?ÃÀÉÚù‡?WÀÎ0Dëáb@þ $áçtÍÀQmå1„·@ 1åæ$«ÀP2žS¦@Ôƒ‡°@…À¢£—B·b@Ûÿ6oPãb@rüÄhè¹p@r”—¥Y@ÍJ²ñ@©ƒ4ÿa$ÀD‚ƒ©²’C@-€~ís9@ô¯ÿ†S"@?™j­Áß@É[¼%~ûq@}]ÐOJ}À$å7>;²E@˜Ñ®j£;@´Ù<ÝwŠ@pI'&Ï›ÀS€Öé»?ÃÀ›­¨¤4tä@ ÍÕôáMn@8Ä»J–OwÀR]A»ÿã¸@ãÌѳàÎÛÀøÙÚÔ›@©7€¨‘‡ÄÀWCÏÑ|ÅZ@¯„/,ê/ŒÀ>#Æ_÷L@ãOol­¦Y@·43äsªC@¤§ç;²ñ#Àž¬áU/@® ­W.@þ/Ô^„#@kOw- C?À¯@‰¶0L@£Øè"“Ës@(òÇ É`À¬c€b×qÀ¾M¡]v S@š¿•´AL@%äå|NYÀ(òÇ É`ÀívÏDL]~@„EµqS@›·¤Ÿ:xÀ‰"Tý²À[ÇZ¨Š?@]CJ·í“@Ö®Ÿëh@ÃXtO‘Š)@ņúþ:5À2*ÒK6æO@ŠWâ¤dÀ"\\ª~û'@°G³ÕO?À?NA|ÅtÀ8aŽ é*Àq, þK@Þö¬XJd‘ÀÖ®Ÿëh@Ï•›.py‡@8$ Mú¨@À”,·¡G²K@ˆ}/ßiÀîÄê=€@œýzFWI?ÀâÕáÚ‘lT@ë²¥Cø#$@É£¨‹”UrÀR…HC,Ø@äæéÕV­¦@êBvjšñõÀQ k ô*ØÀÚ•óÂb¶ª@šÝk[Ç}@¶*Îgh@ö2jX6Ö„ÀØ+»pέÀãh‚¥#–@`¨‘¼_޵@@Bóÿo‡Àï@'4b|—@5è¢[Ou~@üï<§ Ï¡@±òG7@õV[ ‰>”@ß'‘AçÙq@jÖ§ À@Úkg2Cy¤@Vx³r8Áæ@?šVêÑ@-À€Lƒµ@”iµ¬V?„@BЮpÉ-ÓÀzÕÇéUþ¼À‚3Ç›³Ù‡@HáÄ[–Z@:R5C§ŠÀšÒÄt…Á¦@äcðG¾ ™@^5Ý•™ÒÂÀ@Bóÿo‡ÀF•ÄÜ×À@‹žG3øt@œá¬Hâ1[@ø‡Z˜LÍ@0¥¼:ß[@6²€Cr@Äëð«ŠàO@õº«Â»’À¿àrº¶x‡@6¯ÃBÁt@ÝßÄ-,›’@í³²Šg[€@¬áNäôË@¡4av{“@.ªz}.–¾À€˜øx<ŒÀ6/-9¤ˆÀÞÔ[‡µ„´À Sa®ue@VIH¤ÖùR@ø>æq@±A Ù÷è]@¡4av{“@ñ%¶ßÁ@?­u’1ŒÀþ„ï]û¯ÀNÇÊòt’ÀªÌi¤9v‚À6ý„Ð}bÀ°±Ñ˜â¥¶@tÿ¯«< |@1A¹Ÿ¼¶¯À–M˜x…fÀiö$Ï¿@@Ã%©¤+^Àf€ˆ¡Óºh@ º,Áôež,ŸAk‡':²é]Àzde —VÀtÿ¯«< |@šVÿ¯(O©@51…0@ÁNtבªÀ¯†Àl^Àêž’;Tf{@òª&RzÀgŽFó®ÿ°@aÙ]<¾¿„@¥¢Pˆ~g@KâVÏf‚@J‚pM_@>º] ù°ÀøÑŽÀ'.›p»Àˆ@h\±çÌþ~@Ô¿æo&a@?¬„ùýŸ¦@:JB·~„@à ÉäNÔw@E©_fŽ5b@èn³ÍÜ™ÀØëÏYhpÀ:+~Äf@ò”2Ø«?Óè±Ü·o@[‰Ø•„¢Q@ú±óÒÀåá…ÛÚP@õìåà¦s×À'%ÒÊìþ’À»N`š·Õt@[J¨À@Fù0ƒZäÀd«âÂä«@‰4¶äò7¶@Yn$0k\@¬Z½ö?©èg ú”@WäÀÙVÝ À<ϧ\Á@CæÇ2ú7ƒÀ Ï{ƹžÄ@{í½u'·­À°‚ \¤[å@/µ1ÒáSÀØV@tu@d02\~D@˪þ¢ù@C^êÎ÷ý§@|¹ý[èòÀâCÉ/°@pJâtçÀ f v«p@]³â?¯[¥@N@[õï6QÀó^">¬:ÒÀƒJ5CÀˆò˜ùÒ@^°í9½–À^°í9½Ö@õ r$’“À§š»½Ý ÉÀß³X6÷¦ÀùuÖÚ@{í½u'·­@oòHClÇôÀVn$0k\À‰4¶äò7¶@¥ÖŽ…¬Í@%8,]£G¼@%ÑOñÄ@J°¤ÒQ@nB?¸ÂÀs ~©@Ð/—Qðââ@Ú^ÎD|@d‡˜Ý“@×ÀC^êÎ÷ý§@2 ² ÉxAÒ¸!=âÐÀˆò˜ùÒ@ƒJ5CÀ4Ý»Hœ2ÁèØïæz´µ@S¤à$ÔÁ7c:XÜ¢ÀÆ÷c«¿ò@ü ÉÚ¥‹@$8,]£G¼À¦ÖŽ…¬Í@J°¤ÒQÀœ%ÑOñÄ@[VÖrEl®@õÅ/ƒj—òÀ’Ú^ÎD|ÀÐ/—Qðââ@|¹ý[èòÀÒ¸!=âÐÀX3DqØZ AƒJ5C@ˆò˜ùÒ@±¥Ù#´@̳ǣ' ÁxŽ»[ñÎ@ Nù-ÚfÁü ÉÚ¥‹ÀÆ÷c«¿ò@Æ0•^βÀX"seh@A;à_s¸@D–õDVþ”ÀŠF@Ç-6¤À¡PGJV¶Œ@àKcVØ‘@DØ`þX·l@úº ‰f@'%ާöåµÀD–õDVþ”Àu6a}×Ç@ÝLð†)ŸŒ@¢•ªeù¹À©ÃJ‚Šæn@@ ÛšÍÜH@÷ßp~lp@˜ûDä†TAÀC{iê¯ÔÌ@1œ°œctŸ@~6‡6c´ËÀ5‡Nóð˜ÀèSêðÓÀ7¥Ö9S®eÀ·”7Ï€î—@Šhå`ÓÊj@½•º«Ùs@¸ÐænE\@9´(OšÀìrZHÂÁ€À™ûDä†TA@÷ßp~lp@1œ°œctŸ@^ÿ~Èh¬@Ò(š‰àÀœÀùëâbç¨ÀØÁ0#AyaÀëèÓ¥žÆ}À,ì€u3k@·û×àÒs>@8UïB\@èÃÞœy D@e× ÝræxÀÓ* BŠsÀ™(H¯ëQ]@tg+î‚ü®?>W½eIl„ÀvºF4—éQÀ¤|A§Ýæ£@”¾³Äº»À,!Qìòä‘@"vшK{°À¯øt!Ô¨¨ÀÜCöðÁ>Æ@6h+î‚ü®¿™(H¯ëQ]@YH›}ÛQÀ {PëyÀ”¾³Äº»À×vÿŒAÙ@OŸ æ¯ÀäAj ZaÍ@9ùÌÀ¢úÅ@Dõ€¿ÓãÀ°Æˆ#‚@™2ÆåAkS@¦ËoS:óÀ£{jøÓè@pFf‚Ÿ€@Ù¶œ.áÓQ@,!Qìòä‘@OŸ æ¯ÀíÛi¥*A¦`YÙÆ@_ uäÆÀºt1Š‘ŸbÀÃЉT·À@$.OÎþéÀ& NêúíÀmEÏ–Ç»À™2ÆåAkSÀ°Æˆ#‚@r†žzUã@q—.žÈ³ÁÙ¶œ.áÓQÀpFf‚Ÿ€@"vшK{°ÀäAj ZaÍ@¦`YÙÆ@T~Aj1Bö@yãøÑ>TÀÑ…oR™¦ÀþuÉhgãÀü0.ž AOR'…c¿²À8ñóEÒáÀë#û²ÀYýõY:C@ZC}›pQs@M¼’ $"@éÔç²*±@éBÕwg”@Tð,û='@’2@”´PÀ•n@™õ‡ÀÀR}P5@r@¥b5ûД@ü@96’¹oÀj·ù7g´¢@,éúÖ¿vP@_ uäÆÀyãøÑ>TÀÁ»myx¹@zj9ØDyaÀCÛ}Hôw@[vÊ YÞ$ÀÁÒÕg‡õi@ [=^¡}@˜~¶á0¯@›pTGýÝ@á0ù»X™@ìú»ãlõCÀ æD nn@t9ÈÎGÍ¿ý$R¾’@¿&ªÇ?À®;”õU@—$hˆðÄ9À?I’ëyO@7-šµð7´À’M¼’ $"ÀYC}›pQs@’2@”´P@Tð,û='@vd·yX^À­ÐñÁÁÀü@96’¹o@¥b5ûД@+éúÖ¿vPÀk·ù7g´¢@ºt1Š‘ŸbÀÑ…oR™¦Àzj9ØDyaÀAÁèø5Ù½@\vÊ YÞ$@BÛ}Hôw@Ÿ[=^¡}ÀÂÒÕg‡õi@îú»ãlõC@á0ù»X™@29ÈÎGÍ? æD nn@¿&ªÇ?@ý$R¾’@˜$hˆðÄ9@®;”õU@ý@ïãê}«À…s£øï”@D± TrÀó–„a»•@%7“%kÈ­@”Û¦|kU¥ÀüWq&•@‘"ü”™ÂÀ »õâe„•@¤‘Ýbƒ¹À”Û¦|kU¥ÀŽ®Yäy[Ï@»ä/A‘²@IîB>Ð…@ˆ çÓÀ7q„B£“À äCvü¹±@é^Q@£|²TEá@»Èœ!Ñ£@õEçç~ØÀlc%2Ñ8§ÀAhãB7Î@Ù;üY¾c@´‹”þþ“ÀÁfÑØl¿ËÀœÌÕ_ @©.²ø!l@»Èœ!Ñ£@ñ§fW3 Ø@PÛÞm>ªÀ[~ ûÅÀÓ6T7Òßc@çÕpšÜ…ÀBê!èNªÀÛ Á@1tÀ\HsÅ(°Š@.ºªÜxõ?,£ÍD¸Žº@nõsÏn’ƒ@8ðͽ1·ÀSúŽòCõuÀm@yk”ÀäêYÍDÔˆ@J+,†h[@RcT,úxÀ~It2pÍ–@ÇXÞ?ch@æºÊ%¢’@–-ÅH‡c@E±ü\ÖK{ÀÿÂâÿžž@­á­£êYÀ;_æ’ÚZ£ÀÞ-ºªÜxõ¿\HsÅ(°Š@nõsÏn’ƒ@¹žÍª@.õÆÒ4që¿q¦h‰Õ`°Àë>Æ@®ðeC™¤©À$úðÂfÒrÀÓ_tkö&‘@ÇXÞ?chÀ~It2pÍ–@–-ÅH‡cÀæºÊ%¢’@T§´´'c±@£›–3ޤ @AQ¡&È “@p¼TÊ¢vi@V0·½;Ä‚@©ÏtÎ)k@^[ÕÞ]¶@Y1£ ¢aÀXÎbΓ@Î!tß`@8ðͽ1·À.õÆÒ4që¿À´*hAóÖ@q4¸÷vÀcuî(w@óë{+Ü`@²Ù’ÒŸ/¼@Vöø;…leÀoá0â°§@Lq¤¨VyÀ¾-¢&òíÀjƒ]©æ¡@¨úÒcXd¶@ú”E¾Ùò‡À:¦ÏCý_Ò@PgÏŸ?Ç~À¡¹owä’@Á÷Gæ>vh@äÚÜÍ6»@·—¼‚MKhÀÑ|ª¾×’@°îMmd’ÐÀ+»ª¤ÐÀmǽP4§@Ÿ¸˜¿¥Öx@¥›–3ޤ ÀU§´´'c±@®=¡›%’d@ œ¯:@W1£ ¢a@^[ÕÞ]¶@Ýìˆëc@g¨ÿ_å0@SúŽòCõuÀq¦h‰Õ`°Àq4¸÷vÀ¾/ ÑØ@Wöø;…le@²Ù’ÒŸ/¼@Lq¤¨Vy@oá0â°§@À¶»å˜À ÜÓi€ïÀú”E¾Ùò‡@¨úÒcXd¶@NgÏŸ?Ç~@:¦ÏCý_Ò@,s»0ÉÌc@ó"a £9@º—¼‚MKh@åÚÜÍ6»@¹6Wûs¿c@“êH‹À\îr-)ÂÀäâ°u¨Qx@)0Ú¬J@RJâjQmÑÀñ‰RXp²ÀÙ-ÈÂtºÒÀ3ÄÑ(ä·@Y}.ºÞ`à@-#gÝ›¼@ÂëkÊE0«@üj  +ÄÀÀF«÷Ó‹§²ÀvxÂ:¿À³2‰,¬¶@&ŒÄh/ÞÀ-#gÝ›¼@™†©"ßÑ@AZÚß)PÀÀ-M šÔ@K,—¸…èÀþÁ»î ™@åÄ2±°r@q¥· Z@C ‚²Øª@Þœ!žKoÀ®oø] åª@ݧTè¸IÀñLÂÕ_N¯@yP–¹ï“„Àm@yk”Àë>Æ@cuî(w@x!¹çÝJê@òÚ÷4Ý´ÂÀéÁ½á ¶@¹³ôúZ¢@°vÛžíÀ:±y%¸¬Á@ïÑ|u޲@ÖáJšä\”À#ŧ°‰â¹@›Eá<9Ò}Àr\øÌ@hÚâ(æ1…Àr\øÌ@hÚâ(æ1…À%ªZ@y‰óö;þB@Þœ!žKo@C ‚²Øª@ݧTè¸I@®oø] åª@xP–¹ï“„@ñLÂÕ_N¯@äêYÍDÔˆ@®ðeC™¤©Àóë{+Ü`@òÚ÷4Ý´ÂÀKýÉ(¢hõ@·ö}ä”@ÍÖtÞ̯€@/zn[»‹”@݆ʒHóÀÖáJšä\”@ïÑ|u޲@œEá<9Ò}@$ŧ°‰â¹@gÚâ(æ1…@r\øÌ@gÚâ(æ1…@r\øÌ@àd«p3ÉÀ§#W ^ä˜ÀéÁ½á ¶@·ö}ä”@Õ[öÛÈ@ ?J¥EeÊ?’q1k±·ÀQ\F£@ú—ÒºqÀÒ¾¶ªx¬H@|Zû£½4kÀ"Ø:]-q€@oM]¡™Àµ¬MgAðŸÀÈÕ`m‚[¾À¹³ôúZ¢@ÍÖtÞ̯€@ ?J¥EeÊ?mwÙÛÈ@fr@Ó>=¡@¦•5ûÌÀ¢Ô²–lY“@iæ‰ëtíjÀŸÎlñ°@áK«Z«ñ¡Àߌ’I¸ø»@ Œ[¿eˆÀgF%çñP@ê|ªñŸ]iÀo®2ühŒ@@Áçïa@é“Úo`“I@SZ^+YŠ@øçðÛÏB…ÀæÄ¦ ©áP@<aÒ<†À…‰aÛ“@qè—+R˜Àg]¨­ó+I@Ì^T2@øçðÛÏB…ÀCù­Vg£@A’5[1‹À~Î?, @ÿ·g‘¿k@YjJ ,øO@JpÚªä¦@ÅP@ ¶&hþ“2@÷ètàƒ@yiÀîa@˜–QYs¡kÀD,僑@ TPš¬û†ÀLð“nïǵ@‚^±Ý_=}@Æ'VŸ¡Àl1]­é@@F?/1h"@¸Z ¶˜8qÀuÿ;áB¬ÀôOCW2h@”°|èøŒÀk𛍧€¦Àì¼ZŽ+ù”@÷‰¸1zmÀùMêa":±@lŸn½2?X@Ô…íšÀŸZOØ~BqÀ/c8h0ŒÀV+§WYà°@ÎHp¯Þ@p¡ ^ÜcÁÀ†,Éæ/‘@lŸn½2?X@Ï4ËSÑ,¯@ñlV˜¸)qÀ7‰Dk­À<Œ/§@½¸¶ †yÀ½zUK &@8Ó½;H1ÀÉÚù‡?WÀ ÍÕôáMn@oŸè±`]@£À©ê¢±UÀŸ óÊðdF@q`=&uÂ[À©ðÁpË~2@ Òd\ TÀ‰ßÏ“ù @œ(îú À’¯ ûfüYÀÃ?Zµg‰P@¹4üì}óÀ $(Äñ@ÁÕ'/lñ0ÀŽ\⢒:@Î0Dëáb@8Ä»J–OwÀ£À©ê¢±UÀ&é¾ä3 h@—â7QÀö5VzùVe@oø ˜o<À$GÍ :Î^@¶Õ—À»Âv[×*@V.9{¬pP@J-'¾¡dÀavNÚùÁ@UchD=þ¤@³ÛN„* A× ¤´åÁæ@ǧ†LñÍÁµRt8»äÀ½²É«óK¸@és³½Š˜„@ÿ)žœ[Ä@óí÷âdz°@ËâÐ1Ýì@È߬¼ÎÉÎ@ ›\ò¨³üÀÔ¢á½ãÚÀÛZŠº ´@«b{9u& @:ÿˆØLPƒ@× ¤´åÁæ@ÑKybJ¡Ó@µRt8»äÀî1õ¾ØÂÀ…R¯[Z–@ÌÆì½òb@zÊr8º¢@ý”Êo»Ž@œUŽÊ@ØkQCS¬@Ã¥uz¾EØÀ?1™g>ëÎÀ%Lóú’@­7`@³ ³h %Û¿˜äF, ,Á†G}Ì@F´Z©{î¤@)–Úñ d€@ÿÀsÝÈD»@d}v¹p$”À ›ãy/ï@9IÌôòÌÀâbL“•¯@Ánæ|¬ÙoÀ Ô¯ÖÀ„ÃÅßÃ:’@BÍŒŠ«•@s§V |À y£™™›•@Ž¢ †O |À +èñó@[ °ÎÄ’@ųh %Û?­7`@4¾Üe¥aÐ@êFBÁ)–Úñ d€ÀF´Z©{î¤@d}v¹p$”@ÁsÝÈD»@9IÌôòÌÀÜ5óZßù@¿næ|¬Ùo@ãbL“•¯@í{ýÞÛ¤À÷ÉtÀƨÔÀs§V |@BÍŒŠ«•@Ž¢ †O |@ y£™™›•@Y °ÎÄ’À +èñó@žž†ï‘@EßI¦øIÀ˜évÕö. @çaGe5À‰ðÌ´®â3@ä.LÃJÀI…!@­BÕØ 46ÀœiÅåŸÙŠÀ¿óQèMa@™§.{‰RtÀ&Gìþ©V@Ùúö¹sTÀEßI¦øIÀWûÑ»“@@o#5ÀBó¤“K@YVC¸òIÀ-Ç]R#a@ú«FCÐ06Àµ)ºüøL@cði—4Pa@qŒÈ\;’À®€üšE!@ÇYò…sÀôü¯j@Œ$2µð:`@MyŽ£œB@2ÿ„ô`yÀ ¾ÅËtcÀÙ†‡<~’Àk÷1sfqÀŲrX_}¢@$¼iô„ƒ@p‘¢$ÛlÀQ>²òz´ @ùŽç†Àn›É&O«cÀ­T|ÿ;@€4¬"6.RÀGe®¼B@ÙìâÕ$@ç] —èbÀég…Ý^¹KÀ“à ¸ÜsÀ}›.°ËpÀ$¼iô„ƒ@ð꣌ø$†@c'x+$#@}ŠË¬¿|mÀ°Ý¨Õ`À­¾3å²uÀp²ôƒFRÀ¯û"|þ»g@zJ‰œ1Z·@ø‘ùM7š@T™Êwö½ÇÀ²Õ.sƒªÀÇ—OÑ̯@«³¿¹á—@úgýù;Iá@„„Ò€ºÏ»@qä°\=àÀÞA¾¸~ÔºÀ:•xš@œš\¿â}@Ó•»µªÀ #x½¨ÀÍH±;¢ç‘@¶‰:z@„„Ò€ºÏ»@4¬¥'ÍõÇ@[Ð%Z÷‰¹Àf7ŠÌÖÇÀÅã˜<úÃÀ»˜ñ¸;•¬Àqä°\=àÀ[Ð%Z÷‰¹À‰?€¢·ä@³ÖQ‰TÃ@lÉ2KÀ}@Ëát ¡·r@‡ÝÝü&®ªÀuÌå “ÀÞA¾¸~ÔºÀf7ŠÌÖÇÀ³ÖQ‰TÃ@ô®Ê@ª³8ù'x@&Ю‰¹j[@þÇPWXLq@vM¤.Ú¿ÃPd`ì/Ÿ@xÕ…žQ†K@[ö¢V®ÀcEýåO+ÀzY!{÷r@‰ !Ý\@Œ¨ß8%…ÀòÍæäcÀ!wM¤.Ú?þÇPWXLq@xÕ…žQ†K@J™nÓ½@ñåïÉs©*@°ýh‹¬À>álºa@rÓk1J@²›!‡¯SjÀí ý|÷ÜtÀ cûGV“ÀšÂ[’.n@ǧ†LñÍÁµRt8»äÀŽžÂÛôAòöŠE8ä@šÂ[’.n@šPœ‡%¢ÀµRt8»äÀî1õ¾ØÂÀòöŠE8ä@£¹Ö bÇ@PX8?`“c@–ÞÜ03†À¯„?ÏþT×@N §–€ÆÀŒS}9¶œÃÀjœLJôC»@µ{Êa©Œ@ß•åG°À„R¦+&ÍÀž~ÏpQÂ@'õgÏa‡À4­xA„ª@N §–€ÆÀ˜1,Óí@y ».Œõ¹@_ÝÞÔbÖÀ%Aƒî(˜ÀJ©S î»@t%Ieû»@4¤Sá¡òæÀfH‚¹ Aü>aûß»@Ð1&Áy•|è߸ÀõD"sX’È@ѵé H]Àí¨yïâÀsbj\ÛX@áSŒµÓdpÀu_‰œŸÇQ@Q·«ƒ‡9†Àü>aûß»@ˆòùÚø@{!2Ú·À <¯v õÀÓµé H]@õD"sX’È@Ö$ ¸}ÀþÍ>²¡âÀËxñ,j¥@³wŠ7ä†ÀŸíßD¼@ŒS}9¶œÃÀy ».Œõ¹@´ç›¨^ç@¨†çjÓÛÅÀn4zÄ…ýÀÞ© ã§=ËÀ˜•¦–•ô@ÄÒÓÂÒsÕ@|Ÿ7Z®¸†@*©Pϳ#«ÀjœLJôC»@_ÝÞÔbÖÀ¨†çjÓÛÅÀLÿ·³ãó@žûq:õ$ÉÀ+¿TÁ®"ðÀø„°÷„àÑ@çžæž³@¯nyÛ“À²ûµ{Ƕ@™”5¸@3:n‰óœ@½²É«óK¸@…R¯[Z–@Ð1&Á{!2Ú·À|~\gnA¨òU²@Šä†¼@ÎY«§@qA?*çã@ðg2Ø:Å@18hÔÍôÀb¿Ýa´ÑÀ©Óƒ†Er¬@·«`aRÓÑ@ö9Œ¼§°›@[”S„“…„@¡|°“ Šh@és³½Š˜„@ÌÆì½òb@y•|è߸À <¯v õÀ¨òU²@A/´`¤&ù@éý/ìˇ@¶|€†s@aYtÝß°@|0ÿ‘@õa’/¹¼Àv¢é9uVÒÀ© ) x@Z( Lt @F„¼Á_i@Zu¢Åøê©Àq{°"ó¡@Äï”õ\HÄ@½U‡lA¨@ÿ)žœ[Ä@zÊr8º¢@Šä†¼@éý/ìˇ@ ˜DPjCß@^ÅÝ—¬À˜j‘ÀÁ¬ð@’OÎ3WÉÑ@AT—Á?1œ’ÖÀÀCõÕ·@ÒdMÄH•@®¡þ^SÀÀzªÜ‡f¤°@Ö®›uéæ“@óí÷âdz°@ý”Êo»Ž@ÎY«§@¶|€†s@^ÅÝ—¬ÀW+ɧŽä@~µ)²#]Û@‡°_&0½@ºÅ®×cãÀV‘p¶Z`åÀŠe? Ž£@(âxÂì@$£oc2Ñ@ËâÐ1Ýì@œUŽÊ@µ{Êa©Œ@%Aƒî(˜Àn4zÄ…ýÀžûq:õ$ÉÀqA?*çã@aYtÝß°@˜j‘ÀÁ¬ð@~µ)²#]Û@yþw‡JÒ4A}~¾Ò"AÐT\0´û6Á9¯…~‚"ÁD:Û!›åà@ø¬ÌÄt­Î@î%ˆáW²@È߬¼ÎÉÎ@ØkQCS¬@ß•åG°ÀJ©S î»@Þ© ã§=ËÀ+¿TÁ®"ðÀðg2Ø:Å@|0ÿ‘@’OÎ3WÉÑ@‡°_&0½@}~¾Ò"A2¬¤‚èA#®оJÁ…‚ÐßcùÀžµÇÎúÂ@T®òÁ(¤ÀèöZ‹Œ’¿#I`Ä0âÀ@\-ãéK6z@QÊ"¤zÁÀ¡tË¢1ŠÀ ³õŽŠ¦@Y}-K-z@Ð=0;€ö~(¤À\-ãéK6z@Ëö4ÛóD¶@é3n†ì²‰À\F lÔ¨Àv:ù"/y@b3:œz?M@`Ò¼¡l©@»|<ÀŒ@oÐmwk¢­@b8L7z@Žð»âÀ9È.8ä©À¾Vâ.ñ@ä['EÃ@GŒ¢ ;éÀ“aé„bdÈÀüqMcêÁ@…Ô`FX«@Zi‹uäåª@•›R§é+@^çé òŠ@Pnr%Èm@­N9ãNh@™Åí”È[@Iæé0¹©À1ß´.ÚÀä['EÃ@?BvØ.Já@}SïÁî?ÇÀæ–ÝÍÃÀ‰;ÈFÉü¢@WhCûŒ@ŽîroÞŒ@òcô«„p@'’õ6¿ÀÛG…׃%&@heüsÉ@@þÏù´šWÀߥ‘2_ßO@>°[ÄeÀ`ù`¥¯U„À…•œŠ@!€_®àùz@u¿*¯aÀè87µLv8@¥6âC¹ñOÀMQ¨ƒ‰'@ešœ'+™>ÀÈnÊ·N@Ït‰2d~SÀ3Qg'%@Y;ŒµgÀ ‹xAÃ1@¨7 ÞÏWUÀQÒØç6&@(3ð`=ÀáY1ûïaVÀÉRMñxo@@aÌ”?eÀÿê$[j%|@P@v„†@•ö¥«`¤Àu¿*¯aÀødP-¶<‡@›Ð$ÎÝNPÀo$ì×ÐKe@làb?ÀšÅfT@0Ÿ1zdÀÀ› îÚýi@›Á‰|‰<ÀÎù¬ºœ@¼ªö¯GÀŒŸ (ul@Fö—phØ@°E¢ÚG}Ê?Vvÿ#çv®@­ášµn_@ÇÑ"ã¥@“•/ß´qÀd¥6pàÀbT!ì\éa@J£Š¼Ëž@‡t`ÏÙ‚$@FExäÍiÀ°E¢ÚG}Ê?x5¿ô›Ø@¬ášµn_ÀVvÿ#çv®@“•/ß´q@ÇÑ"ã¥@†F»FÕpbÀÇzÛújàÀzt`ÏÙ‚$ÀJ£Š¼Ëž@Ï$]¥×­ÀŸuHœ¤åÀº¤çãjw@+>í2Wµ^@Û(LüÏ%¬@¶N|aÿzx@ÜÐ- ’uÀYÆ,B™Ú¿‚[#‚¶€f@ãÜþòµrM@goÞÄëÀz$˜È¡À¾L=»Ññ^@\›JD@¶N|aÿzx@F°í6ºç£@ëæAó¿ž|•‘ätÀˆökL’M@Ú5yìOV3@‡‹dbƒ¿@r$(Á&M¡@Bƒ W¯êÀÖ#¬íÞ¹ÀÖÔEKï¤@pj£ÀÀgÖ‘ÖïÀѱջPÌ@-] sþ©ú@^ ·˜À#^yÅDh¡@]`(ƒ@µÐ¼`OF¹ÀÙW‘e?ößÀ\²€I´ÂÀKܽÉÞ@9Ç’Z­ýÍ@4èj‚ñûÀ^ ·˜Àó¢rdü@¶šÁÆD¹r@¤„€ƒEK@ÓU¼,ÚYÀ Ç<¼‚ŒÿlÀù†º2¨PÀbϨ€cèA@Ô$yëÁ÷#@¤„€ƒEK@›+þ^ÏÔ]@€}·WŽ ¿MÜyÇÒYÀ©(?=¡PÀki3âë1ÀS2ž?Šç#@vÁd¥µ1@³TødÅÀ¥"Ë‚A’@Ï&nK1RˆÀ$µ/Ÿ`ñ<@hœaÎ6VÀÅ­ËÍ.¬ÀàšÏ{?vÀ³§‚¬‘X@~Ò›5M}À@OÛZ›@X3 A\æp@š#VkçPy@›ª/ºŽ[‹À̵-ÇÓE@dJZs©`Àt?ET¢éÇ@Øýw®ì“@Þuø[°š@+¨ÿ<[ÏÀBíC©Ç¬@¤Â„³áaÀ®’A' z@÷†NK…–*@ 6á'ÙZŸÀe àÞÇ}Àbe/7V¡@Y3 A\æpÀ@OÛZ›@ÝeØõÀV~ƒÅ/°@ öï_ÓiÀ‡Ø*s·ƒ@Øýw®ì“@bËwt´@9k‡Æ­1@i“}οHÀ_¥ˆ“ž@@lqýß¹VÀIÞÙ–4cÀ Œ7cN}@è87µLv8@›Ð$ÎÝNPÀÊ3 Ÿô}G@ºËÔEǦ^Àª¸YÏÑ‹@wÖ''÷è/Às&xYµ9@›\¦.J[PÀ؀Ȓ@@9;ZŠRTDÀÙ9•îªCkÉÕD@`ˆ²`NPÀè&¬®Ue@¼Û )êTÀÓ…bµ%ŒZ@Àº(úyO^@ÐS4ÉsÀcŸ Æ^³,À§gOå$p@ížxª08À»ß]@Äb–F3£@‚t^%„Àpõ…Ý‹@7ïõ°Lý`@“l¯(Ä@·Zhµ§Œ¦À£Æ•Ì3·À ;éÿ*ë’@áøœX‘ÀW*5.{’z@8(K)¨‘¹Àq™u³†‘@Tt^%„@Ãb–F3£@ …–…EV\@l ]ròPp@·Zhµ§Œ¦Àu‹¯„tÐ@8ѵºXÚ•@ŒÎICóÁÀ.­åH $@.º´ˆG Àäàö¥ät@ŒWkk.ÀÀÃXtO‘Š)@8$ Mú¨@À˜évÕö. @@o#5ÀòÈå=;”@Þ­ž¿Ïq@¦—ëx]‹À‡ÇNsøIiÀk?I°÷3@ådKS3JÀÛ]¹þU1@ì¶òT¢FÀºÛlÒ hÀ’ ƒÜ9FÀcø½‰@ÄqÀIËDWµzc@‹¼&–T‰TÀņúþ:5À”,·¡G²K@çaGe5ÀBó¤“K@Þ­ž¿Ïq@Imæj÷̆@ÂDùk¥kÀ·3º VC{À7‹waJÀâ„Ëða@GCÈtBÀݬinÄX@`âÌdö°@;¶ïÙøfÀåQlåì>P@ú1³*ЄÀzÌÎuÍj@¯ÝÌ—ö§ÀàÙ{:Ä¥¿v EýÙ©@%Ë4D'\@uÏuÃ2jÀ%Ë4D'\À 4½yÏ™vö§À%Ë4D'\@´wîIœq¨@%Ë4D'\À+ 2DANÀþ]dZéæˆÀíQΪÏGÀó¿õ‡ 0v@e}Ur@³AûçkG@žíã ²^’@ú«QIŸlÀ Óþi@‡µaÂKY@@ ªv¬yuŽ@õãü“5²À˫߮ÜeÀöhËU¡@xêU0¨up@×Y?Ã1¢A@G‡²ó0@͵Udž_À‰Ô6\‡áv@5˜Y¦âM@Çcp¡@$o<Ð<³ÀéçrLúcÀÖm¬h¾z@™nžÒ¿8v@Zæmaµ¤Àœˆ0kûhÀ¨­t«W€@Z—W\ÑG@ìºv@ú«QIŸlÀìq ‡¬@­ÀØ“OÀ†‘G¿“g`@›+uShÀðP£ØŠ¶@Ã>"eýJ@@çKKBC@ìo®ç‘Îc@Å®¹çé…ÀIñ¹òjwÀæ¸EN¦‹v@qåLÈ$hE@¦˜¦Bï@¸Ð︼ÌvÀ4ˆ´Sfu•@wU иEÀNzj#ݹw@nbַĤ_ÀHº ºl@ò©<öÂM@âƒ<|o#@6sMÔüsð@yb}¿üßÀ@#pk âgÅÀâCÉ/°@-0¯zœA°öKNýÍÀÅ2Äÿ Á±û½›Ý @3Γ¦™u¼@íÌßi0@ýmû ¢°@pJâtçÀ°öKNýÍÀCà+ ”ÂAbb¸­Pª@¨á;£hÅ Á¨ß<Œ„ÀH*Äkƒ 8ÀéÐØÂEŠ@'öÔ&J`]À!gë‚mž@.8ù_/î?C¸?"Rñ‘À¹ør—a@”¢j‰Ì‚8Àâ©aX}pÀ'öÔ&J`]ÀÓ.¨ÌÞ9“@ù7ù_/î¿!gë‚mž@È÷¼­Þa@‡U«× N™ÀAbÖ¾U†S@#”“Òáß=@AËì0ù°|À kàXÖ=@¼ÌŽ´~ŽZ@:Úƒ'4XD@ýíüÛÐg@Å sº¤Ó]À(âçæ’ªÀáÊâ‘ÉN~À㼇x«„@Ü… +>€@G¡µL»b@á‰át‚Xb@ºˆ„ª L@|É€òü•@¨§½¨  r@#”“Òáß=@¨WbõÚ&@ôA-ßLÌ=@‰°“.uk€ÀÒro $QD@f½³Øÿ /@Å sº¤Ó]Àô²-²¦Ú’@¯_â À£÷V*ŒÀó©â»g o@qþŠíZÚh@ &ŨL@T=Š:L@ÒUi§„u5@«w£÷bÒ€@5Flˆ†\@‚¤ÿkV&¶ÀL[~s.¢@ø¡s5Š@VÆÁÚ—qÀ'î@ûY7æQ£ÈÀ`Ûs½GíÀ?™Y¾,Å@›h¬§þ‰ @mdŸPƒÔmÀ¨$‘@ˆáÈ$ôLÃÀVÆÁÚ—q@ø¡s5Š@ûY7æQ£ÈÀ‚å†?€ö@¸Íá¾ÀzÅ@]‘RÔuÏôÀndŸPƒÔm@›h¬§þ‰ @«V|»ó‚@ÿf1ž<œÀtÐòÆRc@»áƒsÊ6zÀ`Ûs½GíÀ¸Íá¾ÀzÅ@VŠŽ¶ãð@@`tò WËÀ°ëÂ÷bÄÀHî¯l ¹@¹K3™ázA@¥]²UðdWÀNTw0º©„@¾:l âšÀmVoH!@»F.Ül6ÀÈtx²ÜmÀß` ¬‡@‹QS)Ö¨ZÀsP[ùD™ÀšË¾¹Ò²@Œ\Yƒ.kyÀj»ž%¶‡‘@?™Y¾,Å@]‘RÔuÏôÀ@`tò WËÀˆkÏëõ@)’*·´@][þ/ÓÆÄÀŒ5û`WÀÉPùIo@6íÑ;ƒÀIJ°uߘ@‚ëµ­‚7À¦>Ê-þM@¯«2ð÷ƒ@*{¢‘èŸÀª=•6úÓq@)SFEå>@|<`é\HÀø ¬h¤+ƒ@uÙãi³g@>cÙzâ‡À ë$,¬bÀñJ²AOrÀî¨Ü †ø @Kj§wîw@á!_¬Å¸¿È!RvCHÀuŽBÁ!S@uÙãi³g@Ù£UÃD{@‹½uz±bÀˆù¬|Í´‚ÀÁ„èï?´ @xˆjÓìŽrÀ&Ý!_¬Å¸?Kj§wîw@½wˆè‚tÀežâð>nk@í/¬~µ›@ÿ½ Li6Àð¹>rÄçxÀî#b›/¬[À"›½/@ÁÂk=6À‹**FW…@e°g½tP@H ³—9!@`ü»4™?À~3®m{î@@˜íëAÀX7ë AË@Y)ó=m5À‚ Ú>'@,ŠœƒýEÀ<%À¾îaS6ÀЊDx ëS@e°g½tP@óèëFB}@ŠwÈî_?Àûz:Ä\@ÏëÁèöË,À¶[˜Ûƒ)`@ïeAu5À»h½»RS@'qoµòõDÀ Ú¾Ÿõb@°/Xo‹;È@ꕼ‘ê@+3ÖìêŒÇÀþÈÊ+Á€ÀyÞRŠÒ7ÕÀ96k†À• tëyEÝÀ2Lyw„°ƒÀÿé,)SF–@\™tÀ7”¦zä@1!¤–Ffƒ@@Âìö&…³@ÐØOpŸ}@Þã{ØX§@ž”¢1ëHø?ꕼ‘êÀ°/Xo‹;È@p‡â~U>À ƒÞZ<‚ÃÀðS/ô¬†Àú¥pNøSÒÀkÿV„¥œ@<äÜd§¬ßÀ\™t@ÿé,)SF–@1!¤–Ffƒ@ ãÕö:ã@ÑØOpŸ}À@Âìö&…³@¸”¢1ëHø¿Þã{ØX§@&6k€¼?Ö@_G~dœieÀ.ÁÝ䉭á@D„Y ðWÊ@6ù SääÁŠ ýÅç)ÍÀ‚¼¦ˆf8èÀ(̵N”°@#’\¸Ö£@#„m{ sŠÀ@Âìö&…³@ÑØOpŸ}ÀÑö´•ü@ŒK®ƒ…¥Àç·¢i¸(±@P˜"–@ZG~dœie@&6k€¼?Ö@´lP‰¹Ç@cµg'±@u8ÓÕÐÉÀ©†¨MùÀpoÀ€]¼“@ç19¸ÍëÀ#„m{ sŠ@#’\¸Ö£@ÐØOpŸ}@@Âìö&…³@ŒK®ƒ…¥À¿f÷Ð`þ@‡l’‰ÀX–@\9ØÇºa}@”!@°¿MjÀEôA Ôq@‚?À«œ‰À‹Vëj[ÀÄŠÃAe@SÂÞ<€=¢?§Û0’—í(@`m%úD@À sæ*,/@í¼×[dDÀ­ÀØ“OÀŽ)#ý‘ˆ@"üËÚ†“b@¹ìqZ.@È:"ÉCÀ6ß«õ s<@ŒJ)Ø¡ÆZÀ4oéê¿ @墓îš=À¦n«Ó|ä]@óÔ» ˆÀEû*§ h[Ào9¶Ú÷ƒÀ¤ÀÞ<€=¢¿ÄŠÃAe@ÆÑHmAR:ÀÌå%[Á-Q@2å©)u@À‰6-!ˆU@†‘G¿“g`@"üËÚ†“b@<¼ÀÈí€@æÂƒI$@Àjý¼ñ8äT@Ø NÀ­лEl@0¶»ižÀzuXšƒBO@ßEuž=‘@£Gma]@X–SO>Ì@e½>iÀ=B½Õ‚žÆÀÿ(™knËÉ@å=<# ¬@Óâ,Fð”@áû×EÃÀHuŽòþèà?ÛÊw;«(ÙÀïI›tº@(˜L*Z¡]@}õ¹z…vÀ·Œ«ÕÆ´@ðE$ïþ‚@FæpÌ\ØÀ·Gìž6ù¸@e÷ëtý_½@DúG£S•£@Õ¬û$¨@;“¹|)8•@]³â?¯[¥@ f v«p@ç·¢i¸(±@‡l’‰ÀX–@tì0D×ò@Xû\™Í·íÀº ãSοØÀbWU°Ñì·@‘߈ƒ(ºÀJÛ˜a¥Ñ·@©á¸Î/À˜O¾£@¾t‹ÏŸ(g@J´Bå±3@0æ;ì2Nr@ãdËé‡ÀqšðPX5¯Àf¶"¸˜±”@Ut•ÓY¨@hz»ÚÉJ‡@»H?4¤ÐÀc¦*0©Ä@|+×v4¸¹@·3Àð»;ˆ@£Gma]ÀßEuž=‘@^½>i@X–SO>Ì@é[ê –‘Ï@ábæ"êÂæÀÍï<1ly’@Üçs]ć{@Õ”'^s@5LæÅÀûpn’ÊT½@‹X *––æÀ~¤b‰¯vÀŸ_ö1>‘@ðE$ïþ‚À·Œ«ÕÆ´@zJÛ ¹@„#Íò´úäÀCX8Ug£@Y ËJ߉@ïeÛÜÌ•@8ñÕÿž‚@ f v«pÀ]³â?¯[¥@P˜"–@\9ØÇºa}@Xû\™Í·íÀjž'b© Au•pæIž›@ø›Éu€¡åÀˆ¬—o¹@Uü<±É×Àñ70PúÊ¡@ðd‡r“ÀÀÕ~nSÐ,4@‡:€S(@,ŽJrÒȆÀâ£ÀY×Â@Ö2ìÎ9v@d3%Ì»Àsª>±6u@,®%”“JT@©[¾â@Î@Y¯rL±JçÀ·3Àð»;ˆÀ|+×v4¸¹@ҽߖJÄÀ?@I"¹eŒÀy nâq@G PW#¨ÀµºXöIßÀè»´(5?•@úé"\>ÒÀN@[õï6QÀCÛ}Hôw@\vÊ YÞ$@º ãSοØÀu•pæIž›@z/…ò—+þ@Üéý ¶P´ÀÕ7{\fze@%[ ËÊÛ”À/±ç„n@*O6a«@‚n8Ñ0ãÀŠ÷§~ÉÄ@²WÄ\ž—Àxœ‘Žc@ðY ½<›ÀÚSØzmq@Šɽ(EË¿ˆ\xu˜ƒÀíüí»U¬ÀLZïy"šÀ2x­jÀC°@­¦ :1HxÀà³çÎw’@å…Ê}¡¢À›wö žÙ@cÌÔ&˜À!²?LH²@ •­µé¤@D1 x¼%èÀÞhÒÓ·]À‰ÏÿE¦@åá…ÛÚP@ó^">¬:ÒÀ[vÊ YÞ$ÀBÛ}Hôw@bWU°Ñì·@ø›Éu€¡åÀÜéý ¶P´ÀÀ09wAÓÛAíöŠÀMl¦ ñ`¤@†õ½ëœË–ÀgÝ)G#Æ@²EyHqÀbß7³2òŽ@ÙÊxK¿XWÀüBå¡ÌŠ@*O6a«À/±ç„n@½…¹xZ˜ À13n›%é²@ÄtâÔ›Ã@,\Z’®Áˆ|.É@7º`Á”Àñs*_èÌ@hɽ(EË?ÚSØzmq@>Ë@Ž»3@|'úv¹IÀõ)‹–Ah@‘ÀÀ®˜R@÷[>ƒ›ätÀ+·ò–îRÀø¸0°l’@Ú=˜Â§Ær@"Ù—ÐQsÀD;Æ$ôÝ$ÀÃê hl‡ÀcR3€©mÀÀOÜD“ÁIÀ-L/;Ê`@ÆÖ¾þ¹›R@‹uaˆ<@¾·Ê×ûRÀ’(à™§dÀÚ=˜Â§Ær@äV{ ã@¤µZB Ž$À¯/HbùÜqÀîf×ùú£mÀ§†HÊ:¸kÀ™²â\>¢ÇÀÎ}&©óÃ@—q¬é0 ƒÀ7ùX$ï@Þ¹Æu’ë`Àoô°J@Õ2MK lÀ5öÕ/ã¼p@`Ü$'–\~Àæ$ÎUw©¢@œÝj«ƒ°½ÀXLnÌú‰Ã@?¿Òû’¥ÀŽúåbÃ@?Kè K—ãÀŠƒrE@‘@·¨¾Z30©À¡×s°Vy@BbüycÀ25„G\V…@I²µúƉÀNTà$Þ»–@Äñ޸޼Àæ~úˆ‹·Ö@?¿Òû’¥ÀÖÏÄ™U!Ñ@Êx#hŸ Á‰™ØÒëåA|‘÷š ¢@$żJ¢¶À¿{qÙL›@Ôn~qä¶À磫Tÿ¶£@2-ÔŒ{¹Àú:lZÔÊÀØ@ fƒqh@1Û:íý@ KÜÀ|LT+ƒ5@ïÔ:,žT®ÀtçÎ;ù@—-[¶ìÏÁÌ3T‡¨A ugk40ÁRJy¸À1\¦c\-Î@*ý ;3²ÀÇ“¨ì…Î@‹ÚäpTIºÀ#8³«üÐ@Ì“ }1Œ@ÊVØž@ÌÀ KÜÀ:›èTÊAüep䮜¥ÀKãÑri8Ä@Nš4iÒ¸ÁuçÎ;)Anì«PŽÀ aÇfC;@N$ü£ƒC@»ÿ¶ÛxYÀ9¾_T@âò©+?@╸} gH@pkó4í_À›+uShÀ¹ìqZ.@æÂƒI$@À"Ù—ÐQsÀ¤µZB Ž$À'ÈùfŒ@0÷)Î3¯YÀ•‚x§*õS@ráó€Ÿ>@=D‚RQEV@¢©‰/òõtÀ¸1uË7%@î Rñ,WÀŒ&‡q‚@…©SrPبÀ2E/"qYÀ’%˜ Ôšp@3#½C=6?@›©wˆà'@,ÑÕ–¨Ð_À,ΚÑöÏt@ðP£ØŠ¶@È:"ÉCÀjý¼ñ8äT@D;Æ$ôÝ$À¯/HbùÜqÀ0÷)Î3¯YÀæ­‘Ç‘@“:‹í“>@+‰Q?u'@<Áf+ mÀhòœìS‹@·wÆ©;ÀÔ|-['7n@>cÙzâ‡À‹½uz±bÀk†Ú3`²@„“ØQe[@D‹Õ¡ƒO@|a]Ì]D@°ºçHa²À¨ÑuM{@¯ÔɃ}$…@,“…¯ À ë$,¬bÀˆù¬|Í´‚À„“ØQe[@¸¯‡|Eú±@­÷ 9mD@%ê>r׌9@Œ'ÉtÐÀª´áBa²ÀO“…¯ @¯ÔɃ}$…@Ùý*K±«@´orI¯Ž@ŠÈ׿ Ñ{@ ØÀø¶O‘ÀQ 5>ØY@þÆd¨sÀÒj ¼´y@£’3@u“À±ŒPч¼ÀSÒàV`ÅkÀ¿¨:‚Q®…@z@ˆ‘F†lÀRèÏ”‡Ao@Éïô´‡À‘߈ƒ(ºÀˆ¬—o¹@ÓÛAíöŠÀåp°eC¸@n®“•B™†ÀmÁ 7eR@×HÁ*xpÀÍ,GcÙ8@ vT (†lÀ—·#Û©@‚*í^´ ”À&¦»v;4š@ƒŸ]ÿteÀ´orI¯ŽÀÙý*K±«@‰5áþ L•ÀÎJç,‚ª@m˜ÉsÀǵP*\Ž@È5ûù_®“ÀˆøÆ/ŠË­@6–.×·@6[d§/ÀÀz@ˆ‘F†l@¿¨:‚Q®…@Þ-ïÍ+î‡À$ô•‡‹&¢@JÛ˜a¥Ñ·@Uü<±É×ÀMl¦ ñ`¤@n®“•B™†À8¾€õ¿@.ÈoGü*lÀ‰÷wéÇ7‰@LÞspSÀpª¬¨¶Ö…@±Ž_ò ›À)[1Ò®@ƒŸ]ÿte@%¦»v;4š@²ÿ>Ô™n@J^ÏmŒ!rÀ·lyJke@¼¢^礮;@v#x+ÆÀ"ÿž÷•ð€@òalÚýs@1“c—ÎJÀ¶JnÅ¢¸À øYÀn@¢º›û’@nèÒØ&¿hÀfÎ àɘ@óOÝÝÎó¿ÁÒÕg‡õi@Ÿ[=^¡}À Óþi@Ã>"eýJ@@9’œ´j¾Õ@»´Ú Àå_7Åøÿ@Õ7GW;\°À~~¦‰øÈhÀõ›.}”@ðïEnÿã§ÀÕ²é 3^BÀÈä-tc@W yc×4@ñZÿíÞP@¯ZËŸ¡KÀ³ÅR®×±Àuâ¤@Á{@Aý> k@WÿG4©A@Ç»_Ç{kŒÀ¢¹­@u\ÉV`KrÀKkóÒä @" Ùó;@Š% `"@%§ÈL.‘@6u“ÐÀ1“c—ÎJ@òalÚýs@·ô³oÀ`Ü a–¸ÀnèÒØ&¿h@¢º›û’@>PÝÝÎó?fÎ àɘ@ [=^¡}@ÂÒÕg‡õi@‡µaÂKY@@çKKBC@»´Ú À uÏÂØ@¦Àü'ˆ}W@“°-xÀ·¸qqm¿–ÀF\ý¼j@kÀUQkŸA@z%j’ͧÀ,-YçEc9@¯)®ÃÔ2 @°ZËŸ¡K@ñZÿíÞP@ÙKôT=…rÀ]˜3ît¥}@\¬—Ç„×PÀ)5³²’ie@fzýjè‰@P”GÚ´•ÁÀ÷¢ˆ^j¥A@°\ÇÀÄ7Ávx¹@ÊA}uÌœ>@“å=^Ù‡Avñ”ݒׇAZßøz’:ˆÁ£ ¨$ë‡Á·U.¸ÕB!A½"JÀ"žû@~î—7¹º}À¨É4v,WÀe&$ASMv¯ZFç@``Þ¿Á•>@ý†µÍÒÀÆA}uÌœ>ÀÄ7Ávx¹@vñ”ݒׇA¦N¯áÙ‡AZßøz’:ˆÁ£ ¨$ë‡Á·U.¸ÕB!A½"JÀ"žû@iyÅ¡)Á¥‡ÀÊÛôéÀaÕÕ(½Ó•@U,=·Ú~²@f1$s‹~§@Zßøz’:ˆÁZßøz’:ˆÁD‘¥.¡ˆAWC£NˆA\ÓrœCÖ!Á¿´p›ªãûÀš:+wÁÑýcGÌçÀÈfÊ9Yíp@i%ÂÛ¯Œ@ѽ+?W8‚@£ ¨$ë‡Á£ ¨$ë‡ÁWC£NˆAu92{ˆA°á¤BK!Á¼½lcëþÀ4];'“ÀàOk–qpÀ¸¹ä'··ÀPÃxä<›@Û-8Ø @WºŽåx¯7À&XŸ3iû/@’«Û¡.EÀåá[(¬VÀq„X|‡0j@MQ¨ƒ‰'@làb?Àª¸YÏÑ‹@ùø´é0À°hÕ›bý»@¦ÊÆK?—À;u½%Ò.@ae²^Š3À–|¹]±%@(¬p‰gÊGÀÒ`JÎáÒ@ˆ+…–j5ÀÞ® ErpÀ>òà ‰ÀPÃxä<›@f žb8ÃÀê,Ô!ãå5Àr%ÓƒÊN@ÆZ.ÑÉDÀrE"l‰[@f›Õ%Uf@µ®CV8½Àešœ'+™>ÀšÅfT@wÖ''÷è/À>ªCkÉÕD@¦ÊÆK?—À&ÆÏ]Æ@H(œŠÀÍ%»K’DÀe{ÍmI@]ˆ×ùÌ}Àiy™†í^@xÇ%¿+'Àÿž—F]×K@6 ˜ª.å›@_‚w“×g@ÂŽ1¬@c9êéûX@.¾i>Ü»6@†rS%eÀÞÁŽ'ZNÀŒ¶}çk|@)xòÿâë´ÀÇ¡S®áÀ_‚w“×g@Ó¹²ýº`4@H(œŠÀc9êéûX@*Χ!§@UeÒReÀªgœ:™“@C\RÈš!|@°@ë•rÝt/@«Î.ò S@k*‹¨fÑ@]º¬KƱ@˜’E—غx@¨ÿCk–c@` â!¬D@ÅÓ®ðL9¤ÀÒøɳ®<ÀŽ á`s@ŒbÃÁO*@3j¨N­Ø@" É+ÄoºÀ}žpi;×À~SEJ?¿@MÀ¡Ö…•f@Rmõ$\r@îöhoœÅ|@œèÞ@“Àa â!¬DÀ¨ÿCk–c@¿£«¨Mú;@qÒµ5¤À†bÃÁO*ÀŽ á`s@" É+ÄoºÀ·‡®\ä@ÔŠïû§N¿@7ö|«¿äÀQmõ$\rÀMÀ¡Ö…•f@Üoë!{“ÀS@…‚ª@ñ…fêëv@q{°"ó¡À@ûücûÀœ¡˜Dû+ÚÀ0&8î̧@Ü|\È;À ›\ò¨³üÀÃ¥uz¾EØÀõD"sX’È@Óµé H]@˜•¦–•ô@ø„°÷„àÑ@18hÔÍôÀõa’/¹¼ÀAT—ÁºÅ®×cãÀÐT\0´û6Á#®оJÁ¶¯»6û+=A÷$51²UA:›üŠOìÀ=ó¬…ïH•ÀqG‚Kàµ@ô¼×Ò³/ÖÀ VšŽÜÀç|\È;@0&8î̧@Ô¢á½ãÚÀ?1™g>ëÎÀѵé H]ÀõD"sX’È@ÄÒÓÂÒsÕ@çžæž³@b¿Ýa´ÑÀv¢é9uVÒÀ?1œ’ÖÀV‘p¶Z`åÀ9¯…~‚"Á…‚ÐßcùÀ÷$51²UA7æâŽxAê8db,ÍÀ3èBd`&¸Àô©‰Ñê)ÁÙ.4µÓ3çÀؘ³î@0 +ƒ´@ö4Ñ.”˜@ÛZŠº ´@%Lóú’@©Óƒ†Er¬@© ) x@ÀCõÕ·@Še? Ž£@D:Û!›åà@žµÇÎúÂ@:›üŠOìÀê8db,ÍÀ£qØqf &AMŠæi=ã@3z9á]¹r@ÖM¿óä£À"2‹k4ÒnÀE“2ehÀ56W›íf³@”&^qþ;Q@ÞVÖw%6…À=ó Âe@²ûÀzì–À9“:ž ä@°zÛƒB²°@u7q}¸ÒwÀðpa7Ä­@ûƒ–îœCëÀF$8ØqÁ >³ÜĽ@3èBd`&¸ÀMŠæi=ã@Æ:”éAUE×åÈ¥À誹4t%×@yù@’ùí¡@TUâµìp³@VÒg¦ðtåÀžHk/ „Àé®E5Ä­¸@ìÿ¸‘“P™ÀëŸÐ À«Ê@%¯m³@ðWäž¼0€@ÛæVߺ®@Ç e ¦.ãÀù—¼X>ÃÀ˜ÿ¤`ˆ2”À£Æ•Ì3·À8ѵºXÚ•@cŠwnSÎ@êk~fýåˆ@oRxIv‡a@Ig0~6fÀÛÐ e[Y_@í “§†ÀdÙ3ëk”À`’<ЩâºÀ ;éÿ*ë’@ŒÎICóÁÀêk~fýåˆ@ŽÃóŠ·¾Ê@ºÆ`JˆwÀrN¬J}@Æ—õµq«tÀ[õüXÊß@?: ×"½ÀˆóA»Î @†·®ô¡“²@ß°uÊ.ܵÀ× ¨æ¥¨@ž§ ±Ÿ@eõhj1ëV@¾2Åý¥ŒÀiP$× Ü|ÀLQá¸]e±@”ž]K @ØUÌY†aÚÀß°uÊ.ܵÀœ}M‚¤7ì@ˆ§ ±ŸÀ× ¨æ¥¨@ÆÏ? `‹ÀÜ!pÇÁ@¸Ã 02B±@°ÃpTëÍäÀ[©ü§©Õ|@B~n/8°À3z9á]¹r@UE×åÈ¥À´0¿sKæü@` rG!ÜÉÀDÀ€ ˜õÀÎdæÃÂõÀá‚ï?â@øÒ®W¢Àp@þ¦Qž¤À!B@–ßÀ qúB½@ZÌšW&…@ÖÏÍpeH¶À‰'¸Û•@]6 + ÎÀ ¸¨LøÑ°À#Ï=V7ìâ@ÖM¿óä£À誹4t%×@` rG!ÜÉÀ’€56fW AHÌŠñÔ¿@SåXoô›ß@í%®h™Á(À)}¬Ì¡ÀYvnÁ6èÕ@T¿Dƒgݽ@Ð'ÄøÀ¿Æx½x¶ÀÓ¬ÚÇë¬ç@ª3™¸8ÇÀ §Òýíÿ@žŽÀOÒ¥Àx’4Í>@2*ÒK6æO@ˆ}/ßiÀÁr·@£š›ßQ9ŠÀ<üNÇ©ÀºÖÃÕ9¯Ù?ñ¼z˜uf@ íeýÂè³ÀŠWâ¤dÀîÄê=€@£š›ßQ9ŠÀ¶z ľ@2³1šß‰à¿Ø/á´Æ©ÀŽ·_+7¸„@Üü(Všò?Ä×´ìô•@U,§q¬À“YîÌF@3’òvåÓ\À?Œ1ôæ Š@kl˜‡Ó`@¨WbõÚ6@#”“ÒáßMÀ€Ø™8¡Àµ‡å“LgˆÀ ªv¬yuŽ@ìo®ç‘Îc@(âçæ’ªÀ¯_â Àå_7Åøÿ@¦Àü'ˆ}W@¨ÙÜÿöò@µ77îT±Ä@|\î%0ÜÀ•Æ6é¡„À^[ÚìSè¸@ÇÂÊH¦‡@d_ÕVY@#¦¡¬T!ÄÀ,#x?›Àñ`WN»®ÀÜê— ª‘À>WöBTWäÀ¼œªù„< À­eD!p@öü9&Qxe@Ñü(Všò¿·_+7¸„@t'UÐë¹ÀŠ_?”2ÊÐ@ù>±¶Õ cÀÈZ&ýÀÿx@#”“ÒáßMÀAbÖ¾U†c@-WÛm ±yÀÔ£ÀÂ.tÀáÊâ‘ÉN~À£÷V*ŒÀµ77îT±Ä@ýÑ‹˜”SÖ@bÜS¢þ£À°‡Îª¥À˜È4Ä'çŠÀ$e9Þ[V±Àœ›\Ë[ƒÀÚÅGÒy“À"œôÆçš’@Ø ®hÚÞÀq¼‡Ò@“QÌÕyHÀpN{Ú€.CÀJ™$š°ÀE×­­¿~}À÷ú!5”c„@vÜ’'‚ïÀVŒ?yæ_@&Wû9,–¿û™2Õ×®@†]oñ MÀdOK4|@¥ýåÐ¥‰e@õãü“5²ÀÅ®¹çé…À㼇x«„@ó©â»g o@Õ7GW;\°À“°-xÀ|\î%0ÜÀbÜS¢þ£Àò× ¥½ô@ë•k_§@I¢âóåÀºTb<î@m,m‰¦AÀŒÌØDîk@vdúJlÀ,B›?Ù­ÀÀø)i@~ÀL+Y2¡@';Da7Ôƒ@9öÄñkƒ@ÌÚɱm@pXÜG·@­$ ®·“@­V‡[šs@#Ô6Å•IÀˆx#ûEµÀŒ{¤LIJ„Àjc1ª‰FÀM­µyí¢zÀM­µyí¢º@øK=#f£uÀ· q…œý¶@ÐæFì/]HÀun°§±¼r@9-.¯m@q’¬î©TÀ"oÆ3ù”ÀiÜ’'‚ï@÷ú!5”c„@Wû9,–?VŒ?yæ_@fxv(rrÀ^>1>ãû²@ ;Íp4CÀÎ-‚‡Éxv@˫߮ÜeÀIñ¹òjwÀ~~¦‰øÈhÀ·¸qqm¿–À•Æ6é¡„À°‡Îª¥Àë•k_§@ÿZ¨Í¦yà@Ú³z4{ÀÊ·ÞhæÀplHR¾AÀ’c%ŒoPk@vdúJl@‹ÌØDîk@òTU¢KfÀÁŒh›9ÃlÀ#Ô6Å•I@­V‡[šs@T¦•(Ö`Ào*K%l –ÀÐE.fAq@ê¨i”!Á ‘óà§‚á@ [ Ì)@ìéÔ%ÊhÀúîºx†’IÀ9ÊÉáÜ@„~³uèÜÀmd33kV"@ a3saÀòaOƒu„§@š{+å@qe¦C£@N ¸¥'s@.í÷©IpÀ­²’=¼&šÀ=”™ñèTŒ@_Îëü¥E!A_Îëü¥EáÀöhËU¡@æ¸EN¦‹v@õ›.}”@F\ý¼j@^[ÚìSè¸@I¢âóåÀÚ³z4{À_Hg´—à@êJTè¤ÀnçB¯_ëš@9ËHóåÖl@Žº? á­@´ âsV¾ÀÇlóµ¢@=ÅÏ*Cpx@œ¥°]ËÒàÀÍÕƒ+X"Á¯¡ѽŒjÀ^iÛf>ƒ©@£3K Tn’@ü0õ¬FÁm¶ýæÐA´šfæÑ{cÀ3—fjÐ-¢@ù™{+åÀñaOƒu„§@÷Á¨j-ð@ã¡æÙŽ|@a sd˜ÔÀ_Îëü¥Eá@_Îëü¥E!AÊ·ÞhæÀêJTè¤ÀS»˜È>Ãö@Ä âsV¾@Žº? á­@¿Š+Ô:lj@guQ9r@Tìö<¡©ÀÖjô˜ªP‡@ì\Ž«èåÀÎwm…ßÎ@† Tüç@p¥ñ$sÐÀ'ùÑzq@~ËÅ¥ï¶X@Sü’­Þœœ@w¼„TvÀÀLSº|ׯÌ@ÄO[X{äÿÀp¥ñ$sÐÀúÊP†öA=¡ÿh@U8ã™^B\@IIÖÎç*ÃÀ}Ÿ*'²·‚À¨{¹,À@”ù'¨²£?0¼¢Þp’À`=xÕ÷vÍš›@àÎ üo{@"¹:8bl@Ù\,YG@X8ã™^B\À=¡ÿh@J”Té{±‚@…ɲâ)ÃÀ”ù'¨²£?Àê:Ÿ,À@¨’ù'¨²£¿s½ ¢‘ÀàÎ üo{ÀxÕ÷vÍš›@Ø\,YGÀ"¹:8bl@º8ó ´~„@~6‡6c´ËÀÒ(š‰àÀœÀ½7Ä{Ñ@$IØKçn@‘<Ÿ»g‘}@ÿDdµ«9e@è^ùrµÀûÒ#Þ=³{À|°JÂR/„@éYêªÑ½l@)¹ë7ÜñV@5‡Nóð˜Àùëâbç¨À$IØKçn@IÅ­G*ü²@Åbæ ½ÍP@ 80¹ù8@‹A¶ßÒ€ÀR$Í÷"›Àƒ1Ôã=ñV@ÆÏ`&~U@@” Ð`ÑÐ~À‰õ‰er@þè$QÓ@0¸b éµÀ_µÂt”@M#ÛöزÀÌ×x±ý7ÔÀÃo§ ½Ã@|ª«›V@´¿ÅoÚ@@šŸVc"-ƒ@)•2–À0¸b éµÀUN(Aâ@ p⯲Àú^9ÅwöÐ@x Ê[wÃ@Ä<Ø­iëéÀ« £‹»H@Ýäü¤ì2@þù.©{À˜_ÒMO˜[À_µÂt”@ p⯲À¹4ÿˆ¸$ã@@6Âùx¡?'4e‰û¶ãÀõ]F뮲@zùáÞÀq@™_ÒMO˜[@cûìæUÀãòa hÀM#ÛöزÀú^9ÅwöÐ@@6Âùx¡?kÜ t±$ã@M#Ûöز@¤ÛrŒëÀ«kܽäU@—!çÛA@­{ œ€ƒÀ¸TŽ€ÛT@Lh$“ò6@QMqà"NÀ´e’£òìÀ}òûÛÀÀW`Ðjï@Ýûr¾.Ã@7 ÏðªX@Çä'rg9vÀÚF¥ÙŠÀ>€Ã¢ÀõC.PœÒÀÀ8¸m9ÞÀÝûr¾.Ã@Ÿ’¢ZIß@LOM"¾PvÀJïšÛ”@êpi©è‚Àé¨Ð!¹¶˜@í…’ªÝY@Q}JyêpÀ€…"åü¤@¦6y>ÃV‚@›mµ‡²[‹@¬j‡]ßÚr@Lak"?¡@ë+˜ò@X•aTxyÀÀôý3€eÛ–À¡2ÃYI™š@ô‡ã–@VÌ—Ù|”ÀOqÔ¶˜@tJ쯑&°À¾"'QçpÀLï!V†@T@bЈ @Ë/®i¸l@rŸy–©çt@œéå¥Ð\@‡) ![[Š@‹34„£mk@M./ªjM¦ÀÕ"säÉÇ—ÀµHrûS„@VÌ—Ù|”À°øN›&±@gÂ[oJ¡@AŽ5bsÜ‚@H€W¿îįÀÂnÙÅ¿”‘À%j'¿š²@ค5œ “@jýêó¢À“Ú€ Þ‘ÀëâKZRÿŽÀS¦¼>Ña‚@ôýÞgÕÈ@\ËcЭaÀ> ü¹¯;ƒ@þP‡VKûd@ÂnÙÅ¿”‘ÀeF1aiusÀค5œ “@4f¥éÚ…@é8š.ñ‘ÀS*>¶n–@d -£r@. ÇoX£À\ËcЭa@ôýÞgÕÈ@cÇ¥ÌØ¬ÙÀŽ‹ˆmá/”Ààe•W¦¶@wuð ’—@IÛ1×@´±Ê-Ey@«ŒõÛÓµ‰@7 Åü8Ëj@Iɹu.±À·™TJŠÀ²}ƒFõšÀ6g'ïeÔÀwuð ’—@ûÙÖcU‡x@´±Ê-Ey@æ~ÓÁœ Ö@éúXhÁs@ÓóêcÅ–T@7ºî¨àyÀaGÇ“¥À6²šéj’À˜ûDä†TA@èSêðÓÀØÁ0#AyaÀ‘<Ÿ»g‘}@Åbæ ½ÍP@–In—@D„*Å? §‡nr Z@=F±ŽõB@”Š"µ_AÀiW6ÎÀ7¥Ö9S®eÀëèÓ¥žÆ}ÀÿDdµ«9e@ 80¹ù8@D„*Å?)*!: m—@ïòê)C@Ö'í p7+@õøF˜ÊÚÀ–g÷{:½Àjýêó¢Àé8š.ñ‘Àݸ¹µØò@‚ÝáW­¡Ï@Aóè›çÀ ƒ€òºÀŽéKu £@ÁúãT!Ø„À +gO½ÀÇtŸ*5ùŸÀ“Ú€ Þ‘ÀS*>¶n–@‚ÝáW­¡Ï@c>õ~Ô@Eµ‹©Í ÀÀ‚v½ BÖÀÁúãT!Ø„@ŽéKu £@W+­@ˆ¦À•¯èH˜—@¢Œ»§Wå@Àÿà¾ÛöÒÀîXÔi×ÄØ@6j‰pä4¶@cåîM¹ÊÀÆrˆÛW‰¼@ R<£éÀTâ+ñv7³@¬›ñ)Û£@ÔmhÉ·%ÃÀÀÿà¾ÛöÒÀ×Ï´þ@ø- Æ´@±Ì¤fùŸ’@lÒ*ýyʼ@â kÎoåÀR^]ÿ?]°@¡—µûÛqñÀÛµ;ò@T·HZ„@Üï¬Wk‡@Ø zÜi©À+Ûœ&Í@`¤õÜÙTw@…J¬8¸@<»ã…@gKðÇìÛÀ’o¦w@+Qr.‘ÝÀ|o¹Àï—À, ކãÀþ¿Þ¡»µ¥@J+,†h[@$úðÂfÒrÀoá0â°§@Lq¤¨Vy@°vÛžíÀ/zn[»‹”@ë| …¾@ýØ•ÊÁŠ@× ¨æ¥¨@ˆ§ ±ŸÀîXÔi×ÄØ@ø- Æ´@r!Š­!Abrà×LÌÀ@G÷Ï`²’ùÀ0_¡@)ÁÝI䙸@B`Þ Ì¬@y'~´e@’@çÓ@}€Ü:¡@ÌÏ’RäðÀÖ?Ù Í@J1®‡W½@N»µˆ@íä aUÁ…ð÷ÀÀQ¾ìn€âÁiÅÇ·ZËÀT·HZ„ÀÛµ;ò@2N´ÉÀ ¥À7‰ywº(Ç@Ov¡p@¨ö1òX@<»ã…À…J¬8¸@F<_J$n@Àб’ÜÀÖ¿/pÌ÷™@H<,ÞÀq|§Šâd©ÀRÏÐ&qâÀRcT,úxÀÓ_tkö&‘@Lq¤¨VyÀoá0â°§@:±y%¸¬Á@݆ʒHóÀýØ•ÊÁŠÀë| …¾@ž§ ±Ÿ@× ¨æ¥¨@6j‰pä4¶@±Ì¤fùŸ’@brà×LÌÀ@8ö¢-K A0_¡À„W;€Þ÷À)ÁÝI䙸@w'~´eÀB`Þ Ì¬@}€Ü:¡À’@çÓ@¨cŠ\X“@³Ý½rBòÀN»µˆÀJ1®‡W½@Nû;ˆªÀN¡ZÖÄjüÀ£ˆC‡s¼ÁÀ>IÐÅ%ÏÁU±±y+•¹@®•ís¨x@'­ìóøöÀYÉ_Ù¯ÀTŠ“!Ñ×@ÓŽOŒ˜@̇“$ È@°”iM–@î…Z…ÁÓ¤ªs1Ó§À4°F ;Ü¡@îîØ@9|@%h¡@Ÿê&f3‚@N$PîV¥@ Ü+å\øq@¯×>P½W@ŽçuåË…À€ÛÒ¥Ð@—s+óÃWD@ˆò˜ùÒ@ƒJ5C@~It2pÍ–@ÇXÞ?chÀ¾-¢&òíÀÀ¶»å˜ÀïÑ|u޲@ÖáJšä\”@Á%µýÿÁàõxð™ÀG÷Ï`²’ùÀ0_¡ÀÉ–ë^×™3Ao B ;£À‰éÞQ'5Á3h2^Øp½@Ë$&ôÚ@Wêv[Ÿ cÀwÏq_ÅÁ§Šé$d†²ÀžtŸt7±@ æköS‹@+àJ`È@êôw´]W@¼ô˜^>Æ@Z%ynå’@ÿžMNûÁ?p]®’¥À["…˜ÛÂ@Õé' ¼— @["…˜ÛÂ@Õé' ¼— @q±eg÷í¡@A#®f:À®•ís¨xÀU±±y+•¹@íڗ·@jòÙ úgûÀÓŽOŒ˜ÀTŠ“!Ñ×@›Ñvë–•@!(#ƒc@È5%šÈ¯}@6ëþV8™ÁîîØ@9|À4°F ;Ü¡@Ÿê&f3‚À%h¡@ Ü+å\øqÀN$PîV¥@Ôîù…";…Àwñ‡÷´@®s+óÃWDÀ€ÛÒ¥Ð@ƒJ5CÀˆò˜ùÒ@ÇXÞ?ch@~It2pÍ–@jƒ]©æ¡@ ÜÓi€ïÀÖáJšä\”ÀïÑ|u޲@„OŒq¥@½ØõϘÁ0_¡@„W;€Þ÷Ào B ;£À×v¹-cÛ3A2h2^Øp½À#­ëq»³ÁOêv[Ÿ c@Ë$&ôÚ@”Ôª õ±±@ëT“d¦Á æköS‹ÀžtŸt7±@êôw´]WÀ+àJ`È@ýxÿº’@¤…Ì@Ó_@pÜÊ¡zHq@­$WM¢„ÁÕé' ¼— À["…˜ÛÂ@Õé' ¼— À["…˜ÛÂ@I#®f:@r±eg÷í¡@ƒ#zVå’#Á wÚ™øtá@…¬S âJ@oÆ9}Ö׌Àx!<ÔNQ"A}ß6›Ð§áÀàgpÞ»Á@ıC‚š<“@“_5Ek©Á_ä~þõ³Àï0âz°äÆ@æòÚj@è“@ƒJ5CÀ4Ý»Hœ2Á±¥Ù#´@¨úÒcXd¶@ú”E¾Ùò‡@¬¾v§¦ØÌ@Jæþí6J™@)ÁÝI䙸@‰éÞQ'5Á2h2^Øp½ÀgiA)Þ¨'”@c3õ1î^@c3õ1îžÀözÒœ»Ïâ@®ûØaŰ@ú¬»Ë@O´œÌ«Z—@M†”œútáÀ°³r@ã’#Á›ža]ÀÁ³a=ÓÐ@}ß6›Ð§á@x!<ÔNQ"AıC‚š<“ÀàgpÞ»Á@b /õÀ¢Æ·F>þÀæòÚj@è“Àï0âz°äÆ@ˆò˜ùÒ@èØïæz´µ@̳ǣ' Áú”E¾Ùò‡À¨úÒcXd¶@Jæþí6J™À¬¾v§¦ØÌ@)ÁÝI䙸@3h2^Øp½@#­ëq»³Á)Þ¨'”@2¶p|Aú]¦yò ¢Àú]¦yò â@®ûØaŰÀözÒœ»Ïâ@O´œÌ«Z—Àú¬»Ë@õU½2§@;.lÄÛNg@sߛ₃Ë@ò‡ê$Y@{œÍåR°@…˜Äs‘@ÿHægÑÀHÓÒ Û³ ÀÆ'xîAÈÅ@ VÞœºó”ÀâbL“•¯@¿næ|¬Ùo@+—µ… Ö@¿•ì§^#œ@ŽW7IæÀ.‘¦c+Š‚ÀËÖ¬úúu¡@BƒÊlÎäÀx¿·"i¡@rLꢤ×À;.lÄÛNgÀõU½2§@P#pþ€äž@ç#‘eÞyp@„˜Äs‘À{œÍåR°@§}î z¡À? ´Ê±¡À VÞœºó”@Æ'xîAÈÅ@Ánæ|¬ÙoÀãbL“•¯@¿•ì§^#œ@£É~•ŽÍ@Å;br£À"flOŠãÀBƒÊlÎä@ËÖ¬úúu¡@rLꢤ×@x¿·"i¡@uÂ+’Ô@«\VM„Ù¢@áð‘öÀ¯Àƒ?/ÖÀÒª£Î44¦@=¥º~Àx@ðË=bŽ(˜@™G•ï+ºÀO¥Ë4ÙÀ#2nü6/’@£¦Ù&Ï}íÀvjBœíÑ@1FöZ?ø¦@4ÌÐ]my³ÀJô-Ñž°@Tn*s‡È{@ï@'4b|—@‹žG3øt@ Ô¯ÖÀí{ýÞÛ¤ÀŽW7IæÀÅ;br£À¹þû`o§Aî F$x±Àqîðä!\ÐÀÁç`Ž ¡@tŠ×¸ÆÀDÜwФ@&ŽäÃG›@[°Öíƒòy@E‰¦WÔÓ@‰Ç1­m@âãÚöh©º@ÑÒ€ ¥¡@Õeä êâ@½W˜V_Ì@úÌg@ayNQÔŸ“À0À 9ù¹@-L”rˆ@'káÚ™§ÖÀŸˆ­ÿ×ÀˆAü{´ËŒ@%k¶Ñ `@ Wà‹ åÆÀN^ˆWyÍè@]”›¬tË@„G¶æ“ áÀÇÈø'€>É@­xM8*ÁÅØ9¬´ÀÉ·nâ†Á@\Üš>´{À÷ìN —’°@5è¢[Ou~@œá¬Hâ1[@„ÃÅßÃ:’@÷ÉtÀƨÔÀ.‘¦c+Š‚À"flOŠãÀî F$x±Àþ„¶›´Â AŒ5„NŸ™¤À\ÔÊÀ5qôô¡À?(îb²ÑÀ,4‰°2ƒ@[69ŒAÓ`@ú«a·Òu@S@ÄïÚI¡@gŸ †@‡¶3 †‡È@äÈ&˜¤e²@Ü (AdÙ•À.$E« ™Â@¬ü!ù¯ðÂ@”…‚%8@ ‡)8CÀû4ª‚–U@AD}Aqí`À 1åæ$«ÀøÙÚÔ›@©ðÁpË~2@oø ˜o<Àö™ãîKïu@…!ÊÊ 0‹À–ìebû§@ægRú <ƒÀºÌ¡k8&†Àþ ·ÈqÀ1`ú"j@`¦0%w@óÿ᤾a@M0uöªK@G1HœA@·€»¢(ZÀ¹bR‚'ªd@{W¸ cwÀG_òV‚@P2žS¦@©7€¨‘‡ÄÀ Òd\ TÀ$GÍ :Î^@v‘ví<×ÀQ¤1®t­@ægRú <ƒÀ´“LlÖµ@=lr넳pÀ©¨ru8‰n@·Z^3PF@…eoÂS@îßâCL>@¬éc'@˜@Ÿù¯J®p@ò½6`w…ÀÚòÌô€ÙÀ[¥XJÌ À×-@6k@€ðc|c¸À@ëô”†o@ùpŒ<¢g‘ÀÇ2W)2¯ÀT ý|ç@Ê|}^¾éº@†¾þQüaÀËÔéÆâóÕ@c™AÄ—@íy°¡>’ÀÁßó‘z§@ûðP9F¢À»³¤—XÞÐÀSÕ1Vc¡À O Ьa£@ãŒðu™=‘À‘›9rY ³@wQöŸj®@G]ì³ÐÀ†¾þQüa@Ë|}^¾éº@c™AÄ—@ ,™ Ð@1$› ˆ íÀ ºÕ¨Wà¢@çà.‡÷ÀLñô©bSh@ƒ"ÏW“´@"hÝ DÀ„ÃØ$9-A×$H­L¤ÀŒ“„„J¥@50 ,ñÀ5Î-zWhÀê §~÷À"hÝ D@ƒ"ÏW“´@×$H­L¤ÀrŠ†Ç €A8d´ÑWEÀ óW˜;ç[@b) !›É…@ŠTà£#ƒ@ãðC)t„À¾û–ìQ]À óW˜;ç[@áÊÂ>rÀŠTà£#ƒ@Öð0l~…@êø•ÒmO]Àså®L3­xÀi¹!©g2@OŸè]¦ýKÀ©âEýxÀ7x&¸C’@xCª¿yÀº²˜üF]@th5Ü <ˆ@gH¡Ö{8“ÀÙ›E¾òKÀ@î–@e@š°ñTcE’@*ØIVݽ«À¯=Ç=ç*]@ÎIƒü°†ÀgH¡Ö{8“À:î¢÷: °@˜Dçü@è±×Jú¿hÑòOè@ÂU©YUCÐ@ûÖªªÐßÀÕ\R yÈÀþÇ ßÑÀEHõ§ª°Àž±×Jú?˜Dçü@ÂU©YUCÐ@Cþñ,ƒ)É@ {ðîwÈÀ~ÁiÒ²ÀðƼ%°ÀbeeŸßÁÀ·›>¹w@qñÒN@`ªÕ`ºþ@ÓŒ>þçÙÀ¸õ¿pc.@uÐiÔ7À¿cSZ1áo@ÖR+`@Ôƒ‡°@…ÀWCÏÑ|ÅZ@‰ßÏ“ù @¶Õ—ÀJèNÍkàN@N=ê%#cÀºÌ¡k8&†À=lr넳pÀù¾A9Ë@ÙJ^àt+š@*è„ûz{¹ÀBðÉu¢tÀH°ØÛ¾ÀmJ<¡Ÿ‹À?;WéÌ@§#45ýa@†Û§}ÙÀZy?“©&|Àw´nv@,Áøós¥_@Óiü¶ì)&À1ÐØÇ=‚1@hrû¡µÐCÀÖ–÷…7O@!ÖR+`À¿cSZ1áo@¢£—B·b@¯„/,ê/ŒÀœ(îú À»Âv[×*@x¸©…4"dÀ¬ õx@þ ·ÈqÀ©¨ru8‰n@ÙJ^àt+š@‡LIS?º@¾YLåì‡À3áÉtÅ_‡Àz”8h5MyÀ9u9-ö µÀG¬¡—ÝfÀT2ÒÒìM€Àѯ$ Uÿ@À^eù=ŸÀC>xðReÀºVÇ“@ -n™L@c ˜ÃMß@#g¬O¼IÀÛÿ6oPãb@>#Æ_÷L@Vvÿ#çv®@¬ášµn_ÀºTb<î@plHR¾AÀ1`ú"j@·Z^3PF@*è„ûz{¹À¾YLåì‡Àfœêàõ¹Õ@fáð”Læ›@#5Fì²”@ÅFã½@?üAu–rÄÀ[þ'¿#"‰À¼[·©Ï8h@¯Óª Ž_@éYX¬:‹@î™p%]À4õ‡·¡ÇÀ³'I;{À°¹âOÐ8ƒ@)Ü©¡0ÀÅØ{ÑÃ*j@òŽ<›Z;`À™.•ŠÀPŽÀ -n™LÀºVÇ“@õ1ÄŠýÕ@ÀX€~DÏs@­ášµn_@Vvÿ#çv®@m,m‰¦AÀ’c%ŒoPk@BðÉu¢tÀ3áÉtÅ_‡Àfáð”Læ›@‰Ã‚ö7€µ@™ÁxvÒ%…ÀGò‰F€±Àî™p%]@éYX¬:‹@!Æ Ó,%ŠÀXXüÓ ºÀ'Ü©¡0@°¹âOÐ8ƒ@ù?ót8ŽîÀ FšÄ¸ÂÀøb²ÃFR@»Š¢ì›“À, è_ßi@ëØö(¦Ü¨À^°í9½–ÀS¤à$ÔÁxŽ»[ñÎ@c3õ1î^@ú]¦yò ¢À†Fñ[A'(gfEš£À”ÉYÅW Á5t´FíÇÆ@²ïÿÓJx@T§B•½Õ»À ùà´VDÔ@؃z¤‘óÀøb²ÃF’À»Š¢ì›Ó@Âi„ IwÀ¡)Þ$/`¶@^°í9½Ö@7c:XÜ¢À Nù-ÚfÁc3õ1îžÀú]¦yò â@'(gfEš£ÀÎë%ÍPÑA‹^ Ùn߯ÀÚKáqEC ÁôSñÿñÜ…À30ïŸ* É@»#.{]^@£@¼û2ÀDìé‘–À06Ó˜#S@BWà6–\‹@‰æ°øt‡`ÀŽ™,J[ž}@WŠe…NÕc@s~úìV@ïzØ+6¸¿wù‚»FbÀ€u±FUÀ¡@¼û2@»#.{]^@2ëV©.lÀC¿¹µ”À‰æ°øt‡`@CWà6–\‹@WŠe…NÕc@Ÿ(f#Þq@ÄzØ+6¸?s~úìV@ :l»ÀUÀVÓõÖ«áGÀ´C†¶8†@hÈ<ÄÏw@cË>‹hZ@1A¹Ÿ¼¶¯À51…0@ì<¬W¨@’bj¢=ZpÀ¿KëOkY@bVÞá<@Û­*;kÀ,AVL×[@¡3áùwh@àzª„_7Z@T××£1=@–M˜x…fÀÁNtבªÀ’bj¢=ZpÀ‡&“Èç®@¾Û59<@!öä{Q @mÌŸòd=\@Ôe êW„‚Àø ±´ÐA@'øÆÌP+@Zbyz;L@º8õ»ÏW/@p‘¢$ÛlÀc'x+$#@\2”8+Ä¡@qéoo[BaÀ·0E¦,|Q@Å (»~ë:@³üO‹:¡À‡4¬"6.R@€G WK+@[ô•{ì@À¼q›? 5@ƒU=@Q>²òz´ @}ŠË¬¿|mÀqéoo[BaÀçmRÁ\&¤@髆ËÉ:@€¬œâž$@Óýª"C+R@°¹’²|¢ÀrĸEÞb@2[‚={vÀÞéISÈ@@×õ©ä†YÀíkæÓëYÀ£µ™V´ w@•…Èí±`@lääDyÀ‡×v–KT@ðFIBqÉnÀ©á¸Î/Àñ70PúÊ¡@²EyHqÀmÁ 7eR@.ÈoGü*lÀ*oØV ~@^&¢Þ€Àqa‘š" @ß/ƒ¼w…RÀHˆ¥Î-ðf@“wQ€#zÀ¼Žœ+€À’äÙ~ ”@4fê|Q ^ÀÜÏà~Úv@ß]üÑ7 w@˜g"»±”ÀÆú ã}ÀÉ‚›˜hŸ–@ÊΊt+rÀCô¸e‹@˜O¾£@ðd‡r“ÀÀbß7³2òŽ@×HÁ*xpÀ‰÷wéÇ7‰@^&¢Þ€À¾Â¶¡@ðxvä<Àýq$å”p@æÂí/‰„Àtèõ‹¿f—@Å ›D¤À0–CöôF¢¿†k)\¡ç@ÛïùŒÍÀ@mSáÍ@«pÌOFnáÀ´¾|ñ%ÕíÀ䉜àÃuÚ@t¡CöôF¢¿ñ£à*D¤ÀÛïùŒÍÀ@‹Ý?ÙÞ@F¥8S]âÀ}Jkálõ@fÝ`=âSÜ@!ž7#LüÀÀó×L§º²ÀЄd–âêtÀ9oúÛ¦]@ãaìØ’GF@Ãê hl‡Àîf×ùú£mÀ•‚x§*õS@“:‹í“>@³VõÚüç @&£Ís–~@/šÙZÅߨ@ð\ø¢ð1@ÕªÄtÀ#è²–įÀß¡b‰§WF@Æ# ‰1@cR3€©mÀ§†HÊ:¸kÀráó€Ÿ>@+‰Q?u'@&£Ís–~@FÆy¡ãÏ@Ö\ø¢ð1À/šÙZÅߨ@þ•RíɸÄ@ýZÔ ›¦@¼]}Jl”@îÙ<úäa@ëâKZRÿŽÀd -£r@Aóè›çÀEµ‹©Í ÀÀóMÊ\ÔÛå@Œ‰8°w°@§n³¬¼ÀÝ¥FÊVÊ„@êÿ”=­¦@¹EO\ý¼ˆ@S¦¼>Ña‚@. ÇoX£À ƒ€òºÀ‚v½ BÖÀŒ‰8°w°@p1VPU Ý@˜í|Y•C‰ÀmðŒ´Àç=±”˼7@¿þzÙˆfÀë×)+!@ùw³îZTÀ‚õ?ÛérÀ†ú$Øo¬ÀW«31æBŽ@ôýÞgÕÈ@\ËcЭa@ŽéKu £@ÁúãT!Ø„@§n³¬¼À˜í|Y•C‰À4„ÒÑ¿@Ù_ÖXÀÞ:¦Éí¢@@<:™-sÀ,3 ykÀZW¸™@2Q8˜SÀ0ß „B;‡@åèÞ#–¥@ó¸ uDKŠ@7«2ÈÀ\ËcЭaÀôýÞgÕÈ@ÁúãT!Ø„ÀŽéKu £@Ý¥FÊVÊ„@mðŒ´ÀÙ_ÖXÀßK’p¥rº@øíè»ürÀÆJžXã¥@ OÁ‚Å ‰@ê®é>þÕÀ¦2b@TØÀK‡äSƒ@y÷‹?s`@þ ,ÉŽ„Í@øZÎ3Ï÷À±òG7@0¥¼:ß[@[°Öíƒòy@[69ŒAÓ`@€Þßl(†@ÇÅ8}©c@µºg_¦YÕÀ¶+–ó-ÇAý9…ª@b6—{…«ÖÀ(•”»±]v@Ž)îáÚ¸S@ï¦k•ó·¡@sº“ž†@W•м#É@ÀÁïgÍÚ²@ +ÒõçºÀ1¤•‘«weÀÌW'g…@S)¹ I¾™ÀB!·[ñ¡™ÀoR[mNZÀ(€ÅJLÑÀþmuN¼@¬ÒÝöÌ)Û@ ꨼²—·ÀŒ`CûÀ1´ÿ-Õr†@®=ãu pe@å> ÑgæºÀ0l…žÀ™›À+ÍŸðÿ˜°@DìâµÉ1À&¨¾¸.|—ÀúzcYÀ@ßμêàÀ ꨼²—·ÀñìŠ#ä@1´ÿ-Õr†Àå"dž6£À²ØAÚÝ}@¬v·O¿ëf@³ÇnÑ µ_@(í+«>H@žšÌšš“@h/>Rõg~@{‚¹L{¼’@Q±%ï`¾:@fV‚j“Nm@“§e¡Î@ðïEnÿã§ÀkÀUQkŸA@ŒÌØDîk@vdúJl@Œ`CûÀ1´ÿ-Õr†À­XKÃû“@ÐîSÀ¬v·O¿ëfÀ²ØAÚÝ}@(í+«>HÀ³ÇnÑ µ_@h/>Rõg~ÀžšÌšš“@N±%ï`¾:À{‚¹L{¼’@“§e¡ÎÀgV‚j“Nm@Õ²é 3^BÀz%j’ͧÀvdúJlÀ‹ÌØDîk@1´ÿ-Õr†@å"dž6£ÀÐî<ž8“¡9<–@Œàú[ƒ>S@tÀ–0Ñ‚@”ÞÛäR0ÖÀ=·±Iï‘@B`Þ Ì¬@w'~´eÀOÁ÷žÚ@„sšar;¡À »NŠÁ¿ÀÅâÖy*“@Ý–XÑ͇@+Ô€ˆuÚÀy'~´e@B`Þ Ì¬@„sšar;¡Àe%Ò{6”á@{™¿€™Ž@Ú>IGkÈÀí¨yïâÀÖ$ ¸}À·«`aRÓÑ@Z( Lt @eõhj1ëV@ÆÏ? `‹Àé!¡Z,Ô@?AÛ2αÀ¥ÚÔU¨˜À´S%fÐÃ}@öC(ú uÀÇ «þ©@sbj\ÛX@þÍ>²¡âÀö9Œ¼§°›@F„¼Á_i@"2‹k4ÒnÀyù@’ùí¡@¾2Åý¥ŒÀÜ!pÇÁ@DÀ€ ˜õÀHÌŠñÔ¿@?AÛ2αÀŸ¡Þ–¬•ñ@܈©q>|¨@Ob„=‹'âÀ+ŒÓ„a“kÀBVø<ø @Þ$ô¦/hÀjËåéV²@½Ú™.¹&¬@››ÂK;eáÀ^Ç Mæü‘À"’ñ©¼»È@Éí×åÙ‹@³ÕþFÂÀE“2ehÀTUâµìp³@ÎdæÃÂõÀSåXoô›ß@Ë$&ôÚ@Oêv[Ÿ c@¥ÚÔU¨˜À܈©q>|¨@VÍ¢aŠ A:¤ö¼ùÀiIº'-êàÀÁÉ pÆìÂ@ ¦^H²ÞÀÉ^¡Ý…YÛ@ì´í}7ÁðŒ®8á@ߢLÛW½ÀbâJê§Aó@áSŒµÓdpÀËxñ,j¥@56W›íf³@VÒg¦ðtåÀá‚ï?â@í%®h™ÁWêv[Ÿ cÀË$&ôÚ@´S%fÐÃ}@Ob„=‹'âÀ:¤ö¼ùÀ*ý¦šÿ{7A*óN˜wÃ@W~ìh9ÎÿÀ`äµÀïŠÜ@XŠÂ±ç¶Á§ÿ1aù½jÀÈ?¿Ü»¶ @:åh¬RÞ@iÍ&ŸÂ&Á!ÊÕ+Àg@M7ôtÀÌ×x±ý7ÔÀx Ê[wÃ@'4e‰û¶ãÀM#Ûöز@BÊõ¡ó»í@N®ÀáÉËÀ¸ÚF¹„À’~r§t’@Ão§ ½Ã@Ä<Ø­iëéÀõ]F뮲@¤ÛrŒëÀN®ÀáÉËÀ\qƒûqú@rüÄhè¹p@ãOol­¦Y@`¦0%w@…eoÂS@H°ØÛ¾Àz”8h5MyÀ#5Fì²”@„-°Šüµ@ÈYŒs£?™CHUsu@ñøÍ[¬äk@r”—¥Y@·43äsªC@óÿ᤾a@îßâCL>@mJ<¡Ÿ‹À9u9-ö µÀÅFã½@ÈYŒs£?‘J@ñʵ@:šêIÜq`@¨ @$„bU@U³Ã_Ý@ŽÍ=’Š@#nñ£œ¼â@¬&ÛPsM@:¦ÏCý_Ò@NgÏŸ?Ç~@Z‰a¼sœç@ sco~:]@”&^qþ;Q@žHk/ „ÀøÒ®W¢Àp@(À)}¬Ì¡À’@çÓ@}€Ü:¡ÀwÏq_ÅÁ”Ôª õ±±@özÒœ»Ïâ@®ûØaŰÀ+ŒÓ„a“kÀiIº'-êàÀ*óN˜wÃ@³¹×ïˆ$Abqô¼ÝpœÀ3øÑwc@¥x Š‚”Àîϵ‡°æ@¼Ê= Ò—UÀµš5Ràt@¹´ q©«ÀŽÍ=’ŠÀU³Ã_Ý@Á&ÛPsMÀ#nñ£œ¼â@PgÏŸ?Ç~À:¦ÏCý_Ò@ sco~:]ÀZ‰a¼sœç@ÞVÖw%6…Àé®E5Ä­¸@þ¦Qž¤ÀYvnÁ6èÕ@}€Ü:¡@’@çÓ@§Šé$d†²ÀëT“d¦Á®ûØaŰ@özÒœ»Ïâ@BVø<ø @ÁÉ pÆìÂ@W~ìh9ÎÿÀbqô¼ÝpœÀ– !Žt9AÝXǯõ—ÀÄ2Ù3>É@¼Ê= Ò—U@îϵ‡°æ@—*O¨ÀÕGòl–á@>]ÜwáÀ² á«æ@Ò›à•·çÑ@4Â2fP}RÀ¾•8ðÁáÀ6ÃýÀç€P@­•Eê@(‚1B(Øñ?D'Pf(v ÀÛì€: váÀ*Â2fP}R@Ò›à•·çÑ@ ƒqúëµPÀÿZv#çÀáÀ(‚1B(Øñ?p¿$¨øBê@@¹¤?¦@TP¡ásÀ±šB±L¸À¯fzß@'@°Ÿ0˜À¨ ½Ú;¸6 9³@¤®,ˆø6…ÀTP¡ás@@¹¤?¦@VJÞļŒv@›D˜ÛÁÀt7cP54›¿éûÖ\Ï/˜À¤®,ˆø6…ÀŒÃ}–•Â@J\{šÀ¯¿þXö8Á@GV‘‡ÜÎ@†n3†ásš@%C(Fó'Ú@3m¿­Ú@AèXÔLÁ=·Öµö#ÁØí¥”ø¼@ðonèà™ˆ@¼¯VÇíõÀž4mO¼Þ¹À¸þ@bµÝõ@b¶"qŸÍÃ@G5U[Ó@xeÇNÅ- @G5U[Ó@xeÇNÅ- @åoÁLEAÿ˜£tÛí Aß©ÛPôoð@Sú Où×½@í]Ø-N$Ar;»JU7æ@£+3'+SA“Û9žá@Xm ¼W†@4#¿ªª”@-6I’(a@œ†žÂì´@ý fIWµ@xš G'Áüñ½ï%ðÿÀÔúIÁÊ‚@`ƒz‡8êO@zfs¿³¶Àxr;ÒÀÇ˵*~Ñ@Ñ#Ñe¯Ÿ@Ží7Š™@ILx¤ýd@Ží7Š™@ILx¤ýd@J\{šÀÿ˜£tÛí A×—Sž‰ìÿ@ÌùºLÊ@Üa¦úß—@бF¾qƒò@õ•bÕÝÅÁ@¶ï(ìˆBô@,öi 0¼@‰Û<‚@~З’>~@‘ÿÁÎ$š\@Q×–H[1À"Ø£ ‹À× ÔX̘‚À´7h+“À ¿eÆ«P@Q±eáʼn@šz‘©Úë^Às~úìV@ÄzØ+6¸?ÃU¾a.@JÒ yU+g@íîa_ºt@žàÅh0q@O×–H[1@‘ÿÁÎ$š\@ö/¥ˆ­{ÀÏfçÊ@†zÀ-7Ž…RãjÀ©ÚšI½’À™z‘©Úë^@Q±eáʼn@ïzØ+6¸¿s~úìV@JÒ yU+g@†^¶ÎD[q@90ƒã[i@ˆ¹'šmg{Àz€XKüƒÀ$8-Ó½º@ñJ²AOrÀÁ„èï?´ @D‹Õ¡ƒO@­÷ 9mD@ƒ8p®Iµ„@ØZXë(fÀ§ÉUÆ9ÿsÀ‡Í¿œ…@œe¾¿ |@¢“B“Àî¨Ü †ø @xˆjÓìŽrÀ|a]Ì]D@%ê>r׌9@ØZXë(fÀñNÒrç‰@iH½…Ë ÁF¹ì™D«4AÃЉT·À@þuÉhgãÀ™èo3Ï A\Í0C 4ÁEàB€}~Àä¼EÒ@¤Ø4A[!Òæ_Á$.OÎþéÀü0.ž A\Í0C 4Á…nUàŠ^AÂòà-ò™¿æÛ-‘~À¢d®:O@ó=yJæÔú?AxhÝFü?ù± ([!!@'?;7å!ü?ÛeÚ §]ÀÀ¤¼î’‹Sù't@Xèó ˆ£Àp0Ôò‚À\[aNÆtB@ÍJ²ñ@¤§ç;²ñ#À’¯ ûfüYÀV.9{¬pP@{vöuL´@¾GÕ©oEY@ƒî_4~@…Ó¿,¤bâ¿'*¬5‡ÀC_üdNRÀ¬²Ÿ|®‹À%õåûNRp@]=ÂAag¬À–þº&€wÀ÷4’6WÁA@„ È£‚î?•G?Fòï?a×GµŒz@UM#*6ýï?x0EXGÀx9Åö>BÀ›i!@œm¿3Ës@_@µu®ìA@ÀòMC{…À©ƒ4ÿa$Àž¬áU/@Ã?Zµg‰P@J-'¾¡dÀ¾GÕ©oEY@ð`»Ž²£¯@\Ô¿,¤bâ?ƒî_4~@M òoþTÀo‚ ˜÷À%õåûNRp@xðÃÛ–À³Ü¶wÀwÀBybwíCžÀùïGªKý@ų“k_,@ÍPkÌã¼CÀš*)>@é¿jíß$@xåv'T]@}T6SgøR@1ucAYòM@¡”YHÀ¬À®è§òufÀ1ucAYòM@Ú|'oÎN@1}ÊEjž@u‚{)ÅxLÀFüߟV$l@ø™x/B@xêU0¨up@qåLÈ$hE@Èä-tc@,-YçEc9@ÇÂÊH¦‡@,B›?Ù­ÀòTU¢KfÀnçB¯_ëš@èî3,.ª@A7ck*g@Ê]¯ÂkËIÀ“×qøhÀ^Ðô½ \e@Ú;4ñÄq@ZõàÂG4G@M~âÒ'ÖP@·q—5WîCÀ·Œ«Tk”r@_SÚ™@T(Ü/–õ?8ÏjöQß.@Ç©Fùø#@þ7[7×…@“¶‡öÚrÀßi!3è –Àþ7[7×…@‡M°E­@ÎWû‚ÒLÀ¾MòÛÍz@õfoW/&>@*h¾„{@×Y?Ã1¢A@¦˜¦Bï@W yc×4@¯)®ÃÔ2 @d_ÕVY@Àø)i@~ÀÁŒh›9ÃlÀ9ËHóåÖl@A7ck*g@î¦Ûž@æºÅ®ùGx@UÞ~#8C^@R Ñ.ìì–À &ÐiC@“F<ë÷Û@^Ýœé|ÀªëΚ@mk!7þV@ÍzÁ fŽzÀ‘]ÙŒ”@|¸Â:2pb@¡JᘌÀ¥‘+I©E@biEñ,X@;ú-bÇuÀŠF@Ç-6¤ÀÝLð†)ŸŒ@7 ÏðªX@LOM"¾PvÀ[ 7"³š´@²°CA[ŸÀÓÁ[Ш¦À|¸Â:2pbÀG×ü"o š@®‹Œf¸|·Àm;÷QA¼zÀôc]áž@>°¶­ k€@8ԖפÀÞ{ÁnýtÀ…yeÊž’@¡PGJV¶Œ@¢•ªeù¹ÀÇä'rg9vÀJïšÛ”@²°CA[ŸÀAÅÁ!€HÈ@&Þœ8™ÀžïVi¿À¡öKéY@`öüª´¤@–R›+c1ÀÓÁ[Ш¦À¬yϲWÀ@¯8[»ÌUÀ…êü²3k@P¡%ÕÁÀR›+c1@aöüª´¤@|¸Â:2pbÀ&Þœ8™À¯8[»ÌUÀtÅB&„¾@ñÕ ý½ÀW>Ü÷11~ÀæŠz§@œI‡x @âµÇ.œ´œ@¼§Ç­Æ¼QÀ´Ã9ÅËÊÀe jG@—BØDQÑ@Ðߢ4æÀ¬‰¨Q“À¾]MüS@ׯÑ{À+~@–ë—½À¥I‡x ÀæŠz§@¾§Ç­Æ¼Q@âµÇ.œ´œ@4Ôjž%Z@â¤4ÙÖÏÀÐߢ4æÀ ¥­ óÕÓ@(ÈyZ.ÿSÀVubNP“À$5c{~iT@àO”$RpÀ)={Ii@Ä&f-„À¼š9Cî®Àâ]”M©@T@d!zƒÀ…È´÷÷\ž@u”Â7ü•@ùãmðT³°À6TsÌ-oÀ}6œÿíˆ@F>ÇQPƒÀOÐßiÑž@þ¼(MƒM©@ü9”+0ÃÀ³5´Þ À@dAàd0·ÀùãmðT³°À·FOÚ_É@ì{Á侨@ù#NøòUÀÅf½é~¨@N _úVf@"C¢ `p@>·±Iï‘À‘{ ÊñѬ@9ÉU‡‰ uÀ#ŧ°‰â¹@œEá<9Ò}@ÌÏ’RäðÀ¨cŠ\X“@žtŸt7±@ æköS‹À »NŠÁ¿À{™¿€™Ž@‰Ê Z ,Ý@×û¦Éì’ÀF5vˆ’É@ù¶†±'t@F5vˆ’É@ù¶†±'t@[$NøòU@ì{Á侨@M _úVfÀÅf½é~¨@Ò£àYˆÀ³l³ n²@8ÉU‡‰ u@‘{ ÊñѬ@›Eá<9Ò}À$ŧ°‰â¹@Ö?Ù Í@³Ý½rBòÀ æköS‹@žtŸt7±@ÅâÖy*“@Ú>IGkÈÀ×û¦Éì’À ±.ýQá@ô¶†±'tÀE5vˆ’É@ô¶†±'tÀE5vˆ’É@¦—ëx]‹ÀÂDùk¥kÀéý§68…„@·®Qgw]@íœHt=V@“âlÁJ@zq­HB`@¾1§daêH@‡ÇNsøIiÀ·3º VC{À·®Qgw]@òr(ç9Äx@Ào%"&A@çþëä‹¡4@îP†ŸñI@õ`ÿíD63@6 [Q³’À–pÆÚ_ítÀ‰ðÌ´®â3@YVC¸òIÀk?I°÷3@7‹waJÀ¨åÓí{1¢@/Úü±;t@0Ýp?zû4@Ru’œeKÀOÝ–?þ¢’Àþw2f5w@Kh|Êö;iÀ;~vèátÀæh&t:|Àä.LÃJÀ-Ç]R#a@ådKS3JÀâ„Ëða@/Úü±;t@'øm}¡"™@鳞Ÿ5ˆKÀßÖøÍ$ùa@Òæät?e@Žª˜»l Àj~ìn<Ž€@’ tþà”ƒ@ IÑ?¯Pq@¤Ç#¨ûõ²ÀFl¯pÞ‰=À·¨Å†¿@˜)Öñ|av@Œs¦zN0­À~¢=—ë‚À߆:*1'[@qXDë§H@ îÍCvÀ0’-ô²°À˜)Öñ|av@€µ’ò*¼@»t[†Ì [À+´Ð0h¨Àjg)ÜÜn@ÜĆ·:T@_Êä:FˆÀÑÇÿAÚW`ÀRö‡1ìÒÀªÓ½Ø E½À2À!Ç–>Î@¢øHï?è¸@4SÉÙU¸@ õS¹|˜@ö0bT>œÀ§™ÅèyÀùG¹FÓ=T@I–î&ûˆ:@Ö„z‹4TlÀd–ˆ9²kÀód°µ="¼ÀSi”oª¯ÀõÌç82¸@èÆ òÿì£@ õS¹|˜@¶¥áNè¢@.dÇ ˆÕyÀLÔ<ÎyŒ†À„,âuñAØ—ŠÑž{ð@t¥WMˆÁ¨)MGr¢©À„8TD!»äÀܲ)*]ïÀØ—ŠÑž{ð@Y Äu¤A] ~]ïÀx´tÍJÁ¶)MGr¢©À5¡#êÀšÕÀ”²òÀÑG@&Ñ.¼b @4¼yxÄw@œ¦·ƒYfá¿è38²Ï@‚À¤)L³ÖCÀ»£ñ=^ÀG¼œ»A"Z@Xš£ªf@=RÂO‚ø?(,u‰E@@2‚(PEUÀæ~pò¤O@àõ gã%@&Ñ.¼b À”²òÀÑG@•¦·ƒYfá?5¼yxÄw@ÐË¥k¼ÀÛãU|<€ÀשöC@ a@q[êÈŸ£|À=RÂO‚ø?c"=1f@¿c[¥Æ6]À°„ s@àõ gã%Àå~pò¤O@SmÙ:IÎà@m»/‚à­@‹Ö–ñÄ*Á‘˜Ô1Æ{t@!B@–ßÀT¿Dƒgݽ@ó{‘LõÓÿ@›ûE—7 ÇÀm»/‚à­@±Ò4œ¬Žz@¨ú,YA~@@\¥ ê°Á qúB½@Ð'ÄøÀ›ûE—7 ÇÀ jµíp AúQ‘ž‰À ªæÆ„•¨@x‡É–hÇÀ>/5.çbá@d3¹Sâ`l@|ˆŠpËÀRIKçÙve@ÑvHc©ÿÀØlÌ‹JR@g´H,àgÀõ/#ü7u@߯hÖÔƒ‹À¸Ð︼ÌvÀ6ß«õ s<@Ø NÀ|LT+ƒ5@üep䮜¥À=D‚RQEV@<Áf+ mÀù C"<†@~E­ÿ5²¤À‘Ô½v]ã3@Ò¨¹eÀªö Ê’¸Ã@ÿq/Ü”ÝÀ@Š‘—ž§@v­¢5#ÇÀ¿Ó²æå@QvïIDÁr„EЊÀ›É/Ϧ @Ц?„Àü´†ÈôÖ @u)7qÀö&O&¢x†@¡V7Zâ“À2­{†ëÈ©@4ˆ´Sfu•@ŒJ)Ø¡ÆZÀ­лEl@ïÔ:,žT®ÀKãÑri8Ä@¢©‰/òõtÀhòœìS‹@~E­ÿ5²¤Àªra«XrÃ@ÈÐ~ß·RÀçòýøúq„@Ð…_ÒysâÀ·H»6­û@]²âšÓ@(zؾqu°@¯øt!Ô¨¨À9ùÌÀ¢úÅ@& NêúíÀOR'…c¿²À˜~¶á0¯@™—>­žä@GY¸œÕÄÀôºÌ½´@ÍB“À˜Þ‘@ÜCöðÁ>Æ@Dõ€¿ÓãÀmEÏ–Ç»À8ñóEÒáÀ›pTGýÝ@GY¸œÕÄÀ¿^fÚ‹ò@¢@~Ô$.ºÀ2ûõ±˜Àä+ n­{Àq–ˆYxTÂÀ åXÊ.xšÀÙL øá&×@t!}â·@ÞÅ¥XrĽÀ‰¿ï)¡À‘Ç߃šÀYFÚš{Ä«Àø^çÏÄ@…N±ùQ1¢ÀNCO¦þÉ£Àt!}â·@)jüài¿@³Wú9]ÀT5sâ¦ÀØj\F6b`@&„\ïÜI@ka|u¯öi@Dæ"¡ÓL@ùŽç†À°Ý¨Õ`À0¼¢Þp’À¨’ù'¨²£¿·0E¦,|Q@髆ËÉ:@ù~´Ìf”@h‰Á¢™£?’‰c9I@çÅ7vV3@kí™üS@szèZ06@n›É&O«cÀ­¾3å²uÀ`=s½ ¢‘ÀÅ (»~ë:@€¬œâž$@h‰Á¢™£?4#bf”@ÈÖ˜Wò¥ÀÏs?ˆ yÀ"A*ÞÆ­@ç]áE6tÀàKcVØ‘@©ÃJ‚Šæn@cI~æ“Oð@c­½½-c@ã4-óÀ{¹>3ï¾z@ÍÑÅ„Â@UgÖ¤¢½ZÀa4^‹òwÀTÈg»P‹Àè]áE6t@"A*ÞÆ­@DØ`þX·l@@ ÛšÍÜH@c­½½-c@µ~{å!ð@‘÷ïžÇzÀÑÓÄnä,óÀcgÖ¤¢½Z@ÍÑÅ„Â@Ô²ãØ†˜À¢>Û¿Y d@¨¢<]çB£@éZ–ÈeÀm⌭ëý‹À]ÿÞÅFû @XêA že@ÍÐ÷ôÔžŸÀéZ–ÈeÀrÌå©Ï¦@áÛ£L]µÀàyè¥û‹À™U©¶,Å@èP6ÉÙ±ÀYŸMDØâ_@è2bˆ:A‚Àd¹@üª‘Àæ™w¾³@­’UúÆ8ÃÀá[c/áÀUÀèP6ÉÙ±ÀÉ«*á?ÃÜ@g3þø–ÑÀW/g¤@l ù²³@yzÛˆ¾ÖÀí<-{VÀ91ÎàxÂÀ‹°CpÂÀßñt™ÀºT¸¬´ÀÓ»I{Àê“8¢@9Ù4bIV‹@Rîõ@þ×Ç@w¡âþ`N’@ÄÖˆ•W²”ÀùG†lÀ²ÀOx‡ „~À w g¬ÀÄ&=÷ „@k½mÃòGn@w¡âþ`N’@!ƒIGÀ@}åŸÒÂ{‹@[Àn]õîh@«ŒõÛÓµ‰@éúXhÁs@–h¨©þ°@€Ûﮂ‰µ?<2àJæË±À‘e?tðhÀ?)ŠûËøŒ@ShÉ*¡ÀêúXhÁsÀÊúI¤l@ÌP×øûI@7 Åü8Ëj@ÓóêcÅ–T@€Ûﮂ‰µ?‡4 XY°@k "•k}ÀyÝ‘áá¥À¾(Òa1n@Š$KkÌjÀ(¹ÚB‚ÖÀó‘¦Ã¹gš@¶ù«Zð³…@L‰“~ÀàλPg“@­äyét@Íš”D{@0æ;ì2Nr@,ŽJrÒȆÀÞÅ¥XrĽÀ³Wú9]À”®Gc–‘°@ïUäÏzðm@…°Þô:…@gt'sq@?iÆ5Ò÷“@½ËŠ¥PX©ÀŠw¾y ¯‡@Ìç”+mºe@ãdËé‡Àâ£ÀY×Â@‰¿ï)¡ÀT5sâ¦ÀïUäÏzðm@úÑ6ûÑ­@ýÐÍìvù?\ÝJ~•,À¡ñ˜ fH@s‚f^^Àƒâ¨Q«&@<ï¹Ê=AÀÖ?Ây,ŒF@‹^¸ÿ6aÀ fj;@›ÎèFËTÀqšðPX5¯ÀÖ2ìÎ9v@ÙÊxK¿XWÀÍ,GcÙ8@LÞspSÀqa‘š" @ðxvä<ÀRˆÉ)J¦ÀSÑl‘ pÀgÌå‰FA7: ®Õ@b†™D´wÁ‰ºMcÕÀ±II.]üN@!úLš§aÀ-½Ulñ-À¨fQÕ7Î`@ì} Ñ|À - n‘@j 7iŽZÀ|V\(‰Ês@ý”bÎáyÀŸÊÇ]—“@/Cø¶TxoÀ¯b}­…Þ‡@f¶"¸˜±”@d3%Ì»ÀüBå¡ÌŠ@ vT (†lÀpª¬¨¶Ö…@ß/ƒ¼w…RÀýq$å”p@ mðÕr‚ÀÛ)æÙHÀ7: ®Õ@dé¹PÑ´è@4ÙzoWÔÀ›ÎstBèÀæm”ãºÈÀšM¤þC”@\ñÓ³Ùi@ßwÆ yœÀ%ÎTç²u@›Tz…S§À¶ú¶PJÍÁi$Æ…e.†ÀV¸š°tÉä@„»‘FP2‹@ê¡«·AÃ2-0ò?6Þ‚<‡À†Ó•‡²Á€ï°Xí µ@(N*Ûx€ŸÀ M¶ÂYÑ@=Khî rªÀ„­ÊmÜ@J;ñH$†@(Ò†gÍÁ‰»‘FP2‹ÀV¸š°tÉä@Ã2-0ò?q«]AÑ6‘¾Q¼@üœßж¹µ@üN<ÁÃXæœV ÁVg¤bnÿ A·”7Ï€î—@,ì€u3k@è^ùrµÀ‹A¶ßÒ€À‰DŒßc"¶@ÿ ¬;K t@­‹°pç@)¹ë7ÜñVÀ]²˜ŽR ÁVg¤bnÿ AŠhå`ÓÊj@·û×àÒs>@ûÒ#Þ=³{ÀR$Í÷"›Àÿ ¬;K t@^¤vš©@­‹°pç@òÏ æ³ˆœÀòy‚œ•Î@!„âôÝ‘Áá­ìsHÊA&чK,©@käõNØ6ÀA²Ävlâ@ºô.b ´QÀêJaÙùö @Ä`413GSÀ<TÍ>@‚›5ÁqÀMn [Ž|ÎÀ­‹°pç@Å  ÄFºÓ@BÛ‡p@E6;ÛÑ^À±Ç$MºÀ[ÿ/Þ@YÀRZ£J`@ÄíydhÁ‹Œc<¹ªrÀk9#ã· Áá­ìsHÊAV²ÿ—µ#<ÀK{:N+k@Ÿ˜EÅQÀMHOå …@Ϧi -TÀH&Õá\í†@Œe€=ãqÀž˜‹¬Øž¤@r(lì A­‹°pç@BÛ‡p@—ºm”üâ»@Ç.¸¥Þå‘@æpÏj@¢Í7m§¶ÀÞ*nÒH Aß!cê]@ÈŽl¶dŒC@bb•>®a@Ѭ¤× >@¥24ò¿Ñ¹@ÆyW_¢ÅS@ë²ýa ÁMíàöÍ3tÀã4-óÀ‘÷ïžÇzÀËRúŽ|hù@3¶‚Ùf@nW;«@¦¹åù¹>z@²;|Xjd@ôæfî¬DK@BL ÐÝØÀœ*̪ŽJÀ?ð:etå@8½pb9@\è&– @r€ÕRæ>@&>·@ÆyW_¢ÅSÀ¥24ò¿Ñ¹@3ï¾z@ÑÓÄnä,óÀ3¶‚Ùf@ëúôñ4ù@÷päO,y@¼Ô¼DV@§‘ŸyRA@q´êUÿ"'@J÷GoJ@ì°ošÝØÀ iɾù+A½ºÔ+¿Œ€@¡øóï¡e@KÅEÎýæƒ@‚ÇFPîW@8ø­“ ¤,Áž½ºO‹!’@eKÚÅ€pÀ‚^±Ý_=}@nW;«@÷päO,y@‰oÐQÞæÑ@ Ð6£À½Xq8š–†@*ÜS¹¦+n@êS Gh1@¤œÂñÕ^TÀ‰µ£Ùc¿AbJ=aÈG]@·ªá¬#"C@>Y$ë…V@ª:ÛZ#{h@U.­—Á…°¨¸ÚÀjÆZ¹ï}@Æ'VŸ¡À¦¹åù¹>z@¼Ô¼DV@ Ð6£ÀkŒ³¼Þ3Ü@§‹ aûc@×}¶òu°J@¸-ÏrŒXSÀˆ±Ûê£v@|/Œ*ÿZ@§ ”Þ+ÙuÀÕRX™°ƒœÀ á`ì‡@ËöÝÕ×ÀF;»ÏÀ@ÈÇ<Ö6V`@åvåy^5ƒÀ÷IâyfP«@`C£ÿ\¿À™…Úu?U}Àòì› 2½—@]Ó®ÙvÓ‡@úßí wp³ÀU/.ô7À@.°SÀhwáÀêâ‹÷"ÀÀÌyéÞ¤@`C£ÿ\¿À‡`·•©Ùá@{zt)—e@Á À+¢¢ˆÀÈû3¾³@V:8Ï(J¢À!ž ,°ïµÀ㆟‰¹ †ÀˆØŠêbòÀÀý9…ª@1Iki@–Ê@”N+¦{@Ë©¢JˆÀ: 8qö¶«@á8=ýÕ¡À¡Aém“Ä@Þßl(†ÀÞPA 5¤À ‘acú©@b6—{…«ÖÀ”N+¦{@©@ÿ÷ãÆ@èÓH¯²é§À‡ãd¿ªŒÀÞ;•JÂÀ_Áô®¼£ÀzùáÞÀq@«kܽäU@ƒî_4~@\Ô¿,¤bâ?5ŠQ ‹Æ@·Š¾“6ª@‹¢5¿w$ÀùÎÑZ²ÀtéÉ£ÀÉzeE¬À™_ÒMO˜[@—!çÛA@…Ó¿,¤b⿃î_4~@·Š¾“6ª@s—³âį@ùƒQF9·¸@K}ª$©Éƒ@¦Øñ”éÊ@­‹#.½j‚@ŸÖ^”ÕÀC˜¬’¶ ®À„ ufåÀzå½Fw ÀÀ#ô$óqEÈ@¿Y¿¬ã©@ÐלÑKÄÃ@1j^Œmç§@GŒ¢ ;éÀ}SïÁî?ÇÀ0…YªÃ„ABHæµÄUà@@•Ù!ô¼ðÀç9Ô.NÇÀó ‚ÑŒ[ÑÀ w§ßˆ´ÀJ}ª$©ÉƒÀùƒQF9·¸@‘’Š‹Ò·‹À(5޳j¹@•_œéËc¥À‘债p(ÅÀǨ%T½À ÖàSô’ÀKæé0¹©@ê9µÌ3p‹@Læ€tj|‘@ð]ÝW%u@“aé„bdÈÀæ–ÝÍÃÀBHæµÄUà@áº}‹b|è@~ ‘ÀÀô@³–ÉãÀÀôŒXôÀ/«½ÿœ7—Àã"’iZ@î¶Š-a†+@y®)Èc"^@»H½ª† ß¿ˆ W´ Á·Xÿf@pRÀ¸né_hÐA$}O3f@"£l8‹Á2@´ÚÒ•²Àùx¦'å[‰@AeÌaH{@Áóó#zP(@š"¤'49®ÀWjˆ†Hj‘À(,u‰E@@¿c[¥Æ6]ÀAÐ{ËÖÅ@Iw®} ˆ@ÈÕxìK8s@"²eæ"žD@ŽËg¡•ÀšÞ%ÖÄwÀ›H½ª† ß?y®)Èc"^@Ü(3!ÑxÀ‡–;·gÀ ‘»ù•@Mc…“B\¹À»óó#zP(ÀAeÌaH{@ÞT†Þ‡ŽÀ¦wZJ°2•À2‚(PEUÀ°„ s@Iw®} ˆ@€ZLzå½@®ô±Ø €tÀÎ×Nì×À}ÀÞIWï ÁÌÅpܹÎÁmSáÍ@F¥8S]âÀdT9æò6AØGTøä™ö@“gÃmÆ1Á®³e32ø@KÈŒå£Áy1²y5ðÀ«pÌOFnáÀ}Jkálõ@ØGTøä™ö@¼¶ÆÞY4A/"I e÷@"+»ÐS­4ÁÇ—­sÀÒ¬±y!Ò`ÀØ ·ë»ÂÀ†"ÏQ–ÀÄ*†"úŽ@‹ÞùÈðnÀ[ ±u#÷[@ÊxnàÚG@íåwtMñ†@оÿµ²X@Œs¦zN0­À»t[†Ì [À>Nô· ŒÉ@móät§˜@ª¤¢Ü]F¢Àоÿµ²XÀgHnd„¢@ŸŸ8sr@î­À ×`ÀY%ý5ÊLÀÑSxÜK–Àtg˜ÆÍ²À‹ÞùÈðn@Ä*†"úŽ@vδ §îG@¼¼«%j4@оÿµ²XÀíåwtMñ†@~¢=—ë‚À+´Ð0h¨Àmóät§˜@ ŠûŽŠÀ@оÿµ²X@~#Œ,B¢Àr¬ [r@éh(ŒÔ[T@)Æ›„k Àx.z$:ÃXÀª¤¢Ü]F¢Àоÿµ²X@j5á;ñX±@p]¤»$„Ð?»åÛ1¢X@0©’ÌØc Àоÿµ²XÀ~#Œ,B¢Àp]¤»$„Ð?« ûjëP±@ý8¼X˜b”À å61/g}Àmû¶n´Œ@³×ç"%'X@maäÏ«]@R>øc›WD@lY³`Α@GôŽR^@Eµ¶¯Kt³@q%•´@¾Ä„iü”`@Ìð>õÕÜH@?ÇýZÄÀfÔŽO#³™À>-x:DØw@Ï)@OA@uÏuÃ2jÀ%Ë4D'\ÀûÖªªÐßÀ {ðîwÈÀm⌭ëý‹ÀáÛ£L]µÀgÕ1O×Ýã@ªìý¶¢OÆ@/ìgÈ6ãÀÀ}öíØ™ãC@4 E+@GôŽR^ÀlY³`Α@á÷¡üö>‘@£¤9¼Dm@qÿh“:F@Zrz)ª0@:”§IpšÀD>ᚨÀ²)@OAÀ?-x:DØw@%Ë4D'\À+ 2DANÀÕ\R yÈÀ~ÁiÒ²À]ÿÞÅFû @àyè¥û‹Àªìý¶¢OÆ@1(FjÑ@}öíØ™€@qþŠíZÚh@#¦¡¬T!ÄÀ˜È4Ä'çŠÀL+Y2¡@|ª«›V@« £‹»H@€hˆ¿ÁF¡@ ˆ<Õõ‡À =æG'†~@ù+èS¬Ug@Ž^pÈJ²@DµØ.ýŽ@a­9ÕcÑ]@«§Ær“f€À=UnxïyY@MAÞ$V„C@G¡µL»b@ &ŨL@,#x?›À$e9Þ[V±À';Da7Ôƒ@´¿ÅoÚ@@Ýäü¤ì2@ ˆ<Õõ‡ÀÖþÞn›±@ ­ü4u™a@nƒs^èJ@1†âö•@'À†eÞq@s&xYµ9@`ˆ²`NPÀ¬D”@Ï‚p’cÀüfLVÔfÀÙhÌH߉¹¿gmàQl³‘ÀE±ÿ,¿0k@›\¦.J[PÀè&¬®Ue@Ï‚p’cÀ<·7tT]™@Y@Øïé{©?D_¸'§fÀš³DÉŸ0k@:È(çŠH™ÀÁ§®U¬Á„ë'GMá@=ó Âe@ìÿ¸‘“P™ÀZÌšW&…@¿Æx½x¶ÀÞ$ô¦/hÀ ¦^H²ÞÀ`äµÀïŠÜ@3øÑwc@ÝXǯõ—ÀÂ}KA/ô/¥ÀµÓÀ7gÔ¬÷§@:p­¡'wÙÀ¼Ä ¦e‰@NAÇ(âuÁÀŸ"Ójeã@§éà¹pz(Á²ûÀzì–ÀëŸÐ À«Ê@ÖÏÍpeH¶ÀÓ¬ÚÇë¬ç@jËåéV²@É^¡Ý…YÛ@XŠÂ±ç¶Á¥x Š‚”ÀÄ2Ù3>É@/ô/¥ÀµÓÀ¡ì‡Ó?$AG0ÇÖußÀ¦Ñ2¶A'FO„óÁºÀ;€öjWeò@"\\ª~û'@œýzFWI?ÀI…!@ú«FCÐ06ÀÛ]¹þU1@GCÈtBÀ0Ýp?zû4@鳞Ÿ5ˆKÀ°Hq àªU@nýûå6’EÀe|¡$ʧBÀ92a35V@¦ÂJú [À~E‘û5g@£¬Ÿœ…”UÀ°G³ÕO?ÀâÕáÚ‘lT@­BÕØ 46Àµ)ºüøL@ì¶òT¢FÀݬinÄX@Ru’œeKÀßÖøÍ$ùa@nýûå6’EÀî\L±ùf@Ö¡^V[[X@úè*%+ÿlÀ{JKGqÒX@tÚ§@,XÀƒÎ&ÿí,l@€„>ÁWUUUUX$Áÿÿÿÿ_ãvÁdffæ„^Aÿÿÿÿ§ËxAº»»;uù[ÁWUUUUX$ÁÉqÇq Ádffæ„^A233ó‡*Áº»»;uù[Á©Oúd¨EAÁ ž¦A©£¬ô*oäÀàÑxµ8 @göœ˜'V@6@ínÔw@µfn©Ú%ÀãñÛy„Áö0][)uä@úûµ#•@Ñhh|¨8DÀ?;WéÌ@?üAu–rÄÀ™ÁxvÒ%…À²äqªèÆ@úC£î§•y@twbåíŒ@ÐQDU€â¿T ì®í?•@N墿f@©£¬ô*oä@Á ž¦AvVJ†¬R@ãv™Þ¢d'@¶fn©Ú%@6@ínÔw@ ÏnuäÀÁ]‘.9„ÁÑhh|¨8D@Žúûµ#•@§#45ýa@[þ'¿#"‰ÀGò‰F€±ÀúC£î§•y@ü,’.ðÀ@ÍQDU€â?uwbåíŒ@G`pf@Dwìy8@ÖÏŒHažÀXû"B>²aÀzÇX<ãƒt@ôÚGzj @Pßì)£ÀñXÌb§aÀÎýðþŒ@¢¼„  @ÔZJˆâUp@§UšÏÔ?ûú‘¦@ÍeÀN5q@ …¼¨…º`À{Êÿ÷z•™ÀùÚGzj ÀzÇX<ãƒt@`räjYÊ`ÀaþÔ:Wš ÀÜŽ¢¼„  ÀÎýðþŒ@ÅUšÏÔ¿ÔZJˆâUp@ÍeÀN5q@Cp¿ Ç¡@I  |tºµ@À†¬™½Ù@ó|å‡ò4ÅÀû M73ŸŠÀÝÝP¢“9¦À¦ ü]¿·U.¸ÕB!A·U.¸ÕB!A\ÓrœCÖ!Á°á¤BK!ÁZ„ëHêÖ@Á±aÔcˆ@ŠíÆ´«@PΩÝÔQ@:€¤Éöa‘@Ì )üõj@÷w¬8)†À[xƒ^ SÁÀÈ#½oò—H9¦À½"JÀ"žû@½"JÀ"žû@¿´p›ªãûÀ¼½lcëþÀÁ±aÔcˆ@˜À'—¥ùÔ@PΩÝÔQÀŠíÆ´«@ž¯O!ô¯þÀáÐéCòãÂ@ýšGôÚäÀ-I&˜*vÈÀÀ­ ÅãßÀ»b(C6½Àž>ˆ»Ì¯ÞÀË<ëe€7²ÀÂëkÊE0«@AZÚß)PÀÀÞã{ØX§@¸”¢1ëHø¿ŠíÆ´«@PΩÝÔQÀ>‡eä´Ó As¨‚KÂÞÖ@ ëõ1Ó·ÊÀ/ïô†`lÀzÏá°SBŸ@ƒ¼uàÅÑ@-b¤QóZÁi­~Š©EÆÀgh}È-ÍÈÀ¼ 7ËÄÀŒld?: £À§ž™}ÒwÀŠžžà›©@hAR‚ϺÀ}{îßÃÔÈÀüj  +ÄÀÀ-M šÔ@ž”¢1ëHø?Þã{ØX§@6Þ‚<‡ÀÑ6‘¾Q¼@PΩÝÔQ@ŠíÆ´«@s¨‚KÂÞÖ@˜`4ϽAÅcvÉ4¦ÀW\‹¼?ÍÀ¿·ˆ#¶yž@äTñÛŸ@ï LÌ"ÌÁST Ó†ÑÀUÇMè¹@"ípÉN¥@?U›ô@ëJ³éÆ…@P@-¯0 @dmo‘P©}@Þd¶¢kñÀø¢îZOíµ@ãçÅkûî@ì‡i!dÀH c<¬–@‰LáÛt@óTôfFËÑ@;Ž8¿=WÀ?G~z¹@Ë]rЇ@+àJ`È@êôw´]WÀß©ÛPôoð@ÌùºLÊ@†Ó•‡²Áüœßж¹µ@ ëõ1Ó·ÊÀÅcvÉ4¦À"£Ï²B[A=àa»ÅÌÀH¯8X£öÚ@L±Tˆâ©@{ §ŽÊÝ@ÆJ&±Ï†¤@aÒˆgªk@E|~?7l@¯CÚ„ûÈÀLRLŒò$áÀЙâµF›·@T)ü!XþÀÕ‡i!d@ãçÅkûî@GŽ8¿=W@óTôfFËÑ@©AÇ ‡@ Ù¦ß6òT@êôw´]W@+àJ`È@Sú Où×½@Üa¦úß—@€ï°Xí µ@üN<ÁW\‹¼?ÍÀ=àa»ÅÌÀ äj5ŠßA Û9z¨@v9]“w@¹¸ §Wɪ@_õ@¿çÝfŽhÀ3GÍ)óƒU@G·“–@¸ ¯ö)Àò®sÊ@7@c çî÷TÀ-ÔoL]t @X)(žÆ¾(ÀX7ë AË@ïeAu5ÀaK~wmL@㎦ˆg1À¤#„TEã@ArYC;4Àro“8ž>@umF@-K@RˆàF_ @]ð³fâ7À+?òÒ­ŠÀ‡´þöHI@šÄí™S@ØÙ*c»S~À*†ÍÐHß-Àë'íbrœF@îvÆjjëTÀÏ=6 ƒÜr@®!À(¹(À@T\Á‡HF@Y)ó=m5À»h½»RS@Y=éÌç`1ÀÚX½ÜXO@äÉ ® ÀýqŶÔR@umF@-K@f½%— š‰@<èÛ"s7Àd«ðø5U@åx  BI@Ûq}Ÿ^íÀSèú‘|H˜@ƒ(<8úT@•°¨ª¨£@ßt¸¸$(qÀõΓŽqÏåÀBš1} ›@_Á³¸ªÂ@È!;ÄJÀö8¨\ƒÇ@¬,¶¯nžƒ@á0ù»X™@îú»ãlõC@ñZÿíÞP@°ZËŸ¡K@ÐÌSþCçÏ@hr)-Ô[Î?‘ƒ(<8úTÀSèú‘|H˜@ßt¸¸$(q@•°¨ª¨£@HüÊ;¶çÀF(˜ªþÉåÀÈ!;ÄJ@_Á³¸ªÂ@­,¶¯nžƒÀö8¨\ƒÇ@ìú»ãlõCÀá0ù»X™@¯ZËŸ¡KÀñZÿíÞP@hr)-Ô[Î?+Eý}åÏ@ö\o==UÀ»+év¿Xj@[ö¢V®ÀñåïÉs©*@…Ù‘‡,h¡@vÛ›ìaÀíL'æ‚g@iŒ*vä+À¯ÁzÑD@…ôŒ­¡‰RÀÜÞ2Ã'Cj@˜bëjø[‰ÀcEýåO+À°ýh‹¬ÀvÛ›ìaÀNÍÌ´¢@iŒ*vä+@íL'æ‚g@Eë¿ýRÀ­Ñ š†`@Xõv¶J§Àíâ›xhczÀ­ìàÆ=Ée@ŸùÇyeßM@¶``ÈYh@§’`qeAR@þÇ ßÑÀðƼ%°À`ŒläE·´@^X/…û³Ÿ@BjàE[Í@/ ÞëÞò @12ä^ú‚@lйä]Nk@Ì—µ.nî{ÀjíwŒëžÀa,ýÁž©P@²£¾ÎíØ6@mœÂŸR@ûÅì«ì;@EHõ§ª°ÀbeeŸßÁÀ¿w5ÒmÓŸ@ív‡WqZˆ@/ ÞëÞò @ÜÀ)¾ÄóÃ@—R]#¤k@(D]jâT@ˆÜ‚xœœÀpºŽÍ™°~@Ôc"L{c@ ×c[€À‚µÜoDÂÀßA¿¬À{•@k7‹‚òµÀ6–3N©x@ZR_;/m!@j A:¿6À2Ãt³Ê%@ÊÅùêÌ‚<ÀwU иEÀ4oéê¿ @0¶»ižÀ¸1uË7%@·wÆ©;À‘Ô½v]ã3@ÈÐ~ß·RÀ0nè4Ð@Ç`’½˜ÀË’CN wp@Áµ·Õž®Àrlˆªæ~ÀüDUlé™@• K"x™@„“dz‘ËÀ1¤‹ƒ@Àè½ÖPÓ»Àó);)ÈSÀ(:ÍW}Øh@¼µgÍWÀÿÄ-¢3$o@Nzj#ݹw@墓îš=ÀzuXšƒBO@î Rñ,WÀÔ|-['7n@Ò¨¹eÀçòýøúq„@Ç`’½˜À*Y:W4Õ@”¹ÅŒsCÑ@#'ÉÏ{? @Ÿ»ýƒïÀ$>šr´ÐÀÑ_žp§#£@²ýyÑèUu@õV[ ‰>”@6²€Cr@„R¦+&ÍÀt%Ieû»@|Ÿ7Z®¸†@¯nyÛ“ÀE‰¦WÔÓ@ú«a·Òu@öø"ú)…™@(•”»±]v@ñD¤ïÍ@„ÀJ7ý¹Àø%?aXû¶@ö—K§V@÷Ìt{ºMà@q3/¹—tÈ@ ê e r®@“'ì1“§|@¼¨ ÒÖÉÀèVhwv3ÀÀBÞ3và€@t¦Šž@ÐR@ß'‘AçÙq@Äëð«ŠàO@ž~ÏpQÂ@4¤Sá¡òæÀ*©Pϳ#«À²ûµ{Ƕ@‰Ç1­m@S@Ÿ‚~߀v@Ž)îáÚ¸S@„ÀJ7ý¹À‘d¢ä™;æ@üœý²ÞC”@w[  ÐÞy@$Pb²À¼@¼É…¥@˶v‰å±ÀŒÚ2’¡É¿ŸèbïŠ@TárrÖã?ŸèbïŠ@TárrÖã?7=¬1|€Z@XDz¡X{¸¿õìåà¦s×Àõ r$’“À#vV‘Þ/h@N]ï$οerV\PýØ@qXŸ”“@oýçI)r@.÷ w;«É¿)59ˆÑÐi@!Û¥‹ ’Ë¿7ŽD*»r@¼O{òžºÕ¿0 ô+ø¿r¯üGÑ ±À•árrÖ㿟èbïŠ@•árrÖ㿟èbïŠ@°Ç²¡X{¸?7=¬1|€Z@'%ÒÊìþ’À§š»½Ý ÉÀN]ï$Î?#vV‘Þ/h@qXŸ”“@”,~MIÌ@ ÷ w;«É?oýçI)r@ Û¥‹ ’Ë?)59ˆÑÐi@±O{òžºÕ?7ŽD*»r@X;„¬OÃÁ['K_ØÀ»N`š·Õt@ß³X6÷¦ÀÅ2Äÿ Ább¸­Pª@ûcÊÜAVÕŽBãó×@¬Jþ0³ ×À\›¼ýÿ£§À[J¨ÀùuÖÚ@±û½›Ý @¨á;£hÅ ÁVÕŽBãó×@Bòû§Ò A%g ½S¨‡Àt’ŽxñœÀ.dÇ ˆÕyÀÈ£Ssûœ@¼ Õo@Á· @TÀ²Âg±Ã€À€áÂâQ@øãa¤M¥-@š?ñ<ˆd@â2ôcÛlP@§™ÅèyÀLÔ<ÎyŒ†À¼ Õo@:][aýe’@¼æìoÀ¦Àâ–ö¡À‚´äÄ}Ö@@Fù0ƒZäÀ{í½u'·­@#Ân^S1å@r[poa×ÀðXüÏ|@ôB}¶›¥Àª-×Er˜¶@ƒÂrv´Ø@Fñžš$TÁd«âÂä«@oòHClÇôÀr[poa×Àsòª’:ATN_9µ´À~õTÖß@+¸ŠÁ‡(œ@œ~32+s@’q1k±·Àfr@Ó>=¡@”"w–ä@¶ø^¸ÀÑÀéšžQŽZ‹ÀFÆQ‰à @IிǕ?@òn“W™…\ÀRÿ»¢ðÀnôܧ¬Kœ@Érg"nuäÀr®·D•Â@t¾«™Ñ¨¶@T²5ú³¢@~32+sÀ+¸ŠÁ‡(œ@ܹ3!eUÀý)³ÄB؈@Q\F£@¦•5ûÌÀ¶ø^¸ÀÑÀ  „²ä5ú@ˆ#"sv@yK·YÉÀÕ¬9~ÑiaÀ5®?ùr@•¸JJT™@a™cò›½À©0˜T=ÊÈ@G°“s!%óÀ™{V@UzѸÿ‡@K";Û/qÀ› Â:¤@ {•KfSÀ7ù(e¡/‰ÀUtW¥ˆ@«I^Æ@ l<øPÀ«I^Æ@ l<øPÀ…œ9Á`6&@äQ´YqUÀ¼ô˜^>Æ@ýxÿº’@éšžQŽZ‹Àˆ#"sv@ØMGO½ÂÐ@Ò’…cŽÀ‰7s“¶EÚÀùÓßÛK¬À.µŽ!@ã“Êec,TÀF-Ì­á†@â«“­ðˆ@è’Dã1/ÁÀ›Ó P”OÀÃÔMYá‚@›Ó P”OÀÃÔMYá‚@—Oˆ3ZÀceÙûȈ@ú—ÒºqÀ¢Ô²–lY“@Z%ynå’@¤…Ì@Ó_@FÆQ‰à @yK·YÉÀÒ’…cŽÀ ü™ýûÞ@¤ô6’cÀ¯Gžg¦ü„@ø|Pú]™À Ù‘{ų@Á¼ÞŠsn…À23fkÔÀá´›I.TÀðîjTˇ@†Å““IBÑÀ z]_KÀÆC_P›@KØÍ‚ÞvwÀ3©œÞb—À±×rKëqÀ›h¬§þ‰ @ndŸPƒÔm@R’‡HäÍ@/Žþ0á}@–÷CNGwÀˆ¶¡ÒôoÐÀKØÍ‚Þvw@ÆC_P›@g;(*ÿLnÀöÆINÆ}ÀmdŸPƒÔmÀ›h¬§þ‰ @/Žþ0á}@Nq‰zqBÊ@‰Ž³š¿`ÀåçëÚæ:Àw×uqôRn@dölõo W@Ý‘„­iŠ[Àjü«:¹SPÀøíV­M;ÀRËT`Z¤YÀdölõo W@Çád²ˆÅa@æ:ŠœGPÀ.SÌ gMCÀö)EDZû@Bë3^¾É@l¼Õ¦& ÁA¹*¾ú×ÁBŒ¯vÃÀôj^á ‰À0ƵÌSÎ@è7ã‚úæ @ŠhÆ·è@£N…s@jÖ§ À@õ‰»Ø@»åž´g#A’2;æLCò@+9å ¾MÁC Bx÷òÀaÅçZBƒõ@ñ#a=ûÇ@Yd*¬˜Á¥¬›ÃcAVx³r8Áæ@Þ†²øQÄ@ +èñó@Y °ÎÄ’ÀÕeä êâ@‡¶3 †‡È@Ùah!W¯ì@W•м#É@÷Ìt{ºMà@$Pb²À¼@ÞInðÔ A¹Zä)}ð@š¯h¾Â“GA>Ù+˜² Á—XîŽB AÚËXYódÛ@1FXÁéNz aAHÁÔ-Äq"à@ÀôÚnü±@U6$ =A‡©ª‘(Á?šVêÑ@KÊ u¢y®@[ °ÎÄ’@ +èñó@½W˜V_Ì@äÈ&˜¤e²@bIYƒÕ@ÀÁïgÍÚ²@q3/¹—tÈ@¼É…¥@e·Ò ´_ó@ˆÖ>‰»Ø@>Ù+˜² Á;F_;5MAŠVe¸y}À+he¨¢ðš@ýøñãÇå@„ *T¨È@p…°6lÁ0:íRæ~êÀKèü®3 @£8EBþ†8ÀG”LÂzÑ@˜ Ï÷+8À‚ Ú>'@'qoµòõDÀÍìDoîÙ"@‘ž¬pFAÀâ~º%y@dWÑÐCÀRˆàF_ @<èÛ"s7À(Y'áÐA‰G(Í”ã@ìÍÔâ%z™@®ßw¬(L·À'Mš4i’È@EŒ1bĬ@!2pêÀ3­éËÁ4‰äWO=À|*È}/V@ÿ¶fBûA8ÀãÿD„'ÝU@,ŠœƒýEÀ Ú¾Ÿõb@ ÈM* AÀ× £lvÁ^@…Órëœ/ÀfÎçé³½a@]ð³fâ7Àd«ðø5U@‰G(Í”ã@ül¼ÚOATW“¿T@}**ˆÀu_‰œŸÇQ@³wŠ7ä†ÀiP$× Ü|À¸Ã 02B±@öC(ú uÀ½Ú™.¹&¬@§ÿ1aù½jÀWS±‘!9„@ØJ=JѸÀk¯€aˆý‡À ÓNݼ@Q·«ƒ‡9†ÀŸíßD¼@LQá¸]e±@°ÃpTëÍäÀÇ «þ©@››ÂK;eáÀÈ?¿Ü»¶ @ØJ=JѸÀ+µ=Soøí@›ð7òÜ]@Ü5É”@@¦€ïô™ÀÉÓðŒåqÀgHnd„¢@r¬ [r@+?òÒ­ŠÀåx  BI@ÀWàžÊ”@FP£Úg·VÀìëôÇÚ˜@@uAZFn"@_,á˜rÀITøâë…ÀŸŸ8sr@éh(ŒÔ[T@‡´þöHI@Ûq}Ÿ^íÀFP£Úg·VÀåÿRÓa™@°ëÂ÷bÄÀ)’*·´@"§®„‡Í@š –o»À̇‹! µÀîüvN#'œ@E7œP20Š@q?vjYTÀHî¯l ¹@][þ/ÓÆÄÀš –o»À†%$ª¼Ï@˜ê{¶’€@’ F$1¹Àq?vjYT@E7œP20Š@·†ï Aq;l÷@´¾|ñ%ÕíÀfÝ`=âSÜ@“gÃmÆ1Á/"I e÷@RmZL®.AýHb§ ó ÁoÁéðr÷@a W…ä@䉜àÃuÚ@!ž7#LüÀ®³e32ø@"+»ÐS­4ÁýHb§ ó Á¼·nóyÑ5A·ÇæªD«@wÍåøëfÀŠN–ŒBu¬@cÄ\G—mÓÀõœjÏ}w)Á˜æ %>A ³»ëÛ@€¶ÿ¢Y¨À¼Óõ£[Ÿ´@w>k ÞÊÀ£)Ï7„)AÍk‡ÕZÉ Á|èiEáÀ:¿®¨§´µ@ °äzOÄ@Q ùh çÀvÍåøëf@·ÇæªD«@þU§ÀÃÀް¶ê@„[<à&A÷;÷s^8Á‚¶ÿ¢Y¨@ ³»ëÛ@#r[ÌÀÑñºy¦xâ@Ík‡ÕZÉ ÁÄÈ$5AñÒÛœ°¥Àr좣ïâÀÐrúHíÛÀo¯tlÀ@Ö”\S¹›ÀJ©ÿݧ¡@®»¸4Pq„@-ýìba@oΈ±ÀÍÇ3ö<Àʼtz“‹@–ðÀ„{@%ŽÒ`žÀ\J‰›r7@g‡(õg c@à ÉäNÔw@ÿî2ë§6b@>ýù ~‘¢@U¡ºn&‚@ýl ¬UÛa@L UšÛwÀ­_õ‹-q@} U –S@<ÏéézÛoÀkƒìøÒM‚@üuо¾(—@He»ÀõS%>o@, h [’J@MÉÖ×ï—À¹JÕQ_‚ŠÀ­$xLu@ÉíÞ³‘ÀÌå Ê[³@ˆéOj@|†»&M@E©_fŽ5b@QÕ#òÕK@U¡ºn&‚@©ò^Ù‘@¹>¤ÓõøvÀ¦>:Y±Ž@^Õ)(@ó@ÎþÜ×ÌÆF@¹î¬ÖMÄ-@xšr;7ìJ@Gœˆr è&@ÛĒҖóÀfýH§»tÀ½•º«Ùs@8UïB\@²;|Xjd@§‘ŸyRA@½Xq8š–†@§‹ aûc@Øq.Jh²¥@è*ß[É5…@­§èT ¥ÀÈïùiG…À‡UûÂd¶Ù@ü]Òl.@þ‡á@c­OPÝú1@ÿÔ¹m˜@ˆ¡è4ˆ%ÚÀ·¦ûÍ©fÀ¸ÐænE\@èÃÞœy D@ôæfî¬DK@q´êUÿ"'@*ÜS¹¦+n@×}¶òu°J@è*ß[É5…@GàLlé‘@ ± °¸"…ÀW)JGñÀÖ1ê,ä«_À{p!>À©¾µã.@¸«G´í:À¬c€b×qÀ„EµqS@ìÿmÜÑx@ 5õå4ÀMø1o¿>ÀÁ¥ :÷UÀ1w$Š;ÀTÊc(²ªH@¾M¡]v S@›·¤Ÿ:xÀ 5õå4Àr7-)b}z@ÈúfÛGt@oÁFýð5•ÀKj§wîw@&Ý!_¬Å¸?°ºçHa²ÀŒ'ÉtÐÀÙKôT=…rÀò¿`D—iµ@à'¥s("eÀâý1| 8@2|±ÖhNÀGv>}â—Àø¡¢…@¥±,c;€À¦Ù<,ñù @á!_¬Å¸¿Kj§wîw@¨ÑuM{@ª´áBa²À]˜3ît¥}@à'¥s("eÀ*L3è5¶@”TA¶ =CÀHåå—uX@9[v‡‹†@Ñ"ˆ ɯÀ¼‚ŒÿlÀ©(?=¡PÀ8.r@CM®z™œR@×Áÿ1yzLÀŽÝós1$Àù†º2¨PÀki3âë1ÀCM®z™œR@Bs1%"ëD@R2ž?Šç#À` ]0çÌ7ÀP(÷ÈôÜÁ©øÅ€EÂÀýŠ“ØîÎ@³Æ<:“FÀXëCãÏÀpJ½•Ñp~;ìA«¢O\Â@‡ày•rÂÀ–GF’YÑýÀÉÆ<:“F@ýŠ“ØîÎ@@ø E<œ¿ß¯Ð›0ãÏÀ«¢O\Â@ÁWÁcîïý@zeÊšùte@K6aß§DK@?NA|ÅtÀë²¥Cø#$@ºÛlÒ hÀ`âÌdö°@íœHt=V@Ào%"&A@e|¡$ʧBÀÖ¡^V[[X@„ó³bÅ‚p@ÏK{Ý~œjÀ]Á+©]îB@Â`û®-@'UW˜rP@ 7üîöæ4@8aŽ é*ÀÉ£¨‹”UrÀ’ ƒÜ9FÀ;¶ïÙøfÀ“âlÁJ@çþëä‹¡4@92a35V@úè*%+ÿlÀÏK{Ý~œjÀìVi“p”„@;Ž¥jÆ6@ƒGu5Us!@i ³ˆ­K@R§2[™bÀ7ìÕ#®ÀTƒúÅÉ@Î9ís÷óX@ ~0–´C@á‰át‚Xb@T=Š:L@ñ`WN»®Àœ›\Ë[ƒÀ9öÄñkƒ@ =æG'†~@ ­ü4u™a@eû±Á³@\çh3dˉÀågÓ ©”@%|LC!€q@D‡'šÎbÀâ7íÒã‹w@<­¨Š•Ð@#ÉŽc¸À…ºÿeC@¹+U€*:-@ºˆ„ª L@ÒUi§„u5@Üê— ª‘ÀÚÅGÒy“ÀÌÚɱm@ù+èS¬Ug@nƒs^èJ@\çh3dˉÀO¿ß¢ æº@úþ¿oœ–@@ÔÕÁZ@Ut•ÓY¨@sª>±6u@ÃÖá&Ñ¢£@‰ø²p@b†™D´wÁ4ÙzoWÔÀlR¿gƒÿ@*ý…·Ê¿Ó@hz»ÚÉJ‡@,®%”“JT@š1<~BÈ‚@ÍÙ´3òO@‰ºMcÕÀ›ÎstBèÀ*ý…·Ê¿Ó@ë§UN0è@²Yñù¼cÀÍ9¿þ¿ÌÀ#›Ï-CLkÀ’º š&@~6›z—Àüiót5À>ó/,Àƒó­€½-ÀøîEoÒJÀn{Ž„…6@¶t|F÷!@:D1ÈJ5,ÀÀåì°AWp@»Qþä§éuÀcQ ðì¢n@zOòò[R@a»bþãau@|ßµJ=ΊÀêNKþ@؃$Ï@@àø é˜@æí*‘1½6@0ø‹Zd”6@IÓ¢9RÀ0%¥áK0,ÀJ±@!!6@»Qþä§éuÀx€öîº^‚@VCÿÛ¦è$Áwžò­øã@­î|7%¸ÉÀµ†j„IÀÄÚz.ø«@>Xhˆ%@›M׆D‹$Au~ ýãÀŽº? á­@Ä âsV¾@3xq„OÑ@Äfm¶écÀŒà¸—r"ÀBgѳ=c@°ôH›ùúãÀUlàJæ$Á€ï¼û†všÙ‰ÉÀ;Xhˆ%ÀÄÚz.ø«@u~ ýã@›M׆D‹$A´ âsV¾ÀŽº? á­@Äfm¶écÀ²s±ÿýÓ@Åfm¶éc@ŒAá…ŤÀ¿KëOkY@¾Û59<@m'GXY‡†@Ù*Ž•öÝD@mÕ?SûyÀ@Ü<[LI"„nyÀ¾ívôxQÀbVÞá<@!öä{Q @Ù*Ž•öÝD@á?èìL‚@ø+ÎG<¢¿£¬ÝÿEùyÀvèbyû¤QÀuiê@µHfÀzY!{÷r@>álºa@!gë‚mž@ù7ù_/î¿òrHcuœÍ@ÓC2"’@F`^‡$‹Àk¾ïSø ÇÀD‡õW8æ?0¾°*]ëªÀû#d«ÚY”À‰ !Ý\@rÓk1J@.8ù_/î?!gë‚mž@ÓC2"’@—¡’™kÆ@*5ù_/î¿ImÔ-† ÇÀìKDáêâ“À–ô“4q~À‹É›SŸ ÀõcŽ>ñ3@ü?rÐAØ]ÀJK-aº‹@ÎÖD)œQ'@¢-CÅYVÀ æD nn@29ÈÎGÍ?/±ç„n@*O6a«ÀF`^‡$‹À´_¬pÑ™@Œ]¦ ‹ÀåUB,ëô†@ppQ:3ÀuïS°‚@/AQÏü´/À€¦üÓsÀåþõŠñb@õMꟹOÀtãÿ¸´NÀzÔ£LÍžÀJK-aº‹@U“yï¹À‰üS× ¿UÀ?Š·ƒ „@t9ÈÎGÍ¿ æD nn@*O6a«@/±ç„n@Œ]¦ ‹À, F’»@qpQ:3@åUB,ëô†@.AQÏü´/@uïS°‚@‰üS× ¿U@DuÐÄp–ÀD1¶ó•}@(¼þF0@‚GÍ xMÀC¸?"Rñ‘ÀÈ÷¼­Þa@k¾ïSø ÇÀ*5ù_/î¿3W8‰ÿÖÉ@Ú—7b ¸TÀåHgEMÀSS-H€j@¹ør—a@‡U«× N™ÀD‡õW8æ?ImÔ-† ÇÀÚ—7b ¸TÀdU™@ý_Ê@Œ¨ß8%…À²›!‡¯SjÀíL'æ‚g@iŒ*vä+@0¾°*]ëªÀìKDáêâ“À„3†JšÃ®@û’4`õ–@òÍæäcÀí ý|÷ÜtÀiŒ*vä+ÀíL'æ‚g@û#d«ÚY”À–ô“4q~Àû’4`õ–@0PPô´ƒ@±ÇŒ>su@ÝoÍÄ e`@èn³ÍÜ™ÀàÛ ¶HdpÀ<§›Pû™@xXí0˜l`@ýK²²ƒÀF Aç!PÀÏ'âÐk™[@äMÕZáNF@ø¢›EuÕ0@e7œd˜_@+­ejSÒG@ÝoÍÄ e`@h¶ýéýI@ØëÏYhpÀôr2( ²ÀxXí0˜l`@ìc>Õb•@c¡U¼ZÀÑž3¢UtwÀBpÇ/E@AÂÓ›Ë1@¦K¾²mÁ@ ²%Õ+ÏG@¼=#u092@³u(µœR@:Kûð7¨dÀ„VI Gœf@yúŠÜÅ¿UO€ð&è•@mÍ|˜F‘nÀO·7*žÀâÕ’¤Åu@Õš|’”Àv4t ]×@æ~pò¤O@àõ gã%À¢:/Ø—@¦¼U‰Ð*ÀÉKÿm«cÀôÀÃ{¯Ôu@2úŠÜÅ?„VI Gœf@nÍ|˜F‘n@UO€ð&è•@'¿š.“WdÀvWöBTWäÀ"œôÆçš’@pXÜG·@/šÙZÅߨ@Ö\ø¢ð1ÀŽ^pÈJ²@1†âö•@ågÓ ©”@úþ¿oœ–@r]|±¿€î@¢¤[KýØÀp¢Ay Ø@§ÖTæöÀêEUi@—@ßÂ?hS@¨§½¨  r@5Flˆ†\@¼œªù„< ÀØ ®hÚÞÀ­$ ®·“@ð\ø¢ð1@/šÙZÅߨ@DµØ.ýŽ@'À†eÞq@%|LC!€q@@ÔÕÁZ@¢¤[KýØÀ‹2ŒÚ/±ý@~1i«„²Àp+=ŠÓù‚\v—@5zs=gºö?k\ÈóÙ'@á0ãç´PÀ½Z¨Pv̱ÀIæ5‘9ZÀ‘@–é"в¡Àî%û0ˆu@G‡²ó0@nbַĤ_À“×qøhÀUÞ~#8C^@ÈÕxìK8s@&…“QDššÀcÂ~Oô“p@Éj‡!î³@Jþùªn¿À3·ÖKö6@•äŒeæí@ÃÈDÝÀ¤ÓõøvÀª„p&ßç@x„ˆŠ†À!6yW³@®µLü'j–@fE•‚v{‡À— z¾èûš@GÛ µ½¾@꛹úŽÝÀ&jN‡tç›@áêØe×~@åQrnü¨“Àò'ÍûüÌ@…Ô`FX«@WhCûŒ@ç9Ô.NÇÀô@³–ÉãÀL UšÛwÀ¦>:Y±Ž@x„ˆŠ†À·KølÂè@¸jvƒ…@³éƒ@_>ýwq@N„>y‰À]Û^Ô9EZÀx  Û7Þ|@cåîM¹ÊÀlÒ*ýyʼ@7êa4$£ÀlŒRBqÀwIˆ’^”Í@ྴZ¦À}÷œÙbl‰@xN±´ÿO®ÀbŒ×-‚’ÀÀ0"ר«@¾“ 8¾Þ|@iЏйŸÀÆrˆÛW‰¼@â kÎoåÀ=²“ŒqÀÔ$x›”ÀྴZ¦À°cÚ@ä°þAÊïªÀÃÕW§óÐ@ÒÞmÿ À«‘ê1ÜiÀ<2àJæË±Àk "•k}À¢mݧÍÂ@÷™† ×,…@;Ž®pߦÀê#ïœ9WÀû¶ %”ÀòÀn~ÚdÀÞhÜ ˜@‘e?tðhÀyÝ‘áá¥ÀE6;ÛÑ^ÀÇ.¸¥Þå‘@÷™† ×,…@íSÔš,µ@Ö"Ä'çÅWÀã{Só b¯ÀÙ)ª±’„@Y:sLQ@æë)h V @IÊaɼ=@*qç;lÀWG’‚%@P}´½€YÀ,œf#˃@%AÎýôa@PÓ`T³±wÀ }aw}­À @Zþ` @Þ:¦Éí¢@@øíè»ürÀ?)ŠûËøŒ@¾(Òa1n@±Ç$MºÀæpÏj@;Ž®pߦÀÖ"Ä'çÅWÀŒíhÔžÁ@ ­Ê6#–ÀXª}¶Q@=í—¬É@Ê÷6ÑZ!l@`†3öì#qÀ‰f…E @>PAOËXÀ=‚Ì¡he@¶º¶gP«@¤Z&m¶@LèëAB•×À<:™-sÀÆJžXã¥@[ÿ/Þ@YÀ¢Í7m§¶Àã{Só b¯À ­Ê6#–À—R).‰Ø@B˜ëx%Q@$„B:À¬ñ‡ª'@:JjÀÌŸ`b#H;@­|‘Å6ä$À‚é@2»€vEªÀkÚ0†<@Ì#çvë°À—Â0i0¨5@ËüíÚŒ• À1&à2Jã›ÀLCÿ5÷©M@'*¬5‡ÀM òoþTÀ¨‹¢@¡œ~‡»¯S@$„B:@B˜ëx%Q@:Jj@¬ñ‡ª'@­|‘Å6ä$@ÌŸ`b#H;@2»€vEª@‚é@Ì#çvë°@kÚ0†<@ËüíÚŒ• @—Â0i0¨5@íŒêA¤¼MÀtU ûÃá›ÀC_üdNRÀo‚ ˜÷À¡œ~‡»¯S@åIz7T¡@ ªªËÏW‘@Uô &–¥ÀܦÓp@·>RÄ‚ˆÀ{fY”ð@³yeC¨À´\ÓÆ|ƒ@ RÖ6·ÀaÐÔ ¸À)ÕÔ=M8•À»H?4¤ÐÀ©[¾â@Î@½…¹xZ˜ À—·#Û©@±Ž_ò ›ÀHˆ¥Î-ðf@æÂí/‰„À±II.]üN@æm”ãºÈÀi]L¶éÒ@ºú]¢©Àã2æÿQãÀ+·W6=™¸@•†¨«\‚ÀúÕPî›@˜ŒgqC¢À×4r离@JÓ¢á4–À³4n‡Ö×°@Þ§öð•ÀõG|¸óº¬Àc¦*0©Ä@Y¯rL±JçÀ13n›%é²@‚*í^´ ”À)[1Ò®@“wQ€#zÀtèõ‹¿f—@!úLš§aÀšM¤þC”@ºú]¢©À_4Á¥šÙÓ@²k]Ÿˆ0<@ŧ)UUÀÜÐ- ’uÀëæAó¿öÆ·ÇÓž @gëŒÈuûx@cá)EgœÀ£¹±)“sÀ¥ p;ñvUÀh‡p°U>p@YÆ,B™Ú¿ž|•‘ätÀgëŒÈuûx@úx?šT5@ X`5—sÀ”ˆ)MfŽÀµ+Џaf@ɦÏììP@w]QmašÀƘ‚">”‚ÀÝÒùG?Ü@Ø™Kõ[‘z@Æòtw, l@®÷e0ßÄJ@N¨Ñ‡>öw@û T¥A@“¹?ží.Z@qÌ]‰ÚD@zæ"ܸ^2@aÃLk5HÀî)ÅÚ sÀ?¬‹wÎV3@÷¡á^.%Q@µˆÝ]î9@Û5ó(BƒÀÌ·{¯0sÀÓ ÑÔy@øŽ' Zd@ð¤W¨íU@NæÅôŽ4@û T¥A@ÇÈ@6rs@å# )²D@¬\c)ó/@z}EõnHÀT…¿êr^_@qb7L J3@еÕÔ®@©`¢os Á EPåC@ã]•à§Å@Yn$0k\@‰4¶äò7¶@¿&ªÇ?Àý$R¾’@·3Àð»;ˆ@|+×v4¸¹@Š÷§~ÉÄ@,\Z’®Á•[§Lãô¾@Éø¿×bñÀppQ:3ÀåUB,ëô†@€æfóèáÀ$~EX(Á#Aw¼ë_ÎÃöÀ”°ö£Aµ@G¼%Ä$²úÀÏk¯à!nø?éJà§%¦@‹—›øÜÀtüÄRš ¦À6¶‹Ž·@Þ*¨ÙUv@£™Œ¸ë@öZÈ@àSô„ÌÏ@ 憎@”: ­î¸@Æ÷c«¿ò@ü ÉÚ¥‹À”ÉYÅW Á‹^ Ùn߯ÀÏQiYFAô äL± ¡À‘)_j+Ð@‘)_j+À»]ÙøœõóÀàC)WœÅ³@ä+Ž‹~éÀ׋³·3(Ù@ó¢pù< u@,æ‰,4@ ôoòGš…ÀXÇi2G¹@öZÈÀ¤™Œ¸ë@ßôC1@nzCGUL@豞{ãv@ ” ÖÕ§¡À+MÆFØ@ü ÉÚ¥‹@Æ÷c«¿ò@²WÄ\ž—Àˆ|.É@ºKŸÃ&š•ÀŸd¹ úÄ@5t´FíÇÆ@ÚKáqEC Á6#¥TÀ»@w¼ë_ÎÃöÀô äL± ¡À—Ä8;¥ A‘)_j+@‘)_j+Ð@[V½•Ó°¤@°vÍûwÁglR%úª“À´„ ýeË@NTw0º©„@6íÑ;ƒÀIிǕ?@Õ¬9~ÑiaÀ̇‹! µÀ˜ê{¶’€@ wj÷³‡º@¯èK-qû`À "¶ŽƒµžÀ²Ñ«“úJv@¾:l âšÀIJ°uߘ@òn“W™…\À5®?ùr@îüvN#'œ@’ F$1¹À¯èK-qû`À‘´únZL¼@¨Ž¿Ð{e@Uj°q”¦Àb~C2­ÀÀÙ¿‰Ê «ÀNŠeª*hž@ilͳˆþ†@oÿ8‘cÆÀoÖäè ¦ÀÖIˆu6?˜@Ý6$^„Ëu@¦a¿ÏŸÐ@°¯ÜP´@âÌ¥Ëþ«Àî/ÝÁ+f–ÀÃõ B'‰@|³}%}s@§í7oU¨ÀËœ±¾ý³À1qv„@g=žžb@°¯ÜP´@Ónl$Ö·@}DŽ1éÒ@»fUÊ]ëÀQ›^Gw+p@/–™úßЃÀ¢¬)ìUëÀgüL(ÊÔË@À»…½±ð@Û·Ð&¨oÍÀ¦äDMlÞÀ6v2e]Ìë@Á_û¡tÔåÀЇ|yW_A\ìÞµ ŒƒÀêbÃ@fô—@TQ÷ÏË@½ Eë5¦ôÀÛ·Ð&¨oÍÀ§ñø@ÓÁò‘Šæ@kíVÚ FÁ®¯mƒSaeÁÊ( &\KAzkõÕ@Ug!Nd‰ëÀïϳό›Ð@ :'4ÚëÀté}›˜ÌÀïûî ©…á@:ÔÐsƒü×@ÎàóRïÀcG€üÂ@ÿ‰žKæÀtçÎ;ù@Nš4iÒ¸Áªö Ê’¸Ã@Ð…_ÒysâÀ¦äDMlÞÀÓÁò‘Šæ@Ô œ‘eA³µË]ïAHÁOÀŠKAžJŒýq¾sÁ›ÐwðÀ ™: §Aå·7SéèÀŠ+@§ãAÝÿ$¿Då@Å™êòyúÀ+ŸÜ–býñÀÚè6>@AóŠžKæ@cG€üÂ@—-[¶ìÏÁuçÎ;)Aÿq/Ü”ÝÀ·H»6­û@6v2e]Ìë@kíVÚ FÁ³µË]ïAHÁÄeÝ3Ä”rA¬²Ÿ|®‹À%õåûNRp@YŸMDØâ_@g3þø–ÑÀp›`UÁ¥@”°½ÉŠ„À‚7ºŸÀØ­ÃCÑ«@%õåûNRp@xðÃÛ–Àè2bˆ:A‚ÀW/g¤@”°½ÉŠ„ÀŸq #œ³@éè,ÔŽ@?™ba¸À]=ÂAag¬À³Ü¶wÀwÀ{o¶@S\Ê@"cvð£€w@$àEðzBÃÀF#YyMŸ¿–þº&€wÀBybwíCžÀ"cvð£€w@¯¹ÛkF Ç@ ž"YyMŸ¿ÿTmÙWBÃÀd¹@üª‘Àl ù²³@‚7ºŸÀéè,ÔŽ@Ò³¨©jÿ¦@9í‰úæµ³ÀJlxµÆj@Y`SèŽÀæ™w¾³@yzÛˆ¾ÖÀØ­ÃCÑ«@?™ba¸À9í‰úæµ³ÀÙƒOŸè×@AË<,%íÀ v.ÅòŰ@î4g_ÊQœ@\@¹1æ¿.ªz}.–¾À?­u’1ŒÀòÜ å»·@HЬ‰6Œ@¬@¹1æ?î4g_ÊQœ@€˜øx<ŒÀþ„ï]û¯ÀHЬ‰6Œ@gáVÓ¡@«¬ð=2·@!L^¦q‘ö¿V^9»^£@ãolJxÀˆÀdÈ?ÞÀ½2ÝDæ À˜¨á½‰@ëÇ^‰¼·À¡ô‚°åØŠÀ¶JÙÇǾ‚@$‘tzÊòO@â¿Ñ9½ÓÙ@w%»ÂYȨ@q1lb„‰@?¿;ì8`@óL^¦q‘ö?«¬ð=2·@ãolJx@V^9»^£@ó}^˜.á¦À³§ðë•ÎÀÓ$wã•a@ÇpxJÔÀÖõõ˜ãaÀýƒçÛY@Âu棋&@w%»ÂYȨ@zó€ ªè¼@Zä_½™a@ÝÓqÔ6@»D*i“ž@Qú…à;kÀIɹu.±À7ºî¨àyÀShÉ*¡ÀŠ$KkÌjÀãa{ï4C²@™˜_4@Oú…à;k@»D*i“ž@·™TJŠÀaGÇ“¥ÀêúXhÁsÀ(¹ÚB‚ÖÀ™˜_4@ÞžAö¡@a§ò¬ãÀÆ^ ðtw´@‹ßeQµ¡@å :ã'€s@S«)ùÒÜÁ(¾ë4)ì@Xáz7§@*¡Œ§3ÄÀ|èiEáÀñÒÛœ°¥À™ f³[BAHìŃèÀákPçr¶Àí_§#í”âÀ_<4Úlh@Á¶an»å:@&õlþJÍí@Ã,žÂ'Á<ù…ݧ(ÅÀg>–YoVâ@:¿®¨§´µ@r좣ïâÀHìŃèÀÏ]ðçA ”lÌÃñsÀÕ,}áa?9@b6ƒèßbo@q‘UVìÎö¿­kÚÅÉ¿ª@Ìj^ß7À‘ ÕJ¿7ªÀŠß.‚¦¿ŒâV°}6@×.üÂÿTuÀ‚‘UVìÎö?b6ƒèßbo@Ìj^ß7ÀJ!n6ìª@ˆdß.‚¦¿¯gŽ€x7ªÀ.Ž»•¾ÎF@þ‹²Ý\Ú:@­§¬4TÒL@÷ƒþJÙc@@dþ®Q`‰@øøª ([@‚[#‚¶€f@ˆökL’M@wù‚»FbÀ :l»ÀUÀÝ‘„­iŠ[Àæ:ŠœGPÀ¢ŸRNxR}@U»ñ¹æFO@cá)EgœÀ X`5—sÀ‘ ÕJ¿7ªÀˆdß.‚¦¿õþ1 Ô(·@þºï^½~u@¼£ø­l¦Àà às]qÀÒ*¤&œD‰@Ö¬b4ËZ@’ Ï ;@ÃGSÒµÖ/@ãúˆ ä^@@ýCüö{ž2@ãÜþòµrM@Ú5yìOV3@€u±FUÀVÓõÖ«áGÀjü«:¹SPÀ.SÌ gMCÀ£¹±)“sÀ”ˆ)MfŽÀŠß.‚¦¿¯gŽ€x7ªÀþºï^½~u@îòT(Bÿ°@½Ÿ¤qR½…@I’$Ž„bR@rq£E^"†@°Voé'W@fE³D¾Aß5AëåâÀ0ÁÂÀÒ#v@Àÿ<)#À¤¿Ì"ÁÎcǻŹâ@i&{hc£“@ò5·8/gBÀtwbåíŒ@ÍQDU€â?Éy¯¡}xn@,N¸ž§ÀŒà$nüžvÀ¼£ø­l¦Àt®d|È@{•1ÏJ’@bŽŒ‰@¿¸«–²½ÀÑÎLZŠÀâCzйs@º“XÊäY\@A{˜çV‘@_x|#ïàb@Ù.óV_ W@XÜ5¶~#@xðGJ œW@ö©£;!)@ß5Aëåâ@fE³D¾AÁÿ<)#@/ÁÂÀÒ#v@è 3WÊãÀ—{i@ÊóÁò5·8/gB@i&{hc£“@ÐQDU€â¿uwbåíŒ@ÐæC@@@!Âv¿¹tÀâëÛMíCÀà às]qÀ{•1ÏJ’@õ@7óŽ@д³UˆZ@\Wúx{}‹ÀpÛú=kXÀ‹Íô¬`@›Äú€%.@ÝD<ûÇžb@N¶9ÃÂ4@ev¥fKqR@Ìf°×ÌIsÀ\¬—Ç„×PÀâý1| 8@”TA¶ =CÀà}(¾]@ ­ãŠ8ìÿ¿ð>o±bÀèzãjÉ¡{@+?Ú€¡_cÀ%dg{?FÀyˆJ§ ïU@âj¬)¾2@0*A¨rgÀÏ1bÐ…ˆ@)5³²’ie@2|±ÖhNÀHåå—uX@ ­ãŠ8ìÿ¿Òf" ‡^@"î±ù,Gq@#e}3’ÀÚ$•~»­MÀ¿®4 1À%öíTÍ@@ñì„`¶@Õ\¿=Ñ@»s!6c’@Ö;Íè>ÕÒ@84õ¡o@¢ÄŠÕÜñ¡@P^Ãy%õÀAÿ’T‘J@)9|\D/}ÀZ×ÏöG¾@!ÞWø;ÉhÀßÛ7›D²ºÀ §$0_ÆPÀ+‹hàꈕ@h.¹ Y‘&@Ê{¹K@ fÀë¯ûtåµ°À`v£Q߃@„Ðø7–ƒ@«VJs9 QÀŠÌËà%\³ÀJÍ5X@ÇgcAŸ@ÿs\E7é9À?ñU_®ù“@ÌæÏ¼Í À‘)_j+Ð@‘)_j+@Ùÿç;vÔÕ@J³Ž6­v@ùžâÕ€¥ïÀ+yÖ:!©À„s›©¡Û‹@tÄ"ÚWÀ(•¹£ µÀ.Éîæ°š6À»s!6c’ÀÕ\¿=Ñ@84õ¡oÀÖ;Íè>ÕÒ@G^Ãy%õ@¢ÄŠÕÜñ¡@µ·»9À)>FÛ?q±@!ÞWø;Éh@Z×ÏöG¾@KYt {À…¢ñxD±Àk.¹ Y‘&À+‹hàꈕ@÷µƒÚWš@µ·»9@YÛóJ!ÄÀ«VJs9 Q@„Ðø7–ƒ@d¤ +õ\XÀ–ð1S†V³Àt\E7é9@ÇgcAŸ@¿æÏ¼Í @?ñU_®ù“@‘)_j+À‘)_j+Ð@J³Ž6­v@G©¸û ŒÝ@+yÖ:!©@ ®Á%‹òÀtÄ"ÚW@„s›©¡Û‹@2T­X+]kÀŒ0¸xÝŒ°ÀoódŸææ Á­[{¯Ò´Àf¸¼DìÇ@ŠFÑz®†@a‘Ç@g7ûÀ)]ÎT3ï¸@'öu›Y%à@¯†¹4Ÿ@ÀÛ œQÉ@æZª}jJ@Y³ÁT‰À²ïÿÓJx@ôSñÿñÜ…À»]ÙøœõóÀ[V½•Ó°¤@ùžâÕ€¥ïÀ+yÖ:!©@·ü¥BéAÏU¹äHÀÀ1G‹2Û¸¨Ào}%ö÷Á[oëâI„‰@ù¬Í“1H@lFÑKŸ%Ë@õ~8¸ÅÊ Á) Jè8¡@{ë茈`@wû!·‹@'ˆ¨ZOÔÀ×òAªÌ@T§B•½Õ»À30ïŸ* É@àC)WœÅ³@°vÍûwÁ+yÖ:!©À ®Á%‹òÀÏU¹äHÀÀ,‘«ôGÌ!A§õÊ4ô%º@Ýþ@œã­˜@ºž° =‹»@±øó²Ý @Z]PUÒÀ²DÐËt‚®ÀEAë°»r›@«:˜¨cV~@¼´Ð0jÓÀ\1Î[HòÀæ/¾:v”@!7ÂPþŸ@£ºpGMl@f†±O-lª@£Ú‚Ž@ ³õŽŠ¦@v:ù"/y@Zi‹uäåª@ŽîroÞŒ@F=³"T¶Àw:ù"/yÀó ‚ÑŒ[ÑÀÀôŒXôÀ!6yW³@¸jvƒ…@öQÑãœÛ@,À¢Oöµ@v† ª;â@޵%×q4|@wztàSØ @ RÍ´f „@ðÙ¬}®Àj3¬½À5UpI!Ï@üd›&”a@D<\\0¶Àü\YDwq•ÀÍöþüç€@‹i Oʉ‚@Ô¿&÷2fP@â+]í|2Ž@Ë3&“”4q@Y}-K-z@b3:œz?M@•›R§é+@òcô«„p@:4÷Õ¢-zÀ¶ÝÇßh’¦À w§ßˆ´À/«½ÿœ7—À®µLü'j–@³éƒ@,À¢Oöµ@wÀÆòÄ@4 ZÅ“Àx ½’ÏWúäæA@"ŒÒ‰HÁ?Ð23rü£@ÿ 9 z@yÓ ¥¯š¬ÀftèP2xmÀ¥ôHóœzÀ'+þc;@­T|ÿ;@p²ôƒFRÀÇÑ"ã¥@“•/ß´q@"¹:8bl@Ø\,YGÀéYX¬:‹@î™p%]@³üO‹:¡ÀÓýª"C+R@°/¿ô]@ÛV}ép@mÕ?SûyÀø+ÎG<¢¿|øvºd¾¸@ :ëúdÀÝÿQzµÀ§BRòí{ÀAF÷_Ó™{@å0†úw}G@˜›Ãc—–¿n`Û)“À"ŒÒ‰HÁ¿‘ÏWúäæA@­1Nýw@i9%Î/YP@Œ“4ݶPiÀÏMš Í¢À¶VíOÐ,KÀ–¶ß!8yÀ€4¬"6.RÀ¯û"|þ»g@“•/ß´qÀÇÑ"ã¥@Ù\,YG@"¹:8bl@î™p%]ÀéYX¬:‹@‡4¬"6.R@°¹’²|¢À×V}épÀ°/¿ô]@@Ü<£¬ÝÿEùyÀ :ëúdÀF÷C½@§BRòí{@é¯sÎuþ´Àå0†úw}GÀAF÷_Ó™{@ë1y–¡~@;ûh Ç}S@d¥6pàÀ†F»FÕpbÀw´nv@4õ‡·¡ÇÀ!Æ Ó,%ŠÀT ì®í?•@G`pf@ÝÿQzµÀ§BRòí{@ôµfõ=é@yìÖ;Žlt@0½µ‚¬Àmÿo¢MDÀ°­ªKP@>\ç™+Ý$@bT!ì\éa@ÇzÛújàÀ,Áøós¥_@³'I;{ÀXXüÓ ºÀN墿f@Dwìy8@§BRòí{Àé¯sÎuþ´ÀyìÖ;Žlt@“XTÌè@Y\‰…‘ÜC@·Cr¬ÀkË€ýÀqö¯´[À5í¹-ú`@Tk±IB±C@ñ%™ä›L@g8bV(@m† è¦|\@l1]­é@@<¹­”‚2p@Z•²P.@«ì•pQÀ«4™Ø @¨f;Ø?YÀ‘UÝ’{bÀ¾¾J’àB@oIrqå%@ævýž‹Î/@å¬êØ @£Ü»̬?@F?/1h"@Z•²P.@ œ¾†œ¯ÀDÌE@àOL©ñr@;=ppðœ@‚3³h@^:ÂâÀê“Rf·ÀuÖÁá+¶@^¬ªƒc¼S@­ ç«ã§À>#0M›‡ÀlÉ2KÀ}@ª³8ù'x@„s›©¡Û‹@tÄ"ÚW@«ì•pQÀL€:à?ðÌO*Uá@¥?š¬ƒ¸@‚H³FÉ«ÀB ÊLZrÀàOL©ñrÀ>œ¯ÀDÌE@‚3³hÀ;=ppðœ@Ò«iƒVȶÀ{Ì·VÒÀ]¬ªƒc¼SÀuÖÁá+¶@î?Ùóßâ„Àÿ?ôS¤¤ŒÀËát ¡·r@&Ю‰¹j[@tÄ"ÚWÀ„s›©¡Û‹@«4™Ø @ 3š¤CJWÀ¥?š¬ƒ¸@¿RϺ†¯Ì@B ÊLZr@îBÀªªÀh½ö^@îÀ|*õs(´ÀGKD™y?¼@9“:ž ä@%¯m³@(•¹£ µÀ2T­X+]kÀ‚H³FÉ«ÀB ÊLZr@&ïbœ&Ö@ÀÀh1 {a@jšÿäqø²Àþ˜Uº¬vËÀ”cª:Ї@°zÛƒB²°@ðWäž¼0€@.Éîæ°š6ÀŒ0¸xÝŒ°ÀB ÊLZrÀîBÀªªÀÀÀh1 {a@a÷'J-oÔ@ìlÎë´@ÅqÖT8—@ÕÕ_+¬ôÀ³¡C~±’ÉÀQŽÈܯQ‘@ìãÌ0R;TÀÍÑÅ„Â@cgÖ¤¢½Z@BL ÐÝØÀJ÷GoJ@“+‹ô@m߸v@-Á@g°@í]Ø-N$AбF¾qƒò@H¯8X£öÚ@ Û9z¨@Æ#¯„A~ê~ýž8ÒÀiæ÷álÅAÀ¤B/(æÌ@·ËzÌD˜”@~È‹p•@Èy úÏ òÀÜÏ GŒøÁY¹CJ8ÓÀ¯§Ô\FÔAáb(lt¤â@8BþÁ˜ì„ˆ7±@ë•rÝt/@r;»JU7æ@õ•bÕÝÅÁ@L±Tˆâ©@v9]“w@~ê~ýž8ÒÀ-Œg~/#Aƒ•‡rºðÓ@·`¦;¾›@±{ÿÖ0Æ„@µ*鯅‘Q@œiÅåŸÙŠÀcði—4Pa@bϨ€cèA@S2ž?Šç#@üfLVÔfÀY@Øïé{©?×Áÿ1yzLÀR2ž?Šç#ÀbŽŒ‰@д³UˆZ@‹¹šõ«—@-ll¥~iÀÅÁ8+Oª°Àmä|‡ÑzÀˆ&¸¬eù`@vhÌH߉¹¿Ó·¹n4[e@¬N Ò]P@CV]5/Ž@ûÝ(Tš[@kŸ·¬¸Ç@w\1S b@¿óQèMa@qŒÈ\;’ÀÔ$yëÁ÷#@vÁd¥µ1@ÙhÌH߉¹¿D_¸'§fÀŽÝós1$À` ]0çÌ7À-ll¥~iÀÎÕlÝüË’@¿gÌH߉¹?ˆ&¸¬eù`@ôG¬˜jbP@gY;Ó9@ôò¼¡»ôÃÀ&ú{iyÀéþ;wÑš@ ¸ímq@éþ;wÑš@ ¸ímq@W3Zö¡j@ìì˜;G §¿ñÜz@ìKŠ@n)i\@.¾i>Ü»6@UeÒReÀÓ•7lNx@ 0“¢X;Ê¿oýçI)r@ ÷ w;«É?Ãܑеb~@x1´¥4P@Ò*¤&œD‰@¿¸«–²½À\Wúx{}‹ÀÅÁ8+Oª°ÀezwwuÞÛ@™Ž•%¸Ÿ¤@÷3¬mñy@½º.^¿Â¿·¨«¹À,Í#È¿#‡ÀþaSdy½À’ÞåƒÀ Ë´‚ÓÒ‚@‚kÉGÑ¿]@_˜wÀs‡Ù8Tr¹Àõ·ímqÀéþ;wÑš@õ·ímqÀéþ;wÑš@’ì˜;G §?X3Zö¡j@=no~jâ[@ý|/ï ³-@†rS%eÀªgœ:™“@|0“¢X;Ê?Ó•7lNx@.÷ w;«É¿oýçI)r@ˆÏH„4P@\Ý€ó&/!@Ö¬b4ËZ@ÑÎLZŠÀpÛú=kXÀmä|‡ÑzÀ™Ž•%¸Ÿ¤@·4tpª<§@ëº.^¿Â?÷3¬mñy@uwrµ…Àf·½XÙSÀ g‚¡{À‘.Zfc¦ÀkÉGÑ?¡Ë´‚ÓÒ‚@œ•÷ˆÀÀ‰@þº?6a´`@_žbÚµ•„À~l¸+WCÖÀY:ÎçeG·@׊"+ðˆ@Êîo&§&U@¡¹owä’@,s»0ÉÌc@ðXüÏ|@TN_9µ´À\ PKåa×@l(Ó‚. `@³¼`û¸ˆ@ô~Š ¼À('½Eð‡Àl)÷»ùqž@‰ÐklKp@-_Ü#¬`@~tí ¡5@í“Çà®@õB}¶›¥@Ú1¾Ç˜]ìÀ]€Îq%`@NQâMáb+@Á÷Gæ>vh@ó"a £9@ôB}¶›¥À~õTÖß@l(Ó‚. `@x/ç¸É Ö@²ó&``@`Ç_ÀÿtŒ—@ÀÓõìŒÏµs@d©†G&E@þÂpê Q‘@»Ɉ³0z@ç´½»±ÃÀä<žRGªÀ·;"æº@b„/®)ޤ@îÛýaÁ%–@<‡Ú‹¶t@6Ù¤„ÊV@µŒJxœooÀmVoH!@‚ëµ­‚7ÀÚlHTLö4@þ< „ö LÀ“¹?ží.Z@å# )²D@¥:¿³ÅSŠ@aÝ á``Àíì6ÍW£gÀËŽÞF>}@–b‹`øOÀÿJ¨Ý{•{@Í/Üd@Ôð“®)¬À&†•‘ý®¡ÀMzǤ@ï{f_@a¼£@¼¸¢“Ø~`@ ÒT"~’mÀÇvoŠe„@»F.Ül6À¦>Ê-þM@VL-øõ2KÀ ‹ËÆl3b@qÌ]‰ÚD@¬\c)ó/@aÝ á``À ‘Îà•‘@Zÿ x@ 4¤Ç‡„“À4ºóÁ½d@Ò¾¶ªx¬H@iæ‰ëtíjÀRÿ»¢ðÀ•¸JJT™@¤ô6’cÀE7œP20Š@q?vjYT@ "¶ŽƒµžÀ¨Ž¿Ð{e@Â\Ôù«f›@¤Ú~’”wƒÀ²Ï°¦q@--j=Öƒ‹À|Zû£½4kÀŸÎlñ°@nôܧ¬Kœ@a™cò›½À¯Gžg¦ü„@q?vjYTÀE7œP20Š@²Ñ«“úJv@Uj°q”¦À¤Ú~’”wƒÀOq°æ°@A\§§rv“À9yÉÁV®@"Ø:]-q€@áK«Z«ñ¡ÀÉrg"nuäÀ©0˜T=ÊÈ@ø|Pú]™ÀÃD¿„÷~a@Â$o¬‚À²Ï°¦q@A\§§rv“ÀDQó/Åè@Ï~V—2²Àþ¶jÈÃÀ„¡­¶¾¡ÀoM]¡™Àߌ’I¸ø»@r®·D•Â@G°“s!%óÀ Ù‘{ų@cÎ"Íp2uÀ–ˆ,Œ®Ÿ–@--j=Öƒ‹À9yÉÁV®@Ï~V—2²Àqƒ¸ð@¢ïìÃã/ŸÀ º˜¶Wî³Àt¾«™Ñ¨¶@™{V@Ý*È&¯ÀÂ$o¬‚@þ¶jÈÃÀ¢ïìÃã/ŸÀ6ןÁ¿@„Û×á¢ß|ÀT²5ú³¢@UzѸÿ‡@0G²éÎ0u@vòûɆ®´À„¡­¶¾¡À º˜¶Wî³À„Û×á¢ß|ÀP_ƒ1šÎÂ@Aœ.€0®m@ŒÌµZ†UƒÀKxú¦Ñô„Àº’ÑŠãF›@‚1z¶±À…¿ð,õ@ÊϪzŠ@{òð¾z‰gÀP¿A!²m†@)ɺ£%@J«»¶.•ª@3Å9»ÞЗÀ¯]$³NƒÀG8Ìn'™@B»Ê“á@‘šKX-r³ÀJôßï“J@¹›hEgµÀ{òð¾z‰g@ÊϪzŠ@5ɺ£%ÀP¿A!²m†@3Å9»ÞЗÀc\ªs¼@ˆ”t(@‘«Ó¡Í?ÀÎg„àzk@Xž°9)7@áÄÉ i q@é˜\{ð™<@:+~Äf@ì’2Ø«¿ýK²²ƒÀc¡U¼ZÀzæ"ܸ^2@z}EõnHÀ˜ªWÊl±Ÿ@®ºë!@l@ß{ƒðO’À ›†Á”áIÀ$8+!cµmÀ½v«Vo2À¿ —cÎ+…ÀMkÓ›3ÀÏÙ©ã×?À *ô¡U@Xž°9)7ÀÎg„àzk@é˜\{ð™<ÀáÄÉ i q@ò”2Ø«?:+~Äf@F Aç!PÀÑž3¢UtwÀaÃLk5HÀT…¿êr^_@®ºë!@l@1»¹¨Cs@bCM!ÍUÀ¿Ÿ) hz„ÀJfÁ]½@BCÖ®ñJgÀVÙ&nAJ@´Y¿–1ñ‚ÀûLŒîĵÀìQƒHd_NÀÓµÝk…“@²/daC@ÓµÝk…“@²/daC@¿DXõÉ%˜Àf±>2µ¨<ÀÕŽäÆÂíb@¨¡kŽsÖ•?d¿jÖ}Fq@ÿoù’Ĥ¨¿)59ˆÑÐi@ Û¥‹ ’Ë?Ï'âÐk™[@BpÇ/E@÷3¬mñy@ëº.^¿Â?ß{ƒðO’ÀbCM!ÍUÀ4h^0ù­@ªÇ!–¥š?@óÃL;¼P@aþÚÍA9@… ùõ0Yg@Ë@msãÞQ@ÔžAÐÁz@ÛC„ Õ´£¿HmÜ[– ÀóMÏØÐ³À«/daCÀÓµÝk…“@«/daCÀÓµÝk…“@]޽½ø;@$¶äˆy ˜À¡kŽsÖ•¿ÕŽäÆÂíb@!pù’Ĥ¨?d¿jÖ}Fq@!Û¥‹ ’Ë¿)59ˆÑÐi@½º.^¿Â¿÷3¬mñy@ ›†Á”áIÀ¿Ÿ) hz„ÀªÇ!–¥š?@ŒÜEþBª@¢B„ Õ´£?ÔžAÐÁz@î¦*¬»aÒÀ$Û23dš@â¹4¼DSš@3Γãèdp@&©ñ"¾‘t@Ó \;šÐJ@¯ÔɃ}$…@O“…¯ @³ÅR®×±Àfzýjè‰@­V‡[šs@#Ô6Å•I@tÀ–0Ñ‚@Œàú[ƒ>S@Gv>}â—À9[v‡‹†@ð>o±bÀ"î±ù,Gq@Jí¯`öÔ@ôÃÒDÊ®À¦ ¤—´<™@xØdi—ØÀ3ΓãèdpÀâ¹4¼DSš@Ó \;šÐJÀ&©ñ"¾‘t@,“…¯ À¯ÔɃ}$…@uâ¤@Á{@P”GÚ´•ÁÀ#Ô6Å•IÀ­V‡[šs@Œàú[ƒ>SÀtÀ–0Ñ‚@ø¡¢…@Ñ"ˆ ɯÀèzãjÉ¡{@#e}3’ÀôÃÒDÊ®ÀÝ¡w½)€á@½ñŠÙuÀ oys_`@äMÕZáNF@AÂÓ›Ë1@$8+!cµmÀJfÁ]½@óÃL;¼P@”äôM’y@9T{eÄáfÀ:3‡GßR@b[½¢ã<@³i­R]`@>ÁWw4„Àø¢›EuÕ0@¦K¾²mÁ@½v«Vo2ÀBCÖ®ñJgÀaþÚÍA9@9T{eÄáfÀ/ý¸H‰@êÆ8ùi{<@o¨ aÈÌ%@Ù9•îP@zq­HB`@îP†ŸñI@OÝ–?þ¢’ÀÒæät?e@¦ÂJú [À{JKGqÒX@]Á+©]îB@;Ž¥jÆ6@Ó·¹n4[e@ôG¬˜jbP@Qa ž»“@¾3¡áôkÀ(Ípo`B|@_±üj]@®§5F@&Gìþ©V@ÇYò…sÀIËDWµzc@ú1³*ЄÀ¾1§daêH@õ`ÿíD63@þw2f5w@Žª˜»l À~E‘û5g@tÚ§@,XÀÂ`û®-@ƒGu5Us!@¬N Ò]P@gY;Ó9@¾3¡áôkÀñ˜ï†ß¹@Y²Ï+Ú4¦ÀeˆeÄìŠ@ža7ÎYV@_4tî9ù›Ài¦n-væ@ÄRk÷CàåÀâCzйs@‹Íô¬`@CV]5/Ž@·¨«¹Àuwrµ…ÀøÏ‡ùJ°@]F&ýÅÂV@àrO°•@…'?í2­f@³ì\½]¹[@ïZ–ÚS‘Àf›‘Ù‰W@ìªjúç#@qoj.F~’@8(H³>†Á)ˆaÐ9¶AÙúö¹sTÀôü¯j@‹¼&–T‰TÀzÌÎuÍj@Kh|Êö;iÀj~ìn<Ž€@£¬Ÿœ…”UÀƒÎ&ÿí,l@º“XÊäY\@›Äú€%.@ûÝ(Tš[@,Í#È¿#‡Àf·½XÙSÀ(Ípo`B|@Y²Ï+Ú4¦À]F&ýÅÂV@·4·^N³@±Á¡5Sc@œšéùÚp4@‘¬€&eQÀÚk8ß’Ã@[ÆÑÇâQ@0ÅZ&Ïí„À(ªgÙïö`@lŸ”ÔÍ“À¾Áé"™ærÀ͆ïÀÊ8„e8'”Àb¤^ªÀ&¦»v;4š@ƒŸ]ÿte@úÌg@Ü (AdÙ•ÀQ`Vî›ï@âN`䈼@KÇBM4ÂÀÑcKªÖ¥à@h6Îqh³@ˆ¡ãúѬåÀ ò íàþ“@Ó{DÆq@;y+mâónÀ+¯ìè>ßÕÀ¡§} óy@3¯´b;™@lc%2Ñ8§À[~ ûÅÀƒŸ]ÿteÀ%¦»v;4š@ayNQÔŸ“À.$E« ™Â@âN`䈼@BöìÌkÝ@kc\ÚÀgÅÎ0Ÿ¿óÅ-Uþ…º@ëš­ eÀ‘ú‹bŸº@?êïð¶hk@q‚`™¿@$.¯ÜŒÀr\øÌ@gÚâ(æ1…@íä aUÁNû;ˆªÀ["…˜ÛÂ@Õé' ¼— ÀF5vˆ’É@ô¶†±'tÀ,}ð4!ô@¯ðѧ˜·@5šp¦#¤Û@¨\=(Z½ól?%ýŽÚÀèš­ e@óÅ-Uþ…º@Dêïð¶hkÀ‘ú‹bŸº@#.¯ÜŒ@q‚`™¿@hÚâ(æ1…Àr\øÌ@…ð÷ÀÀN¡ZÖÄjüÀÕé' ¼— @["…˜ÛÂ@ù¶†±'t@E5vˆ’É@¯ðѧ˜·@†X+–ÒÂë@¨\=4šp¦#¤Û@îQˆç‰ˆv@'W‚Ñ{ÀóÅ-Uþ…º@ëš­ eÀ‘ú‹bŸº@?êïð¶hk@q‚`™¿@$.¯ÜŒÀr\øÌ@gÚâ(æ1…@ R<£éÀR^]ÿ?]°@Q¾ìn€âÁ£ˆC‡s¼ÁÀ["…˜ÛÂ@Õé' ¼— ÀF5vˆ’É@ô¶†±'tÀ}÷œÙbl‰@ä°þAÊïªÀ5šp¦#¤Û@¨\=ê¢.&÷AºNÜhƒÇ@Ü]€ßÝšÀþ¢Ìù[¦³@èš­ e@óÅ-Uþ…º@Dêïð¶hkÀ‘ú‹bŸº@#.¯ÜŒ@q‚`™¿@hÚâ(æ1…Àr\øÌ@Tâ+ñv7³@¡—µûÛqñÀiÅÇ·ZËÀ>IÐÅ%ÏÁÕé' ¼— @["…˜ÛÂ@ù¶†±'t@E5vˆ’É@xN±´ÿO®ÀÃÕW§óÐ@¨\=4šp¦#¤Û@ºNÜhƒÇ@t´=¥ú@þ—:ÐM–ÁïqÄ3û@t¥WMˆÁ] ~]ïÀ7gÔ¬÷§@G0ÇÖußÀ×§–‘%AuX ‰VóÀQüÁk™<Û@Œ"çÁ ]ï@,ÑÃS´ù@ß$Ú÷®¨3Á¨)MGr¢©Àx´tÍJÁ:p­¡'wÙÀ¦Ñ2¶AuX ‰VóÀó™\bY°4A¶)MGr¢©@„ p§Á„½@Eá zZ“@°Kr4µÀ–§5 Z·´À&=ToÌ`ޤÁ§j¿ë®í@8{«äAºÜÒ hëÀEá zZ³À°Kr4Õ@àIONS¿a$ K9·´À\ ¯:­sí@ò"83È%ÁºÜÒ hëÀgÓ;ÜH%A%=äj7@Ô#z²XúLÀHb i¯‰@t®˜—!©`@Õ_=¥@Ô-'%Ý@#É,`߈@ôØ iU@=òî³·ÐÀŽÀQn…å†@Ñ|ª¾×’@¹6Wûs¿c@Ètx²ÜmÀ¯«2ð÷ƒ@îöhoœÅ|@Üoë!{“À+óL<ΑÀc.®­ð§@³¼`û¸ˆ@²ó&``@íì6ÍW£gÀZÿ x@¹†£\tÑ@Rûч·À†W´fõ¾À;,«t8´ˆ@•èpqy]ž@a½zs@p@®²;aòMÀT­ÆjÈÌb@5(þØù‹Ž@[Ӛﺦu@ h3!ÛÀ›@¥7*G>ÕÀß` ¬‡@*{¢‘èŸÀœèÞ@“ÀS@…‚ª@²þs³žª@™rß„ÁÀËŽÞF>}@ 4¤Ç‡„“ÀRûч·À“gA{ /á@ÈðÃϪ³À]E4Y”¼Š@Ë‹ýèËÄÀ*Ô#VB+–À»'À‹vTÀ0£·óöY¼À=á{¥+!jÀ"+#Õ=@WÔ2¹.âPÀ"+#Õ=@WÔ2¹.âPÀ‡Õín'@QÉ[X*VÀ±E²±³§ƒ@Ÿm—â¿P@æºÊ%¢’@–-ÅH‡cÀ°îMmd’ÐÀ“êH‹Àq±eg÷í¡@I#®f:@.µŽ!@á´›I.TÀq1lb„‰@Zä_½™a@ô~Š ¼À`Ç_À†W´fõ¾Àäzÿ -ÿð@»Âþ ™Ä´@ÄóøÇŸÝÀtÞmWb°–Àž®p³@ÿ<Õ:,ºWa@®ŽÓ¤o”À¼ª‰ z–À[X*%‡ ˆ@q¾+ŒÿvÀÿø4 €Ì´ÀM/Þƒ.¦PÀx†~9èƒ@M/Þƒ.¦PÀx†~9èƒ@Ȥ% [À†?_¬["Š@Ua3Y@M`€j©º%@¿JÛ÷“‘ÀWôHÚ>¨@–-ÅH‡c@æºÊ%¢’@+»ª¤ÐÀ\îr-)ÂÀ‹QS)Ö¨ZÀª=•6úÓq@A#®f:Àr±eg÷í¡@ã“Êec,TÀðîjTˇ@¿OˆØ*pÀk 5£…@?¿;ì8`@ÝÓqÔ6@('½Eð‡ÀÿtŒ—@À–b‹`øOÀ4ºóÁ½d@;,«t8´ˆ@ÈðÃϪ³À»Âþ ™Ä´@ñ’w…aØ@ƒE”²Oc“ÀH6†ýª/ÓÀÿ<ž®p³@u7q}¸ÒwÀÛæVߺ®@‰'¸Û•@ª3™¸8ÇÀ^Ç Mæü‘Àì´í}7Á:åh¬RÞ@µš5Ràt@—*O¨À¼Ä ¦e‰@'FO„óÁºÀo ¡HÝA«+À›@ÇÀðpa7Ä­@Ç e ¦.ãÀ]6 + ÎÀ §Òýíÿ@"’ñ©¼»È@ðŒ®8á@iÍ&ŸÂ&Á¹´ q©«ÀÕGòl–á@NAÇ(âuÁÀ;€öjWeò@«+À›@ÇÀ½º  8 A—êå0½«ÀîÜ2Þ(U׿™ü‡~c3@`{ȳò„IÀ›o§ŸÀJy§øj'X@&ï¥TZ1@ÓNr"Ù®FÀ+ω{ž£µ@¬ã×y³»?°Nki­uÑ?T/åÐT¼«Àv/¥¿VÀÅÁñm@?ÑÒœ¶e@ÏØÁW£À;\÷•*\TÀ”©$ &j@¬ã×y³»?³‹Êš¢µ@­’UúÆ8ÃÀí<-{VÀ$àEðzBÃÀ ž"YyMŸ¿JlxµÆj@AË<,%íÀÔà\ŠÓ@ÝŠ!^@á[c/áÀUÀ91ÎàxÂÀF#YyMŸ¿ÿTmÙWBÃÀY`SèŽÀ v.ÅòŰ@ÝŠ!^@¡ÑƒdXÍ@-\ý}(@ùÝ¿ø¨X@ÞÁŽ'ZNÀC\RÈš!|@A{˜çV‘@ÝD<ûÇžb@kŸ·¬¸Ç@þaSdy½À g‚¡{ÀàrO°•@±Á¡5Sc@QŸ²j¨@§gc-öyÀcY_@ç诂*@Œ¶}çk|@vÀ´à¤+ƒ}@]P'ÌâïÀ„èyÑÅ\@Æ3![·›§@¾+ûÀ«ñ@܆H/+–î@å2(j$’À—…Á!>_‡@Ô1ûl$¥§ÀéážïAÛŽ@ÿÖZ‹ðÀ½+ûÀ«ñÀÇ3![·›§@å2(j$’ÀY„²C‹ð@{Mˆ†Å{@ùoÄ®õ¢À­ökƒ¶¤äÀ4`£ ¬|ç@[.œÒ>Ì@qQãX„=©@v…ÿƒ'ãÀDmýŒ}‚@7#_' „@‘ˆÌ58šÀ °äzOÄ@ÐrúHíÛÀâos@0ë@aª–\:ÂÒÀÂáËέ‚ŸÀG0ËEƒÅ@Få±P(xð@€n‚ò{ó Á#ðóÜ]+©@`¢9ë°†@á‘øÄ»„@¿[”LˆäÀôg”ŸÕ¦ÀðË$ãÆ¿½@Q ùh çÀo6À¼ídˆq\@Ž|IjÜ­à¿ÃSáÉt@¾"¡%XÀ„ ²(Îc@­ýcQ·À®;”õU@˜$hˆðÄ9@ÚSØzmq@hɽ(EË?uïS°‚@.AQÏü´/@éJà§%¦@Ïk¯à!nø?;óŶO*À@!ÀÿglŒn@5´ÆÞzN¥Àa§”Š¡ÍjÀŸ!ºÎÛ_ÄÀ]@°§4ìç?Ÿ(5³Ìb@`ðvÇñ?}ö*ýÒ m@†Bä•_lî?‡V!Rh@yòcI>6@›˜¼O†@–|IjÜ­à?¼ídˆq\@Á"¡%X@ÃSáÉt@«ýcQ·@… ²(Îc@—$hˆðÄ9À®;”õU@Šɽ(EË¿ÚSØzmq@/AQÏü´/ÀuïS°‚@®k¯à!nø¿éJà§%¦@!ÀÿglŒn@ Vnd·@_ÂÄÚüþ8@¦—ª^ºUÀí%fÁ,±@ÇüD㛓@ÊD$ÍÅ@èÀUMa«B¾ÀPDFJî²À¸Z ¶˜8qÀêS Gh1@¸-ÏrŒXSÀgïAG×@ýDYƒ@r½@·ù‚~ÀhP­`b+`@Žfh|Õ|É¿•“ m6 |@5ãn9@ÀM@o97í!¬&ÁªeG¨IsÀYLBJ݉@P br'T@ËÃ0šŒ½‹ÀšÕ5ãFÀ?¿G˜ž#ÅÀý=$ÄØ±À]?Ù­J«Å@«móÉ•H@ŠZø¸Š@J¦Çv q@µ¸ºq.õ©@* ¼‹@ ­49L£@ÕÖç?{0r@²Ž½ …í™FÀcQ:µ« |Àc+¾ñ¡@ðÉîÑÌ(ÅÀ«móÉ•H@§å„2 Ä@J¦Çv qÀŠZø¸Š@* ¼‹Àµ¸ºq.õ©@ÕÖç?{0rÀ ­49L£@ÜÜ¥œ”˜ó@ZÆÏ²_@T¿**@iÒîå\@À¬@Õʨ'@7<Ÿ×£ÔdÀÑÉ]-—CÀÙYûü°±ÀEpãv|@ŠZø¸Š@J¦Çv qÀð“ÕQ•@¹ÛE¦s@ðÝ VŽJ–@8TæošhlÀ–çÀmf@XU[)niÀ,3z×’~DÀïÏ,èhwMÀ³§Žn†ŽÀê] –u®ÀJ¦Çv q@ŠZø¸Š@¹ÛE¦s@ Åu›“×€@7Tæošhl@ðÝ VŽJ–@XU[)ni@–çÀmf@~»)èÐdÀ_pÏÝ5À~»)èÐd@’ÀDNå5@’ÀDNå5Ày`n eWÀ’ÀDNå5@Ü¥mÐ…>W@ï÷­’žþÛÀgÔ±hUUI@kSÂyy@[Àµà¡ùÏ]æÀ7õõŠÕޝÀµ¸ºq.õ©@* ¼‹ÀðÝ VŽJ–@7Tæošhl@ñA^âD[ü@Ü¡Âe°Ì@,ÒÄáB¯@}ÍL_5À`Àÿ ‹“ÚÖÀ¤i?·"‡£À©@›¿ %Z@ÜæÑ—^¾gÀþƚмÀ,ïZ/ÝäÞ@i+oz‘©@Ï´o)³!@R–ez+À@zÂÒq?‘@ ¼è+ÀûØÌpäÀÔkÝTÔ±Àq¯œk0›$@:¼’‘ÅBÀÁû,Ï2@<ÓÙ=QÀ&ÃÁ·[ðÁÀƒ¹”¬¡À—ÉÝI¯@ƒÓ*í8Ÿ@‘üâÀ9@÷¯XCgÀÈ-ö zÉÀ/F¶ÆbðÀa8Ðp¶u AR‰¾.ÇñwÀ2[9 þÁ‰@XA28 ë±À¶px¡ê%ÔÀ* ¼‹@µ¸ºq.õ©@8TæošhlÀðÝ VŽJ–@Ü¡Âe°Ì@ܺã„7Ø@~ÍL_5À`@,ÒÄáB¯@Êî÷R<™ÀªrÂÀŠ#C¶ˆÀÛmÔ$ q–@ÓMdTŠ@–¨Ã MÁ¼´o)³!Ài+oz‘©@¬”‚!{‘@¦¯ñVs¥b@,4È®ž<ÀÓEAaZ@õ¡C)ú³ÀÞ¡ä€ÎéÀÀ1i’­úySÀ-xæþ¾q@% (®ÇaÀŒ_O ÝK€@ªÜŒ½³È•ÀŸ(•ð¾‘À„Ó*í8ŸÀ—ÉÝI¯@Q]’p¬VhÀeQáߨü•@ÁpZÏæ À`¡o&|ï‘@3¼°°ÁÂÀDŽÿ™¨Î¿i‹™¦Š•ÄÀ5”÷`¹ów@ ­49L£@ÕÖç?{0rÀ–çÀmf@XU[)ni@,ÒÄáB¯@~ÍL_5À`@dPíùü¶È@ú<,z·×ƒÀ-» V@ÀÖå¼Èsm@Ä~ÿ™¨Î¿ŸA?MÁÂÀrMÞ{@œtå•O¨ÊÀÕÖç?{0r@ ­49L£@XU[)niÀ–çÀmf@}ÍL_5À`À,ÒÄáB¯@ú<,z·×ƒÀ'8O‘ÅÐ@º=“^tm@æŠÈ:šÀ$Ò -I¨@BûVŸ‚¬€@ÿ ‹“ÚÖÀÊî÷R<™Às;ïìèVì@¢jØçî£À%,9‰ÄŽŽ@X\$C*`@»Eó-qÏÀ¾Qêá÷ ›@©x†ø£­@UM›€@ý4œÛ‘@€[+¯.s@0bknÜÀ ¡M ;7‡@9½§5˜@i[õ{8¢i@'Ã1Mz@v&†ªR@¤i?·"‡£ÀªrÂÀ¢jØçî£ÀÚ…¶›ysð@ôû¾è‹`@Õ+9Žœ1@Ò¡¸|›8hÀçºEÁ,ÕÀ¯1ê,Å €@3 ^ëéYQ@¨ç`Vc@Ù•ðõÆD@#f Ë­@Kãu¯kÚáÀ€\DZÞ7j@€f2¯Â;@…"Ê$ÿB#@ñ‹bSµ9Àh4l”Àè9•6õ@*Õ3ÿ4õÀTŽé¡z€°@Õq*‹¤þxÀý0²™Às—ÀØ=‘48¸C%–Àö‹F¯ÿx@òª0xÔ¥:ÀL‡Ìø~ÈQ@¦b‡}œ:@º[}¢Í Ág>íÊV AÕq*‹¤þxÀp>~‹„b´@è_W̃C¿E ˆqUs—Àö‹F¯ÿx@zP¶1ˆ×¢À='@º±@®eN…2fÀg¦#ËF¬g@eç:C-<@eý%9k ™À’Išæ‰b@ÓµmPk¨Àu–Mê?®eN…2fÀÛZ~Yd´@cç:C-<Àh¦#ËF¬g@]@5Wài@Fõ« ±E¡À{À}çsìí¿Þt :j¨ÀX"ÃÛ¶b†À‡Ä#ò™@g¦#ËF¬g@cç:C-<À» E7¯Š@˜ þÚ{IšÀû©•¸#otÀ4Ǧ7Z@^×Á᪙@Æ\¹ ¬Àeç:C-<@h¦#ËF¬g@˜ þÚ{IšÀÑ.˜L®@‡3é…ˆúG@•\$¾F4}Àù CšÁZÂÖˆ÷4‚@@Yò•“À©@›¿ %Z@Š#C¶ˆÀQȧxÚ1´@àI=ŽPlžºÀæ²À®AÁ ?ÃE@“×4ÄßdÀ’Œcì|ž]@ÀõB,vûzÀ܆"- k@J&+_iȈÀL圯r@&Ï厸 ÀY1_Žå±q@þ`,B9¿ Àyô÷É”E"AYŸ©éˆÀåèR»yÉ¡@ÜæÑ—^¾gÀÛmÔ$ q–@àI=QȧxÚ1´@—ÀŸ§V§@íÊ–ÜÛÁ$Á[3ä'oÃSÀ–=L7r@ g÷ æjÀÈü°üˆ@éÙŒxÀ¯]ÌÀ–@o p–΀ÀR(³ ý]®@Òw7á€À×µ–üj®@hP­`b+`@ëfh|Õ|É?HŒ1Å}f×@Go5¿@‘üв4¿h@¢} Êìì÷? ‘7ñûÞÀŽ&bFÈÀØ”æJÝþ@Öõø*B±@ÙÂE CV{ÀÇm "3@Žfh|Õ|É¿hP­`b+`@Go5¿@¦²ß`ÅaË@Ù} Êìì÷¿‘üв4¿h@Ð3¾0ÈÀ3 •5éÏÀ\ý¸ðz±@`Ÿ„L-£@gö§Î–6@îZGm*ï|À ð~ Û^ÀVwOÜß_@•“ mÑ‚Àî.¢ëÌœŽ@ÆsÃc»`¡À‚0Àó k˜@bÏuý‚@Í£ä˜fd@.|ØcÝ>ÀÀ%è% Z¯@€tñž2c@{¨Ÿåj@´@´ÿ¸ž%lAŠHìF¤ÃÌ@¥#í Äÿ@§÷›Ê@FFOu%è°ÁúüÈ–.Aй¸EÁú¯”[›Sk@Ö <7ôÂB@,ïZ/ÝäÞ@–¨Ã MÁX\$C*`@Õ+9Žœ1@æ²À®AíÊ–ÜÛÁ$ÁáòÚÐì*Á$6„Ògà²Aû¯©o¶lÊ@flVÕ[èÀ¥ÄÊ­p@lð&B@þºÄ“\ce@™÷†\xG@ÌüH“:öá@.µWuIgÁ•lyoVð@Nî_ü+ÁPÒ‹rT@›‹•8ˆ•5@7¬ôæ6ö@qµ³O>N$ÁüDEƒõ@1©ü­U$ÁnkÝáɧ½@˜¹[³›@øQ^–pÀh#&‰z-À¨´i3x@Ø6ékâ¿Å;^d‹„À9LaB TÀbõTJ´|@~ƒM!MS@N™·$@­™?ÓCáBÀa¿Š-gŠÁÀ0%Û´R`ÀÅ€0 Â@ ¤yf£5@G—)žbw@¯L_ ’Ža@˜¹[³›@ .«Æ¦Dº@*dKð‰aÀ÷@ãɘnÀUØ6ékâ?¨´i3x@׿IÓnüeÀ%”¯àÐÀ"$Hs׎y@.F×é¢/Q@dö£„øBÀ_­²Ia@ÆÜf^a¨Àxêè^Ã:ºÀ›x‡¢¹Ø@(ÃS_WD3@àáדÒt@Õg»D_@êSµSAÈ™¡Ó¾í&A¥ëêå+?Áe œýî¡@½šZZ“¹@ý“OO¿ÂŠ@}$0¬Û¡@ŠE)•ãŠ@9ý}p¥ŒRÁ–7 ³ 'ÁÈ™¡Ó¾í&A‡šOå~ÑFAæ„:ÜÍÁÀÔ·q$mÿÀRã )X?œ@ñi¸o!n@a‘¯H]„@0‡&xgFn@bæ­¹&Á<ÇÈí×EÁb¼ç¼*Ï@|â4nO¸Àm<ùˆþæ¥@q<Õ'¨YÀ)Tµ˜çÐÀs_ãoOų@c± þXª–ÀK`¦Á“@|â4nO¸Àç0Ä>€wÝ@s<Õ'¨Y@n<ùˆþæ¥@e@5ÇWâ´@ja·ö”ÛÀ+i3Ê0ˆ@AÃ×nÂ}²Ài+oz‘©@¼´o)³!À-» V@Àº=“^tm@»Eó-qÏÀÒ¡¸|›8hÀ9?rÖá¶@ÏÆ–V wÀâÜ”ÇbX»@u’\Ž@Ï´o)³!@i+oz‘©@Öå¼Èsm@æŠÈ:šÀ¾Qêá÷ ›@çºEÁ,ÕÀÏÆ–V wÀ,ê&tÉ@Žu’\ŽÀâÜ”ÇbX»@EB¯Ç¦=Ö@±€Ü±¹@¿ÿ3¬­ÖÀì$$•vʹÀ$^/¡S|@ÓR\bN@±€Ü±¹@Ï239\@Õ’ý‘ºÀƒö‡)Ú³À’¤B"b@ÓÚI•=è5@R–ez+À@¬”‚!{‘@¥ëêå+?Áæ„:ÜÍÁÀm<ùˆþæ¥@s<Õ'¨Y@9iOŒßÚó@R˜Yì¬Ä@‡,°ËàéÀÖ¯>ê!·ÀÎкæ)ùÄÀìƒÁt° À¿M\~û@·É…YÚ´@zÂÒq?‘@¦¯ñVs¥b@e œýî¡@Ô·q$mÿÀq<Õ'¨YÀn<ùˆþæ¥@R˜Yì¬Ä@¿Ò$Ü@ÎvªrC£½ÀýµÍ¯bÃÀ˜òG ÌâÀÃ4R|qf¶À·É…YÚ´À¿M\~û@yôXþ*š@B¶ÚB(o~À ‘7ñûÞÀÐ3¾0ÈÀ}¹uDôñ@ NêhÐ@<‹êuè;åÀª„,°`·®ÀA¶ÚB(o~@yôXþ*š@Ž&bFÈÀ3 •5éÏÀ NêhÐ@ꃑ¼0¿é@h³xþ²Àufê –âÀËJgóµ@f¯Úç VšÀ¿4RãaÀ­'¿4‰@%ypLšjµÀ7%ᔋ@f¯Úç VšÀš8!Š'ÁÍ@­'¿4‰@©õ8Ôr²À7%ᔋ@#VŠc½‡ÄÀtÝ5®{ÀohƒS¶¢¿¹hæ D@“Í’3 2@YÀEÕï “ÀSEEÏ“–gÀí¼ùq@­`ü(c@-9­õ[!ˆ@ºF”Ë_@"ÄIÈÓT@!›iB@çV+»H~@ÈòûV^£?õ¼ #NþzÀu¥œÎ/@¾Eݾ¤¡@ÃCä5Ñ|ÀI/…=Á_À›ûû5u[@âb–‘*¥@óæ‰#/s@¡‚Ýþ I@á˜:ÛÅ?@ú²R¼£ ,@ÈòûV^£?Ä÷ôÇ«E~@Т„D¼ú§@pcQ,ž?Т„D¼ú§À¨.=pcQ,ž?ÑædäNü§@pcQ,ž¿ò¨1”…ú§À,X£ò{áÀI¥ŠV¸ü9ÀT\ÖÏà<@ý0²™Às—Àè_W̃C¿¿4RãaÀ­'¿4‰@üú%å¦tµ@÷V¦xòšÀJJR\ä›&@Zx×@¡ÎDÀÓ½îbNÀ§ÊiÏkã@»!?@ºÆ+@fá)ýÉ8ÀékÜ­Ø83@(Ãöf]À^S<{ѲÀÍLƒ}—u@Î/Ggf—@A$ì×H@Vo¿SÐ AŽu¨T.Ÿ<@¹SÙñFNÀØ=E ˆqUs—À­'¿4‰@©õ8Ôr²À÷V¦xòšÀ?;X2u­É@’4*{°PÀ3»³,ú·n@ Oòp@XÃæ ¼ Á(ù4£Ìq8ÀJ‹ànÊÐE@ñ”×òå`\ÀNÛ¤ª‚³…@‹…H „x@)T›/h ·À‡ñé Ô—{@0ŽHÉGb@XO£g`y£À¶s¤©º€@¢O‰Ät&@Lý û.HÀØ”æJÝþ@\ý¸ðz±@<‹êuè;åÀh³xþ²ÀœX¿†›™â@ø É¿ÁÖà?=wÏÏj{ÀlgÖD¥ÀÒ ˆ,*HÀëX#“j@Öõø*B±@`Ÿ„L-£@ª„,°`·®Àufê –âÀø É¿ÁÖà?H90'v™â@ªYOíAMÇÀ«Hv~-5@ôg§·ü®FÀ ¼è+ÀÓEAaZ@“×4ÄßdÀ–=L7r@N4mÙ¾w@flVÕ[èÀHÝ–b8À›Ò‚ªÓd@`pº¨3ž/À/¤vÓžÍL@›?ºBÜ<À†£€’tZ@(šãBÀžØViàq@ºdñŸI2@T='¥jaÀgÁuž ¹@ƒ âa3‘@ûØÌpäÀõ¡C)ú³À©x†ø£­@¯1ê,Å €@’D‘ð…Ÿ@¥ÄÊ­p@½šZZ“¹@Rã )X?œ@‡,°ËàéÀÎvªrC£½À(tð }ð@e‰_ó~º@äç5ÆX¨@ v«ZT’@ò7†­‹k¢@`léá×Ƀ@í_ª¦yù¨@‚V¥Ýqz@v[%飋@k±Øäh˜b@ÔkÝTÔ±ÀÞ¡ä€ÎéÀÀUM›€@3 ^ëéYQ@ Òßß q@lð&B@ý“OO¿ÂŠ@ñi¸o!n@Ö¯>ê!·ÀýµÍ¯bÃÀe‰_ó~º@Œ×ˆÓ_Ñ@®L­Jøy@»9<ƒ-c@êluãés@»D\–dU@ŸèuÝÿz@x·_r–L@h«ÉÜ›ƒ@þºÄ“\ce@øQ^–pÀ*dKð‰aÀúYâøoÙŠ@Žß t*šTÀ¬1Ð|Žø8@Øz”Ð"@¯p œ–À”Ôôž «`À° o&h@µû…¼oe@þöb&ªƒe@™÷†\xG@h#&‰z-À÷@ãɘnÀŽß t*šTÀ>r4šÃ‘@Ùïé@E@7!ÊØ¡‹@¿kOýËË`ÀSs ÛMÀÞÙˆ¸JJ@$¥b‹iG@nκ³þ¶ßÀ¦€g8,³L@ÌÀ¿á”ß^Àq¯œk0›$@1i’­úySÀ’Œcì|ž]@ g÷ æjÀ¶Ëû5>Ñ‚ÀÌüH“:öá@¨´i3x@UØ6ékâ?{ ´ä&@`pº¨3ž/ÀÿéAC¯Å@€ÇƒYÉž?…ŽÊŸ¨ÅÀWAÇ㣔ò¿çî þN5@6TpÞhˆSÀªÃaA,=@P¯œYÁZjÀÀ;¨nä;@8ß±fjÀï³ÎÓ4äü@p»—\%jÀ)…Tø|@:¼’‘ÅBÀ-xæþ¾q@ÀõB,vûzÀÈü°üˆ@î.¢ëÌœŽ@.µWuIgÁØ6ék⿨´i3x@-­CXþ?/À/¤vÓžÍL@€ÇƒYÉž?Œå:“Å@øÝ6ékâ?‰•Ø*×§ÅÀtÓn]iSÀj}AP@Ëq@Ï.œIC“ZÀÖÝ&!ˆ@Ô¡˜;áhYÀßÕsg ˆ@WçD>´¦@²%Œ²€™ÛÀJJR\ä›&@’4*{°PÀS'au´®¾@óÄÜÈ}oªÀ+Çra$îÂÀóÖ‡WsÀª·½áœõeÀ˜òóJåùÞ@:L…¤à»ŒÀÛ[±i<<ª@òè•i .@1Á˜›kWÀúȃpÀ é'äÖXú@Zx×@¡ÎDÀ3»³,ú·n@óÄÜÈ}oªÀ>s|Ø¥<Ñ@¼Ð …xòk@‰ …h½ÀOÍ’éNˆd@­¦IŠüÀB2ã,<ª@Ÿöû(ôÇÀà sò’/LÀþg¹Êu@<þ¥W"Á~m¬ø4ì@9RŽ\þ¢@¾j\Jj2À“Ø­c§}@?·2ðœê!@+Çra$îÂÀ¼Ð …xòk@?I*‡Û@¥kY#çQ@çrè@°!A·èG9rïÀŽùõU&@ O´Å` @Üò¸À›TïÀæZ/[^• Á»j\Jj2@9RŽ\þ¢@B·2ðœê!À“Ø­c§}@óÖ‡WsÀ‰ …h½À¥kY#çQ@sP-x²Ò×@·èG9rï@çrè@°!A O´Å` ÀŽùõU&@Т„D¼ú§ÀpcQ,ž¿Ü5ÙZ²@Õêv{9åj@ÏùÊÛær™ÀäVÛ=äjÀ¨.=ò¨1”…ú§ÀÕêv{9åj@å[¦ïé¯@×êv{9åjÀ[lO%œ5ŒÀºÏ?‰âΕÁe}sÄÁÄÀ äþU“ÞA£Eo¶™óâ@ß¶‹ÊãÌñ@@ plÕŒÂ@Ó½îbNÀ Oòp@ª·½áœõeÀOÍ’éNˆd@çrè@°!A·èG9rï@4Â?N‹•AQ·í*Ø›þÀRbE’xINÀ ÀÀ7¬ôæ6ö@c± þXª–À+i3Ê0ˆ@wEûo%@(N$ÁK`¦Á“@AÃ×nÂ}²À4Fª]SÀϸêØq@P¯œYÁZjÀÖÝ&!ˆ@V”o‚!âÀôÄ:ÜJ£@ƒîP#UxÀM…_`# –@•׆«¬q@rSäµÔl¸@4€üÞ;}ÀèxÎaÍ­@ÓÄ“jòòÀFÙÑÑP%a@ò¦<¹qrÀrï–Ùxv¤@y>6 |@È-ö zÉÀÁpZÏæ À9½§5˜@€\DZÞ7j@Y1_Žå±q@Òw7á€À€tñž2c@üDEƒõ@çŽßb`~$@ýÿ>šãBÀí_ª¦yù¨@ŸèuÝÿz@À;¨nä;@Ô¡˜;áhYÀç¯þËuI@“véD¥VgÀÄa‰Ž@5‚ƒh¥)p@¾ä;mQ@4€üÞ;}À)B úV¯@“¸RÐËb+@þGÇ’î!Aì¿o},:À%g9 Æt¡@KÁžªu@5ãn9@ÀM@/F¶ÆbðÀ`¡o&|ï‘@i[õ{8¢i@€f2¯Â;@þ`,B9¿ À×µ–üj®@{¨Ÿåj@´@1©ü­U$Á­oReSÀžØViàq@‚V¥Ýqz@x·_r–L@8ß±fjÀßÕsg ˆ@Ÿ/:© xÀ§«ÊE“–@x¢… /Ü_@Àk¸} A@XOG~€ÀèxÎaÍ­@“¸RÐËb+@¨ÁLYc®@Ž™å°@¢«I~Г@ªTH¨§ÀÂO §¨¥‘ÀÁŽý%ïÀßJ¹6SaÀ¢«I~Г@Ù“ló @ F¬\mÀó†*ñxÀ©,ëÔ›kÀtº:î΃Àa¿Š-gŠÁÀÆÜf^a¨À° o&h@ÞÙˆ¸JJ@Ðu—Œu§g@¯g%ÒQ@!ÕÀ$•ÀBjªq­SlÀ65ÝüŠXÊ@ÌZ/X&¬@>Ä$FT£À ;AF¯å2À€ÿH°À\’ä¯~vÀ0%Û´R`Àxêè^Ã:ºÀµû…¼oe@$¥b‹iG@7 ââØe@ÊL ø]¼O@ò)ÆS©€ÀºQðÁOhVÀÌZ/X&¬@YÃ[¡üäÀ@moWš,‘ÀâÉ¡æ™ÀvÀ/ìzÀP*E’–ðpÀéáÖÍßôÀ¶?Λ”ÁÂ@Cr/—Á„¶sG+?_À_yƒd@µà¥«Š[/@lÓÈwñ&v@«&‚?þ³ÀAm~w¢LQ@PmÀkÕ‰Ñ?zyþäc@#òÜoÉ À³`â忎À£Ád!üÐ>À|ºv|›’@ZÆÏ²_@´ÿ¸ž%lAÅ€0 Â@›x‡¢¹Ø@ŽùõU&@ O´Å` À&<´™ô@?ʯ¯gÍÄÀ¹TUÏBu@.€Ûm¦^L@>Ä$FT£ÀmoWš,‘ÀÌu½«°@ø Íç_p@i©/ªE/q@G‘HÎY@ o¹òͬ@ë*ºÛJ44@ÎÔ¡vªÀ_Âä­ãÙpÀNâLÚÄÀ¬4\\ÑòÀÙU¬ÿÌÀ¤¼é¬ÚmÀ°ãàÅœ0@¯ž§K®âù?§&‚?þ³@kÓÈwñ&v@fmÀkՉѿBm~w¢LQ@þ"òÜoÉ @{yþäc@ãÉOC<ÊBÀBÌxÍí#†À¯„‘¶ùæ]@T¿**@ŠHìF¤ÃÌ@ ¤yf£5@(ÃS_WD3@ O´Å` @ŽùõU&@?ʯ¯gÍÄ@&<´™ô@;êH<@0’þHPò? ;AF¯å2ÀâÉ¡æ™Àø Íç_p@}¼w´9š¢@‡J}À/@k·Ñ’¨@ŒDeïBfX@«.`Æœ@^¥ìdÀuÀÆã鿳;À¿ÿ3¬­ÖÀÕ’ý‘ºÀ>®Ž™çà@å “zÑ´@z¹î CÆÀÀ/Ü©]4•@ì$$•vʹÀƒö‡)Ú³Àå “zÑ´@µ²^ÙèfÑ@"h$ðã“@ªØjmÖÏÀG—)žbw@àáדÒt@]íCQçÀíBs'SÊ3@¡Á,šFeÀs¢BçéOÀªTH¨§À F¬\mÀ€ÿH°ÀvÀ/ìzÀi©/ªE/q@‡J}À/@ZöŸ# ´è@Ã$[9ë}Ž@‰Q©ˆáBˆ@É“k‘oj@¯L_ ’Ža@Õg»D_@!ý*F@(èÈ^çÀs¢BçéOÀØ9–qmï7ÀÂO §¨¥‘Àó†*ñxÀ\’ä¯~vÀP*E’–ðpÀG‘HÎY@k·Ñ’¨@Ã$[9ë}Ž@nÞÏÅášç@¶ðXCûr@àHíl=¸S@‘48¸C%–Àö‹F¯ÿx@Î/Ggf—@‡ñé Ô—{@ž"*¨ÀN+óÅÃ6ŽÀTѦO˜v§@pd×ÚX_@ö‹F¯ÿx@zP¶1ˆ×¢ÀA$ì×H@0ŽHÉGb@ªDt+~ëÀ³ŠHtÀpd×ÚX_@™ûä ”3¤@¢ûï}@Ðo9°3H@$^/¡S|@’¤B"b@{j]¬kPSÀºdñŸI2@Z$¨©Ù¥Àœq-Ö‡ÀÁŽý%ïÀ©,ëÔ›kÀ o¹òͬ@ŒDeïBfX@z¹î CÆÀ"h$ðã“@‰Q©ˆáBˆ@¶ðXCûr@®]I½îÍ@Ø“sÛÂ\‡Àò‘.úp¤À,`ñ¶bÀ¦ËF$@Ô¿\ëyð?ÓR\bN@ÓÚI•=è5@ºdñŸI2@T='¥jaÀœq-Ö‡Àì’ÎjÀßJ¹6SaÀtº:î΃Àë*ºÛJ44@«.`Æœ@À/Ü©]4•@ªØjmÖÏÀÉ“k‘oj@àHíl=¸S@Ø“sÛÂ\‡Àµä¿­²Ñ@…±¿åñ<ÀŸÓw ¬“Àh==M4Ác 9pEqÀŽ^ºÖWb@A»´½/–,@óxˆä‚@iÒîå\@¥#í Äÿ@ÎÔ¡vªÀ^¥ìdÀuÀò‘.úp¤À…±¿åñ<À®qœÄÖ½@mc¦”}O€@Ùrû:vÊÀP ç´ôR8Àºx .@®ô A5h÷?I|na [@À¬@Õʨ'@§÷›Ê@_Âä­ãÙpÀÆã鿳;À,`ñ¶bÀŸÓw ¬“Àmc¦”}O€@\g,’•R“@**¿öT@ÝI7»B@8 ÇEÛ‘u@"õrîÏ'eeÀû%ºb·µB@¶°àp1@"õrîÏBƒ×ðÿ@²× ¤´¹À@îR>þ ?çÀðPóÕ6¤‹@έ?cÉc@ÌF(¤@ò¯OnùºÀbþ ?çÀfî°0©«ÀÉkj4Žà@òN¢—èI­À’CÀ'¡ýáÀÅn9™ä@Y×À»à@Ãèd5C`ŒÀíHçp¥ü¢@m×з†ˆ@­á;^ŠùkÀëV4žZ@¸B+ Å„wÀ%Ö;)Ƥ’À|G©Ìkâ¢@4ågI!b @Þ„rÊùrÀi­£l±r@.«‚„•ÀÁÌjú@@þ²³Ÿ/@U’çQèxD@ÖÇi × 3@œ —UOŸ`ÀŒ‚lŒ …GÀg<›]çwD@ê¿èwÀéAßVï:@üâß êLÀ­á;^ŠùkÀ¥üºzh#’@Hÿ©·?“lÀ&Ì,y?‰@º›ùl÷U“@5ØJwœ®¶ÀÁj‘R:‹ÀG´¾‚æbƒ@Ý.(<ZƒÀÕIÝ"°Í¡@žnÖ•/@²¥&k@Zy!j 3@ç#òµ!@Ô_šmªˆGÀŠÄÓØ.ÕJÀÇñ1Ù0ùUÀd¯ˆΪ‰@V ¯XêLÀÀШR _@G F!>nÀÛ"ð>–Õ@2 p±éâ@Ë«tŠO@À?{ħOƵ@÷ñN'Œ…À½WruPĵÀa¤RR}j@³œèþ¼$€@[g,GïÀ IÁ¥Œ­qÀØñD±@÷ñN'Œ…À¸Psžæ§ö@@þÓEa||@Ñù.ÁxàÀWèj“Œ-ç?‘Ï. tVÀ#ðÂEz0ÀèO!(îÔo@½WruPĵÀ@þÓEa||@VNÔµ@\çµà•.ƒÀ;ëS*¯CXÀàK±‘Ç@Ww×âW/@F“a/¾Àa¤RR}j@Ñù.ÁxàÀ\çµà•.ƒÀ Æü§ŽÌÛ@® ÷¼@lØqDüœ…ÀöPak´Àïi¸á\%“@U~,ž‚VžÀqûþ~½­€ÀlØqDüœ…Àº"•ÐÇÂ@ïi¸á\%“@·XÈÑu~ÂÀqûþ~½­€Àö”ϰVbÀÈîÅAól@Hx}€Àñ'²@ÉSOd:@•jp‘Xd@)ŠA¢®‚ÀiúÊgNMÀÉSOd:À’ }_ÉÕ´ÀL&ó"^ž@R§vësýÀ?Ñ9rS-PÀwÉ+tdøQ@m^©NcÀß‹ Àoq@"M’·s¼‚Àû"1‚À NiÁ¥‰”@ÉSOd:@¢1mMù±@IÈlëWyÀÀ*Ê’D—@ÉSOd:ÀHbiÄ'À#>˜Ó’@0Ï÷ÊjÂÀã“à· )Õ¿ÏTèÔ%d@¡ê#b”afÀ%©©?Ü x@J&WÝe·…ÀúRÃU—@įO…€˜M@zLLÀ—Û`À•jp‘Xd@IÈlëWyÀô@¡E/“@è‚Nøû½…ÀÓ=±aöŸÀ¶ÀŽwhJ”@ñý.n^¡?OJ>i©‰0À‰X ˜xÀ¼C2 b@2Ù‘÷^2@KïYœÝ¼CÀBE¬œ€@NLã—ƒóù?‹ ³FÓQ@UÈïhe'cÀþ!£í,kÀ[*=C]õ~@)ŠA¢®‚ÀÀ*Ê’D—@è‚Nøû½…À±òè•!¬@ûs.™½{š@›ì~`ìÿ´À¹Fê¤å¿¿×÷æ^N@ ßà”Ædb@ éôÆ—Àa v`ÞPÀ4C8þ©b@¹Lã—ƒóù¿BE¬œ€@`’n^pÀ>ÛÁßj–@%qÄ3`ûÌ@*Шø¡» À‡`\oHÈÀ0ÞÊ3øè¡@¶ÍHc›CÀià ²cÕbÀ;æz ¹õœÀˆ𽣿*Шø¡» Àç›à¨ËØ@0ÞÊ3øè¡@³!ivòÖÀià ²cÕbÀDÆÆ“²‹DÀx½WÞš1õœÀNФÌÉÀ˜ 8ƒÚƒX@â„êaW“@Gºô7vTÀpvbîÉqÀ' K(0À‚µþ¼X@;½óI¤”ÀGºô7vTÀ€›ùj휗@í,}61À‹RÉ™ˆlÀöPak´Àïi¸á\%“@iúÊgNMÀÉSOd:Ày«éqhÅ@?õWÇ4ht@•.·õ=9±À´ ß병“À±#toéù‰@ ù_%mMl@:»aù^ÀÚÁƒš`†C@ëårŸ†§À3ÚC²s–ŠÀ®i%ý)@*·Ñ„s@ïi¸á\%“@·XÈÑu~ÂÀÉSOd:ÀHbiÄ'À?õWÇ4ht@ùÄÉ1`¾Ã@´ ß병“À¬aï;vÀC B¤;Pl@¥™OTÙN@ÚÁƒš`†C@ÿEgÀÑP*^壉À͉PŽÛúlÀK›b-Mžq@QúÛfFU@mmÁ°¾Ê@ãíóYÃŽ²@𮵢LË@D“=ÌøÐ@dN{¹8b§@·¯¶xOz@$¸­óm€µÀm—Ä EŸÀHϦåhØÀ%4ëÁ¨xÕÀ¢öEö‚j+ÀLó1?;c=@9½³FÁbÀãicÈ•@¤~™dÔ@•—-ééL¼@D“=ÌøÐ@suìþl¸á@SÌå†è@"W ’ˆ®@ÜJ¬_ ú£À¥o̤YÛŒÀ¨§µÈœâÀ*¾©à3_àÀKó1?;c=@O';€OÀ=>óÔ¼•@ôŒ@ Š?ÉÀ8âéÇðÑÀ?ái6Fz@qæ¾ÚüSu@ìò½¾?L/ÀëV4žZ@Hÿ©·?“lÀa–†ÚÚÉ@æ ú±V'‡À›ò¼0–h¹ÀC IÒóŸ@µÎK#t @¥´A±µ|qÀÁEi°tq@Kż¨1ÀyüQ!^p@€"ucL@¢8ûõÂ@ab£ôcj@)âõjÒC@†Ö%'wÀ¬iôá,:@rË0rÜÿKÀ^PwFr”@0*X§ÓÀåò½¾?L/@qæ¾ÚüSu@¸B+ Å„wÀ&Ì,y?‰@æ ú±V'‡À›¥RiýÝÍ@W®†ò˜@Ö¢ª uÉÀ†œ(ü#)ÀëååæŽ@5_Ï~¹ØŽÀEŸb“ü`¬@"ucLÀyüQ!^p@ü`b£ôcjÀ¢8ûõÂ@»ÎøKƒaÀÎÂITôt”@*ôW-² WÀ2UE?½h@H0pÒ°R@¨EKµÝQ@LpB¹°‚@Ç]9¼AóP@ ¸»6¦@[¸Ïÿ:p@%Ö;)Ƥ’Àº›ùl÷U“@dN{¹8b§@SÌå†è@›ò¼0–h¹ÀW®†ò˜@ +\Ô2ä@çjC£»À€ÄH«8²Àf-šŽ’@ñ:öÎÁŽáÀ£ÖÁÃf•Àò„ɧYü|@üæNþéåI@iÝD/uC™ÀdßnZG¼£@ç|r‹ígÀW"fgÔs@«EKµÝQÀH0pÒ°R@Ç]9¼AóPÀLpB¹°‚@Z¸Ïÿ:pÀ ¸»6¦@|G©Ìkâ¢@5ØJwœ®¶À·¯¶xOz@"W ’ˆ®@C IÒóŸ@Ö¢ª uÉÀçjC£»ÀèǽA'!ò@“6™vý}@¢<±ê\ÈÀÈ )Ý=Àõ5ðÖ¼¯áÀýæNþéåIÀñ„ɧYü|@M[£÷Æ>–@2". LÌÀ¯°ä4ò‚@6žËyUê”ÀopnBºZ¯À\ˆ ´ÕÛfÀ-5¥_aÑÀnÚ´¨ eÀ4ågI!b @Áj‘R:‹ÀµÎK#t @†œ(ü#)À€ÄH«8²À“6™vý}@i<ÛˆÆ\Ü@i’ô0MI@µÚ‰˜ðD#@»´ùüMºAÀtòÓ0\]¦À¤'WŸ¶LUÀ’ wDáõ?亮ÜŽ)ÀíižoÝÊì? 0@)‡èþ¿¢'P@šp5踫À¾/)r·-c@æj!0ôÐÀÞ„rÊùrÀG´¾‚æbƒ@¥´A±µ|qÀëååæŽ@f-šŽ’@¢<±ê\ÈÀi’ô0MI@ꡆO•Ý@~Ç~»g¯‡ÀИ1UÊ¥@4¥›OŽT@ÝIµKê(¦À¯à 'ääZÀcpAãCj@±îÁ²QÀÝr¯fèþb@i­£l±r@Ý.(<ZƒÀ$¸­óm€µÀÜJ¬_ ú£ÀÁEi°tq@5_Ï~¹ØŽÀñ:öÎÁŽáÀÈ )Ý=ÀµÚ‰˜ðD#@~Ç~»g¯‡ÀAcàã@ibQp{ÿ·@§áˆWŽØZ@ŒQ<Û[Àuò¿å©Q@EWâü1öbÀ.«‚„•ÀÕIÝ"°Í¡@m—Ä EŸÀ¥o̤YÛŒÀKż¨1ÀEŸb“ü`¬@£ÖÁÃf•Àõ5ðÖ¼¯áÀ»´ùüMºAÀИ1UÊ¥@ibQp{ÿ·@5êßÙB~×@ eÀ²xÀpñœ¼ Ù¬@ÒÔº $@pÀœÜq@¼ÆÊU®Q´@# \û&ožÀDJN©ýÓ@waÑn$sŽÀ:%¯¦ß½@ÚˆÂPDwÀÁŠÙ¼uÀÎF¸þë6†@?6]«m>@–* ËÖÕ[ÀCßSÀ"àÀ ¾¦Jø¦@ØO¾.€P@p­ã‚xîmÀ# \û&ožÀ±“[Æ™Ä@yaÑn$sŽ@DJN©ýÓ@؈ÂPDw@:%¯¦ß½@¦²}bI@É%¨n帡À£e‰²éHÀàu¾ª Òt@ï˽~" o@,O‘Ó[%âÀyOX`¯hÀhÍ2‡c†@PÂSÒù¶“À:5AjBœsÀU~,ž‚VžÀqûþ~½­€À‡`\oHÈÀ0ÞÊ3øè¡@•.·õ=9±À´ ß병“À†2¸·!á@\:öÓv¢@]š7p@Ö¸T´ÃÒT@_»ò$ÇÍÏÀ“(3˜–À¦ÀBÏÂ’­¥e@ç*býjG@©>À¼£p@S»ž3Y"R@­Ñí é@Gß²~4c@$Ž*žšsÀ" µ+¯ÉfÀqûþ~½­€Àö”ϰVbÀ0ÞÊ3øè¡@³!ivòÖÀ´ ß병“À¬aï;vÀ\:öÓv¢@úWoÿ>ÂÝ@IF%û ™Q@•ÊofS™6@Õ>õÖ¦¦À·Qò®Gó¸ÀU³¶¾3UG@Š42èH=)@MâŠ+pïQ@(Á׋3@P·ãG¹Oc@uZ¨-µD@ófÓÆgR@Tr"xi@86™DsZ@ôÁÖθ$@ck%£vn‘À¨øÒ2—‹@’ }_ÉÕ´À#>˜Ó’@Ó=±aöŸÀûs.™½{š@is$VhÂ@ªˆíž0¶À2B¾µƒhÀyî 0n¾^@žšZ¹·÷e@yª~òQ@"Dwšf¿8@¨Ë~qýVÀ¸ÕZß.@‘Õª9%u~@(Ô¸#+ýÀµTÓª±ª„@Ô7Øøh@–=Æ·$4À€Tr"xiÀófÓÆgR@€ôÁÖθ$À86™DsZ@]ïâ¸.µ@&ÒsÈ¿§ÀL&ó"^ž@0Ï÷ÊjÂÀ¶ÀŽwhJ”@›ì~`ìÿ´Àªˆíž0¶À‹|ÑÈÕ@=32@oïqùq7À»ἇHS@¸~¶í>@ϰô¦Q¹VÀ8v7(u@ÍAôÐö€@ )P‘ù„À¶¨¥-SŒ@s‰_ëõΫÀ-D€¢ŒÅ(À”₯`¤E@ÕñLàI{ ÀW¼Â;åôR@cÉUÒš”²ÀÚíîp½c@üUŒ4ж¨?ÄÇ"Óˆ'¼¿R§vësýÀ?ã“à· )Õ¿ñý.n^¡?¹Fê¤å¿¿2B¾µƒhÀ=32@öŸ:"Ò’»@üdHÊ GoÀ‰BÑ–}®Ž?ðZå­n{ ¿þ¬¸±1Å­?Ø%Â;ý¿¿Ð=›‚…U@³ÏÛ ѦÀµ‰×åN³f@žkó~ê ¹Àßž¾ˆ7Àµ]‡¤ÎJ@Ñ9rS-PÀÏTèÔ%d@OJ>i©‰0À×÷æ^N@yî 0n¾^@oïqùq7ÀüdHÊ GoÀ ´v‚ £Â@¿Y¤6À¬B&D c/@·–÷‚X<À‚ˆ¦]uN@i¶CǪ@ðPóÕ6¤‹@ÎþàC"äÀòN¢—èI­ÀpZ­P?ALïó¡Jij@ÓÄ÷Åþ¼>Áùn9™ä@`°%ÀË*ƒ@έ?cÉc@Tx¯&Ú´œ@’CÀ'¡ýáÀLïó¡Jij@ÖòçöK?AAg€­´Ë¤Àùa’ÍÓ¼>ÁKJØ(ô}Ï@å˹lpØ¥Àó!Û'rþ¨ÀÀѼGà”l”ÄÀæË¹lpØ¥@EýJÌ“r¤À®ÖnȰê‡@ªsŠ&4Wû?wÄd3[)ÀˆîL®bh@W‘ ?w„À5u‚Fè Q@ºÄðáô [À¥-O6¨ìBÀ§¢“š¹Á@å˹lpØ¥À>º9èj×@ÀѼó!Û'rþ¨ÀæË¹lpØ¥@Sæn$öÑÀãl’û|Ò”@²¬¨Î/¸ÀÓX)¾,À×øê"‰c0@—3;ƒ–ŽÀ»Þ¯‘ ¬©@Œ…âwívÀîd‘ÕT@ÓX)¾,@¦¾’JÀý ®;^@ôNàæ­K¶@É®æ´`v@9ÌìÔóþ?4Ÿkh›@±Î&á!«AÀWBdÕ9·À÷eÆ¢â?\&UKUeÀò„ɧYü|@ýæNþéåIÀtòÓ0\]¦À4¥›OŽT@ó!Û'rþ¨ÀÀѼP ­@ @b†2ç@\h4éq@Ž(Ž®¨ @7Ý´ãrŽƒÀ½(óü~(BÀn¬¡É9è?Ö™1…DfÀÙ¬™-¦¹G@ #ú0‘}ìÀOÌìÔóþ¿žÉ®æ´`v@¯Î&á!«A@4Ÿkh›@/¼ý€¾í@¡å!~«ÝÀ“¡üŽG@üæNþéåI@ñ„ɧYü|@¤'WŸ¶LUÀÝIµKê(¦ÀÀѼó!Û'rþ¨À @b†2ç@a üÚW­@hïî¡6A@/ÔԫʃÚ?ñ£è¹QÀ„¾'FÀ‡IJÀÛ ª @?O@Gà”l”ÄÀæË¹lpØ¥@‹$‰6h Å@¢8bªñ¾ªÀ­¥ZƒJyÀ<Ò;RŒ#…@?¥dž]F@£ãà)VÉ@`ûfIfÀÇDºÜJJÀæË¹lpØ¥@Sæn$öÑÀ¢8bªñ¾ªÀ×>ž\M&Ó@Ò»Îôæ#…@M—C®d«‘À0$9.•<@Ç_J×ý?#Ю[tSÀ‹xu`ÞUÀdkžpýR@f‘Þ òíE@EýJÌ“r¤Àãl’û|Ò”@Øx1_Rb´@ Bnªß¹ÀýcÖ•ÀþïHø®±@OvÆ"”Àã]íU)€†@ÝšŠé°;H@Ö|²÷û;@®ÖnȰê‡@²¬¨Î/¸À Bnªß¹ÀLjº?G×@!ñ»…ΰ@‰çV6ÌÀyËpÎÑŠ—@á–ƒã<©ÀòŠQ›»9Ø¿…ëÎÓ3 -@E6Ýo†tÀ‡šäS]ZÀžšZ¹·÷e@»ἇHS@²z-† c@És³Ð+@…ëÎÓ3 -@iƒ}l‚ÀbÜûµXÀåÍ g\ _Àyª~òQ@¸~¶í>@És³Ð+@#/0­Ð…@URöëóÇÀ]—µÀ^{M@¬ZÍöñÎ@< •O:À"ïnbžÊ@ˆï`ëý?ª'íƒ/g(À¼¦q–– %@¿îH’§NÀñEØð?tCßÓ ÀÓÄh#Å@<§/µ')Àîé®ìB@F4ˆýk1ÀÓ8’?tü?Ø·—Zú$Àú?³WгjÀ‡±ˆÅ„"@]š7p@IF%û ™Q@ªsŠ&4Wû?ÓX)¾,Àö^Y w1m@ìWN°‚:À#©<ÔqÀ ¼‹õ«SÀ˜“ö1GÀ¸Ò<}X!u@˜.»®SåVÀ±Ï•ªB9À¸zbÉÊ3¥¿I€W¦%GÀ-;0 %@ÚÁÅE@Àªb^6Ã6 ÀB1¿~õ5@ÁÌjú@@žnÖ•/@x º~˜7‡@jY,Ë"3a@*aD`Î#@5TÒâ]#AÀÅUÂY†J@«h- ê8@«´ÿ[)qÀƒÀêïŸó_Àò;¦qŽtÀûár(GÀ+ IÔËBf@†Úõ¥ÿ²¿@‘ÒsæyÀúÒ M1>@þ²³Ÿ/@²¥&k@jY,Ë"3a@É]ûì¿ö@ {5ÀJÑlR@= â´8@¸OP¶‹ù&@­Òek´ô_À¼{ÀMÀÁÕ~—P-GÀû‚?å‘YoÀ~Ûõ¥ÿ²?* IÔËBf@ØÝê1@‚ï) å?Æ,™@8¡À¶m/˜À2=¦ó>8@U‹°ØÖSq@z•l6© Ò¿‚xàfÉä@RÞA#ˆfÌÀC’BÜ”àÀ›Â¬Ï@¦&Ý»\´@:Q·"¬}À¡ÏQ?Ô4·À*,8Ù 'ŒÀx(3HŸ|g@S@!|²K6@bÛ{WÑDq@—þ|ÁÂP@ÙFctÀ—EV½8ãYÀ$þ%yª´·À‡?UÛ ?@$>;ìñ@ùeo½¡À9•l6© Ò?U‹°ØÖSq@RÞA#ˆfÌÀ›õaí~ó@jj•áFÍ@P·]“3¼ñÀ6Q·"¬}@¦&Ý»\´@ã7Æ=á’À•eamÎú¯ÀS@!|²K6Àx(3HŸ|g@–þ|ÁÂPÀbÛ{WÑDq@ùþbzZÀÒ$ÍÓr¦„À³mÀ£¤@ÀWõ=­·ÀeZ>Ÿo&—@»êæPïô\@Y×À»à@Ån9™ä@:%¯¦ß½@؈ÂPDw@ÓÄ÷Åþ¼>ÁAg€­´Ë¤Àñà˜À¢ŒqÄkÂÀ×Pƒû ©>A+Ü ë"ß©ÀPHX‰)¬âÀÆÛÝf脦Àùzï M+Ü@ôÉÆÏ݈£@΃7ηá¢@ ±‡âáñh@›ê•« áÜÀÑ¡²®œBÆ@Åx¼8bÀwzìÚ‡:@»êæPïô\ÀeZ>Ÿo&—@Æn9™äÀY×À»à@ÚˆÂPDwÀ:%¯¦ß½@ùn9™ä@ùa’ÍÓ¼>Á€p'w´ÀÓCáà@+Ü ë"ß©À›¬2áÄ>AGb™Ž«z¥@‡«ôZQCáÀõÉÆÏ݈£Àùzï M+Ü@ ±‡âáñhÀ΃7ηá¢@BE0/- ¾@ÏØ Ó¢ðÀ³{Ü™q:@W¼Zè¼À{­?òzé@£+„jµ@ Ï0î-;˜@MÙó$‹bc@íK˜n÷š@[ùAºB@&©×Àh}[kÌoÀPHX‰)¬âÀGb™Ž«z¥@Ó¯¢câd'Aã6Rˆ<_à@s&†v9&ÁDE¼Ô^äÀH«wq°ÞÀ·¯€Q_@§¶ß©,¦¶@ýÐÊ%*ƒ@\ªÊÉác@ÇC4C©Ï/@ŽØ™¾Z f@&Ç È0’ @èc?Û{ÀAÊòBO‡ÓÀÆÛÝf脦À‡«ôZQCáÀã6Rˆ<_à@UDRý#SA …@y“åáÀRC[À™Á U0 `Ês@˜“êöMàÀšr᪖À‹ •àÊg@r”ÿ^sA@5—ÆžO]"ÀyüQ!^p@"ucLÀ5u‚Fè Q@Œ…âwívÀOvÆ"”ÀyËpÎÑŠ—@³m»z„#s@¼¸TÀ)üíÿ)‘@ÿ­çÑMLÀc9ˆ*ây@RÒBS,hÀ“ý[R¼tÀd‘“þy•À5—ÆžO]"@r”ÿ^sA@€"ucL@yüQ!^p@ºÄðáô [Àîd‘ÕT@ã]íU)€†@á–ƒã<©ÀO™“Qáþ}À>å?Æ,™@ÿ­çÑMLÀFbµD½‘@RÒBS,h@c9ˆ*ây@¾r[1cóÀŽzѽÀ´4-Ù*Î@Êü#©‡`Àùzï M+Ü@õÉÆÏ݈£Às&†v9&Á …@y“åáÀ‡§ˆtÁ‚&A~®ÖI’Ìæ@3òsõïØ@Ñ€ 1fZÀQZ¶9î¾ÀÞÿlôÑqÃÀÆü#©‡`@µ4-Ù*Î@ôÉÆÏ݈£@ùzï M+Ü@DE¼Ô^äÀRC[À™Á~®ÖI’Ìæ@•e@É{AØ€ 1fZ@3òsõïØ@ßWÄÓœzt@S¨Ç9[W“Àù¢†ÀÌF(¤@]S õ—Jm@Ãèd5C`ŒÀÉ\Þ.Hd@Lq€\${ÀO*°fÙg‹À¼™4oâ©@ê²ÊO¼Iž@ò¯OnùºÀ`®¬øp™ƒÀíHçp¥ü¢@Lq€\${Àê‡lE)’@C’BÜ”àÀjj•áFÍ@`9¥ôÅLã@<½4„ŠãÍÀ¿ÿä©?þ¹ÀAQW‰¼Î{@¥é› 0ƒ@¶¾¿KõJ`Àá7*µÌ}@ÜѸ\*(@›Â¬Ï@P·]“3¼ñÀ<½4„ŠãÍÀå¯q]öò@^bý$ {…ÀüÒ—w§ø)@ÒC/ZÄ£t@Ëáï¬Û¹M@å¥Рâu@Å«·»À*,8Ù 'ŒÀ•eamÎú¯Àg³áÉPyƒ@«x`FÚÆÄ@?—w§ø)À›Ÿ\*›Ýk@Êáï¬Û¹MÀÒC/ZÄ£t@ðE›ƒFõÀ5Ì£ÇÔÀ,ƒÐíÌc@ú†±(ÎÝ?¹0ßq_òLÀ,lP i(ÀpvbîÉqÀí,}61Àx(3HŸ|g@S@!|²K6À›Ÿ\*›Ýk@?—w§ø)À†¿mp r@S>ü -M@ ÀuŽM@w½9?”~@Û‰}?MÀYJ‚¨ˆZ€À"‡±(ÎÝ¿,ƒÐíÌc@²œ_®ÔS(À”AÖ_¤­BÀ' K(0À‹RÉ™ˆlÀS@!|²K6@x(3HŸ|g@>—w§ø)@›Ÿ\*›Ýk@S>ü -M@Ñ0a$d@x½9?”~À ÀuŽM@_»ò$ÇÍÏÀÕ>õÖ¦¦À#©<ÔqÀ˜.»®SåVÀði…4.Ð@t†ß‡ó]§@“(3˜–À¦À·Qò®Gó¸À ¼‹õ«SÀ±Ï•ªB9Àt†ß‡ó]§@`ÆJ:¤ ¹@ŽpE3Rà@”¦ÁëWAr@ÁŠÙ¼uÀ¦²}bI@ž<=¥CW´@¼:žaРÀ'a!GeˆÀùÄ2ª²@Úaîd(ŒU@k@_qoÀHdF_}´ÀÅÿݲŽ@–GÉRn›r@êÑÁ$© T@ÎF¸þë6†@É%¨n帡À¼:žaРÀ“ºšvFÚË@"ÛïƒìøF@»ÀII·Ê¥ÀcQÝpÀ¾ÇJ¥·„‡@OؾÅ/.•@—Ɔ¯TÃÀzï0 k–Àqk´yv=cÀ†™S7œÁ—À‡Jýa«´bÀ‡#1WØz”@¿òD;âÀ?6]«m>@£e‰²éHÀ΃7ηá¢@ ±‡âáñhÀH«wq°ÞÀ U0 `Ês@3òsõïØ@Ø€ 1fZ@'a!GeˆÀ"ÛïƒìøF@*%S*þ¶@îCöiBVS@7èæF~­$@,‹BFÁBÀqk´yv=cÀjë–”7ƒ0À‡Jýa«´bÀÒ†56u-À$¿òD;â@†#1WØz”@–* ËÖÕ[Ààu¾ª Òt@ ±‡âáñh@΃7ηá¢@·¯€Q_@˜“êöMàÀÑ€ 1fZÀ3òsõïØ@ùÄ2ª²@»ÀII·Ê¥ÀîCöiBVS@>-|dм³@K}¡n|À]›€zÉ™@CßSÀ"àÀï˽~" o@¨¼\aAâÁ?ªNãïͦÀ›ê•« áÜÀBE0/- ¾@Úaîd(ŒU@cQÝpÀTHšQ<³An9*4³À ¾¦Jø¦@,O‘Ó[%âÀÏÌ^âÕèÁÀkÇ™2qÁÑ¡²®œBÆ@ÏØ Ó¢ðÀk@_qoÀ¾ÇJ¥·„‡@n9*4³À+¬Lˆ8šA‰X ˜xÀ ßà”Ædb@±#toéù‰@C B¤;Pl@"Dwšf¿8@ϰô¦Q¹VÀ4ƒbP:a¯@Æ‹³Ä!q@Îàg¿.÷´À$J(ØõÀ.:¼Ö”v—@9€¤ù:U|@¼C2 b@ éôÆ—À ù_%mMl@¥™OTÙN@¨Ë~qýVÀ8v7(u@Æ‹³Ä!q@.JA„î¨@n?uúÏŽÀ˜¢*þk À¢mõ{y@hçäüÅÞ^@‹±7ÐCÁ^>`ÏÀm‘CWd”@ jÏÁVÀHϦåhØÀ¨§µÈœâÀ¢8ûõÂ@ü`b£ôcjÀc9ˆ*ây@RÒBS,h@ööZÙA¼žUÈšê@†“PÓ½ßÀ‰ßrfúÓ÷À jÏÁV@m‘CWd”@%4ëÁ¨xÕÀ*¾©à3_àÀab£ôcj@¢8ûõÂ@RÒBS,hÀc9ˆ*ây@¼žUÈšê@Ãþ’wæý@VôªóÕ#:@ã4ܤ^ÇMÀwÉ+tdøQ@¡ê#b”afÀ2Ù‘÷^2@a v`ÞPÀ¸ÕZß.@ÍAôÐö€@‰BÑ–}®Ž?¿Y¤6À*aD`Î#@ {5Àæ50–Vl@Ë>žµ@kÀUƒÍ‡qÀdÉHÿ¯ÀUÀVú]Ö¹hUÀpžD9X@íä UµLÀÔ‡dŒþ_@m^©NcÀ%©©?Ü x@KïYœÝ¼CÀ4C8þ©b@‘Õª9%u~@ )P‘ù„ÀðZå­n{ ¿¬B&D c/@5TÒâ]#AÀJÑlR@Ë>žµ@kÀå6«e>¨î‰À±kuVEÀhÇ]"Ù`@—EV½8ãYÀÒ$ÍÓr¦„À SÇkoC@¨ÓÙ‹¶.•@•×û™žZ@Xã–. ð¿VõÑãÀsÀRÒwðzkEÀ˜“ö1GÀ¸zbÉÊ3¥¿ãÑ‘O\&p@v!æèðàE@`ã–. ð?–×û™žZ@1:]òaFÀÐRæ8,ømÀ¸Òi@kA\zñw>@?€«_,@Áã ÷GQ@yÊ©±½@@Œ‚lŒ …GÀŠÄÓØ.ÕJÀƒÀêïŸó_À¼{ÀMÀ<˜Ý!¿_RÀîvìø[ÀdÓ°™ü>i@¨Òö•i@Xˆ­”Ö`,@0UVîZm@`„¤ @@b ²èð-@$þ%yª´·À³mÀ£¤@Àá7*µÌ}@àѸ\*(À¤ñ‰¹q¹ªÀ{u}?;‹e@'GüTW~@%î¡Ï ]À‚G¤Ê†©À@ÏA±ìö@‡?UÛ ?@Wõ=­·ÀÜѸ\*(@à7*µÌ}@:÷³»JdÀ[\¹æ «À%î¡Ï ]@'GüTW~@ÏA±ìö@è9©ðÀ@g<›]çwD@Çñ1Ù0ùUÀ9½³FÁbÀ=>óÔ¼•@)âõjÒC@»ÎøKƒaÀiÝD/uC™ÀM[£÷Æ>–@’ wDáõ?¯à 'ääZÀ§áˆWŽØZ@ eÀ²xÀ¨Aw¢'~˜@^¢tÒŠ ÀÅŠdˆ$@c’B·Ú‡5Àê¿èwÀd¯ˆΪ‰@ãicÈ•@ôŒ@ Š?ÉÀ†Ö%'wÀÎÂITôt”@dßnZG¼£@2". LÌÀ亮ÜŽ)ÀcpAãCj@ŒQ<Û[Àpñœ¼ Ù¬@^¢tÒŠ Àv.#°ýÓ@4ã [ªmWÀWYi„j&i@ðX1·N@e‡Âv%@@`ûfIfÀ#Ю[tSÀyä bRpÀMLÉZ;CÀ n=w@¢[U@f‡Âv%@ÀðX1·N@ÇDºÜJJÀ‹xu`ÞUÀ¥t ¯”—Ù?¦dÜA.ÈdÀ¢[U@zý (1Wh@‹p" $¦—À‹¾í[xq@¨Æoë@Ä6 o"%k@€¦üÓsÀ‰üS× ¿U@Ü\©à‘÷©@9'f±ÀÛÁ+´îuªÀÆv‘ß &iÀ€l«#‹@p¸Qûg@œÿN•êy@VÀïH ²ÀÄ6 o"%kÀ¨Æoë@åþõŠñb@DuÐÄp–À9'f±ÀÛÆ†"Ã@¤bày@B®×*# ¶Àp¸QûgÀ€l«#‹@É›"gùÀ«4å:A˜†ífyàÁòª&RzÀJ£Š¼Ëž@zt`ÏÙ‚$À°¹âOÐ8ƒ@'Ü©¡0@AF÷_Ó™{@å0†úw}GÀ0½µ‚¬ÀY\‰…‘ÜC@žªOðù@3[è¤NÃÀ3[è¤NÃ@ÙÉ­!ñúIÁÙÍò$òaHAgŽFó®ÿ°@‡t`ÏÙ‚$@J£Š¼Ëž@)Ü©¡0À°¹âOÐ8ƒ@å0†úw}G@AF÷_Ó™{@mÿo¢MDÀ·Cr¬À3[è¤NÃÀkÀíÝ A§ÿ8R”ö@…ÓÂ®Ž»À|/1Gµy\Á‰ófRC@2AFÏ*¤çé@ãQ3+œ+ÀfvNÅ dÀç˜a FÎB@yäî @ÔD¬%&Àà˜\«n9@¬œÂ&câ)ÀL-‰\Aö©wÄ$2ÁˆÓÂ®Ž»@¦ÿ8R”ö@û Ó5 2A«ÐµcÁ¥pú;*ÀM,LPDDE@Π t—÷A@mêé‹ß‡pÀƒ¯†V’ä$À•S~®A@O¼žÂ_þ(ÀNn±ìûïC@ö©wÄ$2ÁfÓbAÅx¼8bÀ³{Ü™q:@Þ?í?”Í@GÓîå+NÀųy¢hÝÀ²Ú”7ó»§À¸Aøç…Í@oúÙR @wzìÚ‡:@W¼Zè¼ÀGÓîå+NÀµÚ,ZzÍ@ñn{{å@ögïnFÖÀoúÙR À¹Aøç…Í@õÊà“Ò¢@míÑ;=@ųy¢hÝÀñn{{å@ÌÓãÿ ú@µQvT“Ž@š`}yMóÀ¦‹GS ÀQíÑ;=ÀõÊà“Ò¢@²Ú”7ó»§ÀögïnFÖÀµQvT“Ž@µ-EŠVHø@ 7x8,Q @6;D;MóÀk¤hc×5@[%ýñVLÀ%žÛG¶0r@ /*ŽPÀ‘¡`Åø€@•Áë&H_Àâ¨?¡•ÀAƒÍã“Þs@]­2Ÿ@çdl+†ÀGÍQ~‹¿–À'œÞJ„@0‹ƒ–``ÀÍÜdWëÊt@ /*ŽP@&žÛG¶0r@•Áë&H_@’¡`Åø€@ÞÍLR‚€'@’îeÑ3žÀçdl+†ÀˆXjþËZµ@çh÷'„@ÍÄ4«aZ²À\¯ÿ›´ÌqÀy7ÿ¬À“¨ dNO@`ÐöÖOòC@èÙõKúaV@œŽäŠL@YïÞèÝÊ9@yM1ÚRÀGÍQ~‹¿–Àçh÷'„@Þžhúj˜@˜[ D˜„À:¹¾bð›Y@“Ê\DÒJÀ ë4² 8@Þš)à¾.@_”mô@A@Ì÷@mÿ5@YYæ£~ìbÀJä1sé©{@'œÞJ„@ÍÄ4«aZ²À˜[ D˜„À°iS­!£²@¼Â?ôM¾Àfˆ/ZIùgÀ8]EhÇ›À"p¹ÂÞbÀx£”óߨ›@Ï×…(­R @x£”óߨ›@Ï×…(­R @îÍM1*@ŠGÈ#55ÀÝù”½á¢,@äkW÷BÀ®µw"Y ŸÀÂd{Ö¹d@©á9„âwk@Å^¹B»õ©?3Qg'%@›Á‰|‰<À£lWtoú@cŸ Æ^³,À–|¹]±%@]ˆ×ùÌ}ÀñÌN©y@Ó‡iü[L¡¿7ŽD*»r@±O{òžºÕ?Ý"‘»þ’pÀK(‡ÂµeÀYN¿%Û[@ z{Û@Ì]œÿóÀ+ ðÜœóÚÀQð.pq ó@BE¬œ€@¹Lã—ƒóù¿ëårŸ†§ÀÑP*^壉ÀÎàg¿.÷´Àn?uúÏŽÀN?TòbéË@ egÏT¨@Îë ,¹À¬k;mÇ”ÀNLã—ƒóù?BE¬œ€@3ÚC²s–ŠÀ͉PŽÛúlÀ$J(ØõÀ˜¢*þk À egÏT¨@ò™Î·|°@é°Àéfœ“Àai§ Áã¢À¶ÍHc›CÀià ²cÕbÀ®i%ý)@K›b-Mžq@.:¼Ö”v—@¢mõ{y@Îë ,¹Àé°Àéfœ“ÀCuoØol±@Âs©-W†@ià ²cÕbÀDÆÆ“²‹DÀ*·Ñ„s@QúÛfFU@9€¤ù:U|@hçäüÅÞ^@¬k;mÇ”Àai§ Áã¢ÀÂs©-W†@5jUêm”¡@ò;¦qŽtÀÁÕ~—P-GÀkA\zñw>@Xˆ­”Ö`,@HÈ;Û]¨@ñ·ïpà|À´¬ týg¦À —SS…}@ÒÙ¼áîG@Z—‘ÈC6@ûár(GÀû‚?å‘YoÀ?€«_,@0UVîZm@ñ·ïpà|Ànª5¼q®@Ï£„Èç}}@×§ÍðÞ¬À¦Tw¢I6@^0Hç»$@éAßVï:@V ¯XêLÀ¬iôá,:@*ôW-² WÀç|r‹ígÀ¯°ä4ò‚@íižoÝÊì?±îÁ²QÀuò¿å©Q@ÒÔº $@pÀ+ IÔËBf@~Ûõ¥ÿ²?ÅŠdˆ$@4ã [ªmWÀ´¬ týg¦ÀÏ£„Èç}}@d+ k@÷¢ˆ^j¥A@­eD!p@ˆx#ûEµÀT¦•(Ö`ÀÇlóµ¢@Ú;4ñÄq@ &ÐiC@)ÿL š–@Âè”ãèeÀ%eàéÖxÀìb# ÈÇS@¢–<øT@ÈÖ¾ê‡Ày^QbŒI@s¿-_k‚ @5˜Y¦âM@âƒ<|o#@WÿG4©A@°\ÇŽh*_ÕÀ+?Ú€¡_cÀÚ$•~»­MÀÄl ÁsrFÀ›—P9>9†@kF€ÝÀ_@ÐÙUaÀWu4¶É6À%dg{?FÀ¿®4 1ÀÑuy3zEj@kF€ÝÀ_@&‰ o¥!q@y¹~Ì¡TÀnncºÊ1}ÀyˆJ§ ïU@%öíTÍ@@%eàéÖxÀÄl ÁsrF@ÐÙUaÀy¹~Ì¡TÀTé 9ͱŠ@Ëj!2.@nbæAÀ˜gøÜ.j@jc1ª‰FÀÐE.fAq@âj¬)¾2@ñì„`¶@ìb# ÈÇS@s¨úà–ÀWu4¶É6ÀnncºÊ1}ÀËj!2.@¿É8•w…–@†ä ƒw1³À‚\£ÖhDÀ‘6úY…ž@b¸²ÀbhÀ7¯²€@(´I>h%ý?­3ÂW-OÇÀ <ý-)GÀ|]Ò$ª@{öŠÔçîÀ4yÑ6*x@ ~Ê YLÀ«Ú7oéÀÉìȶ¢¤À?O Ü÷“@´äNF~*@+{5‡â@ƒ{øû§@%xSêþ£‹À°FâNÒ@27âO<@툲ÕýŒj@åÃÓ}>h@ÇRjK–@â³I>h%ý¿7¯²€@ÚcÄž Àןœ4‡¾ÀzöŠÔçî@|]Ò$ª@Ÿ~Ê YL@4yÑ6*x@lDC›mÿ“À$,òTOãÀ½äNF~*À?O Ü÷“@ƒ{øû§@éz|/j¡Ô@Ò_Ùê,&·ÀÄŸ¾¥Q¬xÀãí`/2†@·üÆwTTf@ÛÁ+´îuªÀ¤bày@ÇÝ%É@"ylö”ÔjÀã"Oذ°ÀfMBr=@±Œ æ¨%aÀs…”­¸C@‘› ({hP@$§ÊºL…´Àf®åëÍb@‡KfVêB@õMꟹOÀD1¶ó•}@Æv‘ß &iÀB®×*# ¶À"ylö”ÔjÀw~e‘e|Ì@“¢£›¸y@ífòût´ÀVh*Ã.nÀǼ5Øz“@Bøy«Íið¿€l«#‹@p¸QûgÀã"Oذ°À“¢£›¸y@-h ïE¾¢@‡c6¬×jÀ­R¸(í«¿üð¦Š)nÀ‹øy«Íið?5Øz“@p¸Qûg@€l«#‹@fMBr=@ífòût´À‡c6¬×jÀc‘,iFª@+ÛcØ(î @F”i¨@Œà¸—r"ÀÅfm¶éc@ËHw×.ØÍ@xúQñEƒÀÝ«ÊÕ[ªÕÀêè/DY‚@· ÖG6‹²@Bgѳ=cÀêE”i¨À+ÛcØ(î @Bgѳ=c@ŒAá…ŤÀxúQñEƒ@ÌHw×.ØÍ@1뽇î‚ÀO>Žh*_ÕÀBgѳ=cÀ¸”ö ‹¼@` „@Ñ‹˜ü±&QÀüËõRÀÀF¥ØÑH°^À*oÑ„­ €@Ðõë®§Nâ¿)xòÿâë´ÀÇ¡S®áÀGÂí‡È@m­ÜNÙ‡@Ñ‹˜ü±&Q@` „@:°æBpÀsiŠðɳ¹À½õë®§Nâ?*oÑ„­ €@Ç¡S®áÀ¼Œ|‘NÀm­ÜNÙ‡@è ‚Lzvµ@bK· »Ah•„í  Ï@„8TD!»äÀ¶)MGr¢©ÀQüÁk™<Û@¶)MGr¢©@MÚÈω!AÏM¾U ß@€y Æ&Áp#r ¸çÀh•„í  Ï@j;\° –@ܲ)*]ïÀ5¡#êÀšÕÀŒ"çÁ ]ï@„ p§Á„½@ÏM¾U ß@áÅ{Ì Añ»}¦¸çÀ“¶™õjÁAK„zÇ@2v‹ŠñÇ@?— ¼üê2Áã0 ·ŒÁ‚a äH ã@]º¬KƱ@£+3'+SA¶ï(ìˆBô@{ §ŽÊÝ@¹¸ §Wɪ@iæ÷álÅAƒ•‡rºðÓ@€y Æ&Áñ»}¦¸çÀ8Ǩî3AaÝr´Äó@ß`$ÓâT@†ëâU¨@'óËiVöÀ5ö¬õ mÁ‰|'ON«@˜’E—غx@“Û9žá@,öi 0¼@ÆJ&±Ï†¤@_õÀ¼£p@MâŠ+pïQ@ßz,[ž”@³#^a@Öëˆ×Z}Õ@/Äù wz@ÙR_3ô½ÐÀŒ6ÖkIÀÑmBA˜ƒ @‰º…Rî¸@UN5þ°“À»®Þžõd¬ÀS»ž3Y"R@(Á׋3@d´d5a@çý©R]B@/Äù wz@ÙøYXÅÔ@ÂcÚXI@øxñŒÒ½ÐÀÏ”žQÿ@)Å‘pPc@IôGƒS£@Ü:‚áfIÀ;æz ¹õœÀx½ÙR_3ô½ÐÀÂcÚXI@´ŽÓí"Ð@8B®È³?Ù:‚áfI@IôGƒS£@ˆ𽣿WÞš1õœÀŒ6ÖkIÀøxñŒÒ½ÐÀ8B®È³?¬¤  #Ð@›5È^ÕÀ6ÚËè`…°À­Ñí é@P·ãG¹Oc@²i“ÃÜ{•@*êwD=w@ÑmBA˜ƒ @Ï”žQÿ@^‰eÕNgÑ@m{‡^n¨@àC\wÕx°ÀÃK”LŒ„¼ÀGß²~4c@uZ¨-µD@ë}r“Jw@ž¶g”ðX@‰º…Rî¸@)Å‘pPc@m{‡^n¨@¸‰œoµ\»@]5…@š”^n@@·Ú°:QÀê=^+p‡hÀx>'eeÀa;²;ÙêSÀš”^n@|^|ãnNq@ÌÊ£]Y@ÄLÆ$ðälÀß‹ Àoq@J&WÝe·…À‹ ³FÓQ@`’n^pÀ(Ô¸#+ýÀ¶¨¥-SŒ@þ¬¸±1Å­?·–÷‚X<ÀUƒÍ‡qÀ½C…1SÀâ‰bÞ0›@ŸcÚ×Ôy@²sÊ@ðò¡=";Àì©OAkÀ©¶/ÛÁßj–@µTÓª±ª„@s‰_ëõΫÀØ%Â;ý¿¿‚ˆ¦]uN@dÉHÿ¯ÀUÀ0)PzžcÀŸcÚ×Ôy@Ñ×aU@Iê¯0À—È^'M@Ô7Øøh@-D€¢ŒÅ(À@‘ÒsæyÀØÝê1@Vú]Ö¹hUÀ+/q\føV@Áã ÷GQ@`„¤ @@ÒÙ¼áîG@¦Tw¢I6@²sÊ@Iê¯0Àý¨Û:Œw@m?ÆVÇ`À–=Æ·$4À”₯`¤E@úÒ M1>@‚ï) 'wª©ø@ç0†8²;‡À`ò¿пãÀ"J–¥s™ÀÆC±ÄQÆ@–‹{fòÏ@’ÒATÐAƒ@ˆŠt¬s•@i/¦cÇÊaÀ2èæÛÊÃÀŠ6øD*†ÀŽo¨V·ÇÀÖØ"—yó?¸æ+|¼È"Àn¬¡É9è?‡IJÀVlc‡£ö?U™¦ùú,ÀÏýÖºƒ‘æÀç0†8²;‡ÀtO ñ”ã@bô¹ì‘@×s#BÀmI=ºàöÀ‘ÒATÐAƒÀ–‹{fòÏ@i/¦cÇÊa@ˆŠt¬s•@cð¬|€À±Ù³OŸ¨À|HÇváâ÷@áÄði*#Àl¹á£9ëR@Ö™1…DfÀÛ ª @?O@_O\Í&À-ñ/`/0]@Æýÿû"QWÀ`ò¿пãÀbô¹ì‘@O ˆ³m˜Ù@=M]o‡§ÁÛõ7Us‘±Ñãõ9Oew‰•¡¿Ýçñû/Yk}§Ñé-a•¶ê(2FZ€¦°ºÌÞô 6b ¨°¼ÈÒÜäìö,Xn„оì&8Phr|¢Èâü  6 X l € Š ” ® È Ý ò  : X v ’ ® º Æ Ø ê þ  J ‚ ’ ¢ ´ Æ ö & : N R V h z ¦ ¸ Ê ê   D j ˆ ¦ ² ¾ Î Þ ö ,:JZjzŒž¦®¼ÊÒÚâê,n¬ê6‚Ò"nºî"8NTZ¢ê8†¾ö2ntzÄZ¦ì2zÂb ÞüHvÀ N’¨¾Òæ<^¨òn¾ÜúBd†’ž¨²Öú>z¶Ôò$VˆºFb~Žž°ÂÒâæêþ  " . : H V ` j r z € † š ® Ó ø !!!$!4!D!J!P!†!¼!Ê!Ø!è!ø!"4"H"\"w"’"¨"¾"Ý"ü" ##(#4#L#d#l#t#Œ#¤#´#Ä#Ð#Ü#ä#ì#$$1$J$T$^$z$–$·$Ø$Þ$ä$ì$ô$ü$%% %4%H%N%T%^%h%p%x%„%%–%œ%¤%¬%°%´%Ä%Ô%Ü%ä%î%ø%&&&&8&B&L&T&\&d&l&‚&˜&¢&¬&´&¼&Æ&Ð&à&ð&''&'8'R'l't'|'†''˜' '¨'°'Ê'ä'ò'(( (( (*(4(F(X(^(d(n(x(€(ˆ(Ž(”(ª(À(Ê(Ô(ê()),)6)@)`)€)Œ)˜)¢)¬)È)ä)î)ø)*$***0*:*D*Z*p*~*Œ*–* *ª*´*¾*È*Þ*ô*ú*+++++6+P+p++œ+¨+°+¸+Â+Ì+Ü+ì+,, ,(,0,8,@,H,T,`,h,p,~,Œ,œ,¬,´,¼,Ê,Ø,ê,ü,- -0-@-F-L-V-`-j-t-|-„-œ-´-¾-È-Ü-ð-ø-. ...$.4.D.N.X.`.h.|..š.¤.º.Ð.â.ô. / />/\//¢/¨/®/¶/¾/Ô/ê/ô/þ/0:0O0d0j0p0„0˜0¬0À0Ê0Ô0Ú0à0è0ð0ú011 1(101>1L1^1p1€11³1Ö1â1î12"2,262@2J2V2b2|2–2¡2¬2Ã2Ú23.363>3F3N3`3r3~3Š3’3š3¦3²3º3Â3Ô3æ3ð3ú34*444>4F4N4d4z4†4’4˜4ž4¤4ª4¼4Î4è45 5>5T5j5t5~5’5¦5°5º5Ê5Ú5î566&646B6P6^6t6Š6–6¢6°6¾6Ð6â6è6î67777*767D7R7Z7b7p7~7„7Š7–7¢7°7¾7Ð7â7î7ú78 888.8>8H8R8^8j8x8†8’8ž8´8Ê8Ô8Þ8ä8ê899,9B9\9v9€9Š9”9ž9´9Ê9à9ö9: :::(:6:H:Z:b:j:p:v:Š:ž:°:Â:Ö:ê:ü:;";6;<;B;R;b;l;v;†;–;¦;¶;Ê;Þ;ö;<<<(<2<B<R<`<n<ˆ<¢<¨<®<¼<Ê<Ò<Ú<â<ê<=="=*=D=^=p=‚==ž=¦=®=¸=Â=Ö=ê=þ=>>">6>J>R>Z>f>r>„>–>°>Ê>Ö>â>ð>þ>???"?2?B?Z?r?~?Š?”?ž?®?¾?Ì?Ú?ð?@ @@&@:@D@N@X@b@n@z@†@’@š@¢@°@¾@Â@Æ@Ò@Þ@ì@ú@AA"A.A6A>AJAVAdArA~AŠA¤A¾AÌAÚAêAúABBB.BEDEJETE^EnE~E’E¦EÀEÚEæEòEüEFFF*F6F>FFFTFbFpF~F†FŽFžF®F¾FÎFâFöFþFG GG$G6GDGRG`GnGŠG¦GÀGÚGâGêGðGöG H"H*H2H:HBHJHRHbHrHxH~HH¢H´HÆHÒHÞHðHI III"I(I.I@IRI\IfI|I’II¨I´IÀIÆIÌIÖIàIîIüIJJJ$J,J4J>JHJRJ\JdJlJvJ€JŽJœJªJ¸JÀJÈJÒJÜJîJKKKK$K2K@KNK\KjKxK‚KŒK”KœK¤K¬K¸KÄKÎKØKæKôKLL"L4LHL\LdLlL|LŒL–L L¬L¸LÒLìLöLMM M(M0M@MPMVM\MfMpMˆM M¬M¸MÈMØMèMøMN NNN6NPNXN`NfNlNŠN¨N²N¼NÐNäNìNôNO OOOO$O8OLOlOŒO˜O¤O¬O´OÂOÐOÚOäOêOðOúOPP,P`L`^`p``°`Ä`Ø`à`è`ö`aaa(a8aXaxa~a„aŽa˜aªa¼aàab bb0bLbZbhbpbxbˆb˜b¢b¬b¼bÌbÜbìbcc"c0c>cLcVc`chcpczc„cŠccšc¤c°c¼cÆcÐcâcôcdd&d8d@dHdVdddxdŒd˜d¤d®d¸dÂdÌdÔdÜdîdee,e8eDeVehenete–e¸eÀeÈeÐeØeêeüeff$f8fBfLf^fpf€ff f°fÄfØfg4g^gˆg”g g®g¼gÌgÜgòghhh8hTh~h¨h¶hÄhÐhÜhôh ii$iDidiri€i–i¬iÌiìiöij jj&j8j@jHjjjŒj¾jðjk8k@kHkTk`klkxk‚kŒk–k k²kÄkÊkÐkäkøkll"l4l‹L‹Z‹b‹j‹p‹v‹„‹’‹–‹š‹°‹Æ‹Ð‹Ú‹ð‹ŒŒ.Œ:ŒFŒ^ŒvŒ„Œ’Œ Œ®Œ´ŒºŒÌŒÞŒäŒêŒöŒ &0:FR^jpvަ¸ÊÖâèîúŽŽ6ŽRŽnŽtŽzŽˆŽ–ŽºŽÞŽäŽêŽúŽ .BP^fn~Žš¦²¾ÌÚæò"*2:@FVfxВ𠦶ÆÔâø‘&‘>‘R‘f‘v‘†‘”‘¢‘¶‘Ê‘â‘ú‘ ’’&’.’>’N’f’~’ˆ’’’œ’¦’®’¶’Ø’ú’ ““"“*“4“>“R“f“|“’“¢“²““ғޓê“ò“ú“”””*”<”N”X”b”r”‚”ˆ”ޔ𔦔º”Δؔâ”î”ú”••$•6•<•B•L•V•d•r•‚•’•𕢕ª•²•Æ•Ú•à•æ•ò•þ•––"–2–:–B–N–Z–j–z–ˆ–––ž–¦–®–¶–Â–Î–Ú–æ– —.—D—Z—j—z—„—Ž—˜—¢—¬—¶—À—Ê—Ü—î—˜˜,˜>˜F˜N˜V˜^˜j˜v˜€˜Š˜–˜¢˜¶˜Ê˜Ø˜æ˜ð˜ú˜™™™"™,™6™H™Z™f™r™z™‚™Œ™–™œ™¢™²™Â™Ð™Þ™æ™î™ š&š0š:šNšbšžŸ ¡¬­²³´µÌÍÎÏØÙâã*+RS !,-TUžŸ ¡¬­²³´µÌÍÎÏØÙâã*+RS !,-TUVW”•¨©ª«êëtu()VW”•¨©ª«êëtu()¦§VW~PQØÙúûVW¦§VW~PQØÙúûVW¼½˜™¼½˜™ <=ŒÔÕ¬­ÐÑRS"#./0145@AXY <=ŒÔÕ¬­ÐÑRS"#./0145@AXY  $%ÊËJKÎÏâãèéî﨩üý  $%ÊËJKÎÏâãèéî﨩üý TUlm<=>?z{¨©ÊËèé TUlm<=>?z{¨©ÊËèé°±²³ÜÝÞßþÿ>?~ÜÝhijk¼½ôõ°±²³ÜÝÞßþÿ>?~ÜÝhijk¼½ôõ@A67†‡TUno@ABCDEno„…þÿ@A67†‡TUno@ABCDEno„…þÿ)*-.tu !45€¼½&'&'ÂÃÄÅÆÇ*+fg)*-.tu !45€¼½&'&'ÂÃÄÅÆÇ*+fgHI !š›  BCòóHI !š›  BCòó  ¨©¼½ÎÏÐÑòó*+bc‚ƒˆ‰ÌÍÜÝÞß  ¨©¼½ÎÏÐÑòó*+bc‚ƒˆ‰ÌÍÜÝÞßjkDE˜™âã ^_z{’“ìíôõjkDE˜™âã ^_z{’“ìíôõ01ÆÇ@A˜™¶·¸¹. / 0 1 01ÆÇ@A˜™¶·¸¹. / 0 1 ¨©º»¼½ÐÑâ㨩º»¼½ÐÑâã z{  JKfg¨©ÎÏÐÑîïðñ67Š‹ÌÍ z{  JKfg¨©ÎÏÐÑîïðñ67Š‹ÌÍ!"Èɶ·¼½!"Èɶ·¼½#$"#:;¦§#$"#:;¦§%&23$%89„…LMúûîïôõúû  &',-FGPQRSXY`abcØÙ%&23$%89„…LMúûîïôõúû  &',-FGPQRSXY`abcØÙ'(23bc~‘’“ÂÃØÙ'(23bc~‘’“ÂÃØÙ)*°±²³´µ¼½¾¿ÀÁÆÇÈÉÊËÌÍÎÏÖ׿çö÷þÿÀÁÂÃfg)*°±²³´µ¼½¾¿ÀÁÆÇÈÉÊËÌÍÎÏÖ׿çö÷þÿÀÁÂÃfg+,¸¹ÒÓÔÕèéêëìíôõøùŽhi+,¸¹ÒÓÔÕèéêëìíôõøùŽhi-./0xy45Z[€&'rs’“”•-./0xy45Z[€&'rs’“”•-./0¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÖרÙâãæçö÷þÿZ[€rs”•-./0¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÖרÙâãæçö÷þÿZ[€rs”•1BClm./23FGLM&'@ANOPQêëÖ×èé%&'(23`a~$%6789<=vw„…¢£¶·DELMRSXY´µúûôõ  XYbc ¡ØÙ, - %&'(23`a~$%6789<=vw„…¢£¶·DELMRSXY´µúûôõ  XYbc ¡ØÙ, - 45´µ\]^_„…45´µ\]^_„…67ÚÛÜÝÞßäåòóœbc67ÚÛÜÝÞßäåòóœbc89rsš›œª«   vwØÙÚÛŽ¦§¨©¶·¸¹ÈÉâãòó89rsš›œª«   vwØÙÚÛŽ¦§¨©¶·¸¹ÈÉâãòó:;¶·"#$%Ž:;¶·"#$%Ž <=Œ¸¹ÔÕìí0145XY <=Œ¸¹ÔÕìí0145XY>?š›º»ÚÛÐÑøù  89JK>?š›º»ÚÛÐÑøù  89JK@A67no¶·¸¹ðñ>?TUnoœª«>?@ABCDEnoÊËþÿ@A67no¶·¸¹ðñ>?TUnoœª«>?@ABCDEnoÊËþÿ1BC¾¿Ö×vw€‚ƒäåæç&'BCpqrsÊËèé1BC¾¿Ö×vw€‚ƒäåæç&'BCpqrsÊËèéDE()ÌÍäåDE()ÌÍäåFG²³´µ$%&'BCFG²³´µ$%&'BCHItuòó&'HItuòó&'JK¼½ !JK¼½ !LM^_èé‘LM^_èé‘NO®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÖרÙâãæçö÷þÿÞßàáNO®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÖרÙâãæçö÷þÿÞßàáPQ,-BC€ÚÛîïðñ ¡ÀÁþÿPQ,-BC€ÚÛîïðñ ¡ÀÁþÿRSHI¸¹RSHI¸¹TUz{®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷þÿ²³TUz{®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷þÿ²³VW°±²³¼½¾¿ÀÁÊËæçþÿVW°±²³¼½¾¿ÀÁÊËæçþÿXYjk‚ƒ„…†‡œ ¡®¯ÈÉXYjk‚ƒ„…†‡œ ¡®¯ÈÉZ[®¯²³¾¿ÂÃÆÇÈÉÐÑÖ׿ç~¼½Z[®¯²³¾¿ÂÃÆÇÈÉÐÑÖ׿ç~¼½\]®¯deÌÍ$ % \]®¯deÌÍ$ % ^_®¯°±²³¾¿ÂÃÆÇÈÉÊËÎÏÐÑÖ׿çö÷þÿ†‡ˆ‰˜™^_®¯°±²³¾¿ÂÃÆÇÈÉÊËÎÏÐÑÖ׿çö÷þÿ†‡ˆ‰˜™23`a$%()45>?@A~„…RSš›´µêë23`a$%()45>?@A~„…RSš›´µêë'(bcÈÉ‘’“žŸ'(bcÈÉ‘’“žŸde°±²³´µ¼½¾¿ÀÁÆÇÈÉÊËÎÏÖ׿çö÷þÿ !|}de°±²³´µ¼½¾¿ÀÁÆÇÈÉÊËÎÏÖ׿çö÷þÿ !|}fgÔÕèéêëìíôõøùŒ:;fgÔÕèéêëìíôõøùŒ:;hipqrs !hipqrs !jkŽœNO‚ƒ HIpqìíüýjkŽœNO‚ƒ HIpqìíüý1lm¢£&'Z[èéêëÖ×\]1lm¢£&'Z[èéêëÖ×\]no¬­°±²³´µ¶·¾¿ÌÍÎÏØÙâãæçúûüýÀÁÎÏno¬­°±²³´µ¶·¾¿ÌÍÎÏØÙâãæçúûüýÀÁÎÏpq¬­²³´µ¶·¾¿ÌÍÎÏØÙâãæçúûüýÈÉ  pq¬­²³´µ¶·¾¿ÌÍÎÏØÙâãæçúûüýÈÉ  rs|}ˆ‰rstu˜™ØÙ0167æç<=Žrs|}ˆ‰rstu˜™ØÙ0167æç<=Žtuä刉âã’“èétuä刉âã’“èévw !z{|}fgNOfgvw !z{|}fgNOfg-.xyÖרÙxyVWrs’“”•-.xyÖרÙxyVWrs’“”• TUz{®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçþÿJKfg67Š‹. / 0 1  TUz{®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçþÿJKfg67Š‹. / 0 1 rs|}¬­º»¼½ØÙrs|}¬­º»¼½ØÙ'(23~rstu¬­°±ÂÃØÙ'(23~rstu¬­°±ÂÃØÙ€¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿZ[xy:;<=€¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿZ[xy:;<=‚ƒ®¯ÂÃÆÇÈÉÐÑÖ×àáæç‚ƒ®¯ÂÃÆÇÈÉÐÑÖ×àáæç„…𛄅𛆇ÒÓêëìíôõÎÏrsZ[æç†‡ÒÓêëìíôõÎÏrsZ[æçrsˆ‰rstuvwxy<=VW      rsˆ‰rstuvwxy<=VW      Š‹ÒÓÔÕèéêëìíôõøùŠ‹ÒÓÔÕèéêëìíôõøù <=ŒÔÕ¬­xyŽÐÑPQRS0145JKXY <=ŒÔÕ¬­xyŽÐÑPQRS0145JKXYjkŽ‚ƒjkŽ‚ƒ‘®¯°±²³´µ¼½¾¿ÂÃÆÇÈÉÊËÎÏÐÑÖ׿çö÷þÿrstu‘®¯°±²³´µ¼½¾¿ÂÃÆÇÈÉÊËÎÏÐÑÖ׿çö÷þÿrstu’“ÚÛÜÝÞßàáäåðñòó¬­LMvwxy°±º»ðñ’“ÚÛÜÝÞßàáäåðñòó¬­LMvwxy°±º»ðñ”•ÐÑÞßàáòóúû”•ÐÑÞßàáòóúû–—¶·ÌÍÎÏâãúûüýÜÝ–—¶·ÌÍÎÏâãúûüýÜݘ™¬­²³´µ¶·¾¿ÌÍÎÏØÙâãæç  ˜™¬­²³´µ¶·¾¿ÌÍÎÏØÙâãæç  >?š›ÚÛ>?š›ÚÛjkœäåjk¢£ÔÕüýjkœäåjk¢£ÔÕüýžŸ ¡¬­  *+ !,-žŸ ¡¬­  *+ !,-žŸ ¡¬­  *+ !TUžŸ ¡¬­  *+ !TUlm¢£&'Z[æçlmèé\]lm¢£&'Z[æçlmèé\]¤¥‚ƒæçÚÛ¤¥‚ƒæçÚÛ¦§VWòóVW ¡¦§VWòóVW ¡¨©æç”•^_¨©æç”•^_ª«()’“67ª«()’“67/0nopq€˜™žŸ ¡¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÖרÙâãæçö÷úûüýþÿ*+ !/0nopq€˜™žŸ ¡¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÖרÙâãæçö÷úûüýþÿ*+ !/0NOTUZ[\]^_z{‚ƒ‘¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷þÿ/0NOTUZ[\]^_z{‚ƒ‘¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷þÿ)*/0NOTUVW^_denoz{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³ÀÁÂÃ)*/0NOTUVW^_denoz{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³ÀÁÂÃ)*/0NOTUVWZ[^_denopqz{€‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0NOTUVWZ[^_denopqz{€‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/045NOTUdenopqz{€‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ^_)*/045NOTUdenopqz{€‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ^_:;nopq€–—˜™¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿÜÝ:;nopq€–—˜™¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿÜÝ+,<=¸¹ÒÓÔÕèéêëìíôõøùŽ+,<=¸¹ÒÓÔÕèéêëìíôõøùŽ>?º»ÔÕ>?º»ÔÕ)*/0JKNOTUVWdez{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0JKNOTUVWdez{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0NOTUVWZ[^_denopqz{€‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0NOTUVWZ[^_denopqz{€‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0NOTUVWdez{¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷þÿ)*/0NOTUVWdez{¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷þÿ/0NOTUZ[^_z{‚ƒ‘¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷þÿ/0NOTUZ[^_z{‚ƒ‘¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷þÿÄÅŠ‹ÆÇÄÅŠ‹ÆÇ)*/0NOTUZ[^_dez{€‚ƒ‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ²³)*/0NOTUZ[^_dez{€‚ƒ‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ²³)*/0NOTUZ[^_bcdez{€‚ƒ‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ²³)*/0NOTUZ[^_bcdez{€‚ƒ‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ²³)*/0NOTUVW^_dez{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0NOTUVW^_dez{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0NOTUnopqz{€–—˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿÜÝ)*/0NOTUnopqz{€–—˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿÜÝ)*/0NOTU^_denopqz{€‘–—˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿÜÝ<=)*/0NOTU^_denopqz{€‘–—˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿÜÝ<=TUZ[^_z{‚ƒ‘”•®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙÞßàáâãæçòóö÷þÿTUZ[^_z{‚ƒ‘”•®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙÞßàáâãæçòóö÷þÿ+,†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùrsŽæç+,†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùrsŽæç +,<=fgŠ‹Œ¸¹º»ÒÓÔÕèéêëìíôõøù¬­ŒŽÐÑ:;RShi +,<=fgŠ‹Œ¸¹º»ÒÓÔÕèéêëìíôõøù¬­ŒŽÐÑ:;RShi)*/0NOTUZ[^_dez{€‚ƒ‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ²³)*/0NOTUZ[^_dez{€‚ƒ‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ²³/0NOTUnopqz{€˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ  /0NOTUnopqz{€˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ  67>?’“š›ÚÛÜÝÞßàáäåòó67>?’“š›ÚÛÜÝÞßàáäåòó67’“ÚÛÜÝÞßàáäåòóbc67’“ÚÛÜÝÞßàáäåòóbc67’“”•ÐÑÚÛÜÝÞßàáäåðñòóLMxy67’“”•ÐÑÚÛÜÝÞßàáäåðñòóLMxy‚ƒ’“”•®¯ÂÃÆÇÈÉÐÑÖ×ÚÛÜÝÞßàáäåæçòóúû‚ƒ’“”•®¯ÂÃÆÇÈÉÐÑÖ×ÚÛÜÝÞßàáäåæçòóúû/0NOTUnopqz{€–—˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿÜÝÈÉ  /0NOTUnopqz{€–—˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿÜÝÈÉ  67tu’“ÚÛÜÝÞßàáäåòóˆ‰âã67tu’“ÚÛÜÝÞßàáäåòóˆ‰âã)*/0NOTUVWZ[^_denopqz{€‚ƒ‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ)*/0NOTUVWZ[^_denopqz{€‚ƒ‘˜™¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙàáâãæçö÷úûüýþÿ+,fgŠ‹¸¹ÒÓÔÕèéêëìíôõøùŽ:;hi+,fgŠ‹¸¹ÒÓÔÕèéêëìíôõøùŽ:;hi+,fg†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùŒŽ:;<=hi+,fg†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùŒŽ:;<=hi+,<=fg†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùŒŽ:;+,<=fg†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùŒŽ:;îïhino²³ìí îïhino²³ìí ’“ÞßðñLMxy’“ÞßðñLMxy67’“”•ÐÑÚÛÜÝÞßàáäåòó$%ØÙDEøùúû, - 67’“”•ÐÑÚÛÜÝÞßàáäåòó$%ØÙDEøùúû, - +,fg†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùŒŽ:;hi+,fg†‡Š‹¸¹ÒÓÔÕèéêëìíôõøùŒŽ:;hi)*/0NOTU^_de‘¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷þÿ²³´µ)*/0NOTU^_de‘¬­®¯°±²³´µ¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷þÿ²³´µ+,fgŠ‹¸¹ÒÓÔÕèéêëìíôõøùŒŽhi+,fgŠ‹¸¹ÒÓÔÕèéêëìíôõøùŒŽhinopq€–—¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿª«†‡nopq€–—¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿª«†‡nopq€–—¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿÜÝ<=nopq€–—¬­°±²³´µ¶·¼½¾¿ÆÇÈÉÊËÌÍÎÏÖרÙâãæçúûüýþÿÜÝ<=)*/0NOTUVW^_dez{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³)*/0NOTUVW^_dez{€‘¬­®¯°±²³´µ¶·¼½¾¿ÀÁÂÃÆÇÈÉÊËÌÍÎÏÐÑÖרÙâãæçö÷úûüýþÿ²³+,fgŠ‹ÒÓÔÕèéêëìíôõøùŒ:;hi+,fgŠ‹ÒÓÔÕèéêëìíôõøùŒ:;hi'(^_‚ƒÐц‡ˆ‰˜™'(^_‚ƒÐц‡ˆ‰˜™67œîïðñö÷¾¿67œîïðñö÷¾¿67ÜÝœ`aîïbc67ÜÝœ`aîïbc „… „…  ¨©ÎÏÐÑ45~ÌÍ  ¨©ÎÏÐÑ45~ÌÍ  RSVW|}  RSVW|}jkŽ()pqjkŽ()pqæçèéæçèéjkŽ‚ƒjkŽ‚ƒòó"#òó"#    LMæçèéüýþÿLMæçèéüýþÿ123LMæçèé@APQ€¼½&'ÂÃèé123LMæçèé@APQ€¼½&'ÂÃèéJK¼½ !‘JK¼½ !‘ !‘ !‘JK !^_BC‘JK !^_BC‘"#‘˜™"#‘˜™%&23`aòó$%()4589<=vw~„…¢£¤¥¶·ØÙDELMRSno®¯êëøùúû ¡ØÙ, - %&23`aòó$%()4589<=vw~„…¢£¤¥¶·ØÙDELMRSno®¯êëøùúû ¡ØÙ, - lm¢£&'FGæç”•\]lm¢£&'FGæç”•\]`a$%()45~RSš›êë`a$%()45~RSš›êë*+./0123VW¦§$%&',-~†‡–—ÄÅÞßàá*+./0123VW¦§$%&',-~†‡–—ÄÅÞßàáPQ,-BC€ÚÛîïðñ,-ÀÁPQ,-BC€ÚÛîïðñ,-ÀÁ1*+./0123VW|}¦§ª«$%,-ÜÝÞß0 1 1*+./0123VW|}¦§ª«$%,-ÜÝÞß0 1 *+./0123VW¦§,-Þß. / 0 1 *+./0123VW¦§,-Þß. / 0 1 1*+./0123LMVW¦§,-@APQÞßèé1*+./0123LMVW¦§,-@APQÞßèé`a$%()4567~RSêë`a$%()4567~RSêë23456789RSXY23456789RSXY%&23$%6789„…LMVWXYúû¬­ØÙ%&23$%6789„…LMVWXYúû¬­ØÙ:;žŸÆÇ€:;žŸÆÇ€23$%<=@Avw¢£¶·DERSno ¡, - 23$%<=@Avw¢£¶·DERSno ¡, - `a>?@A„…RSnoš›ÆÇ`a>?@A„…RSnoš›ÆÇ`a<=>?@AnoÆÇ`a<=>?@AnoÆÇPQ,-BC,-PQ,-BC,-DE˜™ÀÁ 89^_z{’“ìíôõDE˜™ÀÁ 89^_z{’“ìíôõ1FGJKLMno޼½bcfglm„…ÂÃÄÅ1FGJKLMno޼½bcfglm„…ÂÃÄÅRSHItu¸¹ÈÉRSHItu¸¹ÈÉ z{FGJKLMfg޼½67fglm„…Š‹Âà z{FGJKLMfg޼½67fglm„…Š‹ÂÃ123FGJKLM޼½@APQfglm„…ÂÃèé123FGJKLM޼½@APQfglm„…ÂÃèéjkNO‚ƒjkNO‚ƒPQêëÚÛPQêëÚÛ  RSTU|}  RSTU|} RSTUlm<=>?ÊË RSTUlm<=>?ÊË  *+./0123VW|}¦§,-Þß  *+./0123VW|}¦§,-ÞßXYZ[‘XYZ[‘XYZ[‘ôõâãXYZ[‘ôõâã\]ö÷de\]ö÷deLM !^_èéBC‘LM !^_èéBC‘`abcNO`abcNO`abcNO–—`abcNO–—defgdefg z{JKdefg67Š‹ z{JKdefg67Š‹hivwÒÓÔÕhivwÒÓÔÕjk./¤¥èéjk./¤¥èé TUlm<=>?ÊËèé TUlm<=>?ÊËèéFGnoŽfgŒÂÃÄÅ  FGnoŽfgŒÂÃÄÅ  hipqrs !ÊËhipqrs !ÊËhipqrsÊËhipqrsÊËHItuúûÈÉHItuúûÈÉ23$%<=vw¢£¶·DERS®¯ ¡, - 23$%<=vw¢£¶·DERS®¯ ¡, - xyžŸÒÓ€ ¡xyžŸÒÓ€ ¡z{‚ƒÊËz{‚ƒÊË  ./RSVW|}  ./RSVW|}`a$%()45~RS®¯êë`a$%()45~RS®¯êëPQ,-€ÚÛîïðñÀÁþÿPQ,-€ÚÛîïðñÀÁþÿjkŽNOz{‚ƒŽ„…jkŽNOz{‚ƒŽ„…%&23`a$%89>?„…LMRSš›´µúûØÙ%&23`a$%89>?„…LMRSš›´µúûØÙ†‡01¨©ÔÕ†‡01¨©ÔÕtuä刉âãèétuä刉âãèéÄÅŠ‹ÆÇª«ÄÅŠ‹ÆÇª«Œ¾¿vwö÷Œ¾¿vwö÷FGJKLMno޼½$%fglm„…ŒÂÃÄÅFGJKLMno޼½$%fglm„…ŒÂÃÄÅ"#XYZ[‘’“˜™œ"#XYZ[‘’“˜™œ‘’“œ‘’“œ”•ÂÃÔÕÖ×|}”•ÂÃÔÕÖ×|}–—Î϶·¸¹–—Î϶·¸¹"#DE‘˜™ z{’“ìí"#DE‘˜™ z{’“ìíš›BCš›BC67œ`a67œ`a:;xyžŸ€:;xyžŸ€ ¡¤¥JK ¡¤¥JK23$%<=vw¢£¤¥¶·DERS ¡, - 23$%<=vw¢£¤¥¶·DERS ¡, - $% ¡¢£¤¥JK$% ¡¢£¤¥JK*+./0123VW¦§¨©ª«*+,-Þß*+./0123VW¦§¨©ª«*+,-Þß  ¦§¨©ª«ÎÏÐÑ*+ÌÍ  ¦§¨©ª«ÎÏÐÑ*+ÌÍ./¦§¨©ª«*+./¦§¨©ª«*+ |}Œ’“ÔÕ¬­vwxy°±º»¼½îïðñÐÑRS |}Œ’“ÔÕ¬­vwxy°±º»¼½îïðñÐÑRS®¯´µÎÏÐÑhi¶·®¯´µÎÏÐÑhi¶·°±ÚÛøùÌÍÎϰ±ÚÛøùÌÍÎÏTU°±²³¼½¾¿ÆÇÈÉÊËÖ×ö÷þÿ²³´µhiTU°±²³¼½¾¿ÆÇÈÉÊËÖ×ö÷þÿ²³´µhiö÷®¯²³´µhiö÷®¯²³´µhi23$%<=vw¢£¶·DERSrs ¡, - 23$%<=vw¢£¶·DERSrs ¡, - ¸¹º»JK¸¹º»JK¸¹º»JKrs¸¹º»JKrsFGJKLM޼½bcfglm„…ÂÃFGJKLM޼½bcfglm„…ÂÃŒ¾¿ìívwxyÒÓö÷Œ¾¿ìívwxyÒÓö÷DEÀÁTU\]^_DEÀÁTU\]^_”•ÂÃÔÕÖ×â㔕ÂÃÔÕÖ×âãÄŤ¥òó,-ÄŤ¥òó,-ÄÅ:;Š‹ÆÇØÙ@A˜™¸¹0 1 ÄÅ:;Š‹ÆÇØÙ@A˜™¸¹0 1 ÈÉ|}Ö×ÈÉ|}Ö×z{ÊËæçz{ÊËæçÌÍøùþÿÌÍøùþÿ  –—¨©®¯ÎÏÐÑhi¶·ÌÍ  –—¨©®¯ÎÏÐÑhi¶·ÌÍ  ¨©®¯ÎÏÐÑòó*+45bc‚ƒ¶·ÌÍÜÝ  ¨©®¯ÎÏÐÑòó*+45bc‚ƒ¶·ÌÍÜÝxyÒÓ  € ¡ÀÁxyÒÓ  € ¡ÀÁ”•ÂÃÔÕâ㔕ÂÃÔÕâ㔕ÂÃÖ×|}Ö×”•ÂÃÖ×|}Ö×òó$%ÆÇØÙDEøù, - òó$%ÆÇØÙDEøù, - PQ,-€°±ÚÛîïðñÀÁÌÍÎÏPQ,-€°±ÚÛîïðñÀÁÌÍÎÏÜÝÞßàḹÜÝÞßàḹNOÜÝÞßàáNOÜÝÞßàáNOÜÝÞßàáNOÜÝÞßàátuä刉âã’“tuä刉âã’“œäåjkÔÕœäåjkÔÕÊËæçèéÊËæçèéLM^_æçèéLM^_æçèéPQêë$%àáPQêë$%à᾿ìívwxyÒÓ$%¾¿ìívwxyÒÓ$% PQ,-€ÚÛîïðñÀÁ PQ,-€ÚÛîïðñÀÁ PQ,-€ÚÛîïðñÀÁ PQ,-€ÚÛîïðñÀÁÐÑòó*+bc‚ƒÜÝÐÑòó*+bc‚ƒÜÝZ[ôõâãZ[ôõâã\]ö÷de\]ö÷de°±ÌÍøùÎÏþÿ°±ÌÍøùÎÏþÿtuúûlmÈÉtuúûlmÈÉüýþÿ !ŒÚÛ  üýþÿ !ŒÚÛ  üýþÿÊËüýþÿÊËæçèéüýþÿÊËæçèéüýþÿÊË    #$òó"##$òó"#–—Î϶·–—Î϶·jkDE˜™ z{’“ìíjkDE˜™ z{’“ìíÒÓ   ¡ÀÁþÿÒÓ   ¡ÀÁþÿ    PQ,-€ÚÛîïðñòóÀÁPQ,-€ÚÛîïðñòóÀÁVW\]deVW\]deö÷üý !deŒÚÛ  ö÷üý !deŒÚÛ    ¨©ÎÏÐÑÌÍ  ¨©ÎÏÐÑÌÍüý !Œ¬­ÚÛèé  üý !Œ¬­ÚÛèé  hiPQnoö÷üý !Œ¬­ÚÛ  hiPQnoö÷üý !Œ¬­ÚÛ  123LMfgüý !@APQŒÚÛèé  123LMfgüý !@APQŒÚÛèé  ÆÇØÙÆÇØÙz{‚ƒÊËz{‚ƒÊËhipqüý !ŒÚÛ  hipqüý !ŒÚÛ  #$"#:;#$"#:;*+./Žêë$%&'45PQfg~†‡ˆ‰–—ÄÅàá*+./Žêë$%&'45PQfg~†‡ˆ‰–—ÄÅàá1*+$%&'NOPQ~†‡–—ÄÅàá1*+$%&'NOPQ~†‡–—ÄÅàá()ÊË()Ê˦§¨©ª«ÐÑòó*+bc‚ƒÜݦ§¨©ª«ÐÑòó*+bc‚ƒÜÝ*+,-./0123BCVW¦§,-Þß*+,-./0123BCVW¦§,-Þßjk./˜™¤¥jk./˜™¤¥†‡01ÔÕ†‡01ÔÕ23œÐÑÔÕ23œÐÑÔÕ  ÐÑ$%45~  ÐÑ$%45~ z{JKfg67ˆ‰Š‹ z{JKfg67ˆ‰Š‹DE89ØÙôõDE89ØÙôõ#$"#:;¦§¨©ª«èé#$"#:;¦§¨©ª«èé TUlm<=>?z{¦§¨©ÊË TUlm<=>?z{¦§¨©ÊË TUlm<=>?z{¨©ÊË TUlm<=>?z{¨©ÊË123LMÆÇ@APQžŸº»âãäåè阙¸¹0 1 123LMÆÇ@APQžŸº»âãäåè阙¸¹0 1  !^_š›BC‘ !^_š›BC‘23òó$%<=vw¢£¶·ØÙDERSøù ¡, - 23òó$%<=vw¢£¶·ØÙDERSøù ¡, - &'FGHIæç”•&'FGHIæç”•jkFGHI”•æçjkFGHI”•æç ¡¤¥¸¹º»JKLM ¡¤¥¸¹º»JKLM%&23’“Þßðñ$%89„…JKLMxyúûØÙ%&23’“Þßðñ$%89„…JKLMxyúûØÙ1`abc&'NOPQ1`abc&'NOPQ123LM$%&'@ANOPQèé123LM$%&'@ANOPQèé23`a$%()4567<=>?vw~„…¢£¶·DERS𛮝êë ¡Ö×, - 23`a$%()4567<=>?vw~„…¢£¶·DERS𛮝êë ¡Ö×, - ÀÁTU\]^_ÀÁTU\]^_89VWXY¬­89VWXY¬­236789VWXYª«¬­°±ÂÃ236789VWXYª«¬­°±ÂÃlm¢£Z[èélm¢£Z[èéÀÁTU\]âãÀÁTU\]âãDEÀÁTU^_ôõDEÀÁTU^_ôõœ`aÔÕœ`aÔÕFG¼½ÐÑòó*+bc‚ƒÜÝFG¼½ÐÑòó*+bc‚ƒÜÝ\]ö÷de\]ö÷deFGJKLMno޼½$%fglm„…ÂÃÄÅFGJKLMno޼½$%fglm„…ÂÃÄÅ®¯²³´µÎÏhi®¯²³´µÎÏhiœäåjkÔÕœäåjkÔÕFGJKLM޼½úûfglm„…ÂÃÈÉFGJKLM޼½úûfglm„…ÂÃÈÉ$%<=>?@AnoÆÇ$%<=>?@AnoÆÇjkpqjkpq¶·º»rs¶·º»rsHItuòó !&'ÄÅÆÇ*+HItuòó !&'ÄÅÆÇ*+’“hiŒ¬­¾¿ìívwxy°±º»ÒÓðñ$%’“hiŒ¬­¾¿ìívwxy°±º»ÒÓðñ$%’“Þßðñ¬­¾¿ìíLMvwxy°±º»ÒÓîïðñXY’“Þßðñ¬­¾¿ìíLMvwxy°±º»ÒÓîïðñXY DE˜™ <=>?z{’“¨©ìí DE˜™ <=>?z{’“¨©ì픕ÈÉÖ×|}Ö×”•ÈÉÖ×|}Ö×  *+$%&'45~†‡–—ÄÅàá  *+$%&'45~†‡–—ÄÅàá:;xyžŸÒÓ€:;xyžŸÒÓ€ÐÑòó*+bc‚ƒˆ‰ÜÝÐÑòó*+bc‚ƒˆ‰ÜÝ FGJKLM޼½fglm„…Âà FGJKLM޼½fglm„…ÂÃ*+$%&'~†‡ˆ‰–—ÄÅàá*+$%&'~†‡ˆ‰–—ÄÅàá$%67‚ƒ†‡ˆ‰Š‹$%67‚ƒ†‡ˆ‰Š‹ z{JKfg67ˆ‰Š‹ z{JKfg67ˆ‰Š‹noŽüý !ŒÚÛ  noŽüý !ŒÚÛ  ‚ƒŽ„…†‡¬­®¯‚ƒŽ„…†‡¬­®¯LM !^_BC‘LM !^_BC‘tuDE˜™âã z{’“ìítuDE˜™âã z{’“ìíHI”•ÜÝHI”•ÜÝ*+bc$%&'~†‡–—ÄÅàá*+bc$%&'~†‡–—ÄÅàá./˜™¢£./˜™¢£`a()>?„…RSš›`a()>?„…RS𛑒“23œžŸ¾¿ÐÑ‘’“23œžŸ¾¿ÐÑ@AœžŸº»@AœžŸº»PQxyÒÓ   ¡ÀÁþÿPQxyÒÓ   ¡ÀÁþÿœ˜™¢£œ˜™¢£jkÄÅ./¤¥òójkÄÅ./¤¥òó#$:;<=¦§¨©ª«èé#$:;<=¦§¨©ª«èé :;<=>?z{¦§¨©ª«èé :;<=>?z{¦§¨©ª«è銋:;¦§¨©ª«è銋:;¦§¨©ª«è鬭è鬭èé$%vw~RS®¯$%vw~RS®¯’“¬­vwxy°±º»ðñXY’“¬­vwxy°±º»ðñXY²³´µÆÇòóö÷²³´µÆÇòóö÷23`a„…²³´µôõ23`a„…²³´µôõ–—®¯ÎÏÐѶ·¸¹–—®¯ÎÏÐѶ·¸¹RSHI–—Üݶ·¸¹RSHI–—Üݶ·¸¹|}’“¬­@AvwxyžŸ°±º»¼½ðñ|}’“¬­@AvwxyžŸ°±º»¼½ðñ|}¬­º»¼½|}¬­º»¼½œ¾¿â㜾¿âãPQ,-€ÒÓÚÛîïðñ   ¡ÀÁPQ,-€ÒÓÚÛîïðñ   ¡ÀÁFGJKLMno޼½fglm„…ÂÃÄÅFGJKLMno޼½fglm„…ÂÃÄÅ*+FGnoŽ$%&'fg~†‡–—ÂÃÄÅàá*+FGnoŽ$%&'fg~†‡–—ÂÃÄÅàá>?@Ano²³ÆÇ>?@Ano²³ÆÇHItuúûlmÈÉHItuúûlmÈÉ TUlmpqrsþÿ()<=>?ÊË TUlmpqrsþÿ()<=>?ÊË  ¨©°±ÎÏÐÑÚÛÌÍÎÏ  ¨©°±ÎÏÐÑÚÛÌÍÎϰ±ÚÛøùÌÍÎϰ±ÚÛøùÌÍÎÏ23œÐÑÔÕ23œÐÑÔÕhi¾¿ìívwxyÒÓÔÕhi¾¿ìívwxyÒÓÔÕœhiäå23`ajkÐÑÒÓÔÕœhiäå23`ajkÐÑÒÓÔÕÈÉÖ×|}Ö×ÈÉÖ×|}Ö×89ØÙâã89ØÙâãPQüý !ŒÚÛ  PQüý !ŒÚÛ  ./ÐÑòó*+bc‚ƒÜÝÞß./ÐÑòó*+bc‚ƒÜÝÞß*+./0123VW¦§,-ÜÝÞß*+./0123VW¦§,-ÜÝÞß*+êë$%&'~†‡–—ÄÅàá*+êë$%&'~†‡–—ÄÅàáZ[ÂÃÔÕôõ@A\]¾¿ØÙâãäåZ[ÂÃÔÕôõ@A\]¾¿ØÙâãäå@Aâãäå@Aâãä墣¨©&'FGHIæç”•^_¢£¨©&'FGHIæç”•^_ lm¬­èé lm¬­èé`a$%()45~RSêëÖ×`a$%()45~RSêëÖ×jkDE˜™ z{’“ìíjkDE˜™ z{’“ìí¬­xyîïðñö÷¾¿JK¬­xyîïðñö÷¾¿JK’“¬­vwxy°±º»îïðñö÷¾¿’“¬­vwxy°±º»îïðñö÷¾¿HItuòóHItuòóDE89^_ôõDE89^_ôõŒ¾¿îïðñö÷¾¿Œ¾¿îïðñö÷¾¿òó$%ØÙDEøùúû, - òó$%ØÙDEøùúû, - %&23”•àáòó$%89„…LMøùúûØÙ, - %&23”•àáòó$%89„…LMøùúûØÙ, - jkœüýjkœüýPQ€ÌÍøù   ¡þÿPQ€ÌÍøù   ¡þÿ¢£*+‘¢£*+‘@A@ABCjk‚ƒ„…†‡TUBCDE„…ÊËBCjk‚ƒ„…†‡TUBCDE„…ÊËþÿÌÍþÿÌÍ    ÊËJK¼½ÊËìí¨©üýxyz{    ÊËJK¼½ÊËìí¨©üýxyz{     JKÊËìí¨©z{     JKÊËìí¨©z{    @AXYÊËpqrs    @AXYÊËpqrsXYpqXYpq üý üý    JKìí¨©üýz{    JKìí¨©üýz{:;TUÆÇ”•¨©¸¹ÈÉ()`a:;TUÆÇ”•¨©¸¹ÈÉ()`aHIhiHIhiPQFGŠ‹þÿ89:;<=~ÌÍPQFGŠ‹þÿ89:;<=~ÌÍLM23Š‹LM23Š‹DEØÙÚÛøù¶·DEØÙÚÛøù¶·@A’“jkôõ,-./‘º»@A’“jkôõ,-./‘º»tu !~²³&'”•ÄÅÆÇ*+œžŸêëtu !~²³&'”•ÄÅÆÇ*+œžŸêë"#\]^_RS*+øù"#\]^_RS*+øù $%bcdeâ㤥JK $%bcdeâ㤥JK&'z{‘°±&'z{‘°±ª«()’“67ª«()’“67*+,-./23ÂÃnovw¬­*+,-./23ÂÃnovw¬­*+,-23ÂÃÄÅ  45novw¬­ÀÁØÙ*+,-23ÂÃÄÅ  45novw¬­ÀÁØÙ*+./¬­®¯vwÂÃ*+./¬­®¯vwÂÃ0123¬­45ÂÃ0123¬­45ÂÃ*+,-0123ÂÃ45no¬­*+,-0123ÂÃ45no¬­-.45€&'‘’“-.45€&'‘’“@A67¸¹no>?@Anoþÿ@A67¸¹no>?@Anoþÿ89    89    :;TU”•¨©¸¹ÎÏ()`a:;TU”•¨©¸¹ÎÏ()`a<=îï\]fg¢£<=îï\]fg¢£>?@A´µ¬­º»>?@A´µ¬­º»>?@A"#ÐѬ­>?@A"#ÐѬ­BCjkhi„…TUBCjkhi„…TUDE¶·DE¶·FGØÙBCtuøùHIèéFGØÙBCtuøùHIèéHIBCHIBCJKpqrsª«  €JKpqrsª«  €LMˆ‰23^_îïðñLMˆ‰23^_îïðñNOpqrs”•àáÈÉ–—NOpqrs”•àáÈÉ–—PQˆ‰Ž‘89 PQˆ‰Ž‘89 RS¦§lm‚ƒRS¦§lm‚ƒ:;TUÆÇ”•–—:;TUÆÇ”•–—¦§VW~ØÙúûVW¦§VW~ØÙúûVWXYZ[’“žŸ ¡XYZ[’“žŸ ¡-./0€XYZ[€xy:;<=rs”• ¡-./0€XYZ[€xy:;<=rs”• ¡45"#\]^_*+„…øù45"#\]^_*+„…øù45´µ"#\]^_ÄÅ„…øù45´µ"#\]^_ÄÅ„…øù`aBC²³Þß`aBC²³Þß67ÜÝ$%bcde¤¥JK67ÜÝ$%bcde¤¥JK$%bcdexyâ㤥JK$%bcdexyâ㤥JKfgèéòóˆ‰fgèéòóˆ‰hiÌÍ  hiÌÍ  BCjkfghi’“BCjkfghi’“¢£lm¦§øù\]¢£lm¦§øù\]@Anoœ@AnoœpqrsäåÀÁÂÃÄÅÈÉ\]ÄÅNOˆ‰pqrsäåÀÁÂÃÄÅÈÉ\]ÄÅNOˆ‰89rsˆ‰pqrstuäåÄÅÈÉüý \]ÄÅØÙÚÛBCäåòó    89rsˆ‰pqrstuäåÄÅÈÉüý \]ÄÅØÙÚÛBCäåòó    rsˆ‰rstu01<=rsˆ‰rstu01<=vw()bcpqžŸ‚ƒvw()bcpqžŸ‚ƒxyz{|}˜™ö÷þÿ‚ƒ„…î拉  xyz{|}˜™ö÷þÿ‚ƒ„…î拉  xyz{|} ¡ö÷øùþÿ„…êëî拉  xyz{|} ¡ö÷øùþÿ„…êëî拉  xyz{|} ¡PQøùþÿ:;„…¾¿ìíî拉    xyz{|} ¡PQøùþÿ:;„…¾¿ìíî拉    !~²³$%&'”•œ !~²³$%&'”•œ-./045Z[€¼½&'&'’“ÂÃrs”•-./045Z[€¼½&'&'’“ÂÃrs”•¤¥‚ƒÔÕÚÛ$%¤¥‚ƒÔÕÚÛ$%‚ƒŽ„…†‡¬­®¯¼½’“‚ƒŽ„…†‡¬­®¯¼½’“Ž„…†‡¬­®¯¼½’“Ž„…†‡¬­®¯¼½’“LMˆ‰23^_ðñ˜™ðñLMˆ‰23^_ðñ˜™ðñŠ‹ÒÓŒ67bcÒÓŠ‹ÒÓŒ67bcÒÓŒXYäåêëŒXYäåêëŽÂÃÆÇîïØÙŽÂÃÆÇîïØÙ‘œÒÓ23æç‘œÒÓ23æç’“úûŒ’“úûŒ”•˜™”•˜™–—VWžŸ./’“–—VWžŸ./’“xy˜™‚ƒxy˜™‚ƒš›()no„…89š›()no„…89‘œ ÒÓ23´µæç‘œ ÒÓ23´µæçžŸ¢£ÔÕÖרÙüý‚ƒôõö÷žŸ¢£ÔÕÖרÙüý‚ƒôõö÷z{|} ¡>?Þßàáòóøù@AÎÏz{|} ¡>?Þßàáòóøù@AÎÏ¢£*+./45de¢£*+./45de¤¥ÀÁ‘¢£ê뤥ÀÁ‘¢£êëRS¦§bclm‚ƒ–—RS¦§bclm‚ƒ–—¨©Ö×°±XY†‡¨©Ö×°±XY†‡úûª«Ö׆‡úûª«Ö׆‡Ž„…†‡¬­®¯Z[bcŽ„…†‡¬­®¯Z[bcŽ„…†‡¬­®¯°±Ž„…†‡¬­®¯°±®¯°±®¯°±FG !~²³´µ$%&'BCFG !~²³´µ$%&'BCFG²³´µÞßâã$%&'BCFG²³´µÞßâã$%&'BC@A¶·>?€Œœ>?@ABCDE@A¶·>?€Œœ>?@ABCDE@A67¸¹>?@A67¸¹>?º»bcÐѺ»bcÐÑ€„…†‡¼½&'ÂÃ’“€„…†‡¼½&'ÂÃ’“îïðñö÷¾¿JKîïðñö÷¾¿JK¤¥ÀÁ”•‘ÄÅ¢£ê뤥ÀÁ”•‘ÄÅ¢£êë*+,-23ÂÃÄÅ  ôõ,-TUno„…¬­ÚÛ*+,-23ÂÃÄÅ  ôõ,-TUno„…¬­ÚÛ,-^_ÂÃÄÅ  ‘ôõŠ‹„…ª«ØÙÚÛö÷,-^_ÂÃÄÅ  ‘ôõŠ‹„…ª«ØÙÚÛö÷TUÆÇ–—TUÆÇ–—ÈÉúûHIÈÉúûHI  ÊËJKÎÏâãî﨩üýxyz{  ÊËJKÎÏâãî﨩üýxyz{ÌÍ,-ÌÍ,-ÎÏ–—¾¿lmÎÏ–—¾¿lmÐÑö÷úûJKÐÑö÷úûJKŠ‹ÒÓ"#DE¦§ŒìíîÒÓ"#DE¦§ŒìíîïÔÕ !ÔÕ !¨©ª«Ö×°±XY†‡"#Œ¨©ª«Ö×°±XY†‡"#ŒFGØÙÚÛ./tuøùHI¶·FGØÙÚÛ./tuøùHI¶·ØÙÚÛ./BCøùØÙÚÛ./BCøù–—¶·ÌÍÎÏâãüýÜÝ<= ¡–—¶·ÌÍÎÏâãüýÜÝ<= ¡´µÞßâãfg´µÞßâãfgàá  nožŸàá  nožŸ´µÞßâã´µÞßâãpqrsäå–—ÄÅÈÉ\]ÄÅNOpqrsäå–—ÄÅÈÉ\]ÄÅNO¤¥æç ÚÛæç¤¥æç ÚÛæçlm¢£jkZ[fgèéêë23ˆ‰lm¢£jkZ[fgèéêë23ˆ‰1lmèéêëÖ×1lmèéêëÖ×ìí,-`aˆ‰Š‹Žìí,-`aˆ‰Š‹Ž<=î<=î@Aðñ¨©noÊË@Aðñ¨©noÊËÄŤ¥fgòóˆ‰ÄŤ¥fgòóˆ‰ôõö÷øù‚ƒZ[ôõö÷øù‚ƒZ[ôõö÷øùÐÑZ[ôõö÷øùÐÑZ[ôõö÷øù‚ƒôõö÷øù‚ƒúûèébcLMúûèébcLMüýz{ÜÝüýz{ÜÝþÿŒÌÍþÿŒÌÍèéîïLMbcèéîïLMbcjkÄÅ./¤¥òóˆ‰jkÄÅ./¤¥òóˆ‰no¸¹¸¹ÎÏ`a–—no¸¹¸¹ÎÏ`a–—noÀÁnoÀÁœæç ÚÛæçœæç ÚÛæçžŸ ¡,-ÂÃÄÅ  ,-TUžŸ ¡,-ÂÃÄÅ  ,-TUàá  nožŸàá  nožŸ  ¶·ÒÓ  ¶·ÒÓ–— ¡–— ¡–—&'ª«–—&'ª«vw–—ª«vw–—ª«vwÌÍ,-vwÌÍ,-vwÌÍvwÌÍDEÔÕ !DEÔÕ !ŒÎÏŽPQRSŒÎÏŽPQRS89 ¡89 ¡devw !z{|}fgfgdevw !z{|}fgfgÒÓ"#DE¦§êëìíîïÒÓ"#DE¦§êëìíîïFG~²³´µ$%&'BC"#ÞßFG~²³´µ$%&'BC"#Þß-.FG45€²³´µ$%&'BC-.FG45€²³´µ$%&'BCDEš›()„…DEš›()„…žŸ ¡¬­*+RS !*+žŸ ¡¬­*+RS !*+ìí,-`aˆ‰ØÙìí,-`aˆ‰ØÙØÙÚÛ./BC"#èéØÙÚÛ./BC"#èé0123456789:;<=z{|}|}(),-230123456789:;<=z{|}|}(),-2301234567z{01234567z{0123456789z{|},-0123456789z{|},-0123456701234567014589z{|},-01†‡014589z{|},-01†‡01:;()01:;()01<=¸¹defg01<=¸¹defg@A ¡¶·>?†‡œ>?@ABCDEÎÏ@A ¡¶·>?†‡œ>?@ABCDEÎÏ  @AXYpqrs  @AXYpqrsFGÚÛ./BCBC"#$%èéFGÚÛ./BCBC"#$%èéÒÓ"#DE¦§ÞßìíîïÒÓ"#DE¦§ÞßìíîïFG€‚ƒŠ‹ª«FG€‚ƒŠ‹ª«HIäåHIäå    ÊËJKÎÏâãìíî﨩üýz{    ÊËJKÎÏâãìíî﨩üýz{LM^_æçèéLM^_æçèéNOö÷NOö÷|}PQdeŠ‹þÿ89:;<=~¦§¾¿ìíîïÌÍ|}PQdeŠ‹þÿ89:;<=~¦§¾¿ìíîïÌÍ"#*+RS*+"#*+RS*+TUno@AŽ89:;˜™êëÐÑÒÓTUno@AŽ89:;˜™êëÐÑÒÓ–—VW’“–—VW’“  @AXYpqrs  @AXYpqrs¬­Z[bc¬­Z[bc<=\]fg<=\]fgLM^_`aæç67LMÔÕTUäåLM^_`aæç67LMÔÕTUäå^_`a0167ÎÏôõRSTUŽæçš›îï  ^_`a0167ÎÏôõRSTUŽæçš›îï  ¦§¬­Z[bclm–—¦§¬­Z[bclm–—de¢£¤¥žŸde¢£¤¥žŸ<=jk\]fghi–—’“<=jk\]fghi–—’“BCjkfghi’“BCjkfghi’“jkº»úûjkº»úûRS¦§bclm–—RS¦§bclm–—š›TUno@AŽ89:;˜™ÐÑÒÓš›TUno@AŽ89:;˜™ÐÑÒÓJKNOpqrsª«àáâã–—JKNOpqrsª«àáâã–—JKNOpqrsª«àဖ—JKNOpqrsª«àဖ—FGØÙtuøùúûHIFGØÙtuøùúûHIvw"#¾¿îïvw"#¾¿îïŒdexy¤¥ÐÑJKŒdexy¤¥ÐÑJKvw !01234589z{|},-01fgfgvw !01234589z{|},-01fgfgdevw !014589z{|},-defgÂÃdefgdevw !014589z{|},-defgÂÃdefgVW~ìí ØÙúûVWVW~ìí ØÙúûVW¶·€†‡Š‹Œ¾¿TUêë’“Ö×¶·€†‡Š‹Œ¾¿TUêë’“Ö×RS¦§ôõøù‚ƒ„…ÊËRS¦§ôõøù‚ƒ„…ÊËBC‚ƒ„…TUpqÊËBC‚ƒ„…TUpqÊË€†‡Š‹Œ¾¿TUêëBCDE„…pq’“€†‡Š‹Œ¾¿TUêëBCDE„…pq’“ˆ‰†‡ÎÏÖ׈‰†‡ÎÏÖ×€†‡Š‹ŒêëÖ×€†‡Š‹ŒêëÖ×¶·€†‡Š‹Œêë@A¶·€†‡Š‹Œêë@AŽ‘š›œ®¯89Ö×ØÙ    ÚÛŽ‘š›œ®¯89Ö×ØÙ    ÚÛÄÅŽ‘š›œ¬­®¯Š‹Ö×     ª«ÌÍØÙÚÛö÷  ÄÅŽ‘š›œ¬­®¯Š‹Ö×     ª«ÌÍØÙÚÛö÷  ª«()’“ª«()’“:;NOTU”•¨©ª«êëtuÈÉ():;NOTU”•¨©ª«êëtuÈÉ()ÎÏäå–—˜™01¾¿NO  ÎÏäå–—˜™01¾¿NO  rs–—˜™0167üýæçŽ  rs–—˜™0167üýæçŽ  89„…Ž‘š›œ®¯  ÚÛ  ¨©¸¹ÚÛòó89„…Ž‘š›œ®¯  ÚÛ  ¨©¸¹ÚÛòó89Ž‘š›œ®¯  ÚÛ  ¨©¸¹ÚÛòó89Ž‘š›œ®¯  ÚÛ  ¨©¸¹ÚÛòó–—žŸ./øù–—žŸ./øù ¡fgš›°±²³´µ ¡fgš›°±²³´µžŸ¢£Ö×üýôõrsº»žŸ¢£Ö×üýôõrsº»¤¥¶·ÐÑXYäåæçòó^_º»¼½jk¤¥¶·ÐÑXYäåæçòó^_º»¼½jkÒÓ"#DE¦§ÞßìíîïÒÓ"#DE¦§Þßìíîï:;”•¨©ª«âãêëtuÈÉ()HI:;”•¨©ª«âãêëtuÈÉ()HI89JKpqrs”•¨©ª«êëtu()¶·¸¹89JKpqrs”•¨©ª«êëtu()¶·¸¹./01‘¬­®¯vwÂà  ./01‘¬­®¯vwÂà  ./Ž‘š›œ¬­®¯  ÂÃÚÛ  ./Ž‘š›œ¬­®¯  ÂÃÚÛ  ¨©Ö×°±XY†‡"#¨©Ö×°±XY†‡"#²³º»hi²³º»hi>?´µ¶·àáä嬭º»>?´µ¶·àáä嬭º»¤¥´µ¶·ÐÑXYàáäåæçòó^_¼½jk¤¥´µ¶·ÐÑXYàáäåæçòó^_¼½jk:;¸¹¸¹ÀÁÎÏ()`a–—:;¸¹¸¹ÀÁÎÏ()`a–—²³º»^_hi²³º»^_hi ¼½ìíxyz{ ¼½ìíxyz{BC€†‡¾¿TUæç&'pqrs’“ÊËBC€†‡¾¿TUæç&'pqrs’“ÊËpqÀÁÄÅäå    pqÀÁÄÅäå    pqŽÂÃÆÇÄÅpqŽÂÃÆÇÄÅpqrsäåÀÁÄÅÈÉ\]ÄÅ  pqrsäåÀÁÄÅÈÉ\]ÄÅ  ŽÂÃÆÇÄÅŽÂÃÆÇÄÅpqrsäåÄÅÈÉ\]ÄÅÚÛˆ‰pqrsäåÄÅÈÉ\]ÄÅÚÛˆ‰     ÊË     ÊËDEÌÍö÷äåDEÌÍö÷ä冇ÎÏRShirs˜™FGRSZ[òó†‡ÎÏRShirs˜™FGRSZ[òóö÷¤¥¶·ÐÑXYZ[äåæçòó^_¼½jkö÷¤¥¶·ÐÑXYZ[äåæçòó^_¼½jk‘œÒÓÔÕ´µæç‘œÒÓÔÕ´µæç‚ƒžŸÒÓÔÕÖרÙ$%‚ƒôõö÷´µ‚ƒžŸÒÓÔÕÖרÙ$%‚ƒôõö÷´µ1BClmxyžŸê뢣ÔÕÖרÙüý$%€‚ƒôõrsö÷´µº»1BClmxyžŸê뢣ÔÕÖרÙüý$%€‚ƒôõrsö÷´µº»rsxy|}žŸÔÕÖ×ØÙ‚ƒôõVWö÷”•rsxy|}žŸÔÕÖ×ØÙ‚ƒôõVWö÷”•¤¥‚ƒæç ÚÛ¤¥‚ƒæç ÚÛ”•ÜÝÞß”•ÜÝÞßÜÝÞß>?ÜÝhijkôõÜÝÞß>?ÜÝhijkôõNOpqrsàáâãêë–—NOpqrsàáâãêë–—pq¨©àáâãêëpq¨©àáâãêëäåèéNOäåèéNOLM^_æçèéLM^_æçèéLMäåæçèéNOLMäåæçèéNO”•¨©ª«àáâãêëtu()”•¨©ª«àáâãêëtu()~ìíðñ º»ÆÇúûXYòóôõ~ìíðñ º»ÆÇúûXYòóôõŽîïØÙŽîïØÙìíðñ º»ÆÇúûVWXYòóôõìíðñ º»ÆÇúûVWXYòóôõ¦§òóVWÔÕ¦§òóVWÔÕÂÃÄÅôõ„…ÚÛÂÃÄÅôõ„…ÚÛÐÑÌÍö÷JKäåÐÑÌÍö÷JKäåFGØÙÚÛtuøùúûHIèéFGØÙÚÛtuøùúûHIèéÈÉÐÑtuøùúûHIJK* + ÈÉÐÑtuøùúûHIJK* + rsžŸ¢£Ö×üýrsžŸ¢£Ö×üýþÿÒÓÜÝDEþÿÒÓÜÝDE¨©Ö×<= ¡\]®¯¨©Ö×<= ¡\]®¯”•˜™”•˜™NOö÷tu˜™NOö÷tu˜™1lm¢£23LM@APQZ[žŸèéêëÔÕÖ×ØÙ‚ƒôõö÷èé1lm¢£23LM@APQZ[žŸèéêëÔÕÖ×ØÙ‚ƒôõö÷èé89rs~ìíðñ º»ÆÇÈÉúûXYòóôõ89rs~ìíðñ º»ÆÇÈÉúûXYòóôõ    ¸¹`aœÎÏÆÇ    ¸¹`aœÎÏÆÇ8989JKš›œ    €ÚÛ¨©¸¹òó  8989JKš›œ    €ÚÛ¨©¸¹òó   ¡DE¦§Þßàá ¡DE¦§Þßàá ¡>?†‡äåòóÎÏ ¡>?†‡äåòóÎÏBC ¡:;vwÞßàáäåæçòópq¤¥ÎÏBC ¡:;vwÞßàáäåæçòópq¤¥ÎÏðñ VWðñ VWÐÑPQÐÑPQŒxyÐÑPQJKŒxyÐÑPQJK‚ƒ‚ƒÔÕôõÔÕôõ:;¸¹ÀÁÎÏ:;¸¹ÀÁÎÏžŸ ¡¬­ÔÕ*+ !žŸ ¡¬­ÔÕ*+ !@Avw"#¾¿@Avw"#¾¿‚ƒÔÕÖ×$%´µ‚ƒÔÕÖ×$%´µHItu !~€¼½&'”•°±ÂÃÄÅÆÇ*+Z[œ¢£HItu !~€¼½&'”•°±ÂÃÄÅÆÇ*+Z[œ¢£vw()bcpqžŸÔÕvw()bcpqžŸÔÕ"#\]*+RS*+"#\]*+RS*+žŸÂà  ,-TUžŸÂà  ,-TU–—žŸ./’“–—žŸ./’“rstu`a–—˜™0167TUæç$%<=ŒŽ¨©îï  rstu`a–—˜™0167TUæç$%<=ŒŽ¨©îï  LMˆ‰23Š‹ðñLMˆ‰23Š‹ðñ,-012345ÂÃ,-012345ÂÃrs^_`a˜™0167TUæçŽîïðñrs^_`a˜™0167TUæçŽîïðñŽ89 ¡  Ž89 ¡  :;¤¥:;¤¥üýÜÝ<= ¡\]®¯üýÜÝ<= ¡\]®¯Þß>?~ÜÝhijkôõÞß>?~ÜÝhijkôõTUno@AŽ 89:;˜™ÐÑÒÓTUno@AŽ 89:;˜™ÐÑÒÓFG`a²³´µ$%&'BCBC"#$%ÞßFG`a²³´µ$%&'BCBC"#$%ÞßDERShi:;DERShi:;FG"#$%:;NOFG"#$%:;NOHI\]²³ØÙHI\]²³ØÙJKxyàáÔÕJKxyàáÔÕ^_LMÔÕ^_LMÔÕäåèéNOÔÕÜÝ67LMäåèéNOÔÕÜÝ67LMPQlm  "#45PQlm  "#45ÎÏDERShi˜™FGRS:;ÎÏDERShi˜™FGRS:;@ABC€„…†‡¾¿TU@ABCDE„…’“@ABC€„…†‡¾¿TU@ABCDE„…’“¦§òóVWÔÕ¦§òóVWÔÕŒ¤¥¶·ÐÑXYäåæçêëòó^_¼½jkŒ¤¥¶·ÐÑXYäåæçêëòó^_¼½jkôõö÷ÐÑZ[äåôõö÷ÐÑZ[äåpqrsäåÄÅÈÉHI\]ÄÅpqrsäåÄÅÈÉHI\]ÄÅLMˆ‰^_RSðñ˜™LMˆ‰^_RSðñ˜™ìí,-`aØÙ !¬­ØÙÚÛìí,-`aØÙ !¬­ØÙÚÛvw()bcpqäåjkvw()bcpqäåjkPQde  :;¦§îïPQde  :;¦§îïÞß ¡fgÞß ¡fgÎÏDERShi˜™FGRSTU|}ŒðñÎÏDERShi˜™FGRSTU|}Œðñjk,-jk,-PQlmÊË  âã45PQlmÊË  âã45@A67àá  no@Anoþÿ@A67àá  no@Anoþÿvw()bcpq‚ƒvw()bcpq‚ƒ†‡ÒÓÎÏrsZ[ÄÅæç†‡ÒÓÎÏrsZ[ÄÅæç”•¨©ª«êëtu()HI¶·”•¨©ª«êëtu()HI¶·89BCˆ‰vwxyÐÑäåæç<=VWpq89BCˆ‰vwxyÐÑäåæç<=VWpqxy€ˆ‰Z[vwxy:;<=VWrsxy€ˆ‰Z[vwxy:;<=VWrs&'z{‘°±&'z{‘°±01|}23ÀÁ*+Z[01|}23ÀÁ*+Z[>?~€ª«>?~€ª«BCFGÖ×~€‚ƒŠ‹ª«BCFGÖ×~€‚ƒŠ‹ª«BCžŸFGÔÕÖ×ØÙ€‚ƒæçôõª«ö÷BCpqèéBCžŸFGÔÕÖ×ØÙ€‚ƒæçôõª«ö÷BCpqèéš›()„…š›()„…>?ˆ‰†‡ÎÏ>?ˆ‰†‡ÎÏPQìí,-ˆ‰Š‹Ž89:;ÚÛPQìí,-ˆ‰Š‹Ž89:;ÚÛÄÅìíPQ‘ˆ‰Š‹Žþÿ89:;<=~ª«ÌÍØÙÚÛö÷ÄÅìíPQ‘ˆ‰Š‹Žþÿ89:;<=~ª«ÌÍØÙÚÛö÷Š‹ÒÓŒì튋ÒÓŒìíPQìíTUno@Aˆ‰Š‹Ž‘89:;˜™ÐÑÒÓPQìíTUno@Aˆ‰Š‹Ž‘89:;˜™ÐÑÒÓPQŽ‘   ®¯°±PQŽ‘   ®¯°±–—VW./’“–—VW./’“ !~ÀÁ&'”•ÆÇœêë !~ÀÁ&'”•ÆÇœêë–—&'–—&'ÎÏRShi˜™FGRSŒÎÏRShi˜™FGRSŒ ¡š›¨©°±²³´µ ¡š›¨©°±²³´µ@Ano¶·>?œ>?@ABCDE@Ano¶·>?œ>?@ABCDEžŸÊËœâ㦧ÆÇÈÉžŸÊËœâ㦧ÆÇÈÉÜÝ<= ¡\]®¯˜™ÜÝ<= ¡\]®¯˜™<=îïde¢£¤¥<=îïde¢£¤¥de¢£¤¥žŸde¢£¤¥žŸlm¦§øù@AFGlm¦§øù@AFGðñ𛍩ðñ𛍩@Aª«®¯´µþÿ@Aª«®¯´µþÿ¬­°±vwxy¬­°±vwxyª«®¯´µþÿª«®¯´µþÿ ¡š›¬­°±²³´µvw ¡š›¬­°±²³´µvw`a ¡š›°±²³´µ`a ¡š›°±²³´µ ¡š›ª«®¯°±²³´µ ¡š›ª«®¯°±²³´µ¶· !–—¶· !–—¸¹  ¸¹ÎÏ`a–—¸¹  ¸¹ÎÏ`a–—jkìíðñ º»ÆÇúûXYòóôõjkìíðñ º»ÆÇúûXYòóôõ¼½TU˜™š›æç¼½TU˜™š›æçÎÏ–—¾¿lmŒÎÏ–—¾¿lmŒno¸¹ÀÁno¸¹ÀÁÂÃ"#01¦§ÂÃ"#01¦§pqrsäåÂÃÄÅÆÇÈÉ\]ÄÅpqrsäåÂÃÄÅÆÇÈÉ\]ÄÅìíðñ º»ÆÇúûÞßXY¾¿òóôõìíðñ º»ÆÇúûÞßXY¾¿òóôõ!" ÈÉXYôõ!" ÈÉXYôõlmžŸÊËš›œâã45ÆÇÈÉlmžŸÊËš›œâã45ÆÇÈÉhiÌÍØÙhiÌÍØÙ ÊËJK`aÎÏâãîïôõލ©üýRS  ÊËJK`aÎÏâãîïôõލ©üýRS  @AvwÐÑ@AvwÐÑþÿÒÓ@ADEþÿÒÓ@ADE^_LMNOÔÕÜÝ67LM^_LMNOÔÕÜÝ67LMŽ‘Ö×ØÙ  Ž‘Ö×ØÙ  Ž`aÖ×ØÙ !tu¬­ØÙÚÛŽ`aÖ×ØÙ !tu¬­ØÙÚÛÈÉÚÛðñˆ‰./ÈÉÚÛðñˆ‰./Þßþÿ>?ÜÝhijkôõÞßþÿ>?ÜÝhijkôõ ¡DE¦§Þßàáìí ¡DE¦§Þßàáìí ¡´µ¶·Þßàáäå ¡´µ¶·Þßàáäå $%deÊËJKÎÏâãî﨩üý $%deÊËJKÎÏâãî﨩üýBCŒ¤¥´µ¶·ÐÑXYZ[bcvwàáäåæçòó^_jkº»¼½89jkpqBCŒ¤¥´µ¶·ÐÑXYZ[bcvwàáäåæçòó^_jkº»¼½89jkpqBC¤¥¶·¾¿ÐÑXYvw‚ƒäåæçòó&'^_¼½BCjkpqrsÊËèéBC¤¥¶·¾¿ÐÑXYvw‚ƒäåæçòó&'^_¼½BCjkpqrsÊËèé úûèéîïbc úûèéîïbcŒ€†‡Š‹ŒXYê대†‡Š‹ŒXYêë   JK¼½ìí¨©z{   JK¼½ìí¨©z{ ÊËJKÎÏâãèéîïbc¨©üý ÊËJKÎÏâãèéîïbc¨©üýÚÛðñˆ‰./º»ÚÛðñˆ‰./º» ¡¤¥¶·ÐÑXYäåæçòó^_¼½jkÎÏ ¡¤¥¶·ÐÑXYäåæçòó^_¼½jkÎÏžŸ`a¢£ÔÕÖ×ØÙ‚ƒÎÏôõrsŽö÷./‘º»  žŸ`a¢£ÔÕÖ×ØÙ‚ƒÎÏôõrsŽö÷./‘º»  xyz{NOö÷øùêëxyz{NOö÷øùêëz{|} ¡ö÷øùêëz{|} ¡ö÷øùêë’“jkìíðñ º»ÆÇúûüýXYòóôõ’“jkìíðñ º»ÆÇúûüýXYòóôõ˜™úûüý¨©âã  ˜™úûüý¨©âã  xyz{|}PQŠ‹þÿ89:;<=~„…î拉ÌÍ  xyz{|}PQŠ‹þÿ89:;<=~„…î拉ÌÍ  Âà  ,- !TUØÙÂà  ,- !TUØÙ`a ¡fg𛬭®¯°±²³´µ`a ¡fg𛬭®¯°±²³´µXYZ[ ¡š›°±²³´µ  vwxy~àá ¡ÜÝXYZ[ ¡š›°±²³´µ  vwxy~àá ¡ÜÝ!"ÈÉXYôõ!"ÈÉXYôõ@A 89vw@A 89vwde  vwxy~¦§àáÜÝde  vwxy~¦§àáÜÝPQlm  "#PQlm  "#()úûüý`aLMNOÎÏÔÕôõŽÜÝ67LM  ()úûüý`aLMNOÎÏÔÕôõŽÜÝ67LM  rs|}rs^_`a¢£ÖרÙ67NOÎÏÔÕôõTUrsŽÜÝ67LMº»  rs|}rs^_`a¢£ÖרÙ67NOÎÏÔÕôõTUrsŽÜÝ67LMº»  rsxy|}¬­¼½tu`aÖרÙ01ÎÏôõŽ<=  rsxy|}¬­¼½tu`aÖרÙ01ÎÏôõŽ<=  lmZ[èélmZ[è鈉^_®¯ðñ˜™ˆ‰^_®¯ðñ˜™)*|}23ÀÁZ[)*|}23ÀÁZ[üýz{ÜÝüýz{ÜÝz{ÌÍz{ÌÍHIÎÏRShi˜™FGRSHIÎÏRShi˜™FGRS¶· !–—¶· !–—$%./BCBCFG"#$%èéNOÞß$%./BCBCFG"#$%èéNOÞßBCBCFG"#$%NOBCBCFG"#$%NOBC¾¿æç&'ÔÕÖ×pqrsÊËBC¾¿æç&'ÔÕÖ×pqrsÊË01:;()./01:;()./¢£*+‘¢£*+‘ÌÍ014589z{|},-ÌÍ014589z{|},-¢£()./45defg¢£()./45defg89z{01¸¹†‡89z{01¸¹†‡01|}23Z[01|}23Z[¢£./45defg¢£./45defgŠ‹6789bcÒÓŠ‹6789bcÒÓPQš›PQTUno@Aˆ‰Š‹Žþÿ 6789:;<=tu~˜™ÌÍÐÑÒÓPQš›PQTUno@Aˆ‰Š‹Žþÿ 6789:;<=tu~˜™ÌÍÐÑÒÓ€Z[|}PQTUno@AFGdexyˆ‰Š‹Žþÿ89:;<=xy~˜™îï  ÌÍÐÑÒÓÚÛ€Z[|}PQTUno@AFGdexyˆ‰Š‹Žþÿ89:;<=xy~˜™îï  ÌÍÐÑÒÓÚÛ€ˆ‰ÎÏZ[PQvwxyŠ‹þÿ89:;<=VW~ÌÍ€ˆ‰ÎÏZ[PQvwxyŠ‹þÿ89:;<=VW~ÌÍ@A67¶·¸¹>?œ>?@ABCDE@A67¶·¸¹>?œ>?@ABCDE@A67 ¡¶·>?ŒTUnoœ>?@ABCDEnoþÿÎÏ@A67 ¡¶·>?ŒTUnoœ>?@ABCDEnoþÿÎÏ@A¶·>?†‡TUœ>?@ABCDE„…@A¶·>?†‡TUœ>?@ABCDE„…@A¶·>?†‡TUœ>?@ABCDE„…@A¶·>?†‡TUœ>?@ABCDE„…ÎÏRShi˜™FGRSTU|}ðñÎÏRShi˜™FGRSTU|}ðñFGÈÉØÙtuøùúûHIFGÈÉØÙtuøùúûHIÐÑö÷úûJKÐÑö÷úûJKLMPQLMPQpqäå–—NOpqäå–—NOPQØÙúûPQØÙúû`aÎÏRS^_hi˜™FGRSTU|}æçðñš›`aÎÏRS^_hi˜™FGRSTU|}æçðñš›^_`a0167hi¼½FGRSTU|}æçðñ˜™š›æç^_`a0167hi¼½FGRSTU|}æçðñ˜™š›æçxyˆ‰ØÙvwxy<=VWrs”•xyˆ‰ØÙvwxy<=VWrs”•¨©Ö×°±XY†‡Œ¨©Ö×°±XY†‡Œ†‡ÎÏrsZ[>?Äņ‡ÎÏrsZ[>?ÄÅ<= ¡\]®¯˜™<= ¡\]®¯˜™¤¥¶·º»ÐÑXYäåæçòó^_¼½jk¤¥¶·º»ÐÑXYäåæçòó^_¼½jk  `aÒÓ  `aÒÓúûèéîïbcLMúûèéîïbcLM¢£|}./45defg¢£|}./45defgvw !z{|}./45defgfgvw !z{|}./45defgfg²³º»Þß>?ÜÝhijkôõ²³º»Þß>?ÜÝhijkôõÞß>?ÜÝäåhijk¼½ôõ89Þß>?ÜÝäåhijk¼½ôõ89lmno‚ƒÊËlmno‚ƒÊË@A67ðñno@AlmnoÊËþÿ@A67ðñno@AlmnoÊËþÿ  @AXYpqrs  @AXYpqrs  @AXY¢£Ö×ôõpqrsº»  @AXY¢£Ö×ôõpqrsº»89tu˜™89tu˜™¬­°±   vwxy~àáÜݬ­°±   vwxy~àáÜÝJK¬­  :;vwxy~àáÜÝJK¬­  :;vwxy~àáÜÝüýz{üýz{hiFGRSTU|}ðñhiFGRSTU|}ðñPQŠ‹þÿ  89:;<=vwxy~àáÌÍÜÝPQŠ‹þÿ  89:;<=vwxy~àáÌÍÜÝJKrs  €JKrs  €xy˜™lm‚ƒ„…xy˜™lm‚ƒ„…xyz{|}†‡TUþÿBCDE‚ƒ„…î拉  xyz{|}†‡TUþÿBCDE‚ƒ„…î拉  úû¨©ª«Ö×°±XY†‡úû¨©ª«Ö×°±XY†‡pqÈÉÚÛðñˆ‰pqÈÉÚÛðñˆ‰FG€Š‹^_FG€Š‹^_fgÔÕêëìíôõøùþÿhi˜™ŒÌÍhi|}~fgÔÕêëìíôõøùþÿhi˜™ŒÌÍhi|}~+,Œ¸¹ÒÓÔÕèéêëìíôõøù`aÎÏôõŽPQRS  +,Œ¸¹ÒÓÔÕèéêëìíôõøù`aÎÏôõŽPQRS  &'45¤¥ÀÁz{*+‘’“&'45¤¥ÀÁz{*+‘’“45€‘’“45€‘’“¨©&'FGæç”•^_¨©&'FGæç”•^_¦§bcfglm–—¦§bcfglm–—TUno@AŽ89:;tu˜™ÐÑÒÓTUno@AŽ89:;tu˜™ÐÑÒÓÊËš›45ÆÇÊËš›45ÆÇ  žŸÊËœâãÆÇÈÉ  žŸÊËœâãÆÇÈÉvw()žŸÔÕvw()žŸÔÕ¦§89 ¡¦§89 ¡¢£ÔÕ  ¢£ÔÕ  $%bcdexy¤¥ÐÑJK$%bcdexy¤¥ÐÑJKPQde  ¦§PQde  ¦§    ÊËJKÎÏâãìíî﨩üýz{    ÊËJKÎÏâãìíî﨩üýz{FG~€‚ƒª«FG~€‚ƒª«>?@A´µ¬­º»>?@A´µ¬­º»<= ¡\]®¯<= ¡\]®¯&'&'z{°±ÄÅ¢£&'&'z{°±ÄÅ¢£HI²³ØÙHI²³ØÙ´µ|}€àá´µ|}€àáDEØÙ¶·DEØÙ¶·<=01¸¹defg†‡<=01¸¹defg†‡>?¤¥´µä嬭º»>?¤¥´µä嬭º»¤¥¶·ÐÑXYäåæçòó^_jk¼½89jk¤¥¶·ÐÑXYäåæçòó^_jk¼½89jk|}PQvw"#¾¿ìíîï|}PQvw"#¾¿ìíîï)*°±|}ÀÁÂÃ)*°±|}ÀÁÂÃ)*°±€¼½|}&'ÀÁÂÃdefg)*°±€¼½|}&'ÀÁÂÃdefgtu !ÀÁ&'°±ÄÅÆÇ*+¢£tu !ÀÁ&'°±ÄÅÆÇ*+¢£tu !&'”•ÄÅÆÇ*+êëtu !&'”•ÄÅÆÇ*+êëNO”•¨©ÈÉNO”•¨©ÈÉ@AðñlmnoÊË@AðñlmnoÊËþÿŒÌÍþÿŒÌÍno:;¸¹  ¸¹ÎÏ`a–—no:;¸¹  ¸¹ÎÏ`a–— >?ŒÔÕ¬­xy¤¥ÐÑRSJK >?ŒÔÕ¬­xy¤¥ÐÑRSJK`aÒÓ`aÒÓòó()VW&'žŸÔÕÖ×òó()VW&'žŸÔÕÖ×&'ÔÕÖ×&'ÔÕÖ×89VWrsŽ~îïHIÌÍPQ²³ØÙÚÛúûVW89VWrsŽ~îïHIÌÍPQ²³ØÙÚÛúûVW89rsš›œ  ØÙÚÛ¨©¸¹òó89rsš›œ  ØÙÚÛ¨©¸¹òóüýNOÔÕÜÝ67LMüýNOÔÕÜÝ67LMÆÇÞߦ§¾¿ÆÇÞߦ§¾¿JK  vwxy~àáÔÕÜÝJK  vwxy~àáÔÕÜÝlmžŸÊËœâã45ÆÇÈÉlmžŸÊËœâã45ÆÇÈÉHI^_äåHI^_äårs`a˜™0167RSTUæçŽš›rs`a˜™0167RSTUæçŽš›FG./BCøù"#èéFG./BCøù"#èéz{"#TUö÷øùêëìíz{"#TUö÷øùêëìí|}ÒÓ"#DEPQ¦§ŒÞß¾¿êëìíîï|}ÒÓ"#DEPQ¦§ŒÞß¾¿êëìíîïxyz{|}ÒÓ"#DEPQvw¦§deþÿ:;„…¾¿ìíî拉  xyz{|}ÒÓ"#DEPQvw¦§deþÿ:;„…¾¿ìíî拉  ˆ‰^_hiFGRSTU|}ðñ˜™ˆ‰^_hiFGRSTU|}ðñ˜™ÎÏòóÎÏòóÞß>?ÜÝhijkôõÞß>?ÜÝhijkôõžŸÔÕÖ×ØÙ‚ƒôõö÷žŸÔÕÖ×ØÙ‚ƒôõö÷lm¦§øùFG\]lm¦§øùFG\]VW~PQØÙúûVWVW~PQØÙúûVW  ÊËJKÎÏâãî﨩üý  ÊËJKÎÏâãî﨩üý@A67noª«®¯@Anoþÿ@A67noª«®¯@Anoþÿ89š›œ  vwÚÛ¨©¸¹òó89š›œ  vwÚÛ¨©¸¹òó@AvwÐÑ@AvwÐѦ§ ¡¦§ ¡vwª«vwª«PQ‘‘   tu®¯°±²³ÌÍPQ‘‘   tu®¯°±²³ÌÍŽ‘š›œ®¯‘:;   ®¯°±ÌÍÚÛŽ‘š›œ®¯‘:;   ®¯°±ÌÍÚÛŽ‘89Ö×  Ž‘89Ö×  ’“Œ’“Œ@A67no@Anoþÿ@A67no@Anoþÿ@A67nonoœ@Anoþÿ@A67nonoœ@Anoþÿ®¯°±Þß>?ÜÝhijkôõ®¯°±Þß>?ÜÝhijkôõ@A¬­ vwxy@A¬­ vwxyÔÕôõÔÕôõØÙtu®¯ØÙtu®¯`aÒÓ`aÒÓfg‘œòóÒÓˆ‰æçfg‘œòóÒÓˆ‰æç`aØÙ !¬­ØÙÚÛ`aØÙ !¬­ØÙÚÛ:;Ö×°±PQÂà  "#$%Ž:;Ö×°±PQÂà  "#$%Ž:;01"#$%ŒŽ¨©:;01"#$%ŒŽ¨©–—&'bc°±²³–—&'bc°±²³:;”•¨©ª«¸¹êëtu()`a:;”•¨©ª«¸¹êëtu()`atu !&'|}ÄÅÆÇ*+Z[tu !&'|}ÄÅÆÇ*+Z[ÄÅjk,-ÄÅjk,-ÚÛðñôõ./‘º»ÚÛðñôõ./‘º»ÂÃ01¦§ÂÃ01¦§‘œèé23‘œèé23PQlmÊËš›âã45ÆÇPQlmÊËš›âã45ÆÇª«()NOÔÕÜÝ67LMª«()NOÔÕÜÝ67LMäåjk¼½89äåjk¼½89fgÔÕèéêëìíôõDERS:;fgÔÕèéêëìíôõDERS:;rsêëtu01<=  rsêëtu01<=  Z[>?˜™ÄÅZ[>?˜™ÄŦ§ÒÓ@ABCDEFG¦§ÒÓ@ABCDEFGBCHIrs‚ƒæç@ABCpqèéäå  BCHIrs‚ƒæç@ABCpqèéäå  þÿÒÓ@ADEþÿÒÓ@ADE¦§øù@AFG¦§øù@AFG¨©tuHI¶·¸¹¼½ÀÁ¨©tuHI¶·¸¹¼½ÀÁîï$%bcde¾¿¤¥JKîï$%bcde¾¿¤¥JKúûNOÔÕbcÜÝ67LMúûNOÔÕbcÜÝ67LMvwFG"#$%NOvwFG"#$%NOŒLMŽPQRSŒLMŽPQRS ŒÔÕ¬­ÎÏŽÐÑPQRS ŒÔÕ¬­ÎÏŽÐÑPQRS ¡Âà  ,-TU ¡Âà  ,-TUVW~ðñØÙúûVWVW~ðñØÙúûVWìíðñ º»ÆÇÈÉúûXYòóôõìíðñ º»ÆÇÈÉúûXYòóôõ&'|}23*+Z[&'|}23*+Z[lm¢£&'lmøù\]lm¢£&'lmøù\]¨©æçŠ‹”•^_¨©æçŠ‹”•^_:;¸¹¸¹ÎÏ()`a–—:;¸¹¸¹ÎÏ()`a–—Š‹º»67&'bcÒÓŠ‹º»67&'bcÒÓ<=|}¸¹ÂÃdefg<=|}¸¹ÂÃdefg)*vw !<=z{|}fg¸¹ÂÃdefg)*vw !<=z{|}fg¸¹ÂÃdefg+,ÔÕèéêëôõøùŒhi+,ÔÕèéêëôõøùŒhi¤¥¶·ÐÑXYbcäåæçòó^_¼½jk¤¥¶·ÐÑXYbcäåæçòó^_¼½jkÎϾ¿lmŒÎϾ¿lmŒ*+,-23ÂÃno¬­¶·ÀÁ*+,-23ÂÃno¬­¶·ÀÁBC„…†‡¾¿vw‚ƒäåæç&'BCpqrsÊËèéBC„…†‡¾¿vw‚ƒäåæç&'BCpqrsÊËèé-./0BCxyZ[€¾¿xyæç&'VWpqrs’“”•ÊË-./0BCxyZ[€¾¿xyæç&'VWpqrs’“”•ÊËØÙ tu®¯ØÙ tu®¯*+,-./¬­vw*+,-./¬­vw Ê˼½xyz{ Ê˼½xyz{   ÊËJK¼½ìí¨©xyz{   ÊËJK¼½ìí¨©xyz{Œ´µ|}€Œ´µ|}€Œ~àáŒ~àá´µ|}€àá´µ|}€àávwpq‚ƒvwpq‚ƒ45\]^_ÂÃÄÅôõ„…ÚÛ45\]^_ÂÃÄÅôõ„…ÚÛ8901¸¹†‡8901¸¹†‡fgèéòóˆ‰fgèéòóˆ‰23Š‹Œ23Š‹Œ’“Ö×01¾¿XY$%lmŠ‹ŒŽ¨©’“Ö×01¾¿XY$%lmŠ‹ŒŽ¨©89:;rs˜™0167æç"#$%ŒŽ¦§¨©ÈÉâã89:;rs˜™0167æç"#$%ŒŽ¦§¨©ÈÉâãôõ./‘º» ôõ./‘º» -.xyXYjk„…†‡¼½fghi€†‡¾¿TUrs’“”•žŸ ¡-.xyXYjk„…†‡¼½fghi€†‡¾¿TUrs’“”•žŸ ¡-./0xyZ[€ØÙVWrs’“”•-./0xyZ[€ØÙVWrs’“”•NOTUÆÇpqrs¸¹àá¶·¸¹ !ÎÏ`a–—NOTUÆÇpqrs¸¹àá¶·¸¹ !ÎÏ`a–—ˆ‰”•^_ ¡¼½TU\]ðñ>?˜™š›æçˆ‰”•^_ ¡¼½TU\]ðñ>?˜™š›æç`a¼½RSTUæç˜™š›æç`a¼½RSTUæç˜™š›æç !~&'”•œžŸ !~&'”•œžŸ !XYàá  de¤¥’“œžŸ ¡ !XYàá  de¤¥’“œžŸ ¡XYZ[’“žŸ ¡XYZ[’“žŸ ¡¤¥ÀÁ&'°±ÄÅ¢£ê뤥ÀÁ&'°±ÄÅ¢£êëxyz{|}:;þÿ„…î拉  xyz{|}:;þÿ„…î拉  89žŸÂÃÞß01ަ§¨©¾¿ÆÇÈÉâã89žŸÂÃÞß01ަ§¨©¾¿ÆÇÈÉâã89š›œ  01üýÚÛ$%ŒŽ¦§¨©¸¹ÈÉâãòó89š›œ  01üýÚÛ$%ŒŽ¦§¨©¸¹ÈÉâãòóÄőЋª«ØÙÚÛö÷ÄőЋª«ØÙÚÛö÷*+,-23ÂÃ`aØÙ !no¬­ØÙÚÛ*+,-23ÂÃ`aØÙ !no¬­ØÙÚÛ‘   tu®¯°±‘   tu®¯°±‘   &'®¯°±²³‘   &'®¯°±²³ &'°±²³ &'°±²³œÒÓÔÕÖ×$%´µœÒÓÔÕÖ×$%´µ!"89ª«tuHIno¶·¸¹¼½ÀÁ!"89ª«tuHIno¶·¸¹¼½ÀÁ89š›œª«  ÚÛHI¨©¶·¸¹¼½ÀÁòó89š›œª«  ÚÛHI¨©¶·¸¹¼½ÀÁòó¢£Ö×ðñôõrs./‘º»¢£Ö×ðñôõrs./‘º»!"HI¶·¸¹¼½ÀÁ!"HI¶·¸¹¼½ÀÁÆÇÞߦ§¾¿ÆÇÞߦ§¾¿,-HIno¶·¸¹¼½ÀÁ,-HIno¶·¸¹¼½ÀÁ./01¬­®¯45ÂÃ./01¬­®¯45ÂÃrsZ[>?ÄÅrsZ[>?ÄÅ  žŸÊËš›œâã45¦§ÆÇÈÉ  žŸÊËš›œâã45¦§ÆÇÈÉ89pqâ㞟ÊËœâ㎦§¨©ÆÇÈÉâã  89pqâ㞟ÊËœâ㎦§¨©ÆÇÈÉâã  BC‚ƒ„…¾¿æç&'pqrsÊËBC‚ƒ„…¾¿æç&'pqrsÊËPQ‘Š‹þÿ89:;<=~   ÌÍPQ‘Š‹þÿ89:;<=~   ÌÍ ¡>?ˆ‰†‡òó@AÎÏ ¡>?ˆ‰†‡òó@AÎϺ»TUno@AŽ89:;˜™ÐÑÒÓº»TUno@AŽ89:;˜™ÐÑÒÓŠ‹TUno@AŽ6789:;˜™bcÐÑÒÓŠ‹TUno@AŽ6789:;˜™bcÐÑÒÓJK¢£àáÔÕ  JK¢£àáÔÕ  €ˆ‰Š‹Ö×€ˆ‰Š‹Ö×,-ÄÅ,-‘`aŠ‹ØÙ !ª«¬­ØÙÚÛö÷,-ÄÅ,-‘`aŠ‹ØÙ !ª«¬­ØÙÚÛö÷ÂÃÄÅŽ‘š›œ®¯ôõ`aˆ‰Š‹ØÙ:;   !„…ª«¬­ØÙÚÛö÷* + ÂÃÄÅŽ‘š›œ®¯ôõ`aˆ‰Š‹ØÙ:;   !„…ª«¬­ØÙÚÛö÷* +   vwxy~àáÜÝ  vwxy~àáÜÝ`a$%BC"#Þß`a$%BC"#Þß´µ~€àá´µ~€àá89üýަ§¨©ÈÉâã89üýަ§¨©ÈÉâãDEÌÍö÷äåDEÌÍö÷ä呜æç ÒÓæç‘œæç ÒÓæç1BC23LM@APQ‚ƒæçBCpqèé1BC23LM@APQ‚ƒæçBCpqèé !¤¥ÀÁ”•ÆÇ¢£êë !¤¥ÀÁ”•ÆÇ¢£êëìí   "#89ìí   "#89%&îïúû  &',-FGPQRS%&îïúû  &',-FGPQRSðñüýðñüý²³òóôõö÷úûüýþÿ  ()HIRS²³òóôõö÷úûüýþÿ  ()HIRS%&23´µòóôõö÷úûüý  XYbc%&23´µòóôõö÷úûüý  XYbc²³òóôõö÷úûüý²³òóôõö÷úûüý>?øù>?øù%&îïòóôõö÷úûüýþÿ  &'(),-FGHINOPQRS%&îïòóôõö÷úûüýþÿ  &'(),-FGHINOPQRSðñòóôõö÷úûüýðñòóôõö÷úûüýòóúûþÿ  ()HINORSòóúûþÿ  ()HINORS>?š›ÚÛ"#^_>?š›ÚÛ"#^_:;HI:;HIº»:;º»:;%&îïúû  &',-FGPQRS%&îïúû  &',-FGPQRSìí   $%89ìí   $%89>?ìí   89>?ìí   89%&23îïòóôõúûþÿ  &'()*+,-FGHIPQRSXYbc%&23îïòóôõúûþÿ  &'()*+,-FGHIPQRSXYbc*+,-<=>?FGVWXY\]*+,-<=>?FGVWXY\]()BCNO()BCNOBCPQBCPQúûüýþÿNOúûüýþÿNOZ[`aZ[`aúû()BCNOúû()BCNOìí $%ìí $%"#@A"#@A>?îïðñö÷¾¿>?îïðñö÷¾¿ !23 !23 ìí"#./4589@ALM^_ ìí"#./4589@ALM^_ìívw $%ìívw $%%&îïúû  &',-FGPQRS`a%&îïúû  &',-FGPQRS`aòóúûþÿ  ()BCHIRSòóúûþÿ  ()BCHIRS  *+<=FGVW  *+<=FGVW%&îïúû  &',-<=FGPQRS%&îïúû  &',-<=FGPQRS "#./014567@A "#./014567@A <=Œ./0145XY <=Œ./0145XY !2367 !2367 <=Œ"#./0145@AXY <=Œ"#./0145@AXY./2367./2367>?ìí   "#89>?ìí   "#89:;HI:;HI*+,-<=VW*+,-<=VW>?VWXY\]>?VWXY\] "#./45@A "#./45@A()BCPQ()BCPQDE\]`aDE\]`a%&îïúû  &'*+,-FGPQRS%&îïúû  &'*+,-FGPQRSòóúûþÿ  ():;HIRSòóúûþÿ  ():;HIRS>?ŒxyÐÑJK>?ŒxyÐÑJK"#LM^_"#LM^_úûþÿNOúûþÿNO%&îïúû  &',-BCFGPQRS%&îïúû  &',-BCFGPQRS%&îïòóúûþÿ  &'(),-FGHIPQRS%&îïòóúûþÿ  &'(),-FGHIPQRSTU\]`aTU\]`a*+<=>?VWXY\]*+<=>?VWXY\] %&23<=Œxy°±ôõ  0145>?VWXY\]`abc %&23<=Œxy°±ôõ  0145>?VWXY\]`abcZ[`aZ[`a>?DETUVWXY\]`a>?DETUVWXY\]`a"#LM^_"#LM^_%&&'DETUXYZ[\]`abc%&&'DETUXYZ[\]`abc%&23ôõ  XY`abc%&23ôõ  XY`abc\]de¼½$ % \]de¼½$ % fgxyz{‘’“žŸÊË& ' fgxyz{‘’“žŸÊË& ' îïhino”•²³ îïhino”•²³ XYjk„… ¡®¯ÈÉXYjk„… ¡®¯ÈÉlmŽÀÁÒÓ  ! " # lmŽÀÁÒÓ  ! " # îïhino”•ª«²³îïhino”•ª«²³pq„…†‡ˆ‰Š‹¢£ÎÏÜÝàá  pq„…†‡ˆ‰Š‹¢£ÎÏÜÝàá  ~‘rstu~‘rstu~‘rstu~‘rstuvw€Žvw€Žfgxyz{€‘’“ÊË& ' fgxyz{€‘’“ÊË& ' fgxyz{‘’“ÆÇÊËúû& ' fgxyz{‘’“ÆÇÊËúû& ' |}Žüý ! |}Žüý ! Z[~¼½Z[~¼½vwxy€ŽÆÇÎÏúûüývwxy€ŽÆÇÎÏúûüýXY‚ƒ†‡Š‹ÈÉÌÍàáXY‚ƒ†‡Š‹ÈÉÌÍàáXYjkpq„…†‡ˆ‰Š‹®¯ÈÉàá  XYjkpq„…†‡ˆ‰Š‹®¯ÈÉàá  XY^_pq‚ƒ„…†‡ˆ‰Š‹˜™àá  XY^_pq‚ƒ„…†‡ˆ‰Š‹˜™àá  ^_pq„…†‡ˆ‰Š‹˜™àá  ^_pq„…†‡ˆ‰Š‹˜™àá  pq‚ƒ„…†‡ˆ‰Š‹àá  pq‚ƒ„…†‡ˆ‰Š‹àá  Œ¤¥ª«ÀÁÂÃÄÅÒÓŒ¤¥ª«ÀÁÂÃÄÅÒÓlmvw|}€Ž ¡¾¿ÒÓ  " # lmvw|}€Ž ¡¾¿ÒÓ  " # '(bcfgxyz{‘’“žŸÆÇÊË& ' ( ) '(bcfgxyz{‘’“žŸÆÇÊË& ' ( ) '(bcfgxyz{‘’“ÊË& ' '(bcfgxyz{‘’“ÊË& ' hino”•ª«hino”•ª«–—˜™š›œ ¡¦§®¯ÚÛ–—˜™š›œ ¡¦§®¯ÚÛ^_ÆÇ@A†‡ˆ‰–—˜™¶·¸¹0 1 ^_ÆÇ@A†‡ˆ‰–—˜™¶·¸¹0 1 –—𛦧ÐÑâã–—š›¦§ÐÑâãXY–—œ¦§®¯XY–—œ¦§®¯bcfg‘žŸbcfg‘žŸ23XY$%<=vw¢£¶·DERSjkŽ–— ¡¾¿Ö×ÚÛ, - 23XY$%<=vw¢£¶·DERSjkŽ–— ¡¾¿Ö×ÚÛ, - pq¢£ÊËÎÏÜÝþÿ  ( ) pq¢£ÊËÎÏÜÝþÿ  ( ) Œ¤¥ª«ÄÅŒ¤¥ª«ÄÅ–—š›œ¦§®¯–—š›œ¦§®¯†‡¨©´µ¶·º»¼½ÐÑÔÕÞ߆‡¨©´µ¶·º»¼½ÐÑÔÕÞßXYnoŒ”•¤¥ª«¬­°±ÂÃÄÅêëXYnoŒ”•¤¥ª«¬­°±ÂÃÄÅêë~89VWXYª«¬­°±ÂÃ~89VWXYª«¬­°±ÂÃXYjk„…–—œ¦§®¯ÈÉXYjk„…–—œ¦§®¯ÈÉ~XYª«¬­°±ÂÃ~XYª«¬­°±ÂÃîïhino²³îïhino²³¨©´µ¶·¸¹Þߨ©´µ¶·¸¹Þߘ™¨©´µ¶·¸¹Þߘ™¨©´µ¶·¸¹Þ߯Ç@A˜™´µ¶·¸¹Þß0 1 ÆÇ@A˜™´µ¶·¸¹Þß0 1 ¨©º»¼½ÐѨ©º»¼½ÐÑZ[de~¨©º»¼½ÐÑZ[de~¨©º»¼½ÐÑŽ ¡¾¿Ž ¡¾¿lmŒÀÁÂÃÄÅÒÓlmŒÀÁÂÃÄÅÒÓ'(~XYŒª«¬­°±ÀÁÂÃÒÓ'(~XYŒª«¬­°±ÀÁÂÃÒÓŒ¤¥ª«ÀÁÄÅŒ¤¥ª«ÀÁÄÅz{€‘ÆÇúûüýz{€‘ÆÇúûüýXYjk‚ƒ„…®¯ÈÉXYjk‚ƒ„…®¯ÈÉfgxyz{‘’“¢£ÊË& ' ( ) fgxyz{‘’“¢£ÊË& ' ( ) \]‚ƒÌÍ\]‚ƒÌÍpq€¢£ÎÏÜÝpq€¢£ÎÏÜÝš›¨©º»¼½ÐÑâãš›¨©º»¼½ÐÑâãlmŒŽÀÁÂÃÒÓ  " # lmŒŽÀÁÂÃÒÓ  " # †‡01¨©ÔÕ†‡01¨©ÔÕRSêë ¡Ö×RSêë ¡Ö×%&'(23~$%89„…LMúûØÙ%&'(23~$%89„…LMúûØÙ–— ¡ÚÛ–— ¡ÚÛpq¢£ÎÏÜÝþÿ( ) pq¢£ÎÏÜÝþÿ( ) ¨©´µ¶·¸¹Þߨ©´µ¶·¸¹Þßpq‚ƒ„…†‡ˆ‰Š‹àá  pq‚ƒ„…†‡ˆ‰Š‹àá  š›ÐÑâãš›ÐÑâãrsÀÁBCäå    rsÀÁBCäå    †‡ÒÓrs¼½TU˜™š›æç†‡ÒÓrs¼½TU˜™š›æçtuˆ‰:;¦§¨©ª«èétuˆ‰:;¦§¨©ª«è骫êëìí ª«êëìí îïêëìí îïêëìí LM`a0167îïðñLM`a0167îïðñLMˆ‰2367îïðñLMˆ‰2367îïðñ89rsš›œìíðñ   º»ÆÇúûÚÛXY¨©¸¹òóôõ89rsš›œìíðñ   º»ÆÇúûÚÛXY¨©¸¹òóôõìíðñ º»ÆÇÈÉúûXYòóôõìíðñ º»ÆÇÈÉúûXYòóôõÄőЋª«ØÙÚÛö÷* + ÄőЋª«ØÙÚÛö÷* + "#\]^_žŸøù"#\]^_žŸøùz{€ÆÇúûüýz{€ÆÇúûüý|}€ÆÇúûüý|}€ÆÇúûüý¢£ÜÝþÿ  ( ) ¢£ÜÝþÿ  ( ) pq„…†‡ˆ‰Š‹¢£àáþÿ  pq„…†‡ˆ‰Š‹¢£àáþÿ  rs`aÎÏôõŽ   rs`aÎÏôõŽ   pqˆ‰âã89  ÈÉ      pqˆ‰âã89  ÈÉ      ˆ‰      ˆ‰      ‘   ‘   rs‘   rs‘   îïhiêëìí îïhiêëìí ˜™ØÙ‘¬­®¯  ˜™ØÙ‘¬­®¯  noüý !ŒÚÛ  noüý !ŒÚÛ  rsÀÁÄÅBCäå    rsÀÁÄÅBCäå    hiÀÁäå    hiÀÁäå    ˆ‰<=      ˆ‰<=      –—˜™01üý  –—˜™01üý  |}¢£ÔÕ    |}¢£ÔÕ    xyz{|}þÿ„…î拉    xyz{|}þÿ„…î拉    lmŽÒÓ  ! " # lmŽÒÓ  ! " # lm|}  ! lm|}  ! lmŽÒÓ  " # lmŽÒÓ  " # \]de$ % \]de$ % fgxyz{‘’“ÊË& ' ( ) fgxyz{‘’“ÊË& ' ( ) ‘¢£ÊËÜÝþÿ& ' ( ) ‘¢£ÊËÜÝþÿ& ' ( ) úûÚÛö÷* + úûÚÛö÷* + 23òó$%<=vw¢£¶·ØÙDERSøùúû ¡, - 23òó$%<=vw¢£¶·ØÙDERSøùúû ¡, - z{01. / 0 1 z{01. / 0 1 z{./01ÆÇ@A˜™¸¹. / 0 1 z{./01ÆÇ@A˜™¸¹. / 0 1 (œ0€™Ó@fÝ>+ 7§À,{3âB@Uü‰wdÌ$@giM¯Ý?@Ü*ü£ 5@~##K@n1Àmè?à!À˜¿>.¸Ú@èQ«ˆ´iA ¹SÔKÀ|¥ÛÄÛt@µUòuµøù@„TØ?µ¡Àô;\ÌÙC&À ¹ý‚ëÆX@‘ßHù¥@S›Gxœ@¯(‘ÝuÛ@sAº2§ÄÀ¶yòýS@¶¼±$j\@{”Qû{Û@©’å…–ä@¤ò3´§>Æ@qôRkÎ@Û¿Øã@©EobYA—+¿Ç–<À狻ąT@rþ‘g@ƒÄ$œÚ@w©ÌñÏ”@@µ¨7³Þ2@V‘óƒØ@V@Uó @a&–A“UlËœiA}iäÞ“òU@±ÑÙ:Ü$ÀJO“¢¶Àñs¯ ŽzÐÀO‹õIžÜ@ÀT™$@Uà&@ä'qò….Ó@ûû»¬—ß¡@€n‘î­²ªÀ<ó㡺ÿÞÀŠ Áì"•@Ñc§që@ '2m-À²7`õ~|˜@,Î#ŽÁ ^@˜/÷œÀAõ?Kœ®Ûëë@ÒoccÎd@›¬Z¬òÀp@ðpŸ¸‰Y@p…þXoS$@ \Á?.}Àìáx‡|ó«ÀS‹Õä*KÀZ¶¯üüh@Jî&wø@tÎz¾¶ÆÀVÉax;r@ù©Vò çtÀØ÷îׯp@ûº!´ÒD@´±7t>HfÀÉÁ˜üWÀLëI¼0bÀ]Îö2¯ØÀgY¤3ÝÃ@@vV‰ì?Žo@øÃý#©À@JƒCª2@=Pàï0Àïûò0rM¬Àiù? ¡É¾@„å±Â3À­öà‘áÜ^ÀÏÄRïÐic@61EZ¶3âÀ†û¹Æ> ¾Àªÿ¹¸aoÀ`Hv8Z:³À‡’ä#ÀtCÛ†ó?9vnýo¹MÀî·*u1X@`6›™@˜‡ç‚@Æú3ú&I£@2íeÏkfŒ@ŽYiÛ®K@/¦äéÓÀ…Y}áÖUjÀ†LUºD¤À—«µý#FAFèg5“ô@}3e׌{@(»È;¼£À¿‰Ú†Yn@!> [èLB@ Á¦çúˆ¢@ªk2Š#\d@„4.·YÀŸû˜È×Dâ@×{F¤4¶ú@Òÿ.ÊÆGÞ@=éÙŠÆâ5À_CÂ!`ë=À=½¬Ý…¦ßÀîκV»Ä@‡Ò½ßcAÀð2G‡³@âÓb‹ôf@3í¦Ê=D@е¡@¡3¸„tŽÀ!­ i¯]@eQç—k@•‰™¡ƒ–ÀxŠrccÛI@0ôbZ‘À]÷>ËQbÀ§<ÀoÒ1•Ào70ãŠTiÀ…Á’¢À;¥¤žÌˆÀÎQr“sZþ?žNjöpG@m¶!g³çæ?ƒEÈC-@R•©ˆ9@ÉYÿ[ºí?Úãqløí¿Y3Ö$:×Ó?”›ùI›ÐÀíM0½Sª@ֈϾÝY@‘³¾%ŠW¬@€g3kvD¶@óð`дtÐ@÷Ô/7-‘@¶<C” ß@T·‰ù@€@€rF¦»@€cøùQN@Ya&#y@#ä¶Ö±Àú±çÄÀC2äØzTf@±”H2`²@bÁ¬‹#~@—:›»À«@àçN‘øÀ_ìÆ¤–Æ@> ÛSt.`@z*V« Ø@rùë ³¬ÀÀ¾Út`oR#ÀHnÕkœ@¢‘ëÄV@€mUäÓ–¾À÷EçZ2ÀU‰5ÜœEâ@Ct"ù¾@²Pÿ;OØm@‡DØjAý²@¦aeü5ÀgŒÏâÔ@°ÛfȺÃß@ÖðžäfpÄÀM$1ò.E@¡Z¾––³Àóå6ŸKtX@wŠHª;ï@«îVËìÁ@Æâ³Ìjì»@ígÇ xÁV2¶”ÀÔ@|ãIð… À¢Ë—S§Ž@Çç•-^ÀS”0 ÛgÀnŽZO÷¶À(Ž›”‡:‡@`‘»f”)Ì@qmæþ,•ò?äC ÈÀ`×  ¿Àðè?S"ƒ@x²¾H˜l£@¯vb¨"xÀ§¤§â£@ëëÕ k—@lÞ¾mJч@ÚNç1$C ÀÕóû5Ž@D„4Gý‡¡Àf…ûpƒÀ³ {–miBÀ(hÄ)À„Eõ³–ð¿Àé$Ç_@?û{¨ ÀÜŽŽkr4À ó*È«ëV@øÑòð>Œ0ÀX(ˆZ¶@ÀÄ"‹©6Àj¿é(0@ºbɘßÞ)@cË4¸«û@ñrÔÅëê?±t™ÇÀø)°ÕgB@P†ßvÄnì¿xJxt´#À^>`¯åõ¿ƒÿ-I¯‘âÀŠoáP`åÀ³¿ëµ7å¿(§Uqêú?„¯¡ðê%QÀO´°_<î?sÒÿ¨’˜@3A¶jÃÒ+ÀGbK¨èÀj.ÀWçá7À”}º2!À˜{6Bjê<ÀŽö鱺À `µÂV@c\Þª1sKÀS:)þÿ€ À”±èÀ©ÕeéÀÐ*…$ÓÀ?qö #tò¿=Û6Á À²:3á”’OÀ}„›D(VÀÐÔ?Úº²1À°½T³TÀ©Ò‹yYÀ H9¨nÀÅNœÀôûlÀðFu ‰AÀuA×VçÙ¿ <)bb%@’:dVFBÀrîk¢"ÀWË÷}GÖ4@ŒÛ¾®&/@‚îÆlTÍ%À ØftÂ0À¼ÜÛõ´êÀÒŸ!E+ëaÁy ·â,;9@tkñ`sÓ6@YÇâÿr6A@´rS¿G¦0@á ¹­?@í#T6å W@ùKþÌã<Àõ€ÇD‘ü"@ÆÓ9ômZÀíAaB‰xÀ!Þ@ŽúÓ @ >ÿçv`@Òm*yžqÀ®íâr¡YÀ‡R5ã{Àn¥tuÜ=À†õ$¾JâGÀfžV+ÝlÀ†-”'œ@Ë@M«ãÒÀbŸ[‡Öçò?…·²ÂÓÀû'T1ˆ…Àâ®a6ž±@§Ö^~ªÏE@ØËþä™8À„)ÿ:LÃ)@cÙ0”;À"OSQœ@³¹3òÑÕà?£ûË0ÆÀ…µ>±AêÍÀ ké›ÐcÀ ß¯­Å¶E@¨˜Ñ®nÀõÁ£2ÚBÀ‚z`F@ù ‰Ž3PÀ b³âIiÀåfP ?¤XÀ¯Þ™ûèÀLöïà¶HÀÐ…nk!¾…ÀZïH¯yrÀñl›‚*åqÀh. ifÀµã¨¶f@+Jÿ‡}¿\@öÿŠ»o#@é~¦}„G@e6'ÍC)À<*é„À‚‹.&G@Ãô´ô:ñ1@ëß7XúÊd@@å @Àp 1] @H§ð»àÂÀ‡a‡µZ@PŠHH >À3o#6´,ZÀØ[ÇÂC8À4î–ƒ<9ÀàåÉ8øß¿hd;Þr"A@/åž?bß7À° ` ú?¹5ö"*3ï?öd ÌAgÀCáÄjYƒQÀ1ÔƒüQÔBÀÌ«ÃIå1À £ü2ZZS@·cWeQ@NÖ|ÙÂI%@E Db1QÀªW5Y™y À€¢¸mŸ @srи0¹QÀ’öÇ@@‘Êă_f¯À°¶z¬Ö@µÚ_ùÔMÀÁÝÅçVÿ¿3¡!Æ$y8À´u¸áx%À5Æöp¶WÀ]WÌ.ÉlA@€Ulîý8@kÙí¸FT¨¿I°mßEPÀ<í:-J@žÆŸëíQ@]:#Þ ÐUÀ&€tžéz@í¸bú:ÔÀÝÔîdMŠã?>|;…‰k@¨†žÆÃˆ@˜‰i|{†@òƒJî„‹ÀŒ:m6ÍXÀëüòtÞmeÀר.ß FÀSJÉûÖìX@‘!ŸˆÓyBÀt Mn6@‡MŠæï&@Ô]úM[1Àâ¹?0>À„8‡k¦µS@i7†p¥Ê:@è=Īץ6ÀÌ÷]T À·8QÖ•Š(À¢Î_EÀ…ÃgöÈ`@˜’å¸b@@¥K°7Ž©>Àx¶ÔXŒô&À"…'¼æ9!ÀêI¬A/ÀÖÊ#T«鿟ŒL =пs¾pÆE?„Àý1H_!4‘@Œè~P<÷o@ÚÿSb@_°fñÒû¿ê"³›ùP@`h@b÷0À³†î²±+S@TÅØ)§¦-@Ô·}¹;TSÀ dqÈf’úÀR·÷¥2ÞÀ}ÏUwáSÀxù{ìê>Àö(í(vÂÀØh‚×À$ÀÐs#¤#À}³K¥‚pÀß¶nÒa“$@×rÈžD± À" ™4:ˆÀÐ*`‹B/²@l˜0º«%@>Ø$[ø-!Àÿ “÷KÀ~ L¹Àåo÷]ûEÀ"w Þ…G3À,öòÍc[@óLFT@=o¯?‰<@ýW‡ú±I0@æSÊ*¯6(ÀÙ¹‹ÒÄæÀµa¯+ÀWw´0¢@â×pÖBƒãÀvóÕ‡ELZÁ‹F*!ö›8À=6o’6#@ ÷ôR;Šô¿1nüã4‘?Þ2ü®VGÀ§«/”—BÀBÖ¨TôÀS^¶Àkd@`YÃ¥œMÛÀ|5¦­®±äÀ­ÏÂNÈV2@îˆÁËŠ3@0LƒÈ.ÀÎL¹³¢ÀÐEŒ>ýº=@18 ®÷VCÀ®Ñ …:Ž?8îs LVÚ?-´=iÒ¥hÀçrK¹ƒN@¤–É­ueÀ­Âkü±5EÀ?-]Àíf9%.-Ày>37À!âßQeÀ÷´Œ=‹®ê¿õó´LIô¿Ívò“…gÀ ‘b¬û‚ý?_Ï«ÇTz@Ó•&pwçf@1$7w’,P@óÕJ/ËZgÀGŒåbJÀ±ÝMn WÀJÔ;̇0@ïîså->D@q>y­¦Œ8ÀZã–?–.O@ZÝœ'º‰À"îD®;z[@`,¸•—V8Àª:jy"ÀQ„½_YÀNÈݲ9ëQÀÜP‚(kFT@±I…ÒPÀ–¢«%£YA@%¢[¤¢+@]¡™"X&Àu÷M|l&Í?ÌUnöÃß@=Þl®‰˜'@ÛJÇU”%ÀseWÔBN'ÀÌy4Î@»ìÎ× @Ó'B$ù5"@üð¢ÅÿÀU뎭¤!A@›È ¼õÿ?KQüRATÀ9T„‚ï¢7Às‹wÙƒ!ò?;ÛTð#À‘·ÝÿnÅTÀ¼Û-B-À5ù•™ÃÒ(Àfyd ‚Å(ÀÕ*¨8²Œ3À¾5¼y©¼'@21³EÒqyÀÿK©á!a@©îÇP¹KÀC…‹ýÒV@ÿèK­Æk@èÅzÔ ŸIÀÙ¿ÿÔ!(ÀɪJh¹ÁA@Ý÷Ì!¶~xÀUe—ÐÀ®Ë£Ø9„À}¢û%@JðQ ~ÿ¿Ï@Ù(ãñ¿£)ÿ…d@,ÌfàÉ%À9b ¬A@ùq×DÀ³1Ô\Àžñ2êãËÿ¿,ãð4-ù[Àް×ÈxÀ+î¬ò¾4ÀXè%½‚¶\@#&·):¥Àãâ*ŒÚWã?Ë’¾ ÷QÀ5#a-‚+À 7t— yñ¿¦ùôÛ/6@Å),VÁ!@b¿dLO@Õ±°h?Òá?.€ýëý¿Kž UÚ¿™9c$6¹ù?› ÞQ€ó?¿ðR"@Œ5äM˜Ð$@Õ°°Æƒu@„tþJ«µ*ÀfÆÉ“aÀ.¹GIï?X¾§+¾ûÀ¶ÐíMÚâùÀÝÜ{󠘢@±}å¸âðVÀr¡þ,¼,6À ÔxXç-…@W8L#HžÀë >x¦ƒ0Àá·ƒ7±@â·UDØÀ€ÕØI+¹@†Í­·©P @ÝÏ÷íZœ @Š-uÖ¬ -À£}Öë!ÀŒÅDPËQÀÐ#;N#u?Àó5¨À@‰@ p ó³À¹kãå½È7À,³à=£L@ý;%Ð?}ÀÍÆô+ÜVoÀbö¨S|‘‡ÀcÜ?Ao­@øÕ'Ñ>Àäû6¿·"AÀ‘}d®‰¿UÀœ]T²hqÀñIABåY@cá0ž[@u÷ôŠLÀ®u­hzEÀg7on!a,@ºŸ„±>Àƒüž«èî5ÀcFdØ#À,ÏŠ·ì$:@£-ïÉ–  @ ³²àO5À¯•„yÖ’@‹iÝ>°£BÀqÌ·!@­Ë•-_ÀÿwSÍ@.¶‹ï&À[;à}µ À¨¯Ah/UÀ‹XÐÍÝ*:À|T:¦‚IÉ¿H6…ô¨Eó¿&":|'4Àî9¥½ÀKär7ÀŸ™yxÁÀWäpv7@Îj©j.4@ÚèI<[âBÀK“ÍwE4À¤àK,„*À±ô°ù À À)¦iSY'À¹ìäž}J@ÐZÕþÀªE!G^ÀöQkW 6@þÀV½c1Àå3 GÂñ¿=Ÿç¤…À$}kÎÝüˆ@Q±z_z~@{Îk‰0<@úxvͺMÀ°.ê°‘.QÀÈ“¿½4R@©¶\ $¢OÀ ºU@E@µ’­mP@ÀC]¦;ŠJIÀYhL€ ­Àÿ`Ïìýqj@LñPû¾êIÀÛVÕRHÀ¿±ôæ91À´ ©¥l*!À„Z!½l¤!@ämH$û@½ºBôOš@@…{HŒÂà\Ààû¨+Àç à WÀX¸3º/”nÀ<úaÄE¶c@tžf4a YÀBš>ö@Àc-Õ/òm0À)Tq ¾û@gBõ×Ùx]ÀHšì>VAÀÔÛÚ,J«P@$€^±2DVÀö Ÿƒâ{–@jwìÎÀH`åÐ"WÀ*=mUÁZ‚ÀÊ2C©^@}À2B@ÒA‡÷Ç"@£‰M2 ö?ämhp‹"À|Ç\7*y ÀËÐìR ÀOêÙÒôï4@îMXø6›ù?ôn_|]¦ÿ¿yÈ9 (ö@±œ­¶Ü·qÀéá>^•JHÀÀÚ:P‘@=LÚé]]@e(±TK@¥SÆ-N:À"à bÛ•À¡vÂÌÕ@R„¸£û1ÀÀ|Þ#ÛEÀÈ–tîר'À¾ªJ±JÀ^ùñ&¡ À¹ø·ÓÃ+@¤å“ÜÆ@T­?ï¥*[@íq„×pÀÛ÷Åýµ$@ƒÖbþ¹8@z-7ÜÆ®À:;’nÛå?)t¡™uYÀñ8vóä’7À´ñÜG–7À9&#ãÅ”ÀjîËB_@Sm¥h%@°Œgu`ñ?¾–„X,]Ú¿QÊýøV2À3#Ž|…Àõcç3I@ÜðëïÜ@ÖtUæ»x4@Ð9e±@h½iâ…ÊXÀˆáp4$}GÀWçy˜¤5À‰RFŒ|êÀå§¢3Ò3@ÜÄH´–«Ó?*¥ô•KM@ÛT<>Uy,@ì†óGg@À?7í×ÃØ1À儱àe@›¿;Ë“bS@\4’åH"À}³f€|4@¨AtX]W@ëç8_À˜é’lvÝ@öm¤‹{v@Géc~›4@ËÅŒïA#À‡ ÐL)ìb@\ÀsxÜ;`@÷ÚT›ÕXÀE$ŽutKÀJ^x†¡JÀôa+4ÀÛ‚ëÃQ @ü:.Ó¯:Å? #K-\0Ó?â)VÛÀ<<Ë÷1SÀ×À Îv=ÀBÍ$Ὶ±qŽ…¨ë?}"LnøÀÎ(š¶¿è~æu¼{[À¤ÕáœhËCÀ9Ìx]œ#ÀWø-Ð7@§?Zí Àse ‡¢ˆ#À‡ç²’G±Àc”²×tÿ¿ãNI¸¦@¶v¢ß:‹@^O- C«ÀôqCÉù‡Àl¸9­`U+À&ÄP¢´Ú"Àåp³;ÀZ’Þv’0À½ˆGòƒï?9´ä_%@ƒä–מW@±/Í¿¹“:@c;}I¤å[À"y|Ì×?À”™%5¡&8ÀZDÀp'@ÒüÀMc&À–zÃKšjÀœœZ™ mW@Ö¢·ÎV‚@Àóo¥Œùi Àº'ý›lÀIÆÊck€ÀøMŒZÝuÀíK´Á„:Àï5jªä2@û„uE.ÀT@ TYßurÀ‡±æv5¡ÀÀt'ª‘eD@+yT-òÇ@xæÆN»û÷?¾:<àH1@õ$²L@`8tž´/1ÀÎÍHÄr;=À°žF³|›Àc™sÏ÷õuÀ=d´«Š+@ÂH¬Ç†@T~""¡ÀøQE¹jwU@w‚¬—üE@Vºi n)@MrîBä€ À³4ªÑx_À™ÎNa±7QÀÕßÐçDâh@J.0Ⱥ@ÇT3£‹µ¿6% ±NSû¿ŠSZp†¾?ŠÅÃJ2ÞK@IýR©üQÀòž‡ÛN52@j¯gAsÝ-ÀøŽó.Æ0~ÀµMg òò`À°ú ‚2'À zÖ¡RÀ·5ªßù?Àd_rð1À¬iQ^F@5I?×éð¿mRŽ/ŠÈAÀ½÷aû2:Àœ·XU¸ÀㆄôJ@ÀF¦l"iæy@‚MŠƒ‚X@¦9Dé‹0@•‹4n @Kz‚µ)h@\ì ÞO@.r·Ž91P@QÅ„>{;:@W#ì«Ý?VQj ‘ÀH10Æ–Û?.=i1˜ë¿Qჺ!À4°¤ð^áÀ³+>ïx@A²„HD%Àþÿ9;áàû¾AÀΦ§KÑ;ÀÚÓo[ÈÂô?ùr³=é@u€¾º­ À-‹‡#ËÀzÞC1ô©3@PÉ=N%U1À¡i>Ë4@ìÁ™\¬Â=@ß±4Áœ\@ëàYg=:À©éD‡‡¿ë3ð?@;ˆWÏc•$À‡ré°i@Zhó‰%AÀH`ª‚ø¿O¸S#yÀQÑ ´)Ì@CõPI¤Ø@õžq€8F@@}ñ!#BÀ,Šò”¿Y@»BÁÉp©&ÀÊuÑ^ä¦HÀìÙ)xâè7ÀôÐ×7W!GÀàR®î¸?+À7,( .À[5#¸ø?sFF”çN@‡?MÂúìÀN(2á%I@ÒÞ‡f@¯—^¼DA@R‰Ì'¾J%@Pš£s^À!äÀHãDÀ œírŽCÀÚ1:>o4,À* íá„ûÝ¿nÿõwÀÀË4¬©2(Àø ˆV€Àgî5í¾Îh@»~Q@šçM÷–¡À#'ÓQñrÀ_Uÿ3³@"Þ¿ôR@ZÌ®ö™DÀÝí-¿O$,ÀRåûX±§@WøœÔhñQÀôWĺæßX@“]µj«I@;Q?æG_MÀ¬œ3ÀñÅ.ø›4@iãw‚®é¿ Ë[vVXÀÑß÷MÀgü›n{k@F¹ø¬Õ¨'@Ù•–•Ñ—@®^B£]­ý?{s]lò§.Àô`JWŸÀ À7Û=i Œ@ aÈRCô?"=Në,@À0[£|Yl=ÀdÅÃVñ&ÀƒJJq\Àm5¥ë!5À†m"ç&¶/À‘Øu¨B<À~‡øØ¯ À„÷žî?$%À( È£´ÜÀ¨vW^#@wD²;À5¿sÀ{äN@d¹‘&zyAÀ6ü‰ÎªeÀ܈Då9Àð-q¯¹b@¿A%§‚€@åšpÏÉÈc@çøxys2sÀGÎ"8Kù?œDøö5á?ÒšüÓ) ÀµO‚Uå“à¿øxò™Q@B®îµ,3@ð´Ð J¯P@©•=£U )Àµ ¼ þ~À9½ó3ehÀ rSŠá§¬?Ð鲺¾Ë⿜“ñôâH@ÀÖLbe—ý3À—#Ч-a@Ìb]cÀl+?ÕÿlZÀè »=rAÀ[5‚a6 À/õÞúuÀÛe2Îy`1À8M¶T!À3UV›& @€L¹äô׿Ö]§Ÿ´÷ÀµìKlÌø¿‡.é×Ïc@á¡g5ºü7@œuOáàE@Ejü=LÀmR„~>À­Ãš‘ljÀøekh cÀ7¢ +³áEÀüLì6mGÀ¤Î¥À{JrÞò¿XÀáÚ Y·>À’·FUYD@ðbÀæ6À9rV­2”T@IõáÕŽ(UÀxó) CÀ¥îýŸ¢ì¿jn×ýÒ@ˆÿÜÌœ"ð?Nñ9 të@%™ÇÛW @…¯s[ÀÚ™ ËÔ·ÀÐX5˜ÖÀ#&‘ŠðƒÀžPį0žF@‹ðIDWp)À<âý®&J@_ ‚ÜóB@å;®> @@€É!H@¨ ÿT$é^@°«”7oÀ¦ÇãÛÊä@)fÅljg @qðÐÆ².ÀVVH<0À›´?IìÚÀ?C‰ ‚ @""4—B@l¸â.[D @êŽÙ×,Àgd¡ž/[Àçeø£§=<@ßj”’eð$Àò ûˆ¯@†É‘!—Þ@‚”u:@Iˆ›¨"@G6¸Á¨ßç¿]s«}1DÁ?3E©ÕøW@JÚ,«=ù?÷0Ô#kÏ@‡zÖm›6Àý[dø7H@ßž›¬3\@À3­­ñŒ;A@ˆ\F \á0@å 8'Z¼BÀ1@¾±ÁH@ý[éÌ$@¯e7öü@Hï‚jU…T@é$ +J@¾HÐ0@¤ƒ”¶âÛ@ü›BÈÓc(@÷!1»±Äa@´–O*:S@øí¸u®wÀ'.j:"IÀ8ZÄTsÀJÀç @„×LÀóI¥Ž«(@!hÇÀþê{ ÌNy@ÅT “lþk@424)ÍÑ¿M¤ Ž$0ÀOâR)Ö½A@ÕKî}íÀ"¯â§Ež>@„ÁԱÖJ@ö@Z ç¿Ð*ÞhU?èƒ&Ì.ÀIZÙ±6À¡¶êôªÀ_KS’byë¿„Õ¾Ä)ú¿Ë¶ü#hÄ6@è D´ñ‘À1NÀSà‚Ó,‘ÀȰ»@ÀÁÓ!^Žå?dëÉso€=@½´Î«ù&Àv;µ‹Î­BÀQý’ºFY=@ bÓ¢Ÿ(À™^áU75ÀKFFS%«4À–bþÿ`bDÀØ–"YÐÃ9À h”«¢$@'®Þm%@ÖMÊ;@ʉ½´™¡'À¤pe+À¨Äz0zy=@NÏ*ï=5EÀ½¥±F€¥1Àü%œ×ÅÄ @‰ÔY¼™ÃÀ|·•‡¥/@2ÁÿÁ/%@¼ž÷xdk+@þxÏä@8ÓÕïë9ÀÞÚ)°EÀâ˜%‘j«aÀV"ÁG@?)DL @Ž8‚5šcþ¿®@_ Êê)@¨¤³I‡0@ÞÂú`í€ÀœSÁ-‡ÀW]ŠN @}*Ë EÝ#@DmbmÀ£¼¡á°æ?€üH-½7Ààú G&² À§eË”ÿ¿®ÝÆbÀÌ”7øï2Àð%ƒ~%`/ÀnV ˜@ÆXÀ@®íÎzRÀ'‹cƒ‰é/ÀŒje˜<Ï"ÀÁ¡£0=@{±üz:õ¿U 4¡HÀ6Iþ#¦¤0ÀG¦.­=@˰Û7"@ÁåÚ¯Ž@pf1|1&@¨¸Lo´Œq@Å’ ËÂ@%DbC­3—À<Ìäq@B¤8'%cOÀÉÃÕÌ7>ÀÂìÛB) @´íÒ¼Cã?±¶îd”! À{´Ñ¹«“&À¯âŽíî^ÀÄ”ËûJ(@ÀI¬Áa„(À[תší@-' 0Àà–ê">$ÀÊÞ|8ENÀ]ÄjŒÿ²DÀØP2hW@'“¼x:@ã~íüœ"@þ¡°¤ÀÝU˜92ÀóË]zR%ÀzR‡7GÀ_—g°†G@f=P$Õ;–¿–Õzº–ÛÙ?ÿV÷ò²ø¿¿PE)-ò¿€ƒ” ðþ˜¿òYÊ ´MÀ„|?ŠêO@4þLjÚ¿­7-8\?ÀaŒï”2ý=@ö8h¹‹Ì>@b2vBŽ>Àysa2ø<ð?ÍÅðó?®‚9sá?U¨×¾@"liN@¢eš<@ƒkJÄnBÀÊ:9*¯HÀ[‡g^šÀ0½Ö[uðœ@”7ÇWÖ?Ø5N©&u;@Þ’Ó«_›4@p,T \TÀ€ëMûr`@rýªlSÀâ• XUreÀ¹  &lÄoÀz­@q×ÇBÀà< Æž#M@³µDø)@Q·æ“æ]@XvŽO=,e@Ç#+ªDfÀƬ\o€_"Àløä0¨þ¿çÞ']òf Àf$rô/^Àlï½A'~Õ?Z.Ï•`ñÕ?Õ¡Ö©HÀnA HÀâ΋xߎ/À¥Ã :@É74@sZñD<3À0º5‰À^6)O·lvÀTò¾¾ÎaÀ„_¯Ì~@´X²~‚î @ š¨Mp*ÛÀ oM)¤ãÃ@/´v–{„ÀM:#¿6 À¸1J¿­fÿ¿‡ñ1Çû¿ 0,&4CÖ?“©õ–½Þ?KÁgGõb!ÀÌŽ&…… ö¿ïMÏèÞíÁ°8ÖŽ¬OôÀÍ£¿›¤"À™xWKñÀ¾Ü‹rI5Àµ4Þ%Àá€tIÊD@545~HM:À»;¡ZÃ~@¿‡/M—g@\ƒ¼‚´fÀÈ\çÈzaÀ¯jX0À"ÅñP‹uÀéŠÓ:À?ëûõ[¨FÀġ9g(A@YSÃZ Àˆ–ÎpŸÝ¿ž>µ9E@à;£´èÐ?>6óV°ÀXÜÍpc@ü9´@ 5À“`*Àl˜aaç|×?}ˆ €¸ð¿^£«t@~v6é= @œ¦ä¸:ˆpÀ”—¨dw@Cƒ³˜¯#À¾GˆÚ—À}ˆQ5Û( @Gå-]Roø?´xDÀµ0ÀÀ÷€añ&À0[D“ À¿uÔo&@ðõ>\þC@Ý,ùÅïh@({,Qß7fÀCd÷¼¤©YÀ·äÖA¹2ÀóL6‘þ6@×–ýÕÓR#ÀÆA‘@ŽÀí¥3ÍEÀOBå6OÂ"À%ÐÎT@oˆb”g`ÀqƒB•iCÀôæÜÅ !Àe¿M’Z@çñkÈ·D@Ø{rx±*!ÀßÅB¥ªÙ ÀxÜ¡ö>Àþ™ðLÀ¨hcè*@ß Œh/5À-fR¶Ï"ÀOJÌ©Às}¿Þi¶é¿Kªb×Í¿ž(þ·?£>Àx }Ûþ Àm”}`@ß%´Öå>@ä¨Ñ¡¬Ày0dÔÙ@ë rÿ¿i®UÉý¿A$øawD@?ƒè¸¾#@[¼6ƒ LÀK1õZÇê/À0[ j1ÜÀ–3b)0À\D •o€JÀˆñ© …y?ÀíÕñf´AÀ „¯†KKÀª»èåRWÀˆŒ¯' 3@ÂóqJ õ,À’Ôsf¯$@Á9^'Z‚b@'©‘®Ú¥Ì@¤Þ…–jHÀ€[TbRtÀ œ$=+UÀõò6ýc @ÑŒ”ÛÌÀ™F&™M@J;·î9'Àb÷4á"ÀÖŒ :7!Àóâ >šöGÀoàçþIÀ.ôßÈÀ°¹€À‚%=MÀ– O¢NÅ)@!è WïÂÜ¿h+'Õ)Zó¿2È:ºn@0À¸gå[i@ÕÝAÊö—?ºØÉrWà´¿9'¼|æ@<`öMf*À Cu+ç¿›¿2S­~ò¿4íi†=<@xžãÏcÑ@ªàÒå—@Pãçί1GÀý µ4X¾k@:ïª+$-m@jà[špÀ¬(Ë7!Ì¿înCJ¬ À|]7n®æ¿–eqSÏN@n"²`ó¿ØÏb·FNÀ¥Œj /³È?ö¨ØÓ‚ÀfÖOÓéò¿écªºÛ@è <í$u0À—iº\M@ä8§ö5 @ª¸’úÌu;@-”FO;@éü7ö~ê@LóD¯µéÀ©Óqÿ•KhÀf#gÔøoX@Š¥»ÀÕc@¦é¹l;wÀo×í½KÆ6Àh5Ya—œ%À´ê£527À ŠZ¹À†U?æüƒ?À4”6Ç9'1@=sÈG}@ñ ­ÀÂ@ÀÅ‹T*û?q¤þ2‡HÀb²4ØJu+À(>§_'À¢Ïô׬ã@ÀþbPŸð0@³2%ÍpHpÀqPu;$JpÀi­;ÐGél@†½ñá]µp@Rb^ªßÀ0–þÃ@ìß>>q‡'@y@ã˜B@ׄ(‰®{C@ð9Þ̶yÀ^í2ÔÓ‰,ÀNNEcú˜À—Û?nj |@ÒýÈ¥ž(^@â ò^«Àyr‹4ðGŽÀƒSËm ÆDÀY¨†‹³ÀS Y}? <@é™’5á¿W°!aÀÌlۼܷ)À««¨Un¤À ý¿ÓñÀTþ/¯ HÀ…2Ú9+¶CÀßO$GцÀãÔ¿B•€À³¼Æ4©­jÀKI Õ~@U/YqN@W$Ö&@É#VWtbð¿™E)þhÀŸ!Stkz1@ûW=—ÿ?Ê? hYpM@ o·,@·*®3Ù`Àᥑº‹B5ÀžþHs‚Ó>@Â]lQö?À” mGƒ=ÀAêfÀoÜõ㪾ؿËÓü « ÀàçvbSB@.Ï}® š@—$ QÀHµ“åqÀšÞä%@‹äòN¢@‘f±``,EÀñücù3ÀƒÈúŠ×¿7"$T´î?kãÀeøè!@ «m[pi@Ý;­®'ÀdýýÈ&ÀÀ¹­ží¿›c°G꿘ï )“]Àas‚~­HÀý¿×Ïô‰N@òÍõà")À(Y:Ð^PÀ|bF7÷.:ÀÖ*ȇsH@Ïã·Š¨@ňñ2•ÀÕp‘¥ªQÀª~m'Àøµõ¯ jó?…÷CšdÀ â`¢zØ.@à˜° —´@iïؾG$Àë^ñ2ec[À½ PÞ^;EÀ…kýªëÒ%@P8¬~ºÜ¿ËìŒVaL0À1z’zëä @F£?»Ó @ ³×oü«;Àz€ØA» @ñŠð†÷?›`åoÌZß?³1Ãù@±€6P>N5ÀHt…5Àë¶nƒÛ@’´ºQ—0@/2Ú‚­ófÀ‡Á+[ÚÊGÀPt—¿Š@tUb̉@¬‹H—͈ò¿ÞlžŽˆRú¿håßD¬¢@ ³à eÀÌPZDÉI@“üçhîˆ6@~ËÀ3C{*@e)eêÓ¨ÀDéàZTh2ÀÝ”™‡ ßÀ»¹×g;A@nÓîj7À¥D²=¨é8@Ùõ5ö(m1@3è9䀄鿆D+bö@aSðS°dGÀQÔr¥ô³EÀï”wFù¿µ(WAÎkÝ?{ÓïŸZÀG÷d÷žVô? éo¥rŠÀº‚0»S£Ì¿fqDm®(ÀùUàšµú¿4—,fÀätY´™/@Œ¥ê÷·mÀƒ6™è|VÀb¡ ¡µŽÀr¤‡±dUÀ{¡Ñ®„=@Ð’Ð[À$-Òsb¾A@?¹ÍöBÐÀ(OyàR–HÀ¨iºBx¡$ÀàòzXçýæ??e1¤ýïå¿Þî‹Ã×Xü?¬Z»$úb4@ÁbªL>7ÀrÝèã1Ð5À,ÐO4“7À"fF×AœÀ%WŠm¨À´i¡ ›Àùãv fƒÿ¿¹6!K À†/ ÇÅA-@À‰ãi3~@»Èëù=@A̹›fG@>ô2!8yRÀǯðkOÀoeÅ~ûá@¦ÒÌdqÛû¿³Þ ˆüT@Òa‘}‹@Ï: A=À]c—†@ÀO*ŸõXKÀ:É…ØGƒ@ÀÚ¾>5eó¿q¬š -0@jõ‚ý…DÀ+(3M,2À (?[K‡'@t­?^JJ#@¬:ü­³ÏGÀ°Ê`$5ÀoÁ³Õ84/Àß͘®©A@Ž63¾GÀÆYž´MW@à¢Dñ5@Ú¹)Ü?0@„x1eöå@ö Pà3ÅÀ@¬u’\?Àmw ûCB@)ÿÌ0„°\Àp‘¥ ?>@X% 'õ @çL8#¨t³?Pû¯YÀó.ÀÊávÔ%À M³àù#†@DÀŽØ¦C@RÚX ÀÍ©]ù—Áø¿/UÄt] ÀM û†±á”ÀUê¢ynUh@‚µi%±)@ Ççoá@ê?ßêZN ¿Lå=ñúþJ@Iíü*A+@?; ´]Àê™hþ›&@*nþI|]À @G‘ ÀÆ’ƒtMñ? WLˆ~›@pñø A·ð¿¡”ûï rí¿uF‚`#À²jϲÑ À ®g Ý'ÀÄeCVÅ 9Àq3i6 @³i~Jp@ì‡#·†J<ÀÈ19ñ¨ÀÇXesG)À{¸ŠÒÔ-À–ß û@Pß0A@Mö™NÀ`À´« É)¨#@ÀOÜͱ³YÀ±06A¬ËqÀ/Ê¡b%À¦ÁÙTÀ]ªí&‘|Àñ_¡Ï†Îr@Qa°¹ŽIB@Ðñÿí¢:@‰vÏŽŠYBÀtךX=À­·Ì mo7À…ur#þ%À‚dA7oðÀ\ftèÌ?„ÃM©f1cÀ5p×*ñHÀél F«‰ÀwÕ8‘†À“uÆ÷…Ø@À¼`(»˜1RÀ)+Œ“íºÝ¿egŸ@èf\Írî@‹úlá”"ÀKñ=ý6éÀdÔäêÀÀ)ÉŸHB^;@´«àgqZÀÁÞúš†vÀqã4 8VÀÖœùó3@ôúßlê"@Ñ_kþÌŸC@>BÁŸÖÆ5@Œ Z¢ï_>@øK«Ìâ}@M±öz(À¯HðRbí¿ UªpªÀÍ”5kr<@ã=!@g‹ö·‰ö?Ø †å®î?2P§çí¿Né@P󿟘tÓ3@Ú.tæJå?«7a qÎ?ø8æg£xu@üIäëT@m«†÷¿÷?¼·ëÍQŸ÷?‘œ`Û"ÀHŽL š ÀÊ\Ä·„HÀ0ç·JÀ±Ž9Ä€õ?³÷ùì<» À p®c“@©¶@®gÀ¨Šõ®œ"@S¸u ñ?S[4Fn#ÀÑF8̺³?h¡DèÔTÀAìϹ± 5À­TVfx#Àìƒy`Ê?ð~ïæ´ð¿£aÎ¥U•·?ˆ´t=l À—€ÓIýÀæYþTØëÀ#ëæ­t¯å?ÕãÙåðtRÀ»å@Àb.€ŠTÀRÖò Â5ÀRWKÔ€EÀ'ðò¥¦ÀÜÃ5.7ÀΈà²Ó @6¬1À¢"Àª´,™®ÈÀZ4!"šÀQÊó¾Ræ@Ù¹Õ´¤÷ù¿VÝ#áÂÆ÷¿Ò˜ƒÁë’)À×b›0ãSÀä91v˜(#ÀÓO”B·³À¨À_°0"ÀÛºb¼ˆÀ<8Wm1Àæ+FŒ4ÀÜÇÓt;ÀA÷üFâ0ÀH3MÚ¬rÀgØGº@'*'|‹'Àñ‘/é[îæ¿}ª‡~ Àüg¬ƒTÀwjšÛú¿kˆÑÃC&ÀAb91…ä? u'{Gñ¿›î4mJ/Ò?òùì•"dÀ¿â"~³Il@Ö˜ou4”¢@â4ÓÀ¤H¦Àn‚Bu©‚”ÀÞJ6§Ð:ä?¸Cà»öÙ @1¿SªcÒ´¿›šk)ÉÀë2¬Œ„ê)À¼vï’‚ù2ÀL塸ônÀHƒbèm@Mì6¹Z¡ÀòPL™£À«ál­nµ @)4odUà@ÀE^êÀ‰Kbÿ¿°£6þ?‘ѳ gj@L=œâ¸`ÀwPïŠËy7ÀU/ hAÀ$E'§àÀš&l©Æ\WÀ¸ âÓFKFÀNÄNÒ?À®Êô‘ÇÖ-À ©¶„zîA@/ Ç1‚2@Ìï2ÓPå?Œ¬r-ÌûÀ¬f›òÏ?yæ(Ò¾Œ¡?…§s„f»m@ÉfõAÑpÀBWTë ¸ÀªRºµ@G@*ýõË4:@o"E @§é‹ÅÓb!ÀjÅ‹ù!ÀFUãž=À^ÈUð/NJ@ÒXúí@-?ø<îó?2&:èž`@(õž–¸ú0@×qUIÀ9m,É`b@9c‚µWC@röþ #@&ÈZ)E*jÀY ‹‘:;BÀ»¬w:"@O@\"Ô…è¿]ÁsByÀç§^HµÀï,®ÜÍSÀM…xYædÅ¿QœÐܺ&@²âÌÎá@˜Aùí%ù¿`¨¼}d[ù¿Û:5×FÀj±E“}7;À—ó鯿 @§~² Á"À„±·M@ÀÓT‚Eº´#Àlí•ÕCÀ@›“G†ÉÒ¿·JXÏoÀ’Ý×4ÀböGÓRPS@sÎ¥ðO&3@ ’œwÞ?Ø7$.…á¿q”ã}íu*@ÖYò !@ÍsÓ${@õÎu"iÀÐ…RÔZ1@b7o¦‹Ü.À.ñ¼€'É Àx”Ïü6&À‡.ö¯@NCgråx ÀÙüÒT¬@Àfg0zp-À(&†C9h@3$ª®vÀéOT$^@›ßV„3wÀ(ZúËÛYÀw”±¶€·@¢×?7Á2Àɨ)y˜0@c÷ß2¾_Àö²ºëîŒAÀÃŒs‡«pÀl¼Àª¤I@IQM°”C|ÀQö7þ˜mÀL¨ RÆû8ÀsÕFôaÀÛ…nÂÃ×F@Þ‡2ÂqÈñ¿&º=ñd˜@}°ò8P@wErãDÂ2ÀóoÍU ÀÄí«‚™Àmú°;«ùÀK´(p—:ÀŒ£ðŒô¿•IÎhþ¨"@Ù+øgñpú?ð.Dg˜86Àè÷`VÜð#À3”I‚ÀøTŽ;ú'aÀ&²YœHÀŽH«kv7À>ÜKØ|Íø? „‡ ¹¾@„-Ð&Â=ÀÀpœS¤€nÑ@j—ˆÎHÞTÀ>6;;"_CÀ³¨Yo™<@Ph— ÆFÀdTq'ƒÀTòÄì?\@&ÔhF*5À”–1¡ý€D@ ë‡ h›ÀWXÉÞÑïÀË …I¼™Àú„3$,QÆ@‘°flþGQ@iØ)--d@=]Í¡¯ÃTÀ–¼Ç³A%Àú"ŸÄcX"@›oÄÙl@³¨GW%?À)ÜP’þ‰&ÀRâ*ù½ð¿û¤ÜMK @aÓ+'ÁÄÐÀ7·®ÅbÞ@ê%õSÀ,~ïH?À¿Þ¥ÚÉÏ@ÛÁ(’R@çÕ_îm×øÀ=p3XT™lÁ¬?T-Í6ÀÿwLy=ÀŠÈÄ®6oÀ?šUצbÀé×Oú@ÚŸ¥ þÀ~©úù+U:@p4êûg@GKÿa}IÀ(ÄFE+-ÀËtÀR/·NÀ˜sCZ(À»ÄL½4@ºúòÌ<@»Õ¹)ÑBÀŒé{²Ô*À¤¯ÛÊ60@m|ÛÒeÚç¿3ëÒh«@”Iz%Z#@‚ëûÚÀ}‡e½yÅ@=ÐoDf§B@JÝñëú#õ¿3@RlƒÀ$Ÿ›Õ/Ú¡@$];\@$MãÕ>¬,@ ½yùæ"@}0ÇaØ??AŸ7@šÀ>X$ò ¸@LÌ«f¥t˜ÀÎÀÂÛÁ\´@jÒa:ðò¦@r!]¸=¯ÛÀZÓÇ2ÜK2À·bÁ×—‚À4=0ù_ÚÀµ¾äí9^lÁ<û2$×Ë,@ BçÑä @:ŸeÁr#Àÿ‰ŠÛŒè!Àõs$jõ†@÷œ“ HÈ?­õµ"?Ü$À“«R£ â¿nŠF&BwE@èð©ÞÌÁ+@wŠ¥çÌc£ÀËA´Ö!Î@Ý2ôÜq?ÀòõŒw À;جÜLÀ4À]ªMÀÜE`M¨ÀÞáhmJÆ@½G`U4õ@s°@ë%ÈŒýì?@^¢¸~Ö?jžÝð8ÀA…Ì[ÀÀôm6#¤o@Žè$Ãè`@³ÒÞ±ÓܰÀÄ~ÑÈÝ@í5˜Ó®ÀxS%ë3ÙÝ@p¯·xh3Àc\Å"ÀzÇ1«[B@}®m±0ÀÌ#|¯:v@è¡ü©0°À&ÓKc0@ tcœ{»@r~Æ:FÀŪ<€(Àˆòï¾ö#À’Ò;Lé.ÀĹ´¯<è)¢ @ˆº‘êS®3À~’œ Ü;\ÀÆæ$ððî=À;޶ÕÀ]L²‰_,À#ƒœ"©8À—BéÊ0=Àsø]‰BÃf@§·Y# hÀq ‚ó‹!@°ù&µMMf@-/ l`ÀÄ—¨ èðL@Rðó@“6@$+¹#,œ@ÜüÐás@Ðô!”,X@,–¯%­¸"Àô”ì¶«@Òû‘E_öA@ŸSCc4À¡˜n¹JÁÀšæmNŰ€ÀZÑœ¸¾,@ý‹° H™A@Gþ¢Æ*oÀÓ÷_—á:@SOBÛÛ«bÀóF|M쓊ÀDu…•‰¡¢?´ úiÃ¸»Š¸¿BÀ6 mXKÀÝÓF#"ý?–—éék\À ™3C‘r@3þÕ¤ÀWš³¯ùÆ3ÀË'hQ9GÀ„fpÊÌô¿‘´íŠÀÙ%£ðçBÀƒµè°)ÀçJqõŠ|$@º˜Ë¾ÎNÀ<º£z¤Ï@Àè<]ÌÃBÀìÿV‘0wdÀß íŠ\ÀÅ'¯[0ÀnNR¸§«À9*z\d$AÀG¿úkfÀ6Ô ]…"ý?˜Ã?ß¿øøý{Hf.@Ò¬w–ÇBÀõk”’è—Ð?êሾn¶?Î Ý»HåÀ©,’!rÜ%Àš›®õVäÀü,<½lbC@áS?¼‡T@kêCýþ?Ô ¡äM°¿Ú ô í¤­¿"X‘4c®‡@¹@È)½À~&2øŽñ¿kc¤@¼ð¿ÒéRC] Àê¢h÷fÀVžäåìBÀ+UáÅoõ¿ŸÅBÿ¡ñ?ÂrºÏãü¿]¦:"¯y&ÀÅØç÷µLæ?zPú: ,@o§¥Ú@}üéD€@aì|fÄ\d@ž ð ðñlÀœõŠUÀ"€Q3`…@i 6Ò•À\ŒàÜQý¿´ÊÊ÷ÞÚ¿²Á£ÈV ÀúëèW%Qó?Œù7Ãë@»f@ñìÏ@@‘Ùm_<1•¿snæ‡ÎX@uâíêü`@, ¾ÅGÀˆ$ëÂw:À{v·—!@+\ji”*@ОœÏÝ@ôt뇖XÀz(w]•À Ý<©*7À “•‹·m@}y8,Äã@Àq](7­xmÀ“GMô# 2Àeà£Q QÀ™]å•yV<À+,‹¬“¿I@õy§[4@Ûr{­ºYR@%w˜±]J3@?œãð4¹¿¢¤‡a‡°À„0yõ¬ÀxDõ\3ê Àf‡Á«ö¨ø?mú=cMáû?VA(±H>ÀÅ Ý<Â4Àd ðm­­Àˆ[Ùj¤@²oÔ‹ÀR'°…&¹S@øÂ]“ir@k›:µNµ¢Àarmci-mpi/tests/contrib/cg/compute.c0000644000175000017500000000545412662706250017235 0ustar mbanckmbanck#include #include #include #include #include "mp3.h" extern int na,nz; extern int me, nproc; extern int myfirstrow,mylastrow; void computeminverse(double *minvptr,double *aptr,int *rowptr,int *colptr) { int i,j; for(i=myfirstrow;i<=mylastrow;i++){ for(j=rowptr[i];j=i){ if(colptr[j]==i){ /*printf("\n%d:i=%d j=%d aptr=%f",me,i,j,aptr[j]);*/ minvptr[i]=10.0/aptr[j]; } if(colptr[j]>i){ minvptr[i]=0.0; /*printf("\n%d:l=%d i=%d mycolptr[j]=%d",me,j,i,colptr[j]);*/ } break; } } } /*MP_BARRIER();*/ } void computeminverser(double *minvptr,double *rvecptr,double *minvrptr) { int i; for(i=myfirstrow;i<=mylastrow;i++) minvrptr[i]=minvptr[i]*rvecptr[i]; /*MP_BARRIER();*/ } void acg_printvec2(char *v, double *vec, char *v1, double *vec1) { int i; for(i=myfirstrow;i<=mylastrow;i++) printf("\n%d:%s[%d]=%f %s[%d]=%f",me,v,i,vec[i],v1,i,vec1[i]); fflush(stdout); MP_BARRIER(); } void acg_printvec(char *v, double *vec) { int i; for(i=myfirstrow;i<=mylastrow;i++) printf("\n%d:%s[%d]=%f",me,v,i,vec[i]); fflush(stdout); MP_BARRIER(); } double acg_ddot(double *vec1,double *vec2) { int i; double dt=0.0; for(i=myfirstrow;i<=mylastrow;i++) dt+=(vec1[i]*vec2[i]); armci_msg_dgop(&dt,1,"+"); /*MP_BARRIER();*/ return(dt); } void acg_zero(double *vec1) { int i; for(i=myfirstrow;i<=mylastrow;i++) vec1[i]=0.0; MP_BARRIER(); } void acg_addvec(double *pscale1,double *vec1,double *pscale2,double *vec2, double *result) { int i; double scale1=*pscale1,scale2=*pscale2; for(i=myfirstrow;i<=mylastrow;i++) result[i]=(scale1*vec1[i]+scale2*vec2[i]); /*MP_BARRIER();*/ } void acg_2addvec(double *pscale1a,double *vec1a, double *pscale2a,double *vec2a, double *resulta, double *pscale1b, double *vec1b,double *pscale2b, double *vec2b, double *resultb, int *rowptr, int *colptr) { int i; double scale1a=*pscale1a,scale2a=*pscale2a, scale1b=*pscale1b,scale2b=*pscale2b; for(i=myfirstrow;i<=mylastrow;i++){ resulta[i]=vec1a[i]*scale1a+vec2a[i]*scale2a; resultb[i]=vec1b[i]*scale1b+vec2b[i]*scale2b; } /*MP_BARRIER();*/ } void acg_matvecmul(double *aptr,double *vec, double *result,int *rowptr, int *colptr) { int i,j; double tmprowsum=0.0; ARMCI_Barrier(); for(i=myfirstrow;i<=mylastrow;i++){ for(j=rowptr[i];j #define MP_INIT(ARGC,ARGV) MPI_Init(&(ARGC),&(ARGV)) #define MP_BARRIER() MPI_Barrier(MPI_COMM_WORLD) #define MP_FINALIZE() MPI_Finalize() #define MP_PROCS(X) MPI_Comm_size(MPI_COMM_WORLD,X) #define MP_MYID(X) MPI_Comm_rank(MPI_COMM_WORLD,X) #define MP_TIMER() MPI_Wtime() #endif /* _MP3_H_ */ armci-mpi/tests/contrib/cg/generateinput.c0000644000175000017500000000217312662706250020426 0ustar mbanckmbanck#include #include #include #include #include void printsparse_(int *irow, int *icol, double *a, double *b, int n,int nz) { int fd; int i,max,j; fd = open("matrix.bin",O_CREAT|O_WRONLY,0777); if(fd<=0) { printf("open failed"); return;} write (fd, &n, sizeof(int)); write (fd, &nz, sizeof(int)); write (fd, a, sizeof(double)*(nz)); write (fd, irow, sizeof(int)*(n)); write (fd, icol, sizeof(int)*(nz)); write (fd, b, sizeof(double)*(n)); close(fd); printf("dumped sparse matrix: dim = %d %d nonzeros\n", n, nz); } int main(int argc, char **argv) { int NZROW=8,NZSQ=64; int i,k,irow[NZROW+1],icol[NZSQ+4],n=NZROW,nz=NZSQ; double a[NZSQ], b[NZROW], xvec[NZROW]; for(i=0;i n) { kl = n; strK = kl - k; } else { strK = bs; } /* factor diagonal block */ diagowner = block_owner(K, K); if (diagowner == me) { A = a[K+K*nblocks]; lu0(A, strK, strK); } MPI_Barrier(MPI_COMM_WORLD); /* divide column k by diagonal block */ if(block_owner(K, K) == me) D = a[K+K*nblocks]; else { D = buf1; get_remote(D, K, K); } for (i=kl, I=K+1; i n) { il = n; strI = il - i; } else { strI = bs; } A = a[I+K*nblocks]; bdiv(A, D, strI, strK, strI, strK); } } /* modify row k by diagonal block */ for (j=kl, J=K+1; j n) { jl = n; strJ = jl - j; } else { strJ = bs; } A = a[K+J*nblocks]; bmodd(D, A, strK, strJ, strK, strK); } } MPI_Barrier(MPI_COMM_WORLD); /* modify subsequent block columns */ for (i=kl, I=K+1; i n) { il = n; strI = il - i; } else { strI = bs; } if(block_owner(I,K) == me) A = a[I+K*nblocks]; else { A = buf1; get_remote(A, I, K); } for (j=kl, J=K+1; j n) { jl = n; strJ= jl - j; } else { strJ = bs; } if (block_owner(I, J) == me) { /* parcel out blocks */ if(block_owner(K,J) == me) B = a[K+J*nblocks]; else { B = buf2; get_remote(B, K, J); } C = a[I+J*nblocks]; bmod(A, B, C, strI, strJ, strK, strI, strK, strI); } } } } free(buf1); free(buf2); } void get_remote(double *buf, int I, int J) { int proc_owner; int edge, size; double t1; proc_owner = block_owner(I, J); edge = n%block_size; if (edge == 0) { edge = block_size; } if ((I == nblocks-1) && (J == nblocks-1)) { size = edge*edge; } else if ((I == nblocks-1) || (J == nblocks-1)) { size = edge*block_size; } else { size = block_size*block_size; } size = size * sizeof(double); t1 = MPI_Wtime(); #ifdef MPI2_ONESIDED { int target_disp = ( ((char*)(a[I+J*nblocks])) - ((char*)(ptr[proc_owner])) ); if(target_disp<0) { printf("ERROR!: target disp is < 0, target_disp= %d\n", target_disp); MPI_Abort(MPI_COMM_WORLD, 1); } MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc_owner, 0, win); MPI_Get(buf, size, MPI_CHAR, proc_owner, target_disp, size, MPI_CHAR, win); MPI_Win_unlock(proc_owner, win); } #else ARMCI_Get(a[I+J*nblocks], buf, size, proc_owner); #endif comm_time += MPI_Wtime() - t1; get_cntr++; } void lu0(double *a, int n, int stride) { int j; int k; double alpha; for (k=0; k #include #include #include #include /* required with C99 */ #include "mp3.h" #include #define DEBUG_ #define MAXRAND 32767.0 #define DEFAULT_N 1500 #define DEFAULT_B 16 /* global variables */ int n = DEFAULT_N; /* The size of the matrix */ int block_size = DEFAULT_B;/* Block dimension */ int nblocks; /* Number of blocks in each dimension */ int num_rows; /* Number of processors per row of processor grid */ int num_cols; /* Number of processors per col of processor grid */ double **a; /* a = lu; l and u both placed back in a */ int nproc, me = 0; int proc_bytes; int num; int doprint = 0; /* function declaration */ void lu(int, int, int); void lu0(double *,int, int); void bdiv(double *, double *, int, int, int, int); void bmodd(double *, double*, int, int, int, int); void bmod(double *, double *, double *, int, int, int, int, int, int); void daxpy(double *, double *, int, double); int block_owner(int, int); void init_array(void); double touch_array(int, int); void print_block(void); void print_array(int); void get_remote(double *, int, int); /* timing functions */ extern void start_timer(void); extern double elapsed_time(void); extern double stop_time(void); int main(int argc, char *argv[]) { int i, j; int ch; extern char *optarg; int edge; int size; /* ARMCI */ void **ptr; double **ptr_loc; MP_INIT(argc,argv); MP_PROCS(&nproc); MP_MYID(&me); while ((ch = getopt(argc, argv, "n:b:p:h")) != -1) { switch(ch) { case 'n': n = atoi(optarg); break; case 'b': block_size = atoi(optarg); break; case 'p': nproc = atoi(optarg); break; case 'h': { printf("Usage: LU, or \n"); printf(" LU -nMATRIXSIZE -bBLOCKSIZE -pNPROC\n"); MP_BARRIER(); MP_FINALIZE(); exit(0); } } } if(me == 0) { printf("\n Blocked Dense LU Factorization\n"); printf(" %d by %d Matrix\n", n, n); printf(" %d Processors\n", nproc); printf(" %d by %d Element Blocks\n", block_size, block_size); printf("\n"); } num_rows = (int) sqrt((double) nproc); for (;;) { num_cols = nproc/num_rows; if (num_rows*num_cols == nproc) break; num_rows--; } nblocks = n/block_size; if (block_size * nblocks != n) { nblocks++; } num = (nblocks * nblocks)/nproc; if((num * nproc) != (nblocks * nblocks)) num++; edge = n%block_size; if (edge == 0) { edge = block_size; } #ifdef DEBUG if(me == 0) for (i=0;i n) { kl = n; strK = kl - k; } else { strK = bs; } /* factor diagonal block */ diagowner = block_owner(K, K); if (diagowner == me) { A = a[K+K*nblocks]; lu0(A, strK, strK); } MP_BARRIER(); /* divide column k by diagonal block */ if(block_owner(K, K) == me) D = a[K+K*nblocks]; else { D = buf1; get_remote(D, K, K); } for (i=kl, I=K+1; i n) { il = n; strI = il - i; } else { strI = bs; } A = a[I+K*nblocks]; bdiv(A, D, strI, strK, strI, strK); } } /* modify row k by diagonal block */ for (j=kl, J=K+1; j n) { jl = n; strJ = jl - j; } else { strJ = bs; } A = a[K+J*nblocks]; bmodd(D, A, strK, strJ, strK, strK); } } MP_BARRIER(); /* modify subsequent block columns */ for (i=kl, I=K+1; i n) { il = n; strI = il - i; } else { strI = bs; } if(block_owner(I,K) == me) A = a[I+K*nblocks]; else { A = buf1; get_remote(A, I, K); } for (j=kl, J=K+1; j n) { jl = n; strJ= jl - j; } else { strJ = bs; } if (block_owner(I, J) == me) { /* parcel out blocks */ if(block_owner(K,J) == me) B = a[K+J*nblocks]; else { B = buf2; get_remote(B, K, J); } C = a[I+J*nblocks]; bmod(A, B, C, strI, strJ, strK, strI, strK, strI); } } } } free(buf1); free(buf2); } void get_remote(double *buf, int I, int J) { int proc_owner; int edge, size; proc_owner = block_owner(I, J); edge = n%block_size; if (edge == 0) { edge = block_size; } if ((I == nblocks-1) && (J == nblocks-1)) { size = edge*edge; } else if ((I == nblocks-1) || (J == nblocks-1)) { size = edge*block_size; } else { size = block_size*block_size; } size = size * sizeof(double); ARMCI_Get(a[I+J*nblocks], buf, size, proc_owner); } void lu0(double *a, int n, int stride) { int j; int k; double alpha; for (k=0; k #include #include #include #include /* required with C99 */ #include "mp3.h" #include #define DEBUG_ #define MAXRAND 32767.0 #define DEFAULT_N 512 #define DEFAULT_B 16 /* global variables */ int n = DEFAULT_N; /* The size of the matrix */ int block_size = DEFAULT_B;/* Block dimension */ int nblocks; /* Number of blocks in each dimension */ int num_rows; /* Number of processors per row of processor grid */ int num_cols; /* Number of processors per col of processor grid */ double **a; /* a = lu; l and u both placed back in a */ int nproc, me = 0; int proc_bytes; int num; int nnodes; int doprint = 0; /* function declaration */ void lu(int, int, int); void lu0(double *,int, int); void bdiv(double *, double *, int, int, int, int); void bmodd(double *, double*, int, int, int, int); void bmod(double *, double *, double *, int, int, int, int, int, int); void daxpy(double *, double *, int, double); int block_owner(int, int); void init_array(); double touch_array(int, int); void print_block(); void print_array(int); void get_remote(double *, int, int); /* timing functions */ extern void start_timer(void); extern double elapsed_time(void); extern double stop_time(void); int main(int argc, char *argv[]) { int i, j; int ch; extern char *optarg; int edge; int size; /* ARMCI */ void **ptr; double **ptr_loc; MP_INIT(argc,argv); MP_PROCS(&nproc); MP_MYID(&me); while ((ch = getopt(argc, argv, "n:b:p:h")) != -1) { switch(ch) { case 'n': n = atoi(optarg); break; case 'b': block_size = atoi(optarg); break; case 'p': nproc = atoi(optarg); break; case 'h': { printf("Usage: LU, or \n"); printf(" LU -nMATRIXSIZE -bBLOCKSIZE -pNPROC\n"); MP_BARRIER(); MP_FINALIZE(); exit(0); } } } if(me == 0) { printf("\n Blocked Dense LU Factorization\n"); printf(" %d by %d Matrix\n", n, n); printf(" %d Processors\n", nproc); printf(" %d by %d Element Blocks\n", block_size, block_size); printf("\n"); } /* num_rows = (int) sqrt((double) nproc); */ /* for (;;) { */ /* num_cols = nproc/num_rows; */ /* if (num_rows*num_cols == nproc) */ /* break; */ /* num_rows--; */ /* } */ nblocks = n/block_size; if (block_size * nblocks != n) { nblocks++; } nnodes = nproc / 4; if((nnodes * 4) != nproc) { num_cols = nproc - nnodes * 4; nnodes++; num_rows = 1; } else { num_cols = 2; num_rows = 2; } num = (nblocks * nblocks)/nnodes; if((num * nnodes) != (nblocks * nblocks)) num++; #ifdef DEBUG if(me == 0) for (i=0;i n) { kl = n; strK = kl - k; } else { strK = bs; } /* factor diagonal block */ diagowner = block_owner(K, K); if (diagowner == me) { A = a[K+K*nblocks]; lu0(A, strK, strK); } MP_BARRIER(); /* divide column k by diagonal block */ if(block_owner(K, K) == me) D = a[K+K*nblocks]; else { D = buf1; get_remote(D, K, K); } for (i=kl, I=K+1; i n) { il = n; strI = il - i; } else { strI = bs; } A = a[I+K*nblocks]; bdiv(A, D, strI, strK, strI, strK); } } /* modify row k by diagonal block */ for (j=kl, J=K+1; j n) { jl = n; strJ = jl - j; } else { strJ = bs; } A = a[K+J*nblocks]; bmodd(D, A, strK, strJ, strK, strK); } } MP_BARRIER(); /* modify subsequent block columns */ for (i=kl, I=K+1; i n) { il = n; strI = il - i; } else { strI = bs; } if(block_owner(I,K) == me) A = a[I+K*nblocks]; else { A = buf1; get_remote(A, I, K); } for (j=kl, J=K+1; j n) { jl = n; strJ= jl - j; } else { strJ = bs; } if (block_owner(I, J) == me) { /* parcel out blocks */ if(block_owner(K,J) == me) B = a[K+J*nblocks]; else { B = buf2; get_remote(B, K, J); } C = a[I+J*nblocks]; bmod(A, B, C, strI, strJ, strK, strI, strK, strI); } } } } free(buf1); free(buf2); } void get_remote(double *buf, int I, int J) { int proc_owner; int edge, size; proc_owner = block_owner(I, J); edge = n%block_size; if (edge == 0) { edge = block_size; } if ((I == nblocks-1) && (J == nblocks-1)) { size = edge*edge; } else if ((I == nblocks-1) || (J == nblocks-1)) { size = edge*block_size; } else { size = block_size*block_size; } size = size * sizeof(double); ARMCI_Get(a[I+J*nblocks], buf, size, proc_owner); } void lu0(double *a, int n, int stride) { int j; int k; double alpha; for (k=0; k #define MP_INIT(ARGC,ARGV) MPI_Init(&(ARGC),&(ARGV)) #define MP_BARRIER() MPI_Barrier(MPI_COMM_WORLD) #define MP_FINALIZE() MPI_Finalize() #define MP_PROCS(X) MPI_Comm_size(MPI_COMM_WORLD,X) #define MP_MYID(X) MPI_Comm_rank(MPI_COMM_WORLD,X) #define MP_TIMER() MPI_Wtime() #endif /* _MP3_H_ */ armci-mpi/tests/contrib/transp1D/0000755000175000017500000000000012662706250016510 5ustar mbanckmbanckarmci-mpi/tests/contrib/transp1D/transp1D-c.c0000644000175000017500000001421012662706250020566 0ustar mbanckmbanck/** @file * transpose of 1-d array. * E,g: (1 2 3 4 5 6 7 8 9 10) => (10 9 8 7 6 5 4 3 2 1) */ #define TOTALELEMS 1007031 #include #include #include #include #include #include #include "mp3.h" #include "armci.h" void VERIFY(void **b_ptr, int *dims, int *map) { int i, j, length, icnt, ichk, lmin, lmax; int *buf, *b; void *src_ptr, *dst_ptr; int me, nprocs; /* Find local processor ID and number of processors */ me = armci_msg_me(); nprocs = armci_msg_nproc(); /* Process 0 verifies that inversion is correct. Start by allocating buffer and guarantee that it is big enough */ length = (int)(((double)dims[0])/((double)nprocs)) + 1; buf = (int*)malloc(length*sizeof(int)); if (me == 0) { icnt = 0; ichk = 0; for (i=0; i= map[i]) { pmin = i; } else { break; } } pmax = nprocs-1; for (i=nprocs-2; i>=0; i--) { if (max < map[i+1]) { pmax = i; } else { break; } } /* Loop over processors that will receive data and copy inverted data to processors */ for (i=pmin; i<=pmax; i++) { /* Find min and max indices owned by processor i */ lmin = map[i]; if (i min) { cmin = lmin; } else { cmin = min; } if (lmax < max) { cmax = lmax; } else { cmax = max; } /* Find offsets on source and destination processors */ src_offset = cmin - min; src_ptr = (void*)(buf + src_offset); dst_offset = cmin - lmin; dst_ptr = (u_int8_t*)b_ptr[i] + sizeof(int)*dst_offset; /* Find length of data (in bytes) to be sent to processor i */ length = sizeof(int)*(cmax-cmin+1); /* Send data to processor */ ARMCI_Put(src_ptr, dst_ptr, length, i); } ARMCI_AllFence(); MP_BARRIER(); free(buf); VERIFY(b_ptr, dims, map); free(map); MP_BARRIER(); ARMCI_Free(a_ptr[me]); ARMCI_Free(b_ptr[me]); free(a_ptr); free(b_ptr); } int main(int argc, char **argv) { /* int heap=300000, stack=300000; */ int me, nprocs; /* Step1: Initialize Message Passing library */ MP_INIT(argc, argv); /* Step2: Initialize ARMCI */ ARMCI_Init(); /* Step3: Initialize Memory Allocator (MA) */ /*bjp if(! MA_init(C_DBL, stack, heap) ) ARMCI_Error("MA_init failed",stack+heap); */ me = armci_msg_me(); nprocs = armci_msg_nproc(); if(me==0) { printf("\nUsing %d processes\n\n", nprocs); fflush(stdout); } TRANSPOSE1D(); if(me==0)printf("\nTerminating ..\n"); ARMCI_Finalize(); MP_FINALIZE(); return(0); } armci-mpi/tests/contrib/transp1D/mp3.h0000644000175000017500000000034512662706250017362 0ustar mbanckmbanck#ifndef _MP3_H_ #define _MP3_H_ #include #define MP_INIT(ARGC,ARGV) MPI_Init(&(ARGC),&(ARGV)) #define MP_BARRIER() MPI_Barrier(MPI_COMM_WORLD) #define MP_FINALIZE() MPI_Finalize() #endif /* _MP3_H_ */ armci-mpi/tests/contrib/transp1D/Makefile.mk0000644000175000017500000000046112662706250020557 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # check_PROGRAMS += tests/contrib/transp1D/transp1D-c TESTS += tests/contrib/transp1D/transp1D-c tests_contrib_transp1D_transp1D_c_SOURCES = tests/contrib/transp1D/transp1D-c.c tests_contrib_transp1D_transp1D_c_LDADD = libarmci.la armci-mpi/tests/contrib/Makefile.mk0000644000175000017500000000116612662706250017066 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # check_PROGRAMS += \ tests/contrib/armci-perf \ tests/contrib/armci-test \ # end TESTS += \ tests/contrib/armci-perf \ tests/contrib/armci-test \ # end tests_contrib_armci_perf_LDADD = libarmci.la -lm tests_contrib_armci_test_LDADD = libarmci.la -lm include tests/contrib/cg/Makefile.mk include tests/contrib/lu/Makefile.mk include tests/contrib/transp1D/Makefile.mk include tests/contrib/non-blocking/Makefile.mk armci-mpi/tests/contrib/LICENSE0000644000175000017500000000313012662706250016016 0ustar mbanckmbanckUnless otherwise noted, files contained within the tests/contrib directory are copyright: Copyright (c) 2006 Pacific Northwest National Laboratory, Battelle Memorial Institute. 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 Battelle nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. armci-mpi/tests/contrib/armci-perf.c0000644000175000017500000004272612662706250017220 0ustar mbanckmbanck/* * Author: Jialin Ju, PNNL */ /* $Id: perf.c,v 1.21 2006-09-12 23:21:21 andriy Exp $ */ #include #include #include #include #include #include #include #define SIZE 550 #define MAXPROC 8 #define CHUNK_NUM 28 #define FORCE_1D_ #ifndef ABS #define ARMCI_ABS(a) ((a)>0? (a): -(a)) #endif #ifndef ARMCI_MAX_STRIDE_LEVEL #define ARMCI_MAX_STRIDE_LEVEL 6 #endif /* tells to use ARMCI_Malloc_local instead of plain malloc */ #define MALLOC_LOC int CHECK_RESULT=0; int chunk[CHUNK_NUM] = {1,3,4,6,9,12,16,20,24,30,40,48,52,64,78,91,104, 128,142,171,210,256,300,353,400,440,476,512}; char check_type[15]; int nproc, me; int warn_accuracy=0; void fill_array(double *arr, int count, int which); void check_result(double *src_buf, double *dst_buf, int *stride, int *count, int stride_levels); void acc_array(double scale, double *array1, double *array2, int *stride, int *count, int stride_levels); static double _tt0=0.0; /*\ quick fix for inacurate timer \*/ double Timer() { #define DELTA 0.000001 double t=MP_TIMER(); if(t<=_tt0 + DELTA) _tt0 += DELTA; else _tt0 = t; return _tt0; } #define TIMER MP_TIMER double time_get(double *src_buf, double *dst_buf, int chunk, int loop, int proc, int levels) { int i, bal = 0; int stride[2]; int count[2]; int stride_levels = levels; double *tmp_buf = NULL, *tmp_buf_ptr = NULL; double start_time, stop_time, total_time = 0; stride[0] = SIZE * sizeof(double); count[0] = chunk * sizeof(double); count[1] = chunk; if(CHECK_RESULT) { tmp_buf = (double *)malloc(SIZE * SIZE * sizeof(double)); assert(tmp_buf != NULL); fill_array(tmp_buf, SIZE*SIZE, proc); tmp_buf_ptr = tmp_buf; } start_time = TIMER(); for(i=0; i0)for(j=0; j< count[1]; j++){ char *s = (char*) src_buf, *d= (char*)dst_buf; s += j*stride[0]; d += j*stride[0]; ARMCI_Get(src_buf, dst_buf, count[0],proc); } else #endif if(levels) ARMCI_GetS(src_buf, stride, dst_buf, stride, count, stride_levels,proc); else ARMCI_Get(src_buf, dst_buf,count[0], proc); if(CHECK_RESULT) { sprintf(check_type, "ARMCI_GetS:"); check_result(tmp_buf_ptr, dst_buf, stride, count, stride_levels); } /* prepare next src and dst ptrs: avoid cache locality */ if(bal == 0) { src_buf += 128; dst_buf += 128; if(CHECK_RESULT) tmp_buf_ptr += 128; bal = 1; } else { src_buf -= 128; dst_buf -= 128; if(CHECK_RESULT) tmp_buf_ptr -= 128; bal = 0; } } stop_time = TIMER(); total_time = (stop_time - start_time); if(CHECK_RESULT) free(tmp_buf); if(total_time == 0.0){ total_time=0.000001; /* workaround for inaccurate timers */ warn_accuracy++; } return(total_time/loop); } double time_put(double *src_buf, double *dst_buf, int chunk, int loop, int proc, int levels) { int i, bal = 0; int stride[2]; int count[2]; int stride_levels = levels; double *tmp_buf = NULL; double start_time, stop_time, total_time = 0; stride[0] = SIZE * sizeof(double); count[0] = chunk * sizeof(double); count[1] = chunk; if(CHECK_RESULT) { tmp_buf = (double *)malloc(SIZE * SIZE * sizeof(double)); assert(tmp_buf != NULL); } start_time = TIMER(); for(i=0; i0)for(j=0; j< count[1]; j++){ char *s = (char*) src_buf, *d= (char*)dst_buf; s += j*stride[0]; d += j*stride[0]; ARMCI_Put(src_buf, dst_buf, count[0],proc); } else #endif if(levels) ARMCI_PutS(src_buf, stride, dst_buf, stride, count, stride_levels,proc); else ARMCI_Put(src_buf, dst_buf,count[0], proc); if(CHECK_RESULT) { ARMCI_GetS(dst_buf, stride, tmp_buf, stride, count, stride_levels, proc); sprintf(check_type, "ARMCI_PutS:"); check_result(tmp_buf, src_buf, stride, count, stride_levels); } /* prepare next src and dst ptrs: avoid cache locality */ if(bal == 0) { src_buf += 128; dst_buf += 128; bal = 1; } else { src_buf -= 128; dst_buf -= 128; bal = 0; } } stop_time = TIMER(); total_time = (stop_time - start_time); if(CHECK_RESULT) free(tmp_buf); if(total_time == 0.0){ total_time=0.000001; /* workaround for inaccurate timers */ warn_accuracy++; } return(total_time/loop); } double time_acc(double *src_buf, double *dst_buf, int chunk, int loop, int proc, int levels) { int i, bal = 0; int stride[2]; int count[2]; int stride_levels = levels; double *before_buf = NULL, *after_buf = NULL; double start_time, stop_time, total_time = 0; stride[0] = SIZE * sizeof(double); count[0] = chunk * sizeof(double); count[1] = chunk; if(CHECK_RESULT) { before_buf = (double *)malloc(SIZE * SIZE * sizeof(double)); assert(before_buf != NULL); after_buf = (double *)malloc(SIZE * SIZE * sizeof(double)); assert(after_buf != NULL); } start_time = TIMER(); for(i=0; i MAXPROC) { if(me == 0) fprintf(stderr, "USAGE: 2 <= processes < %d - got %d\n", MAXPROC, nproc); MP_BARRIER(); MP_FINALIZE(); exit(0); } /* initialize ARMCI */ ARMCI_Init_args(&argc, &argv); if(!me)printf("\n Performance of Basic Blocking Communication Operations\n"); MP_BARRIER(); CHECK_RESULT=1; test_1D(); CHECK_RESULT=0; /* warmup run */ /* test 1 dimension array */ if(!me)printf("\n\t\t\tContiguous Data Transfer\n"); test_1D(); /* test 2 dimension array */ if(!me)printf("\n\t\t\tStrided Data Transfer\n"); test_2D(); MP_BARRIER(); if(me == 0){ if(warn_accuracy) printf("\nWARNING: Your timer does not have sufficient accuracy for this test (%d)\n",warn_accuracy); printf("\n\n------------ Now we test the same data transfer for correctness ----------\n"); fflush(stdout); } MP_BARRIER(); CHECK_RESULT=1; if(!me)printf("\n\t\t\tContiguous Data Transfer\n"); test_1D(); if(me == 0) printf("OK\n"); MP_BARRIER(); if(!me)printf("\n\t\t\tStrided Data Transfer\n"); test_2D(); if(me == 0) printf("OK\n\n\nTests Completed.\n"); MP_BARRIER(); /* done */ ARMCI_Finalize(); MP_FINALIZE(); return(0); } void fill_array(double *arr, int count, int which) { int i; for(i=0; i (count[j]-1)) bvalue[j] = 0; } size = count[0] / sizeof(double); for(j=0; j 0.000001 ){ fprintf(stdout,"Error:%s comparison failed: (%d) (%f :%f) %d\n", check_type, j, ((double *)((char *)src_buf+idx))[j], ((double *)((char *)dst_buf+idx))[j], count[0]); ARMCI_Error("failed",0); } } } /* array1 = array1 + array2 * scale */ void acc_array(double scale, double *array1, double *array2, int *stride, int *count, int stride_levels) { int i, j, size; long idx; int n1dim; /* number of 1 dim block */ int bvalue[ARMCI_MAX_STRIDE_LEVEL], bunit[ARMCI_MAX_STRIDE_LEVEL]; /* number of n-element of the first dimension */ n1dim = 1; for(i=1; i<=stride_levels; i++) n1dim *= count[i]; /* calculate the destination indices */ bvalue[0] = 0; bvalue[1] = 0; bunit[0] = 1; bunit[1] = 1; for(i=2; i<=stride_levels; i++) { bvalue[i] = 0; bunit[i] = bunit[i-1] * count[i-1]; } for(i=0; i (count[j]-1)) bvalue[j] = 0; } size = count[0] / sizeof(double); for(j=0; j #define MP_INIT(ARGC,ARGV) MPI_Init(&(ARGC),&(ARGV)) #define MP_BARRIER() MPI_Barrier(MPI_COMM_WORLD) #define MP_FINALIZE() MPI_Finalize() #define MP_PROCS(X) MPI_Comm_size(MPI_COMM_WORLD,X) #define MP_MYID(X) MPI_Comm_rank(MPI_COMM_WORLD,X) #define MP_TIMER() MPI_Wtime() #endif /* _MP3_H_ */ armci-mpi/tests/contrib/non-blocking/overlap.c0000644000175000017500000006716212662706250021224 0ustar mbanckmbanck/** @file * Copyright (c) 2006 * Pacific Northwest National Laboratory, * Battelle Memorial Institute. * 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 Battelle nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. * * $Id$ */ #include #include #include #include #include #include #include #include #include "mp3.h" #include #define MP_ASSERT(X) X extern double exp2(double); extern double round(double); extern double log2(double); #define NDEBUG // #define LOG2FILE typedef int t_elem; /* type of an array element */ #define SIZE_ELEM sizeof(t_elem) #define STRIDE_OFF (SIZE_ELEM * 4 - 1) #define MIN_MSG_SIZE 8 #define MAX_MSG_SIZE (1024 * 1024) #define MSG_COUNT 20 int armci_error_code; #define ARMCI_ASSERT(error_code) if ((armci_error_code = error_code)) { \ fprintf(stderr, "ARMCI error %d\n", armci_error_code);pause(); \ ARMCI_Cleanup(); MPI_Abort(MPI_COMM_WORLD, armci_error_code); } #define FIX_TIME(t) if (t < 0.0) t = 0.0; int size, rank, second; #define ITERS 18 #define ITER_STEPS 20 double iterations_times[ITERS]; int iterations[ITERS]; int *p_srcs, *p_dsts; enum {CONT_PUT, CONT_GET, STRIDED_PUT, STRIDED_GET, STRIDED_ACC, VECTOR_PUT, VECTOR_GET, VECTOR_ACC}; #define OPS_COUNT (STRIDED_ACC + 1) #define NON_CONT(op) (op > CONT_GET) enum {NOWORK, TOTAL, OVERLAP}; #define STATS_COUNT (OVERLAP + 1) /* prints formatted numbered message with processor's rank */ int log_debug(const char *fmt, ...) { int r = 0; #ifndef NDEBUG static int log_counter = 1; va_list ap; va_start(ap, fmt); printf("%03d@%1d: ", log_counter++, rank); r = vprintf(fmt, ap); va_end(ap); #endif return r; } FILE *log_file = NULL; void start_logging(const char *fname) { #ifdef LOG2FILE char exe_name[255]; char log_path[255]; size_t i; char k; strcpy(exe_name, fname); if (exe_name[strlen(exe_name) - 2] == '.') /* remove .x */ exe_name[strlen(exe_name) - 2] = 0; if (exe_name[0] == '/') { /* full path given */ for (i = strlen(exe_name) - 1, k = -1; i >= 0; i--) if (exe_name[i] == '/') { if (k == -1) k = i + 1; else { exe_name[i] = 0; break; } } log_debug("exe: path=%s, name=%s\n", exe_name, exe_name + k); sprintf(log_path, "%s/data/%s.dat", exe_name, exe_name + k); } else { /* only executable name */ // sprintf(log_path, "../data/%s.dat", exe_name); sprintf(log_path, "%s.dat", exe_name); } log_debug("log: %s\n", log_path); log_file = fopen(log_path, "w"); if (!log_file) { perror("cannot open log file"); abort(); } #else log_file = stderr; #endif } void finish_logging() { fclose(log_file); } /* prints formatted message to ../data/.dat */ int log_printf(const char *fmt, ...) { va_list ap; int r; va_start(ap, fmt); if (log_file) r = vfprintf(log_file, fmt, ap); else { fprintf(stderr, "warning: logging is not enabled for this process\n"); r = vfprintf(stderr, fmt, ap); } va_end(ap); return r; } /* computes approximate time of n iterations for variable n */ void time_iterations() { double time_start, time_after_start, time_stop; int i, j, k, l; for (i = 0, j = 1; i < ITERS; i++, j *= 2) { time_start = MP_TIMER(); time_after_start = MP_TIMER(); for (l = 0, k = rand(); l < j; l++) k *= rand(); time_stop = MP_TIMER(); iterations_times[i] = time_stop - time_after_start + time_start - time_after_start; FIX_TIME(iterations_times[i]); iterations[i] = j; log_debug("it takes %.8f sec to iterate %d times\n", iterations_times[i], iterations[i]); } } /* computes useful overlap time for contiguous/vector/strided arrays * * op - operation * * msg_size - size of a message/ 1st dimension (bytes) * * size2 - not used for contiguous arrays * * - size of 2nd dimension for strided arrays (bytes) * * - # of vector segments for vectors * * returns pointer to static array of stats (STATS_COUNT doubles) * */ double * benchmark(int op, int msg_size, int size2) { static double stats[STATS_COUNT]; /* return statistics in static array */ void *array_ptrs[size]; int stride_dist, block_sizes[2], scale = 2; int i=0, j=0, k=0, l=0, less=0, more=0; double time_start=0, time_after_start=0, time_after_call=0, time_after_work=0, time_after_wait=0; double time2call_nw=0, time2wait_nw = 1.0, time_total_nw=0; double time2call_fw, time2work_fw, time2wait_fw, time_total_fw; armci_hdl_t handle; log_debug("barrier O\n"); MP_ASSERT(MP_BARRIER()); /* initialize: obtain remote address and generate random array */ switch (op) { case CONT_PUT: case CONT_GET: ARMCI_ASSERT(ARMCI_Malloc(array_ptrs, msg_size)); for (i = 0; i < msg_size; i++) ((char *)array_ptrs[rank])[i] = (char)(rand() >> 24); break; /* 2D strided array of ints */ case STRIDED_PUT: case STRIDED_GET: case STRIDED_ACC: block_sizes[0] = msg_size; block_sizes[1] = size2; stride_dist = STRIDE_OFF + msg_size; log_debug("strided: dim1 = %d (%d bytes), dim2 = %d, stride = %d\n", msg_size / SIZE_ELEM, msg_size, size2, stride_dist); ARMCI_ASSERT(ARMCI_Malloc(array_ptrs, (size2 - 1) * stride_dist + msg_size)); for (i = 0; i < size2; i++) for (j = 0; j < (msg_size / SIZE_ELEM); j++) { l = stride_dist * i + SIZE_ELEM * i; *(int *)((char *)array_ptrs[rank] + l) = rand(); } break; } /* warm up call */ log_debug("barrier A\n"); MP_ASSERT(MP_BARRIER()); if (second != -1) { log_debug("testing message size %d bytes\n", msg_size); switch (op) { case CONT_PUT: ARMCI_INIT_HANDLE(&handle); time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbPut(array_ptrs[rank], array_ptrs[second], msg_size, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case CONT_GET: ARMCI_INIT_HANDLE(&handle); time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbGet(array_ptrs[second], array_ptrs[rank], msg_size, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_PUT: ARMCI_INIT_HANDLE(&handle); time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbPutS(array_ptrs[rank], &stride_dist, array_ptrs[second], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_GET: ARMCI_INIT_HANDLE(&handle); time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbGetS(array_ptrs[second], &stride_dist, array_ptrs[second], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_ACC: ARMCI_INIT_HANDLE(&handle); time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbAccS(ARMCI_ACC_INT, &scale, array_ptrs[rank], &stride_dist, array_ptrs[second], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; } time2call_nw = time_after_call - time_after_start + time_start - time_after_start; time2wait_nw = time_after_wait - time_after_call + time_start - time_after_start; time_total_nw = time_after_wait - time_after_start + time_start - time_after_start; log_debug("time (warm up): %.8f call, %.8f wait, %.8f total\n", time2call_nw, time2wait_nw, time_total_nw); } log_debug("barrier B\n"); MP_ASSERT(MP_BARRIER()); if (second != -1) { /* no work */ ARMCI_INIT_HANDLE(&handle); switch (op) { case CONT_PUT: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbPut(array_ptrs[rank], array_ptrs[second], msg_size, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case CONT_GET: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbGet(array_ptrs[second], array_ptrs[rank], msg_size, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_PUT: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbPutS(array_ptrs[rank], &stride_dist, array_ptrs[second], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_GET: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbGetS(array_ptrs[second], &stride_dist, array_ptrs[rank], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_ACC: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbAccS(ARMCI_ACC_INT, &scale, array_ptrs[rank], &stride_dist, array_ptrs[second], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; } time2call_nw = time_after_call - time_after_start + time_start - time_after_start; FIX_TIME(time2call_nw); time2wait_nw = time_after_wait - time_after_call + time_start - time_after_start; FIX_TIME(time2wait_nw); time_total_nw = time_after_wait - time_after_start + time_start - time_after_start; FIX_TIME(time_total_nw); log_debug("time (no work): %.8f call, %.8f wait, %.8f total\n", time2call_nw, time2wait_nw, time_total_nw); } /* only perform tests if wait time is not 0 */ if (time2wait_nw > 0.0) { /* time2wait_nw is always 1.0 on seconds (receiving nodes) */ if (second != -1) { /* compute approximate range of iterations */ less = 0, more = iterations[ITERS - 1]; assert(time2wait_nw < iterations_times[ITERS - 1]); for (i = 0; i < ITERS; i++) if (time2wait_nw > iterations_times[i]) less = iterations[i]; else break; for (i = 0; i < ITERS; i++) if (time2wait_nw < iterations_times[ITERS - i - 1]) more = iterations[ITERS - i - 1]; else break; log_debug("wait time (%.8f) is between %d and %d iterations\n", time2wait_nw, less, more); } /* benchmark ITER_STEPS steps within computed range */ double overlaps[ITER_STEPS], totals[ITER_STEPS]; for (i = 0, j = less; i < ITER_STEPS; i++, j += (more - less) / (ITER_STEPS - 1)) { /* time noneblocking call with j interations of fake work */ log_debug("barrier C\n"); MP_ASSERT(MP_BARRIER()); if (second != -1) { ARMCI_INIT_HANDLE(&handle); switch (op) { case CONT_PUT: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbPut(array_ptrs[rank], array_ptrs[second], msg_size, second, &handle)); time_after_call = MP_TIMER(); for (l = 0, k = rand(); l < j; l++) k *= rand(); time_after_work = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case CONT_GET: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbGet(array_ptrs[second], array_ptrs[rank], msg_size, second, &handle)); time_after_call = MP_TIMER(); for (l = 0, k = rand(); l < j; l++) k *= rand(); time_after_work = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_PUT: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbPutS(array_ptrs[rank], &stride_dist, array_ptrs[second], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); for (l = 0, k = rand(); l < j; l++) k *= rand(); time_after_work = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_GET: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbGetS(array_ptrs[second], &stride_dist, array_ptrs[rank], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); for (l = 0, k = rand(); l < j; l++) k *= rand(); time_after_work = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; case STRIDED_ACC: time_start = MP_TIMER(); time_after_start = MP_TIMER(); ARMCI_ASSERT(ARMCI_NbAccS(ARMCI_ACC_INT, &scale, array_ptrs[rank], &stride_dist, array_ptrs[second], &stride_dist, block_sizes, 1, second, &handle)); time_after_call = MP_TIMER(); for (l = 0, k = rand(); l < j; l++) k *= rand(); time_after_work = MP_TIMER(); ARMCI_ASSERT(ARMCI_Wait(&handle)); time_after_wait = MP_TIMER(); break; } time2call_fw = time_after_call - time_after_start + time_start - time_after_start; FIX_TIME(time2call_fw); time2work_fw = time_after_work - time_after_call + time_start - time_after_start; FIX_TIME(time2work_fw); time2wait_fw = time_after_wait - time_after_work + time_start - time_after_start; FIX_TIME(time2wait_fw); time_total_fw = time_after_wait - time_after_start + time_start - time_after_start; FIX_TIME(time_total_fw); log_debug("time (%d iters): %.8f call, %.8f work, " "%.8f wait %.8f total\n", j, time2call_fw, time2work_fw, time2wait_fw, time_total_fw); overlaps[i] = time2work_fw; totals[i] = time_total_fw; } } /* pick overlap with closest total (less or equal) */ if (second != -1) { double closest_total, closest_overlap; double smallest_total = totals[ITER_STEPS - 1], smallest_overlap = overlaps[ITER_STEPS - 1]; for (i = ITER_STEPS - 1; i >= 0; i--) { closest_total = totals[i]; closest_overlap = overlaps[i]; if (closest_total < smallest_total) { smallest_total = closest_total; smallest_overlap = closest_overlap; } if (closest_total <= time_total_nw) break; } if (closest_total > time_total_nw) { closest_total = smallest_total; closest_overlap = smallest_overlap; } stats[NOWORK] = time_total_nw; stats[TOTAL] = closest_total; stats[OVERLAP] = closest_overlap; } } else { if (second != -1) { for (i = 0; i < ITER_STEPS; i++) { log_debug("barrier C0\n"); MP_ASSERT(MP_BARRIER()); } stats[NOWORK] = time_total_nw; stats[TOTAL] = 0; stats[OVERLAP] = 0; } } /*ARMCI_ASSERT(ARMCI_Free(array_ptrs[rank]));*/ log_debug("barrier D\n"); MP_ASSERT(MP_BARRIER()); return stats; } int main (int argc, char *argv[]) { int i, j, k, l; double u; char buf[255]; int dist, pos, time_seed; int msg_sizes[MSG_COUNT], dim1_sizes[MSG_COUNT], dim2[MSG_COUNT], mul_elem; double *stats=NULL, *stats_all=NULL; MP_ASSERT(MP_INIT(argc, argv)); MP_ASSERT(MP_MYID(&rank)); MP_ASSERT(MP_PROCS(&size)); assert((size & 1) ^ 1); /* works with even number of processors only */ log_debug("Message passing initialized\n"); ARMCI_ASSERT(ARMCI_Init()); log_debug("ARMCI initialized\n"); if (!rank) start_logging(argv[0]); /* generate MSG_COUNT message sizes MIN_MSG_SIZE thru MAX_MSG_SIZE */ double from_log = log2(MIN_MSG_SIZE); double to_log = log2(MAX_MSG_SIZE); double step_log = (to_log - from_log) / (MSG_COUNT - 1); for (i = 0, u = from_log; i < MSG_COUNT; i++, u += step_log) { mul_elem = round(exp2(u)); msg_sizes[i] = mul_elem % SIZE_ELEM ? (mul_elem / SIZE_ELEM + 1) * SIZE_ELEM : mul_elem; /* multiple of SIZE_ELEM */ } /* generate MSG_COUNT respective dim1 sizes and dim2 for strided */ for (i = 0; i < MSG_COUNT; i++) { mul_elem = msg_sizes[i] / SIZE_ELEM; mul_elem = sqrt(2.0 * mul_elem); dim1_sizes[i] = mul_elem * SIZE_ELEM; dim2[i] = mul_elem / 2; } /* print msg_sizes and appropriate derivatives (debug mode only) */ if (!rank) { log_debug("msg_sizes:\n"); for (i = 0; i < MSG_COUNT; i++) log_debug("cont: %d bytes | strided: %d bytes X %d\n", msg_sizes[i], dim1_sizes[i], dim2[i]); } /* inialize PRNG, use seed generated on processor 0 for uniform sequence */ time_seed = time(NULL); MP_ASSERT(MPI_Bcast (&time_seed, 1, MPI_INT, 0, MPI_COMM_WORLD)); srand(time_seed); rand(); log_debug("seed: %d\n", time_seed); /* generate random pairs of processors */ #define HALFSIZE (size / 2) assert(p_srcs = malloc(sizeof(int) * size)); for (i = 0; i < size; i++) p_srcs[i] = -1; p_dsts = p_srcs + HALFSIZE; for (i = 0, j = size - 1, pos = 0; i < size; i++, j--) { dist = round((double)rand() * j / RAND_MAX + 1); /* random 1..j */ for (l = 0; l < dist; ) { pos = (pos + 1 == size) ? 0 : pos + 1; if ((p_srcs[pos] == -1) && (pos != i)) l++; } p_srcs[pos] = i; } for (i = 0, j = 0; i < HALFSIZE; i++) j += sprintf(buf + j, " %d->%d", p_srcs[i], p_dsts[i]); log_debug("random pairs:%s\n", buf); /* time interations: 1 thru ITERS */ time_iterations(); /* determine if processor initiates communication and where it sends to, * * -1 for second(receiver) */ second = -1; for (i = 0; i < HALFSIZE; i++) if (p_srcs[i] == rank) second = p_dsts[i]; log_debug("second: %d\n", second); /* allocate memory for statisticis */ #define MSG_OFF (STATS_COUNT * size) #define OPS_OFF (MSG_OFF * MSG_COUNT) assert(stats_all = malloc(OPS_COUNT * OPS_OFF * sizeof(double))); for (i = 0; i < OPS_COUNT; i++) for (j = 0; j < MSG_COUNT; j++) { switch (i) { case CONT_PUT: case CONT_GET: stats = benchmark(i, msg_sizes[j], 0); log_debug("stats: %8d | %.8f | %.8f | %.8f | %.2f\n", msg_sizes[j], stats[NOWORK], stats[TOTAL], stats[OVERLAP], 100.0 * stats[OVERLAP] / stats[TOTAL]); break; case STRIDED_PUT: case STRIDED_GET: case STRIDED_ACC: stats = benchmark(i, dim1_sizes[j], dim2[j]); log_debug("stats: %8d | %.8f | %.8f | %.8f | %.2f\n", dim1_sizes[j] * dim2[j], stats[NOWORK], stats[TOTAL], stats[OVERLAP], 100.0 * stats[OVERLAP] / stats[TOTAL]); break; } MP_ASSERT(MPI_Gather(stats, STATS_COUNT, MPI_DOUBLE, stats_all + i * OPS_OFF + j * MSG_OFF, STATS_COUNT, MPI_DOUBLE, 0, MPI_COMM_WORLD)); } if (!rank) for (l = 0; l < HALFSIZE; l++) { /* interate thru pairs */ log_printf("for pair of processors %d -> %d:\n", p_srcs[l], p_dsts[l]); for (i = 0; i < OPS_COUNT; i++) { /* iterate thru operations */ switch (i) { case CONT_PUT: log_printf("ARMCI_NbPut\n"); break; case CONT_GET: log_printf("ARMCI_NbGet\n"); break; case STRIDED_PUT: log_printf("ARMCI_NbPutS\n"); break; case STRIDED_GET: log_printf("ARMCI_NbGetS\n"); break; case STRIDED_ACC: log_printf("ARMCI_NbAccS\n"); break; } log_printf("msg size | nowork | total | overlap |" " ratio\n"); log_printf("---------+------------+------------+------------+" "------\n"); for (j = 0; j < MSG_COUNT; j++) { /* iterate thru msg sizes */ k = i * OPS_OFF + j * MSG_OFF + p_srcs[l] * STATS_COUNT; log_printf("%8d | %.8f | %.8f | %.8f | %.2f\n", NON_CONT(i) ? dim1_sizes[j] * dim2[j]: msg_sizes[j], stats_all[k + NOWORK], stats_all[k + TOTAL], stats_all[k + OVERLAP], (stats_all[k + NOWORK] < stats_all[k + TOTAL]) || (stats_all[k + TOTAL] <= 0.0) ? 0 : 100.0 * stats_all[k + OVERLAP] / stats_all[k + TOTAL]); } log_printf("\n"); } } if (!rank) finish_logging(); ARMCI_Finalize(); MP_FINALIZE(); free(p_srcs); free(stats_all); return 0; } armci-mpi/tests/contrib/non-blocking/Makefile.mk0000644000175000017500000000074612662706250021451 0ustar mbanckmbanck# # Copyright (C) 2010. See COPYRIGHT in top-level directory. # check_PROGRAMS += tests/contrib/non-blocking/overlap tests/contrib/non-blocking/simple TESTS += tests/contrib/non-blocking/simple tests_contrib_non_blocking_overlap_SOURCES = tests/contrib/non-blocking/overlap.c tests_contrib_non_blocking_overlap_LDADD = libarmci.la -lm tests_contrib_non_blocking_simple_SOURCES = tests/contrib/non-blocking/simple.c tests_contrib_non_blocking_simple_LDADD = libarmci.la -lm armci-mpi/tests/contrib/non-blocking/simple.c0000644000175000017500000000326612663426407021044 0ustar mbanckmbanck#include #include #include #include "mp3.h" #include int me, nprocs; int LOOP=10; int main(int argc, char **argv) { int i; double **myptrs; double t0, t1, tnbget=0, tnbwait=0, t2=0; MP_INIT(argc,argv); ARMCI_Init(); MP_PROCS(&nprocs); MP_MYID(&me); if (nprocs < 2) ARMCI_Error("This program requires at least two processes", 1); myptrs = (double **)malloc(sizeof(double *)*nprocs); ARMCI_Malloc((void **)myptrs, LOOP*sizeof(double)); MP_BARRIER(); if(me == 0) { for(i = 0; i < 10; i++) { // This is a bug: // ARMCI_Get(myptrs[me]+i,myptrs[me+1]+i,sizeof(double),me+1); ARMCI_Get(myptrs[me+1]+i, myptrs[me]+i, sizeof(double), me+1); } t0 = MP_TIMER(); for(i = 0; i < LOOP; i++) { // This is a bug: // ARMCI_Get(myptrs[me]+i,myptrs[me+1]+i,sizeof(double),me+1); ARMCI_Get(myptrs[me+1]+1, myptrs[me]+i, sizeof(double), me+1); } t1 = MP_TIMER(); printf("\nGet Latency=%lf\n", 1e6*(t1-t0)/LOOP); fflush(stdout); t1 = t0 = 0; for(i = 0; i < LOOP; i++) { armci_hdl_t nbh; ARMCI_INIT_HANDLE(&nbh); t0 = MP_TIMER(); //ARMCI_NbGet(myptrs[me]+i, myptrs[me+1]+i, sizeof(double), me+1, &nbh); ARMCI_NbGet(myptrs[me+1]+i, myptrs[me]+i, sizeof(double), me+1, &nbh); t1 = MP_TIMER(); ARMCI_Wait(&nbh); t2 = MP_TIMER(); tnbget += (t1-t0); tnbwait += (t2-t1); } printf("\nNb Get Latency=%lf Nb Wait=%lf\n",1e6*tnbget/LOOP,1e6*tnbwait/LOOP);fflush(stdout); } else sleep(1); MP_BARRIER(); ARMCI_Free(myptrs[me]); free(myptrs); ARMCI_Finalize(); MP_FINALIZE(); return 0; } armci-mpi/tests/contrib/non-blocking/README0000644000175000017500000000421212662706250020253 0ustar mbanckmbanckNonblocking operations initiate a communication call and then return control to the application. The user who wishes to exploit nonblocking communication as a technique for latency hiding by overlapping communication with computation implicitly assumes that progress in communication can be made in a purely computational phase of the program execution when no communication calls are made. All the non-blocking transfer functions are prototyped to work as transfers with both "explicit" and "implicit handle". It stores important information about the initiated data transfer. The descriptor is implemented as an abstract data type. This is motivated by a simpler implementation so that a data transfer descriptor can be stored and managed in the application rather in the ARMCI library space. If a NULL value is passed to the argument representing a handle (thus representing "implicit handle"), the function does an implicit handle non-blocking transfer. A request data structure embedded in the handle should not be copied in the application. Upon completion of the data transfer, handle can be reused. A handle can be used to represent multiple operations of the same type (i.e., all puts or all gets). Such handle is an aggregate handle. Underneath, ARMCI combines multiple requests and processes them as a single message (actually by calling ARMCI_PutV/GetV/AccV). An explict handle should be initialized using the following macro, before it is used in any non-blocking operation. It is initialized as follows: - ARMCI_INIT_HANDLE(armci_hdl_t* nb_handle) Nonblocking operations in ARMCI allow user ot initiate a one-sided call and then return control to the user program. The data transfer is completed locally by calling a wait operation. Waiting on a nonblocking put operation assures was injected into the network and the user buffer can be now reused. Both in case of blocking and nonblocking store operations, to access the modified data safely from other nodes programmer has to call an ARMCI_Fence call first. ARMCI_Fence completes data transfers on the remote side. Unlike the blocking operation, the nonblocking operations are NOT ordered. armci-mpi/tests/contrib/armci-test.c0000644000175000017500000014617612663426407017253 0ustar mbanckmbanck#include #include #include #include #include #define MP_BARRIER() MPI_Barrier(MPI_COMM_WORLD) #define MP_FINALIZE() MPI_Finalize() #define MP_INIT(arc,argv) MPI_Init(&(argc),&(argv)) #define MP_MYID(pid) MPI_Comm_rank(MPI_COMM_WORLD, (pid)) #define MP_PROCS(pproc) MPI_Comm_size(MPI_COMM_WORLD, (pproc)); #include #define ELEMS 500 #define DIM1 5 #define DIM2 3 #ifdef __sun /* Solaris has shared memory shortages in the default system configuration */ # define DIM3 6 # define DIM4 5 # define DIM5 4 #elif defined(__alpha__) # define DIM3 8 # define DIM4 5 # define DIM5 6 #else # define DIM3 8 # define DIM4 9 # define DIM5 7 #endif #define DIM6 3 #define DIM7 2 #define OFF 1 #define EDIM1 (DIM1+OFF) #define EDIM2 (DIM2+OFF) #define EDIM3 (DIM3+OFF) #define EDIM4 (DIM4+OFF) #define EDIM5 (DIM5+OFF) #define EDIM6 (DIM6+OFF) #define EDIM7 (DIM7+OFF) #define DIMS 4 #define MAXDIMS 7 #define MAX_DIM_VAL 50 #define LOOP 200 #define BASE 100. #define MAXPROC 128 #define TIMES 100 /***************************** macros ************************/ #define COPY(src, dst, bytes) memcpy((dst),(src),(bytes)) #define MAX(a,b) (((a) >= (b)) ? (a) : (b)) #define MIN(a,b) (((a) <= (b)) ? (a) : (b)) #define ABS(a) (((a) <0) ? -(a) : (a)) /***************************** global data *******************/ int me, nproc; void* work[MAXPROC]; /* work array for propagating addresses */ /*\ generate random range for a section of multidimensional array \*/ void get_range(int ndim, int dims[], int lo[], int hi[]) { int dim; for(dim=0; dim 0)? rand()%range : lo[dim]; new_lo[dim] = toss; new_hi[dim] = toss + diff -1; assert(new_hi[dim] < dims[dim]); assert(diff == (new_hi[dim] -new_lo[dim]+1)); } } /*\ print range of ndim dimensional array with two strings before and after \*/ void print_range(char *pre,int ndim, int lo[], int hi[], char* post) { int i; printf("%s[",pre); for(i=0;i=100) ARMCI_Error("increase MMAX", g_idx); ARMCI_Memget(bytes, &meminfo[g_idx][me], 0); for(i=0; i "); print_range("remote",ndim,loB, hiB,"-> "); print_range("local",ndim,loC, hiC,"\n"); } idx1 = Index(ndim, loA, dimsA); idx2 = Index(ndim, loB, dimsB); idx3 = Index(ndim, loC, dimsA); for(j=0;j=nproc){ distance=nproc/2; if((nproc%2)!=0)distance++; distance-=me; } } else { distance--; if((me-distance)>=(nproc/2)){ distance=nproc/2; if((nproc%2)!=0)distance++; distance=distance+(me-distance); } } if(ndim!=1 && MAXDIMS>nproc && (ndim%(nproc/2)==0)){ distance=nproc/2; if((nproc%2)!=0)distance++; } } return(proc); } void test_nbdim() { int elems=1,elems1=1; int i,j, proc,ndim,rc; void *b[MAXDIMS+1][MAXPROC]; void *a[MAXDIMS+1], *c[MAXDIMS+1]; armci_hdl_t hdl_put[MAXDIMS+1],hdl_get[MAXDIMS+1]; int idx1=0, idx2=0, idx3=0; /* create shared and local arrays */ for(ndim=1;ndim<=MAXDIMS;ndim++){ elems1*= dimsB[ndim-1]; elems *= dimsA[ndim-1]; rc = ARMCI_Malloc(b[ndim], sizeof(double)*elems1); assert(rc==0);assert(b[ndim][me]); a[ndim] = malloc(sizeof(double)*elems); assert(a[ndim]); c[ndim] = malloc(sizeof(double)*elems); assert(c[ndim]); init(a[ndim], ndim, elems, dimsA); ARMCI_INIT_HANDLE(hdl_put+ndim); ARMCI_INIT_HANDLE(hdl_get+ndim); } ARMCI_AllFence(); MP_BARRIER(); (void)get_next_RRproc(1,0); for(ndim=1;ndim<=MAXDIMS;ndim++){ strideA[0]=sizeof(double); strideB[0]=sizeof(double); for(i=0;i "); print_range("remote",ndim,nloB[ndim], nhiB[ndim],"-> "); print_range("local",ndim,nloC[ndim], nhiC[ndim],"\n"); fflush(stdout); sleep(1); } idx1 = Index(ndim, nloA[ndim], dimsA); idx2 = Index(ndim, nloB[ndim], dimsB); idx3 = Index(ndim, nloC[ndim], dimsA); for(j=0;j0.001){ printf("\n%d:while verifying data of a op from proc=%d ",me,dst); printf("giov index=%d ptr_arr_index=%d \n :element index=%d",kc, (j%PTR_ARR_LEN),k); printf(" elem was supposed to be %f but is %f", (me+facto+dst)*((kc+1)*(j%PTR_ARR_LEN + 1)) ,data[i]); fflush(stdout); sleep(1); ARMCI_Error("vector non-blocking failed",0); } k++; if(k==VEC_ELE_LEN){ j++;k=0; if(j%PTR_ARR_LEN==0){ kc++; if((kc%GIOV_ARR_LEN)==0){kc=0;dst++;} } } } } void test_vec_small() { double *getdst; double **putsrc; armci_giov_t dsc[MAXPROC*GIOV_ARR_LEN]; void **psrc; /*arrays of pointers to be used by giov_t*/ void **pdst; void *getsrc[MAXPROC]; /*to allocate mem via armci_malloc*/ void *putdst[MAXPROC]; /*to allocate mem via armci_malloc*/ armci_hdl_t hdl_put[MAXPROC],hdl_get[MAXPROC]; int i=0,j=0,k=0,kc=0,kcold=0,rc,dstproc,dst=0; int lenpergiov; lenpergiov = PTR_ARR_LEN*VEC_ELE_LEN; rc = ARMCI_Malloc(getsrc,sizeof(double)*nproc*GIOV_ARR_LEN*lenpergiov); assert(rc==0);assert(getsrc[me]); rc = ARMCI_Malloc(putdst,sizeof(double)*nproc*GIOV_ARR_LEN*lenpergiov); assert(rc==0);assert(putdst[me]); /*first malloc for getdst and putsrc, both are 2d arrays*/ getdst = (double *)malloc(sizeof(double)*nproc*GIOV_ARR_LEN*lenpergiov); putsrc = (double **)malloc(sizeof(double *)*nproc*GIOV_ARR_LEN*PTR_ARR_LEN); assert(getdst);assert(putsrc); for(i=0;i MAXPROC) ARMCI_Error("permute_proc: nproc to big ", nproc); /* initialize list */ for(i=0; i< nproc; i++) ProcList[i]=i; if(nproc ==1) return; /* every process generates different random sequence */ (void)srand((unsigned)me); /* list permutation generated by random swapping */ for(i=0; i< nproc; i++){ iswap = (int)(rand() % nproc); temp = ProcList[iswap]; ProcList[iswap] = ProcList[i]; ProcList[i] = temp; } } /*\ Atomic Accumulate test: remote += alpha*local * Every process/or has its patch of array b updated TIMES*NPROC times. * The sequence of updates is random: everybody uses a randomly permuted list * and accumulate is non-collective (of-course) \*/ void test_acc(int ndim) { int dim,elems; int i, proc; void *b[MAXPROC]; void *a, *c; double alpha=0.1, scale; int idx1, idx2; int *proclist = (int*)work; elems = 1; strideA[0]=sizeof(double); strideB[0]=sizeof(double); for(i=0;i "); print_range("patch",ndim,loB, hiB,"\n"); fflush(stdout); } ARMCI_AllFence(); MP_BARRIER(); for(i=0;i "); print_range("remote",ndim,loB, hiB,"-> "); print_range("local",ndim,loC, hiC,"\n"); } /* printf("array at source\n");*/ /* print_2D_double((double *)a, dimsA[0], loA, hiA);*/ cols = hiA[1]-loA[1]+1; rows = hiA[0]-loA[0]+1; mrc =MIN(cols,rows); /* generate a data descriptor for a lower-triangular patch */ for(i=0; i < mrc; i++){ int ij[2]; int idx; ij[0] = loA[0]+i; ij[1] = loA[1]+i; idx = Index(ndim, ij, dimsA); psrc[i]= (double*)a + idx; ij[0] = loB[0]+i; ij[1] = loB[1]+i; idx = Index(ndim, ij, dimsB); pdst[i]= (double*)b[proc] + idx; dsc[i].bytes = (rows-i)*sizeof(double); dsc[i].src_ptr_array = &psrc[i]; dsc[i].dst_ptr_array = &pdst[i]; /* assume each element different in size (not true in rectangular patches) */ dsc[i].ptr_array_len = 1; } if((rc=ARMCI_PutV(dsc, mrc, proc)))ARMCI_Error("putv failed ",rc); /* printf("array at destination\n");*/ /* print_2D_double((double *)b[proc], dimsB[0], loB, hiB);*/ /* generate a data descriptor for the upper-triangular patch */ /* there is one less element since diagonal is excluded */ for(i=1; i < cols; i++){ int ij[2]; ij[0] = loA[0]; ij[1] = loA[1]+i; psrc[i-1]= (double*)a + Index(ndim, ij, dimsA); ij[0] = loB[0]; ij[1] = loB[1]+i; pdst[i-1]= (double*)b[proc] + Index(ndim, ij, dimsB); mrc = MIN(i,rows); dsc[i-1].bytes = mrc*sizeof(double); dsc[i-1].src_ptr_array = &psrc[i-1]; dsc[i-1].dst_ptr_array = &pdst[i-1]; /* assume each element different in size (not true in rectangular patches) */ dsc[i-1].ptr_array_len = 1; } if((cols-1))if((rc=ARMCI_PutV(dsc, cols-1, proc))) ARMCI_Error("putv(2) failed ",rc); /* we get back entire rectangular patch */ for(i=0; i < cols; i++){ int ij[2]; ij[0] = loB[0]; ij[1] = loB[1]+i; psrc[i]= (double*)b[proc] + Index(ndim, ij, dimsB); ij[0] = loC[0]; ij[1] = loC[1]+i; pdst[i]= (double*)c + Index(ndim, ij, dimsA); } dsc[0].bytes = rows*sizeof(double); dsc[0].src_ptr_array = psrc; dsc[0].dst_ptr_array = pdst; dsc[0].ptr_array_len = cols; /* note that we do not need ARMCI_Fence here since * consecutive operations targeting the same process are ordered */ if((rc=ARMCI_GetV(dsc, 1, proc)))ARMCI_Error("getv failed ",rc); idx1 = Index(ndim, loA, dimsA); idx3 = Index(ndim, loC, dimsA); compare_patches(0., ndim, (double*)a+idx1, loA, hiA, dimsA, (double*)c+idx3, loC, hiC, dimsA); } free(c); destroy_array((void**)b); free(a); } /*\ Atomic Accumulate test for vector API: remote += alpha*local * Every process/or has its patch of array b updated TIMES*NPROC times. * The sequence of updates is random: everybody uses a randomly permuted list * and accumulate is non-collective (of-course) \*/ void test_vector_acc() { int dim,elems,bytes; int i, j, proc, rc, one=1; void *b[MAXPROC]; void *psrc[ELEMS/2], *pdst[ELEMS/2]; void *a, *c; double alpha=0.1, scale; int *proclist = (int*)work; armci_giov_t dsc; elems = ELEMS; dim =1; bytes = sizeof(double)*elems; /* create shared and local arrays */ create_array((void**)b, sizeof(double),dim,&elems); a = malloc(bytes); assert(a); c = malloc(bytes); assert(c); init(a, dim, elems, &elems); if(me==0){ printf("--------array[%d",elems); printf("]--------\n"); fflush(stdout); } GetPermutedProcList(proclist); /* initialize all elements of array b to zero */ for(i=0;i 0.1) ARMCI_Error("Float register-originated put failed", 0); if( ABS(fdst_get[i]-100.01*(i+1)) > 0.1) ARMCI_Error("Float register-originated get failed", 0); } if(me==0)printf("OK\ndouble data type: "); for(i=0; i 0.1) ARMCI_Error("Double register-originated put failed",0); if(ABS(ddst_get[i]-100.001*(i+1)) > 0.1) ARMCI_Error("Double register-originated get failed",0); } if(me==0){printf("OK\n"); fflush(stdout);} ARMCI_AllFence(); MP_BARRIER(); destroy_array((void **)idst); destroy_array((void **)ldst); destroy_array((void **)fdst); destroy_array((void **)ddst); destroy_array((void **)isrc_get); destroy_array((void **)lsrc_get); destroy_array((void **)fsrc_get); destroy_array((void **)dsrc_get); } #define MAXELEMS 6400 #define NUMAGG 20 /* NUMAGG < MAXELEMS/10 */ #define MAX_REQUESTS 325 /* MAXELEMS/NUMAGG */ #define COUNT 50 void test_aggregate() { int i, j, k, rc, bytes, elems[2] = {MAXPROC, MAXELEMS}; double *ddst_put[MAXPROC]; double *ddst_get[MAXPROC]; double *dsrc[MAXPROC]; armci_hdl_t usr_hdl_put[MAXPROC]; armci_hdl_t usr_hdl_get[MAXPROC]; armci_giov_t darr; void *src_ptr[MAX_REQUESTS], *dst_ptr[MAX_REQUESTS]; int start = 0, end = 0; create_array((void**)ddst_put, sizeof(double),2, elems); create_array((void**)ddst_get, sizeof(double),2, elems); create_array((void**)dsrc, sizeof(double),1, &elems[1]); for(i=0; i 0.1) { ARMCI_Error("aggregate put failed...1", 0); } } } MP_BARRIER(); if(me==0) printf(" aggregate put ..O.K.\n"); fflush(stdout); for(i=0; i 0.1) { ARMCI_Error("aggregate get failed...1", 0); } } } MP_BARRIER(); if(me==0) printf(" aggregate get ..O.K.\n"); fflush(stdout); ARMCI_AllFence(); MP_BARRIER(); if(me==0){printf("O.K.\n"); fflush(stdout);} destroy_array((void **)ddst_put); destroy_array((void **)ddst_get); destroy_array((void **)dsrc); } void test_implicit() { int i, j, k, rc, bytes, elems[2] = {MAXPROC, MAXELEMS}; double *ddst_put[MAXPROC]; double *ddst_get[MAXPROC]; double *dsrc[MAXPROC]; armci_giov_t darr; void *src_ptr[MAX_REQUESTS], *dst_ptr[MAX_REQUESTS]; int start = 0, end = 0; armci_hdl_t usr_hdl[MAXPROC]; create_array((void**)ddst_put, sizeof(double),2, elems); create_array((void**)ddst_get, sizeof(double),2, elems); create_array((void**)dsrc, sizeof(double),1, &elems[1]); for(i=0; i 0.1) { ARMCI_Error("implicit handle(s) failed...(a)", 0); } } } MP_BARRIER(); for(i=0; i 0.1) { ARMCI_Error("implicit handles(s) failed...(b)", 0); } } } MP_BARRIER(); ARMCI_AllFence(); MP_BARRIER(); if(me==0){printf("O.K.\n\n"); fflush(stdout);} destroy_array((void **)ddst_put); destroy_array((void **)ddst_get); destroy_array((void **)dsrc); } /* we need to rename main if linking with frt compiler */ #ifdef FUJITSU_FRT #define main MAIN__ #endif int main(int argc, char* argv[]) { int ndim; MP_INIT(argc, argv); MP_PROCS(&nproc); MP_MYID(&me); /* printf("nproc = %d, me = %d\n", nproc, me);*/ if(nproc>MAXPROC && me==0) ARMCI_Error("Test works for up to %d processors\n",MAXPROC); if(me==0){ printf("ARMCI test program (%d processes)\n",nproc); fflush(stdout); sleep(1); } ARMCI_Init_args(&argc, &argv); /* if(me==1)armci_die("process 1 committing suicide",1); */ if(me==0){ printf("\nTesting strided gets and puts\n"); printf("(Only std output for process 0 is printed)\n\n"); fflush(stdout); sleep(1); } for(ndim=1; ndim<= MAXDIMS; ndim++) test_dim(ndim); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting non-blocking gets and puts\n"); fflush(stdout); sleep(1); } test_nbdim(); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting non-blocking vector gets and puts\n"); fflush(stdout); sleep(1); } test_vec_small(); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting atomic accumulate\n"); fflush(stdout); sleep(1); } for(ndim=1; ndim<= MAXDIMS; ndim++) test_acc(ndim); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting Vector Interface using triangular patches of a 2-D array\n\n"); fflush(stdout); sleep(1); } test_vector(); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting Accumulate with Vector Interface\n\n"); fflush(stdout); sleep(1); } test_vector_acc(); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting atomic fetch&add\n"); printf("(Std Output for all processes is printed)\n\n"); fflush(stdout); sleep(1); } MP_BARRIER(); test_fetch_add(); // FIXME ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting atomic swap\n"); fflush(stdout); } test_swap(); // FIXME ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting register-originated put and get\n"); fflush(stdout); sleep(1); } test_rput(); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting aggregate put/get requests\n"); fflush(stdout); } /** * Aggregate put/get requests cannot be tested for\ number of procs * greater than 32. (Current implementation of aggregate put/get * can use at the maximum of 32 handles (defined by macro * _MAX_AGG_BUFFERS in aggregate.c). This test case is written in * such a way that each process puts/gets data to all the other * processes, thus the number of aggregate handle used is equal to * the number of processes created. */ if(nproc > 32) { if(me==0){ printf("\n WARNING: Aggregate put/get requests cannot be tested for number of procs greater than 32.\n\n"); fflush(stdout); } } else test_aggregate(); ARMCI_AllFence(); MP_BARRIER(); if(me==0){ printf("\nTesting implicit handles\n"); fflush(stdout); } test_implicit(); ARMCI_AllFence(); MP_BARRIER(); MP_BARRIER(); /*test_memlock();*/ MP_BARRIER(); if(me==0){printf("All tests passed\n"); fflush(stdout);} sleep(2); #ifdef NEWMALLOC { int i,j; for(i=0; i #include #include #include #define XDIM 1024 #define YDIM 1024 #define ITERATIONS 10 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double **buffer, *src_buf; int count[2], src_stride, trg_stride, stride_level; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); buffer = (double **) malloc(sizeof(double *) * nranks); bufsize = XDIM * YDIM * sizeof(double); ARMCI_Malloc((void **) buffer, bufsize); src_buf = ARMCI_Malloc_local(bufsize); if (rank == 0) printf("ARMCI Strided Put Test:\n"); src_stride = XDIM * sizeof(double); trg_stride = XDIM * sizeof(double); stride_level = 1; count[1] = YDIM; count[0] = XDIM * sizeof(double); ARMCI_Barrier(); peer = (rank+1) % nranks; for (i = 0; i < ITERATIONS; i++) { for (j = 0; j < XDIM*YDIM; j++) { *(src_buf + j) = rank + i; } ARMCI_PutS( src_buf, &src_stride, (void *) buffer[peer], &trg_stride, count, stride_level, peer); } ARMCI_Barrier(); ARMCI_Access_begin(buffer[rank]); for (i = errors = 0; i < XDIM; i++) { for (j = 0; j < YDIM; j++) { const double actual = *(buffer[rank] + i + j*XDIM); const double expected = (1.0 + rank) + (1.0 + ((rank+nranks-1)%nranks)) + (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } ARMCI_Access_end(buffer[rank]); ARMCI_Free((void *) buffer[rank]); ARMCI_Free_local(src_buf); free(buffer); ARMCI_Finalize(); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/test_parmci_lib.c0000644000175000017500000000113512663426407016664 0ustar mbanckmbanck#include int parmci_calls = 0; int ARMCI_Init(void) { parmci_calls++; return PARMCI_Init(); } int ARMCI_Finalize(void) { parmci_calls++; return PARMCI_Finalize(); } void ARMCI_Barrier(void) { parmci_calls++; #if defined(_CRAYC) || defined(__PGI) PARMCI_Barrier(); return; #else return PARMCI_Barrier(); #endif } int ARMCI_Get(void *src, void *dst, int size, int target) { parmci_calls++; return PARMCI_Get(src, dst, size, target); } int ARMCI_Put(void *src, void *dst, int size, int target) { parmci_calls++; return PARMCI_Put(src, dst, size, target); } armci-mpi/tests/test_igop.c0000644000175000017500000000302312662706250015513 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #define DATA_SZ 100 #define SHARED_BUF 1 int main(int argc, char ** argv) { int rank, nproc, i; int *buf; #ifdef SHARED_BUF void **base_ptrs; #endif MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI GOP test with %d processes\n", nproc); #ifdef SHARED_BUF base_ptrs = malloc(nproc*sizeof(void*)); ARMCI_Malloc(base_ptrs, DATA_SZ*sizeof(int)); buf = base_ptrs[rank]; #else buf = malloc(DATA_SZ*sizeof(int)); #endif if (rank == 0) printf(" - Testing ABSMIN\n"); for (i = 0; i < DATA_SZ; i++) buf[i] = (rank+1) * ((i % 2) ? -1 : 1); armci_msg_igop(buf, DATA_SZ, "absmin"); for (i = 0; i < DATA_SZ; i++) if (buf[i] != 1) { printf("Err: buf[%d] = %d expected 1\n", i, buf[i]); ARMCI_Error("Fail", 1); } if (rank == 0) printf(" - Testing ABSMAX\n"); for (i = 0; i < DATA_SZ; i++) buf[i] = (rank+1) * ((i % 2) ? -1 : 1); armci_msg_igop(buf, DATA_SZ, "absmax"); for (i = 0; i < DATA_SZ; i++) if (buf[i] != nproc) { printf("Err: buf[%d] = %d expected %d\n", i, buf[i], nproc); ARMCI_Error("Fail", 1); } #ifdef SHARED_BUF ARMCI_Free(base_ptrs[rank]); free(base_ptrs); #else free(buf); #endif if (rank == 0) printf("Pass.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_puts_gets.c0000644000175000017500000000453312662706250016601 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define XDIM 5 #define YDIM 98 #define ITERATIONS 10 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors; double **buffer, *src_buf, *dst_buf; int count[2], src_stride, trg_stride, stride_level; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); buffer = (double **) malloc(sizeof(double *) * nranks); bufsize = XDIM * YDIM * sizeof(double); ARMCI_Malloc((void **) buffer, bufsize); src_buf = ARMCI_Malloc_local(bufsize); dst_buf = ARMCI_Malloc_local(bufsize); if (rank == 0) printf("ARMCI Strided Put Test:\n"); src_stride = XDIM * sizeof(double); trg_stride = XDIM * sizeof(double); stride_level = 1; count[1] = YDIM; count[0] = XDIM * sizeof(double); ARMCI_Barrier(); peer = (rank+1) % nranks; for (i = 0; i < ITERATIONS; i++) { for (j = 0; j < XDIM*YDIM; j++) { *(src_buf + j) = rank + i; } ARMCI_PutS( src_buf, &src_stride, (void *) buffer[peer], &trg_stride, count, stride_level, peer); ARMCI_GetS( (void *) buffer[peer], &trg_stride, dst_buf, &src_stride, count, stride_level, peer); } ARMCI_Barrier(); ARMCI_Access_begin(buffer[rank]); for (i = errors = 0; i < XDIM; i++) { for (j = 0; j < YDIM; j++) { const double actual = *(buffer[rank] + i + j*XDIM); const double expected = (1.0 + rank) + (1.0 + ((rank+nranks-1)%nranks)) + (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } ARMCI_Access_end(buffer[rank]); ARMCI_Free((void *) buffer[rank]); ARMCI_Free_local(src_buf); ARMCI_Free_local(dst_buf); free(buffer); ARMCI_Finalize(); MPI_Finalize(); if (errors == 0) { printf("%d: Success\n", rank); return 0; } else { printf("%d: Fail\n", rank); return 1; } } armci-mpi/tests/test_accs.c0000644000175000017500000000503012662706250015466 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #define XDIM 1024 #define YDIM 1024 #define ITERATIONS 10 int main(int argc, char **argv) { int i, j, rank, nranks, peer, bufsize, errors, total_errors; double **buffer, *src_buf; int count[2], src_stride, trg_stride, stride_level; double scaling, time; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nranks); buffer = (double **) malloc(sizeof(double *) * nranks); bufsize = XDIM * YDIM * sizeof(double); ARMCI_Malloc((void **) buffer, bufsize); src_buf = ARMCI_Malloc_local(bufsize); if (rank == 0) printf("ARMCI Strided Accumulate Test:\n"); ARMCI_Access_begin(buffer[rank]); for (i = 0; i < XDIM*YDIM; i++) { *(buffer[rank] + i) = 1.0 + rank; *(src_buf + i) = 1.0 + rank; } ARMCI_Access_end(buffer[rank]); scaling = 2.0; src_stride = XDIM * sizeof(double); trg_stride = XDIM * sizeof(double); stride_level = 1; count[1] = YDIM; count[0] = XDIM * sizeof(double); ARMCI_Barrier(); time = MPI_Wtime(); peer = (rank+1) % nranks; for (i = 0; i < ITERATIONS; i++) { ARMCI_AccS(ARMCI_ACC_DBL, (void *) &scaling, src_buf, &src_stride, (void *) buffer[peer], &trg_stride, count, stride_level, peer); } ARMCI_Barrier(); time = MPI_Wtime() - time; if (rank == 0) printf("Time: %f sec\n", time); ARMCI_Access_begin(buffer[rank]); for (i = errors = 0; i < XDIM; i++) { for (j = 0; j < YDIM; j++) { const double actual = *(buffer[rank] + i + j*XDIM); const double expected = (1.0 + rank) + scaling * (1.0 + ((rank+nranks-1)%nranks)) * (ITERATIONS); if (actual - expected > 1e-10) { printf("%d: Data validation failed at [%d, %d] expected=%f actual=%f\n", rank, j, i, expected, actual); errors++; fflush(stdout); } } } ARMCI_Access_end(buffer[rank]); MPI_Allreduce(&errors, &total_errors, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); ARMCI_Free((void *) buffer[rank]); ARMCI_Free_local(src_buf); free(buffer); ARMCI_Finalize(); MPI_Finalize(); if (total_errors == 0) { if (rank == 0) printf("Success.\n"); return 0; } else { if (rank == 0) printf("Fail.\n"); return 1; } } armci-mpi/tests/test_onesided_shared_dla.c0000644000175000017500000000671712662706250020532 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #include #include #define VERBOSE 0 #define DATA_NELTS 1000 #define NUM_ITERATIONS 10 #define DATA_SZ (DATA_NELTS*sizeof(int)) int main(int argc, char ** argv) { int rank, nproc, i, test_iter; int *my_data, *buf; void **base_ptrs; void **buf_shared; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); if (rank == 0) printf("Starting ARMCI test with %d processes\n", nproc); base_ptrs = malloc(sizeof(void*)*nproc); buf_shared = malloc(sizeof(void*)*nproc); for (test_iter = 0; test_iter < NUM_ITERATIONS; test_iter++) { if (rank == 0) printf(" + iteration %d\n", test_iter); if (rank == 0 && VERBOSE) printf(" - Allocating shared buffers\n"); /*** Allocate the shared array ***/ ARMCI_Malloc(base_ptrs, DATA_SZ); ARMCI_Malloc(buf_shared, DATA_SZ); buf = buf_shared[rank]; my_data = base_ptrs[rank]; if (rank == 0 && VERBOSE) printf(" - Testing one-sided get\n"); ARMCI_Access_begin(buf); /*** Get from our right neighbor and verify correct data ***/ ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank*test_iter; ARMCI_Access_end(my_data); ARMCI_Barrier(); // Wait for all updates to data to complete ARMCI_Get(base_ptrs[(rank+1) % nproc], buf, DATA_SZ, (rank+1) % nproc); for (i = 0; i < DATA_NELTS; i++) { if (buf[i] != ((rank+1) % nproc)*test_iter) { printf("%d: GET expected %d, got %d\n", rank, (rank+1) % nproc, buf[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Barrier(); if (rank == 0 && VERBOSE) printf(" - Testing one-sided put\n"); /*** Put to our left neighbor and verify correct data ***/ for (i = 0; i < DATA_NELTS; i++) buf[i] = rank*test_iter; ARMCI_Put(buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); ARMCI_Barrier(); ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != ((rank+1) % nproc)*test_iter) { printf("%d: PUT expected %d, got %d\n", rank, (rank+1) % nproc, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); ARMCI_Barrier(); if (rank == 0 && VERBOSE) printf(" - Testing one-sided accumlate\n"); /*** Accumulate to our left neighbor and verify correct data ***/ ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) buf[i] = rank; for (i = 0; i < DATA_NELTS; i++) my_data[i] = rank; ARMCI_Access_end(my_data); ARMCI_Barrier(); int scale = test_iter; ARMCI_Acc(ARMCI_ACC_INT, &scale, buf, base_ptrs[(rank+nproc-1) % nproc], DATA_SZ, (rank+nproc-1) % nproc); ARMCI_Barrier(); ARMCI_Access_begin(my_data); for (i = 0; i < DATA_NELTS; i++) { if (my_data[i] != rank + ((rank+1) % nproc)*test_iter) { printf("%d: ACC expected %d, got %d\n", rank, (rank+1) % nproc, my_data[i]); MPI_Abort(MPI_COMM_WORLD, 1); } } ARMCI_Access_end(my_data); ARMCI_Access_end(buf); if (rank == 0 && VERBOSE) printf(" - Freeing shared buffers\n"); ARMCI_Free(my_data); ARMCI_Free(buf); } free(base_ptrs); free(buf_shared); if (rank == 0) printf("Test complete: PASS.\n"); ARMCI_Finalize(); MPI_Finalize(); return 0; } armci-mpi/tests/test_groups.c0000644000175000017500000000221012662706250016071 0ustar mbanckmbanck/* * Copyright (C) 2010. See COPYRIGHT in top-level directory. */ #include #include #include #define PART_SIZE 1 int main(int argc, char **argv) { int me, nproc; int i, *procs; ARMCI_Group g_world, g_odd, g_even; MPI_Init(&argc, &argv); ARMCI_Init(); MPI_Comm_rank(MPI_COMM_WORLD, &me); MPI_Comm_size(MPI_COMM_WORLD, &nproc); procs = malloc(sizeof(int) * ( nproc/2 + (nproc % 2 ? 1 : 0 ))); if (me == 0) printf("ARMCI Group test starting on %d procs\n", nproc); ARMCI_Group_get_world(&g_world); if (me == 0) printf(" + Creating odd group\n"); for (i = 1; i < nproc; i += 2) { procs[i/2] = i; } ARMCI_Group_create_child(i/2, procs, &g_odd, &g_world); if (me == 0) printf(" + Creating even group\n"); for (i = 0; i < nproc; i += 2) { procs[i/2] = i; } ARMCI_Group_create_child(i/2, procs, &g_even, &g_world); if (me == 0) printf(" + Freeing groups\n"); if (me % 2 > 0) ARMCI_Group_free(&g_odd); else ARMCI_Group_free(&g_even); free(procs); ARMCI_Finalize(); MPI_Finalize(); return 0; }