pax_global_header00006660000000000000000000000064152410365230014513gustar00rootroot0000000000000052 comment=079611b654ad89afd9c3c3a1796d64bdd6a6b340 .clang-format000066400000000000000000000001651524103652300134340ustar00rootroot00000000000000--- Language: Cpp BasedOnStyle: Google # Always use `T* p`. DerivePointerAlignment: false PointerAlignment: Left ... .github/000077500000000000000000000000001524103652300124175ustar00rootroot00000000000000.github/dependabot.yml000066400000000000000000000004121524103652300152440ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "bazel" directory: "/src" target-branch: "master" schedule: interval: "weekly" - package-ecosystem: "github-actions" directory: "/" target-branch: "master" schedule: interval: "weekly" .github/workflows/000077500000000000000000000000001524103652300144545ustar00rootroot00000000000000.github/workflows/build.yml000066400000000000000000000221621524103652300163010ustar00rootroot00000000000000name: build and test on: pull_request: push: release: types: - released workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} cancel-in-progress: true permissions: read-all jobs: cmake: strategy: matrix: runs-on: - ubuntu-22.04 - ubuntu-latest - ubuntu-22.04-arm - ubuntu-24.04-arm # Standard (free) macOS runners. # https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories - macos-14 # AArch64 - macos-15 # AArch64 - macos-26 # AArch64 - macos-15-intel # x86-64 - macos-26-intel # x86-64 fail-fast: false runs-on: ${{ matrix.runs-on }} timeout-minutes: 15 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set NUM_CORES run: | NUM_CORES=$(getconf _NPROCESSORS_ONLN) echo "NUM_CORES=$NUM_CORES" >> $GITHUB_ENV echo "Detected $NUM_CORES cores" - name: Setup ccache uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 with: key: ${{ github.job }}-${{ matrix.runs-on }} - name: Install dependencies (macOS) if: runner.os == 'macOS' run: brew install swig - run: mkdir build - run: > cmake -DWITH_PYTHON=ON -DWITH_PYTHON_LIMITED_API=${{ !startsWith(matrix.runs-on, 'ubuntu-22') && 'ON' || 'OFF' }} -DFETCH_ABSEIL=ON -DCMAKE_BUILD_TYPE=Dev -DCMAKE_CXX_STANDARD=17 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. working-directory: build/ - run: cmake --build . --parallel ${{ env.NUM_CORES }} working-directory: build/ - if: always() run: | set -u # Join one-regex-per-line list (same alternation as a single POSIX ERE). # macOS doesn't support long options. FLAKY="$(paste -s -d '|' ../flaky_tests.txt)" ctest --parallel ${{ env.NUM_CORES }} --output-on-failure \ --exclude-regex "${FLAKY}" ctest --parallel ${{ env.NUM_CORES }} --output-on-failure \ --tests-regex "${FLAKY}" \ --repeat until-pass:3 working-directory: build/ cmake-big-endian: runs-on: ubuntu-24.04-arm timeout-minutes: 15 env: ARM_TOOLCHAIN_VERSION: "13.3.rel1" steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set NUM_CORES run: | NUM_CORES=$(getconf _NPROCESSORS_ONLN) echo "NUM_CORES=$NUM_CORES" >> $GITHUB_ENV echo "Detected $NUM_CORES cores" - name: Install QEMU user-mode run: sudo apt-get update && sudo apt-get install -y qemu-user - name: Download Arm GNU Toolchain run: | TARBALL="arm-gnu-toolchain-${ARM_TOOLCHAIN_VERSION}-aarch64-aarch64_be-none-linux-gnu.tar.xz" URL="https://developer.arm.com/-/media/Files/downloads/gnu/${ARM_TOOLCHAIN_VERSION}/binrel/${TARBALL}" wget -q "$URL" echo "46e8e8a573766f761efe7a16240bc2355b67cb30fab7ecc508b03f36c3034290 $TARBALL" | sha256sum --check tar xf "$TARBALL" -C /opt TOOLCHAIN_DIR="/opt/arm-gnu-toolchain-${ARM_TOOLCHAIN_VERSION}-aarch64-aarch64_be-none-linux-gnu" echo "${TOOLCHAIN_DIR}/bin" >> $GITHUB_PATH echo "TOOLCHAIN_DIR=${TOOLCHAIN_DIR}" >> $GITHUB_ENV - name: Create CMake toolchain file run: | cat > toolchain-aarch64_be.cmake << 'EOF' set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64_be-none-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64_be-none-linux-gnu-g++) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) EOF - run: mkdir build - run: > cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-aarch64_be.cmake -DCMAKE_CROSSCOMPILING_EMULATOR="qemu-aarch64_be;-L;${TOOLCHAIN_DIR}/aarch64_be-none-linux-gnu/libc" -DWITH_PYTHON=OFF -DFETCH_ABSEIL=ON -DSKIP_OPENSSL_TESTS=ON -DCMAKE_BUILD_TYPE=Dev -DCMAKE_CXX_STANDARD=17 .. working-directory: build/ - run: cmake --build . --parallel ${NUM_CORES} working-directory: build/ - if: always() name: Run tests run: | set -u # Known failures due to unimplemented big-endian encoding/decoding. EXCLUDE="EncodedS2PointVectorTest\.(Empty|OnePoint|AllExceptionsBlock|RoundtripEncodingFast)" EXCLUDE+="|EncodedS2ShapeIndex\.(OneEdge|RegularLoops|OverlappingPointClouds|OverlappingPolylines|OverlappingLoops|JavaByteCompatibility)" EXCLUDE+="|S2LaxPolygonShape\.(EmptyPolygon|FullPolygon|ManyLoopPolygon|InvertedLoops|S2CoderWorks)" EXCLUDE+="|S2LaxPolygonShapeTest\.BadLoopOffsets" EXCLUDE+="|S2LaxPolylineShape\.S2CoderWorks" EXCLUDE+="|S2Point\.CoderWorks" EXCLUDE+="|S2RegionEncodeDecodeTest\.S2(Loop|Polygon|Polyline)" EXCLUDE+="|FastEncodeTaggedShapes\.MixedShapes" EXCLUDE+="|DecodeTaggedShapes\.(DecodeFromByteString|DecodeFromEncoded)" EXCLUDE+="|OutgoingEdgeButNoIncomingEdge" FLAKY="$(paste --serial --delimiters='|' ../flaky_tests.txt)" ctest --parallel ${NUM_CORES} --output-on-failure \ --exclude-regex "${EXCLUDE}|${FLAKY}" ctest --parallel ${NUM_CORES} --output-on-failure \ --tests-regex "${FLAKY}" \ --exclude-regex "${EXCLUDE}" \ --repeat until-pass:3 working-directory: build/ bazel: strategy: matrix: runs-on: - ubuntu-latest - macos-latest fail-fast: false runs-on: ${{ matrix.runs-on }} timeout-minutes: 15 # We would like to test on the oldest and newest supported. # https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md # https://bazel.build/release#support-matrix # It's not clear how to do that since bazelisk has some magic to pick a # bazel version. steps: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Setup Bazel uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0 with: # Avoid downloading Bazel every time. bazelisk-cache: true # Share caches between workflows. disk-cache: true repository-cache: true # The Bazel workspace is in the src directory. module-root: src - name: Build and Test run: | bazel test \ --config=ci \ --config=dev \ --keep_going \ --test_verbose_timeout_warnings \ //... working-directory: src python: timeout-minutes: 10 strategy: matrix: runs-on: - ubuntu-latest - ubuntu-24.04-arm # Standard (free) macOS runners. # TODO: Expand to the full set of 5 macOS runners if this won't # cause trouble for the PyPI upload. - macos-15 # AArch64 - macos-15-intel # x86-64 fail-fast: false runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-tags: true persist-credentials: false - uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0 with: package-dir: ./ output-dir: dist/ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: dist-${{ matrix.runs-on }} path: ./dist/ python-publish: if: (github.event_name == 'release') && (github.event.action == 'released') needs: [python] timeout-minutes: 30 runs-on: ubuntu-latest permissions: id-token: write attestations: write # Requires environment protection rules in GitHub Settings: # Settings > Environments > pypi > Add required reviewers environment: name: pypi url: https://pypi.org/p/s2geometry steps: - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: dist* path: dist/ merge-multiple: true - uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 with: subject-path: "dist/*" # To upload to PyPI without a token, add this workflow file as a Trusted Publisher in the project settings on the PyPI website - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 .github/workflows/lint.yml000066400000000000000000000036121524103652300161470ustar00rootroot00000000000000name: lint on: pull_request: push: branches: - master workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} cancel-in-progress: true permissions: contents: read jobs: lint: runs-on: ubuntu-latest timeout-minutes: 1 steps: # Default clone depth is enough here: we only run buildifier on the # checked-out tree (no PR-range git diffs in this workflow). - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Install buildifier run: | set -u BUILDIFIER_VERSION=8.5.1 BUILDIFIER_SHA256=887377fc64d23a850f4d18a077b5db05b19913f4b99b270d193f3c7334b5a9a7 BUILDIFIER_DL=/tmp/buildifier curl -fsSL -o "${BUILDIFIER_DL}" \ "https://github.com/bazelbuild/buildtools/releases/download/v${BUILDIFIER_VERSION}/buildifier-linux-amd64" echo "${BUILDIFIER_SHA256} ${BUILDIFIER_DL}" | sha256sum --check - chmod +x "${BUILDIFIER_DL}" sudo mv "${BUILDIFIER_DL}" /usr/local/bin/buildifier - name: Check Starlark / BUILD formatting (buildifier) run: buildifier -r -mode=check . - name: Install keep-sorted run: | set -u KEEPSORTED_VERSION=0.8.0 KEEPSORTED_SHA256=0d9801785ac354232ea754bbfd8cc204a5e255905e14bcbff5fe8733e4dbd85c KEEPSORTED_DL=/tmp/keep-sorted curl -fsSL -o "${KEEPSORTED_DL}" \ "https://github.com/google/keep-sorted/releases/download/v${KEEPSORTED_VERSION}/keep-sorted_linux" echo "${KEEPSORTED_SHA256} ${KEEPSORTED_DL}" | sha256sum --check - chmod +x "${KEEPSORTED_DL}" sudo mv "${KEEPSORTED_DL}" /usr/local/bin/keep-sorted - name: Check keep-sorted run: git ls-files -z | xargs -0 keep-sorted --mode=lint .gitignore000066400000000000000000000001041524103652300130420ustar00rootroot00000000000000bazel-* build/ MODULE.bazel.lock # compiled module src/s2geometry* AUTHORS000066400000000000000000000007411524103652300121310ustar00rootroot00000000000000# This is the official list of glog authors for copyright purposes. # This file is distinct from the CONTRIBUTORS files. # See the latter for an explanation. # # Names should be added to this file as: # Name or Organization # The email address is not required for organizations. # # Please keep the list sorted. Aurora Innovation Dan Larkin-York Google Inc. Koordinates Limited Mike Playle Tiago Brito CMakeLists.txt000066400000000000000000000726251524103652300136330ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.18) # avoids error: aligned allocation function of type 'void *(std::size_t, std::align_val_t)' is only available on macOS 10.13 or newer # see https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md#macos set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum macOS version") # Custom "Dev" build type: optimized but without -DNDEBUG so that asserts remain # active. Use with -DCMAKE_BUILD_TYPE=Dev. Defining the _INIT variables before # project() seeds the cache via the same mechanism CMake uses for the built-in # build types (Debug, Release, etc.). set(CMAKE_CXX_FLAGS_DEV_INIT "-O1") project(s2-geometry VERSION 0.12.0) include(CMakeDependentOption) include(CheckCXXCompilerFlag) include(FeatureSummary) include(FetchContent) include(FindPackageHandleStandardArgs) include(GNUInstallDirs) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Avoid "Policy CMP0042 is not set" warning on macOS. if (APPLE) set(CMAKE_MACOSX_RPATH TRUE) endif() # s2geometry needs to use the same C++ standard that absl used to avoid # undefined symbol errors since ABSL_HAVE_STD_STRING_VIEW etc will # end up defined differently. There is probably a better way to achieve # this than assuming what absl used. We require at least C++17. # Using CACHE allows the user to override the default. set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard to build with") set(CMAKE_CXX_STANDARD_REQUIRED ON) # No compiler-specific extensions, i.e. -std=c++17, not -std=gnu++17. set(CMAKE_CXX_EXTENSIONS OFF) option(BUILD_SHARED_LIBS "Build shared libraries instead of static." ON) add_feature_info(SHARED_LIBS BUILD_SHARED_LIBS "builds shared libraries instead of static.") option(BUILD_EXAMPLES "Build s2 documentation examples." ON) option(BUILD_TESTS "Build s2 unittests." ON) option(WITH_PYTHON "Add python interface" OFF) # Requires SWIG >= 4.2 and CMake >= 3.26. option(WITH_PYTHON_LIMITED_API "Use Python Limited API for SWIG" OFF) add_feature_info(PYTHON WITH_PYTHON "provides python interface to S2") option(S2_USE_SYSTEM_INCLUDES "Silence warnings in s2 headers by marking them as SYSTEM includes." OFF) add_feature_info(S2_USE_SYSTEM_INCLUDES S2_USE_SYSTEM_INCLUDES "Silence warnings in s2 headers by marking them as SYSTEM includes.") # when s2geometry is included as subproject (i.e. using add_subdirectory(s2geometry)) # in the source tree of a project that uses it, install rules are disabled. if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) option(S2_ENABLE_INSTALL "Enable install rule" OFF) else() option(S2_ENABLE_INSTALL "Enable install rule" ON) endif() feature_summary(WHAT ALL) # Don't output anything for LOG(INFO). add_definitions(-DABSL_MIN_LOG_LEVEL=1) # If we already have abseil we don't need to find it, for an example: # add_subdirectory(absl-submbodule) # add_subdirectory(s2-submodule) if (NOT TARGET absl::base) option(FETCH_ABSEIL "Download and build abseil-cpp" OFF) if (FETCH_ABSEIL) message(STATUS "Downloading and building abseil-cpp...") FetchContent_Declare( absl URL https://github.com/abseil/abseil-cpp/archive/refs/tags/20260526.0.zip DOWNLOAD_EXTRACT_TIMESTAMP TRUE ) set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "" FORCE) set(ABSL_ENABLE_INSTALL ON CACHE BOOL "" FORCE) set(BUILD_TESTING OFF CACHE BOOL "" FORCE) set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(absl) else() find_package(absl REQUIRED) endif() endif() # pthreads isn't used directly, but this is still required for std::thread. find_package(Threads REQUIRED) if (NOT TARGET absl::vlog_is_on) message(FATAL_ERROR "Could not find absl vlog module. Are you using an older version?") endif() if (WITH_PYTHON) # Use Python3_ROOT_DIR to help find python3, if the correct location is not # being found by default. if (WITH_PYTHON_LIMITED_API) # Development.SABIModule requires CMake 3.26; be explicit. cmake_minimum_required(VERSION 3.26) find_package(Python3 3.10 COMPONENTS Interpreter Development.SABIModule REQUIRED) # SWIG requires 4.2 for stable ABI support. # https://www.swig.org/Doc4.2/Python.html#Python_stable_abi find_package(SWIG 4.2 REQUIRED) else() find_package(Python3 3.10 COMPONENTS Interpreter Development.Module REQUIRED) find_package(SWIG 4.0 REQUIRED) endif() endif() if (MSVC) # Use unsigned characters add_definitions(-J) # Make sure cmath header defines things like M_PI add_definitions(-D_USE_MATH_DEFINES) # Make sure Windows doesn't define min/max macros that interfere with STL add_definitions(-DNOMINMAX) else() # Avoid megabytes of warnings like: # util/math/vector.h:178:16: warning: optimization attribute on # ‘double sqrt(double)’ follows definition but the attribute doesn’t # match [-Wattributes] add_definitions(-Wno-attributes) add_definitions(-Wno-deprecated-declarations) add_definitions(-Wno-nullability-completeness) # Suppress noisy AArch64 ABI notes about parameter passing changes in # GCC 10.1. Irrelevant since we don't mix objects from old compilers. # TODO: Use check_cxx_compiler_flag(-Wno-psabi) to guard this. add_compile_options(-Wno-psabi) # Some files use sized deallocation, which should be enabled by # default for C++14 and later. There appears to be a bug with clang # < 19 causing this not to be enabled. # https://github.com/google/s2geometry/issues/411#issuecomment-2726949607 # This can be removed when clang19 is the minimum supported version. add_compile_options(-fsized-deallocation) endif() # If OpenSSL is installed in a non-standard location, configure with # something like: # OPENSSL_ROOT_DIR=/usr/local/opt/openssl cmake .. # TODO: Unused? bignum_test uses target_include_directories instead. include_directories(${OPENSSL_INCLUDE_DIR}) if (WITH_PYTHON) include_directories(${Python3_INCLUDE_DIRS}) endif() include_directories(src) add_library(s2 src/s2/base/malloc_extension.cc src/s2/encoded_s2cell_id_vector.cc src/s2/encoded_s2point_vector.cc src/s2/encoded_s2shape_index.cc src/s2/encoded_string_vector.cc src/s2/id_set_lexicon.cc src/s2/internal/s2incident_edge_tracker.cc src/s2/internal/s2index_cell_data.cc src/s2/mutable_s2shape_index.cc src/s2/r2rect.cc src/s2/s1angle.cc src/s2/s1chord_angle.cc src/s2/s1interval.cc src/s2/s2boolean_operation.cc src/s2/s2buffer_operation.cc src/s2/s2builder.cc src/s2/s2builder_graph.cc src/s2/s2builderutil_closed_set_normalizer.cc src/s2/s2builderutil_find_polygon_degeneracies.cc src/s2/s2builderutil_get_snapped_winding_delta.cc src/s2/s2builderutil_lax_polygon_layer.cc src/s2/s2builderutil_lax_polyline_layer.cc src/s2/s2builderutil_s2point_vector_layer.cc src/s2/s2builderutil_s2polygon_layer.cc src/s2/s2builderutil_s2polyline_layer.cc src/s2/s2builderutil_s2polyline_vector_layer.cc src/s2/s2builderutil_snap_functions.cc src/s2/s2cap.cc src/s2/s2cell.cc src/s2/s2cell_id.cc src/s2/s2cell_index.cc src/s2/s2cell_union.cc src/s2/s2centroids.cc src/s2/s2chain_interpolation_query.cc src/s2/s2closest_cell_query.cc src/s2/s2closest_edge_query.cc src/s2/s2closest_point_query.cc src/s2/s2contains_vertex_query.cc src/s2/s2convex_hull_query.cc src/s2/s2coords.cc src/s2/s2crossing_edge_query.cc src/s2/s2debug.cc src/s2/s2density_tree.cc src/s2/s2earth.cc src/s2/s2edge_clipping.cc src/s2/s2edge_crosser.cc src/s2/s2edge_crossings.cc src/s2/s2edge_distances.cc src/s2/s2edge_tessellator.cc src/s2/s2error.cc src/s2/s2fractal.cc src/s2/s2furthest_edge_query.cc src/s2/s2hausdorff_distance_query.cc src/s2/s2latlng.cc src/s2/s2latlng_rect.cc src/s2/s2latlng_rect_bounder.cc src/s2/s2lax_loop_shape.cc src/s2/s2lax_polygon_shape.cc src/s2/s2lax_polyline_shape.cc src/s2/s2loop.cc src/s2/s2loop_measures.cc src/s2/s2max_distance_targets.cc src/s2/s2measures.cc src/s2/s2memory_tracker.cc src/s2/s2metrics.cc src/s2/s2min_distance_targets.cc src/s2/s2padded_cell.cc src/s2/s2point_compression.cc src/s2/s2point_region.cc src/s2/s2pointutil.cc src/s2/s2polygon.cc src/s2/s2polyline.cc src/s2/s2polyline_alignment.cc src/s2/s2polyline_measures.cc src/s2/s2polyline_simplifier.cc src/s2/s2predicates.cc src/s2/s2projections.cc src/s2/s2r2rect.cc src/s2/s2random.cc src/s2/s2region_coverer.cc src/s2/s2region_intersection.cc src/s2/s2region_sharder.cc src/s2/s2region_term_indexer.cc src/s2/s2region_union.cc src/s2/s2shape_index.cc src/s2/s2shape_index_buffered_region.cc src/s2/s2shape_index_measures.cc src/s2/s2shape_measures.cc src/s2/s2shape_nesting_query.cc src/s2/s2shapeutil_build_polygon_boundaries.cc src/s2/s2shapeutil_coding.cc src/s2/s2shapeutil_contains_brute_force.cc src/s2/s2shapeutil_conversion.cc src/s2/s2shapeutil_count_vertices.cc src/s2/s2shapeutil_edge_iterator.cc src/s2/s2shapeutil_edge_wrap.cc src/s2/s2shapeutil_get_reference_point.cc src/s2/s2shapeutil_visit_crossing_edge_pairs.cc src/s2/s2text_format.cc src/s2/s2wedge_relations.cc src/s2/s2winding_operation.cc src/s2/util/bits/bit-interleave.cc src/s2/util/coding/coder.cc src/s2/util/coding/varint.cc src/s2/util/math/exactfloat/bignum.cc src/s2/util/math/exactfloat/exactfloat.cc src/s2/util/math/mathutil.cc src/s2/util/units/length-units.cc) target_link_libraries( s2 absl::absl_vlog_is_on absl::base absl::btree absl::check absl::config absl::core_headers absl::dynamic_annotations absl::endian absl::fixed_array absl::flags absl::flat_hash_map absl::flat_hash_set absl::hash absl::inlined_vector absl::int128 absl::log absl::log_severity absl::memory absl::span absl::status absl::statusor absl::str_format absl::strings absl::type_traits absl::utility absl::vlog_is_on ${CMAKE_THREAD_LIBS_INIT}) # Allow other CMake projects to use this one with: # list(APPEND CMAKE_MODULE_PATH "/third_party/cmake") # add_subdirectory( s2geometry) # target_link_libraries( s2) if (S2_USE_SYSTEM_INCLUDES) target_include_directories(s2 SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) else () target_include_directories(s2 PUBLIC $ $) endif () # Add version information to the target set_target_properties(s2 PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION}) if (BUILD_TESTS) # Used to avoid otherwise unneeded dependency for AArch64-BE cross-compilation. # Currently only bignum_test requires OpenSSL. option(SKIP_OPENSSL_TESTS "Skip tests that require OpenSSL." OFF) if (NOT SKIP_OPENSSL_TESTS) find_package(OpenSSL REQUIRED) endif() # We could use a pre-installed benchmark with # `find_package(benchmark QUIET)` then, `if (NOT benchmark_FOUND)`, but # that could run into trouble if benchmark isn't PIC, but # s2geometry is. benchmark isn't PIC by default, but s2geometry is # when building a shared lib. Always build benchmark for simplicity. message(STATUS "Downloading and building benchmark...") FetchContent_Declare( benchmark # https://github.com/google/benchmark/releases/tag/v1.9.4 URL https://github.com/google/benchmark/archive/eddb0241389718a23a42db6af5f0164b6e0139af.zip DOWNLOAD_EXTRACT_TIMESTAMP TRUE ) # Don't install benchmark when s2geometry is installed. set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) FetchContent_MakeAvailable(benchmark) # https://google.github.io/googletest/quickstart-cmake.html#set-up-a-project message(STATUS "Downloading googletest...") FetchContent_Declare( googletest # https://github.com/google/googletest/releases/tag/v1.17.0 URL https://github.com/google/googletest/archive/52eb8108c5bdec04579160ae17225d66034bd723.zip DOWNLOAD_EXTRACT_TIMESTAMP TRUE ) FetchContent_MakeAvailable(googletest) include(GoogleTest) add_library(s2testing STATIC src/s2/gmock_matchers.cc src/s2/s2builderutil_testing.cc src/s2/s2shapeutil_testing.cc src/s2/s2testing.cc src/s2/thread_testing.cc) target_link_libraries( s2testing absl::check absl::flags absl::log absl::memory absl::strings GTest::gmock) add_library(test_main OBJECT src/s2/testing/test_main.cc) target_link_libraries(test_main PRIVATE benchmark::benchmark PRIVATE GTest::gtest) set(S2TestFiles src/s2/encoded_s2cell_id_vector_test.cc src/s2/encoded_s2point_vector_test.cc src/s2/encoded_s2shape_index_test.cc src/s2/encoded_string_vector_test.cc src/s2/encoded_uint_vector_test.cc src/s2/gmock_matchers_test.cc src/s2/id_set_lexicon_test.cc src/s2/internal/s2disjoint_set_test.cc src/s2/internal/s2index_cell_data_test.cc src/s2/mutable_s2shape_index_test.cc src/s2/r1interval_test.cc src/s2/r2rect_test.cc src/s2/s1angle_test.cc src/s2/s1chord_angle_test.cc src/s2/s1interval_test.cc src/s2/s2boolean_operation_test.cc src/s2/s2buffer_operation_test.cc src/s2/s2builder_graph_test.cc src/s2/s2builder_test.cc src/s2/s2builderutil_closed_set_normalizer_test.cc src/s2/s2builderutil_find_polygon_degeneracies_test.cc src/s2/s2builderutil_get_snapped_winding_delta_test.cc src/s2/s2builderutil_lax_polygon_layer_test.cc src/s2/s2builderutil_lax_polyline_layer_test.cc src/s2/s2builderutil_s2point_vector_layer_test.cc src/s2/s2builderutil_s2polygon_layer_test.cc src/s2/s2builderutil_s2polyline_layer_test.cc src/s2/s2builderutil_s2polyline_vector_layer_test.cc src/s2/s2builderutil_snap_functions_test.cc src/s2/s2builderutil_testing_test.cc src/s2/s2cap_test.cc src/s2/s2cell_id_test.cc src/s2/s2cell_index_test.cc src/s2/s2cell_iterator_join_test.cc src/s2/s2cell_iterator_testing_test.cc src/s2/s2cell_range_iterator_test.cc src/s2/s2cell_test.cc src/s2/s2cell_union_test.cc src/s2/s2centroids_test.cc src/s2/s2chain_interpolation_query_test.cc src/s2/s2closest_cell_query_base_test.cc src/s2/s2closest_cell_query_test.cc src/s2/s2closest_edge_query_base_test.cc src/s2/s2closest_edge_query_test.cc src/s2/s2closest_point_query_base_test.cc src/s2/s2closest_point_query_test.cc src/s2/s2contains_point_query_test.cc src/s2/s2contains_vertex_query_test.cc src/s2/s2convex_hull_query_test.cc src/s2/s2coords_test.cc src/s2/s2crossing_edge_query_test.cc src/s2/s2density_tree_test.cc src/s2/s2earth_test.cc src/s2/s2edge_clipping_test.cc src/s2/s2edge_crosser_test.cc src/s2/s2edge_crossings_test.cc src/s2/s2edge_distances_test.cc src/s2/s2edge_tessellator_test.cc src/s2/s2edge_vector_shape_test.cc src/s2/s2error_test.cc src/s2/s2fractal_test.cc src/s2/s2furthest_edge_query_test.cc src/s2/s2hausdorff_distance_query_test.cc src/s2/s2latlng_rect_bounder_test.cc src/s2/s2latlng_rect_test.cc src/s2/s2latlng_test.cc src/s2/s2lax_loop_shape_test.cc src/s2/s2lax_polygon_shape_test.cc src/s2/s2lax_polyline_shape_test.cc src/s2/s2loop_measures_test.cc src/s2/s2loop_test.cc src/s2/s2max_distance_targets_test.cc src/s2/s2measures_test.cc src/s2/s2memory_tracker_test.cc src/s2/s2metrics_test.cc src/s2/s2min_distance_targets_test.cc src/s2/s2padded_cell_test.cc src/s2/s2point_compression_test.cc src/s2/s2point_index_test.cc src/s2/s2point_region_test.cc src/s2/s2point_test.cc src/s2/s2point_vector_shape_test.cc src/s2/s2pointutil_test.cc src/s2/s2polygon_test.cc src/s2/s2polyline_alignment_test.cc src/s2/s2polyline_measures_test.cc src/s2/s2polyline_simplifier_test.cc src/s2/s2polyline_test.cc src/s2/s2predicates_test.cc src/s2/s2projections_test.cc src/s2/s2r2rect_test.cc src/s2/s2random_test.cc src/s2/s2region_coverer_test.cc src/s2/s2region_sharder_test.cc src/s2/s2region_term_indexer_test.cc src/s2/s2region_test.cc src/s2/s2region_union_test.cc src/s2/s2shape_index_buffered_region_test.cc src/s2/s2shape_index_measures_test.cc src/s2/s2shape_index_region_test.cc src/s2/s2shape_index_test.cc src/s2/s2shape_measures_test.cc src/s2/s2shape_nesting_query_test.cc src/s2/s2shapeutil_build_polygon_boundaries_test.cc src/s2/s2shapeutil_coding_test.cc src/s2/s2shapeutil_contains_brute_force_test.cc src/s2/s2shapeutil_conversion_test.cc src/s2/s2shapeutil_count_edges_test.cc src/s2/s2shapeutil_count_vertices_test.cc src/s2/s2shapeutil_edge_iterator_test.cc src/s2/s2shapeutil_edge_wrap_test.cc src/s2/s2shapeutil_get_reference_point_test.cc src/s2/s2shapeutil_shape_edge_id_test.cc src/s2/s2shapeutil_visit_crossing_edge_pairs_test.cc src/s2/s2text_format_test.cc src/s2/s2validation_query_test.cc src/s2/s2wedge_relations_test.cc src/s2/s2winding_operation_test.cc src/s2/s2wrapped_shape_test.cc src/s2/sequence_lexicon_test.cc src/s2/value_lexicon_test.cc src/s2/util/math/exactfloat/exactfloat_test.cc src/s2/util/math/exactfloat/exactfloat_underflow_test.cc) if (NOT SKIP_OPENSSL_TESTS) list(APPEND S2TestFiles src/s2/util/math/exactfloat/bignum_test.cc) endif() enable_testing() foreach (test_cc ${S2TestFiles}) get_filename_component(test ${test_cc} NAME_WE) add_executable(${test} ${test_cc}) target_link_libraries( ${test} s2testing s2 absl::base absl::btree absl::check absl::core_headers absl::flags absl::flags_reflection absl::log absl::memory absl::random_random absl::span absl::status absl::strings absl::synchronization benchmark::benchmark test_main) # Compared to `add_test()`, displays progress and success/failure of each # test case rather than just the binary, so we see # `S2Cell.TestSubdivide ... PASSED`. Also lists disabled tests. gtest_discover_tests(${test}) endforeach() if (NOT SKIP_OPENSSL_TESTS) target_link_libraries( bignum_test ${OPENSSL_LIBRARIES}) target_include_directories( bignum_test PRIVATE ${OPENSSL_INCLUDE_DIR}) endif() endif() if (BUILD_EXAMPLES AND TARGET s2testing) add_subdirectory("doc/examples" examples) endif() if (WITH_PYTHON) add_subdirectory("src/python" python) endif() if(S2_ENABLE_INSTALL) # We don't need to install all headers, only those # transitively included by s2 headers we are exporting. install(FILES src/s2/_fp_contract_off.h src/s2/encoded_s2cell_id_vector.h src/s2/encoded_s2point_vector.h src/s2/encoded_s2shape_index.h src/s2/encoded_string_vector.h src/s2/encoded_uint_vector.h src/s2/gmock_matchers.h src/s2/id_set_lexicon.h src/s2/mutable_s2shape_index.h src/s2/r1interval.h src/s2/r2.h src/s2/r2rect.h src/s2/s1angle.h src/s2/s1chord_angle.h src/s2/s1interval.h src/s2/s2boolean_operation.h src/s2/s2buffer_operation.h src/s2/s2builder.h src/s2/s2builder_graph.h src/s2/s2builder_layer.h src/s2/s2builderutil_closed_set_normalizer.h src/s2/s2builderutil_find_polygon_degeneracies.h src/s2/s2builderutil_get_snapped_winding_delta.h src/s2/s2builderutil_graph_shape.h src/s2/s2builderutil_lax_polygon_layer.h src/s2/s2builderutil_lax_polyline_layer.h src/s2/s2builderutil_s2point_vector_layer.h src/s2/s2builderutil_s2polygon_layer.h src/s2/s2builderutil_s2polyline_layer.h src/s2/s2builderutil_s2polyline_vector_layer.h src/s2/s2builderutil_snap_functions.h src/s2/s2builderutil_testing.h src/s2/s2cap.h src/s2/s2cell.h src/s2/s2cell_id.h src/s2/s2cell_index.h src/s2/s2cell_iterator.h src/s2/s2cell_iterator_join.h src/s2/s2cell_range_iterator.h src/s2/s2cell_union.h src/s2/s2centroids.h src/s2/s2chain_interpolation_query.h src/s2/s2closest_cell_query.h src/s2/s2closest_cell_query_base.h src/s2/s2closest_edge_query.h src/s2/s2closest_edge_query_base.h src/s2/s2closest_point_query.h src/s2/s2closest_point_query_base.h src/s2/s2coder.h src/s2/s2contains_point_query.h src/s2/s2contains_vertex_query.h src/s2/s2convex_hull_query.h src/s2/s2coords.h src/s2/s2coords_internal.h src/s2/s2crossing_edge_query.h src/s2/s2debug.h src/s2/s2density_tree.h src/s2/s2density_tree_internal.h src/s2/s2distance_target.h src/s2/s2earth.h src/s2/s2edge_clipping.h src/s2/s2edge_crosser.h src/s2/s2edge_crossings.h src/s2/s2edge_crossings_internal.h src/s2/s2edge_distances.h src/s2/s2edge_tessellator.h src/s2/s2edge_vector_shape.h src/s2/s2error.h src/s2/s2fractal.h src/s2/s2furthest_edge_query.h src/s2/s2hausdorff_distance_query.h src/s2/s2latlng.h src/s2/s2latlng_rect.h src/s2/s2latlng_rect_bounder.h src/s2/s2lax_loop_shape.h src/s2/s2lax_polygon_shape.h src/s2/s2lax_polyline_shape.h src/s2/s2loop.h src/s2/s2loop_measures.h src/s2/s2max_distance_targets.h src/s2/s2measures.h src/s2/s2memory_tracker.h src/s2/s2metrics.h src/s2/s2min_distance_targets.h src/s2/s2padded_cell.h src/s2/s2point.h src/s2/s2point_array.h src/s2/s2point_compression.h src/s2/s2point_index.h src/s2/s2point_region.h src/s2/s2point_span.h src/s2/s2point_vector_shape.h src/s2/s2pointutil.h src/s2/s2polygon.h src/s2/s2polyline.h src/s2/s2polyline_alignment.h src/s2/s2polyline_measures.h src/s2/s2polyline_simplifier.h src/s2/s2predicates.h src/s2/s2predicates_internal.h src/s2/s2projections.h src/s2/s2r2rect.h src/s2/s2random.h src/s2/s2region.h src/s2/s2region_coverer.h src/s2/s2region_intersection.h src/s2/s2region_sharder.h src/s2/s2region_term_indexer.h src/s2/s2region_union.h src/s2/s2shape.h src/s2/s2shape.h src/s2/s2shape_index.h src/s2/s2shape_index_buffered_region.h src/s2/s2shape_index_region.h src/s2/s2shape_measures.h src/s2/s2shape_nesting_query.h src/s2/s2shapeutil_build_polygon_boundaries.h src/s2/s2shapeutil_coding.h src/s2/s2shapeutil_contains_brute_force.h src/s2/s2shapeutil_conversion.h src/s2/s2shapeutil_count_edges.h src/s2/s2shapeutil_count_vertices.h src/s2/s2shapeutil_edge_iterator.h src/s2/s2shapeutil_edge_wrap.h src/s2/s2shapeutil_get_reference_point.h src/s2/s2shapeutil_shape_edge.h src/s2/s2shapeutil_shape_edge_id.h src/s2/s2shapeutil_testing.h src/s2/s2shapeutil_visit_crossing_edge_pairs.h src/s2/s2testing.h src/s2/s2text_format.h src/s2/s2validation_query.h src/s2/s2wedge_relations.h src/s2/s2winding_operation.h src/s2/s2wrapped_shape.h src/s2/sequence_lexicon.h src/s2/thread_testing.h src/s2/value_lexicon.h DESTINATION include/s2) install(FILES src/s2/internal/s2disjoint_set.h src/s2/internal/s2incident_edge_tracker.h src/s2/internal/s2index_cell_data.h src/s2/internal/s2meta.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/internal") install(FILES src/s2/base/casts.h src/s2/base/log_severity.h src/s2/base/malloc_extension.h src/s2/base/spinlock.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/base") install(FILES src/s2/testing/gtest_prod.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/testing") install(FILES src/s2/util/bitmap/bitmap.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/bitmap") install(FILES src/s2/util/coding/coder.h src/s2/util/coding/varint.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/coding") install(FILES src/s2/util/endian/endian.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/endian") install(FILES src/s2/util/gtl/compact_array.h src/s2/util/gtl/container_logging.h src/s2/util/gtl/dense_hash_set.h src/s2/util/gtl/densehashtable.h src/s2/util/gtl/hashtable_common.h src/s2/util/gtl/requires.h src/s2/util/gtl/unaligned.h src/s2/util/gtl/value_or_die.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/gtl") install(FILES src/s2/util/hash/mix.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/hash") install(FILES src/s2/util/math/mathutil.h src/s2/util/math/matrix3x3.h src/s2/util/math/vector.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/math") install(FILES src/s2/util/math/exactfloat/bignum.h src/s2/util/math/exactfloat/exactfloat.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/math/exactfloat") install(FILES src/s2/util/units/length-units.h src/s2/util/units/physical-units.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/s2/util/units") if (BUILD_TESTS) set(S2_TARGETS s2 s2testing) else() set(S2_TARGETS s2) endif() install(TARGETS ${S2_TARGETS} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") # Create an export type "s2Targets" detailing the targetable artifacts created # by this project. install(TARGETS s2 EXPORT s2Targets) # Install the export targets as a CMake config file in the share/s2 folder so # that they can referenced by downstream projects as `s2::s2` after a # successful `find_package` call. install(EXPORT s2Targets NAMESPACE s2:: FILE s2Targets.cmake DESTINATION share/s2/) endif() # S2_ENABLE_INSTALL include(CMakePackageConfigHelpers) # Generate the config file that includes the exports. configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/s2Config.cmake" INSTALL_DESTINATION "share/s2/" NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/s2ConfigVersion.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMinorVersion) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/s2Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/s2ConfigVersion.cmake DESTINATION "share/s2/") CONTRIBUTING.md000066400000000000000000000061631524103652300133160ustar00rootroot00000000000000# How to contribute # We'd love to accept your patches and contributions to this project. There are a just a few small guidelines you need to follow. ## Contributor License Agreement ## Contributions to any Google project must be accompanied by a Contributor License Agreement. This is not a copyright **assignment**, it simply gives Google permission to use and redistribute your contributions as part of the project. * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA][]. * If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA][]. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. [individual CLA]: https://developers.google.com/open-source/cla/individual [corporate CLA]: https://developers.google.com/open-source/cla/corporate Once your CLA is submitted (or if you already submitted one for another Google project), make a commit adding yourself to the [AUTHORS][] and [CONTRIBUTORS][] files. This commit can be part of your first [pull request][]. [AUTHORS]: AUTHORS [CONTRIBUTORS]: CONTRIBUTORS ## Submitting a patch ## 1. It's generally best to start by opening a new issue describing the bug or feature you're intending to fix. Even if you think it's relatively minor, it's helpful to know what people are working on. Mention in the initial issue that you are planning to work on that bug or feature so that it can be assigned to you. 1. Follow the normal process of [forking][] the project, and setup a new branch to work in. It's important that each group of changes be done in separate branches in order to ensure that a pull request only includes the commits related to that bug or feature. 1. Do your best to have [well-formed commit messages][] with a [good description][] for each change. This provides consistency throughout the project, and ensures that commit messages are able to be formatted properly by various git tools. 1. Keep PRs [small and focused][] on a single issue. Do not make unrelated changes in the same PR "because you're there"; this includes reformatting of code, whether automatically or manually. 1. Finally, push the commits to your fork and submit a [pull request][]. [forking]: https://help.github.com/articles/fork-a-repo [well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html [good description]: https://google.github.io/eng-practices/review/developer/cl-descriptions.html [pull request]: https://help.github.com/articles/creating-a-pull-request [small and focused]: https://google.github.io/eng-practices/review/developer/small-cls.html ## Style ## Contributions should follow the [Google C++ Style Guide]. Code may be [formatted] with `git clang-format`. [Google C++ Style Guide]: http://google.github.io/styleguide/cppguide.html [formatted]: http://google.github.io/styleguide/cppguide.html#Formatting CONTRIBUTORS000066400000000000000000000024201524103652300127350ustar00rootroot00000000000000# People who have agreed to one of the CLAs and can contribute patches. # The AUTHORS file lists the copyright holders; this file # lists people. For example, Google employees are listed here # but not in AUTHORS, because Google holds the copyright. # # Names should be added to this file only after verifying that # the individual or the individual's organization has agreed to # the appropriate Contributor License Agreement, found here: # # https://developers.google.com/open-source/cla/individual # https://developers.google.com/open-source/cla/corporate # # The agreement for individuals can be filled out on the web. # # When adding J Random Contributor's name to this file, # either J's name or J's organization's name should be # added to the AUTHORS file, depending on whether the # individual or corporate CLA was used. # # Names should be added to this file as: # Name # # Please keep the list sorted. Dan Larkin-York David Eustis Eric Veach Jesse Rosenstock Julien Basch Mike Playle Phil Elson Robert Coup Tiago Brito Zachary Burnett Config.cmake.in000066400000000000000000000002051524103652300136700ustar00rootroot00000000000000@PACKAGE_INIT@ include(CMakeFindDependencyMacro) find_dependency(absl CONFIG) include("${CMAKE_CURRENT_LIST_DIR}/s2Targets.cmake") LICENSE000066400000000000000000000261361524103652300120740ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. NOTICE000066400000000000000000000002241524103652300117610ustar00rootroot00000000000000S2 Geometry Library Copyright 2017 Google Inc. All Rights Reserved. This product includes software developed at Google (https://www.google.com/). README.md000066400000000000000000000161631524103652300123450ustar00rootroot00000000000000# S2 Geometry Library ## Overview This is a package for manipulating geometric shapes. Unlike many geometry libraries, S2 is primarily designed to work with _spherical geometry_, i.e., shapes drawn on a sphere rather than on a planar 2D map. This makes it especially suitable for working with geographic data. If you want to learn more about the library, start by reading the [overview](http://s2geometry.io/about/overview) and [quick start document](http://s2geometry.io/devguide/cpp/quickstart), then read the introduction to the [basic types](http://s2geometry.io/devguide/basic_types). S2 documentation can be found on [s2geometry.io](http://s2geometry.io). ## API/ABI Stability Note that all [releases](https://github.com/google/s2geometry/releases) are version 0.x, so there are [no API or ABI stability guarantees](https://semver.org/#spec-item-4). Starting with 1.0 we will adhere to [SemVer](https://semver.org/) and follow the [Google OSS breaking change policy](https://opensource.google/documentation/policies/library-breaking-change) The Python API is particularly unstable, and it is planned that the SWIGged API will be replaced by a pybind11 version with more Pythonic names and more complete functionality. ## Requirements for End Users using Bazel ## Build This bazel build requires [Bazel 8 or newer](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md#compilers-tools-build-systems). Builds were tested using C++20 as set in .bazelrc. This setup relies on abseil-cpp and googletest from the bazel central repository as set in MODULE.bazel. To build and test using bazel, from within s2geometry/src, run: `bazel test "//:*"` To build the libary without testing, from within s2geometry/src, run: `bazel build //:s2` ## Status All tests enumerated in the BUILD.bazel file pass on x86 machines. On Apple M1, s2loop_measures_test fails due to a 6% excess accumlated error. This issue may require revision of boringssl or exactfloat. ## Requirements for End Users using CMake * We aim to support all platforms supported by the [Google foundational C++ support policy](https://opensource.google/documentation/policies/cplusplus-support) * [CMake](http://www.cmake.org/) >= 3.22 * A C++ compiler with C++17 support, such as [g++ >= 7.5](https://gcc.gnu.org/) or [clang >= 14.0.0](https://clang.llvm.org/) * [Abseil](https://github.com/abseil/abseil-cpp) LTS [`20260526`](https://github.com/abseil/abseil-cpp/releases/tag/20260526.0) (standard library extensions). This exact version must be used. * [googletest testing framework >= 1.10](https://github.com/google/googletest) (to build tests and example programs, optional) * [OpenSSL](https://github.com/openssl/openssl) (for its bignum library) On Ubuntu, all of these other than abseil can be installed via apt-get: ``` sudo apt-get install cmake libssl-dev ``` abseil-cpp may need to be installed from source if an LTS release is not packaged for the platform. See the use of `-DCMAKE_PREFIX_PATH` in the [build instructions below](#building). On macOS, use [MacPorts](http://www.macports.org/) or [Homebrew](http://brew.sh/). For MacPorts: ``` sudo port install cmake abseil gtest openssl ``` ## Build and Install You may either download the source as a ZIP archive, or [clone the git repository](https://help.github.com/articles/cloning-a-repository/). ### Via ZIP archive Download [ZIP file](https://github.com/google/s2geometry/archive/master.zip) ``` cd [parent of directory where you want to put S2] unzip [path to ZIP file]/s2geometry-master.zip cd s2geometry-master ``` ### Via `git clone` ``` cd [parent of directory where you want to put S2] git clone https://github.com/google/s2geometry.git cd s2geometry ``` ### Building First, [install Abseil](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md#traditional-cmake-set-up). It must be configured with `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`. s2geometry must be configured to use the same C++ version that abseil uses. The easiest way to achieve this is to pass `-DCMAKE_CXX_STANDARD=17` to `cmake` when compiling both abseil and s2geometry. From the appropriate directory depending on how you got the source: ``` mkdir build cd build # You can use -DBUILD_TESTS=no to skip tests. # Use the same CMAKE_CXX_STANDARD value that was used with absl. cmake -DBUILD_TESTS=yes -DCMAKE_PREFIX_PATH=/path/to/absl/install -DCMAKE_CXX_STANDARD=17 .. make -j $(nproc) make test ARGS="-j$(nproc)" # If -DBUILD_TESTS=yes was used above. sudo make install ``` On macOS, `sysctl -n hw.logicalcpu` is the equivalent of `nproc`. Disable building of shared libraries with `-DBUILD_SHARED_LIBS=OFF`. Enable the python interface with `-DWITH_PYTHON=ON`. # For Testing If BUILD_TESTS is 'on' (the default), then OpenSSL must be available to build some tests: * [OpenSSL](https://github.com/openssl/openssl) (for its bignum library) If OpenSSL is installed in a non-standard location set `OPENSSL_ROOT_DIR` before running configure, for example on macOS: ``` OPENSSL_ROOT_DIR=/opt/homebrew/Cellar/openssl@3/3.1.0 cmake -DCMAKE_PREFIX_PATH=/opt/homebrew -DCMAKE_CXX_STANDARD=17 ``` ## Installing From `build` subdirectory: ``` make install ``` Prefix it with `sudo` if needed: ``` sudo make install ``` _NOTE_: There is not `uninstall` target but `install_manifest.txt` may be helpful. All files will be installed at location specified in `CMAKE_INSTALL_PREFIX` variable. Several suffix variables used for some file groups: Variable | Default | Description -------- | ------- | ----------- `CMAKE_INSTALL_INCLUDEDIR` | `include` | For header files `CMAKE_INSTALL_BINDIR` | `bin` | For executables and `*.dll` files on `DLL`-based platforms `CMAKE_INSTALL_LIBDIR` | `lib` | For library files (`*.so`, `*.a`, `*.lib` etc) If needed set this variables on command line as `cmake` arguments with `-D` prefix or edit from `build` subdirectory: ``` make edit_cache ``` For more info read: [The CMake Cache](https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#the-cmake-cache). ## Python If you want the Python interface, you need to run cmake using `-DWITH_PYTHON=ON`. You will also need to install the following dependencies: * [SWIG 4](https://github.com/swig/swig) (for Python support, optional) * python3-dev (for Python support, optional) which can be installed via ``` sudo apt-get install swig python3-dev ``` or on macOS: ``` sudo port install swig ``` SWIG version 4.0 is required. [Python 3.10 is required](https://github.com/google/oss-policies-info/blob/main/foundational-python-support-matrix.md). ### Creating wheels First, make a virtual environment and install `build` into it: ``` python3 -m venv venv source venv/bin/activate pip install build ``` Then build the wheel: ``` python -m build ``` The resulting wheel will be in the `dist` directory. > If OpenSSL is in a non-standard location make sure to set `OPENSSL_ROOT_DIR`; > see above for more information. ## Other S2 implementations * [Go](https://github.com/golang/geo) (Approximately 40% complete.) * [Java](https://github.com/google/s2-geometry-library-java) ## Disclaimer This is not an official Google product. doc/000077500000000000000000000000001524103652300116245ustar00rootroot00000000000000doc/design/000077500000000000000000000000001524103652300130755ustar00rootroot00000000000000doc/design/images/000077500000000000000000000000001524103652300143425ustar00rootroot00000000000000doc/design/images/s2shapeindexva--39vql36wm1d.png000066400000000000000000000176221524103652300217770ustar00rootroot00000000000000‰PNG  IHDR~„—¤@7 cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ü’ŽurIDATxÚíÝùwTç™'ðïÝkßKª’„$dcv mŒÁ ';ÝIú¤{fg;g&gÒÿÜüÖs:v&í¶°b“„@Ih_J%Uݺû2?¢#•nÕ­åùœÃ1ÈHu«�¾õÞç}Ÿ÷e\×uA!¤c°~_!„�Æ¢à'„�CÁO!†‚ŸB: ?!„t ~Bé0ü„Òa(ø !¤ÃPðBH‡áý¾Bie–åàᲆ‘é2 Ëŧæü¾¤W¢à'„�=rSËF˘\R� ‰Èe#X[.cd¦ŒQ¿/ñ{QðBÈ.¸.0_¨†ýø\A‘GO6ŠK§S ñŸ·—q¨' IhÞJ:C›´BÈË­–tÜ�®`dF†À1èNEp +‚p@Øñïß}¸ŠL„ÃΤü¾ô—¢à'„�笖tŒÏVpwF�c»ÈgÃ8��"^ù¹†åàË[søôúã¢ßOeGü„`C6qoVÁ�™tȧCȧÂHÅ{þZS‹%6+øÝGy¿ŸÖލÆOéX¥Š… Œ=VP(›È¥‚8>˜­)ì·ÌÅ0»RÆØ¬Œc"~?Ítìˆ_Ñm|9RD>)âh_‘óû’!  è6-©¸=%c¹¨#— "ŸŽ +Ã0ž=N±¬áæÄ*þðI/D¾¹&z;.ø]¸õ¨„¯ïa»@""bCÖ1ÐÄ›ƒQ å‚`Yïþñ !þÓ “‹ ÆW0·¦¡+DoWÙd¬‡aÿ¼[+È%y|tª¹&z;*ø—Öuüñæ‹Åñ×Ò¸qgg�x,­+˜_•±!ë8Ò©Á(ú2û»Ý#„øÇ²]L/«¸=-cfYA:D.FO* ŽkÌàN7l|u{¿½œC:Ö<½üšáà«‘uŒÏ*82�Â�®jÍí‹á9œ;ÚýÌL½ª[˜_­àñjŒãàØ@§‡¢HF^=›O¼cYX–¡»/²'–å`zEÃ謌‰y©˜„ÞlùT<çO¹åáü&Ê¿ºÔ<½mü#32þãvéX'†2ÏÔÚþ|cïÏ#ØyŽ{CÖ1¿ZÆÜjÑ €ÓCaë� $Ñ|@½Ý�)ã›ÑM¼w4�“ƒÔñnœ´¸­Æª;S2Æ*ˆ…DäSaôdÂ�ÿV]×Å_n-àòé$÷†ü¾müK>¿¾ Õbpê`‰¨ôÂßù×gñþÉ<‚Ò÷/nr]`mSÅÂj‹ë*úÒN Eq¨'ŽF¤u3·¦á›Ñ"6*ÎIà̓Qz žë¢}\A È£7EO6ü´‹¶™JnO®â÷Aüÿ&n»à× _�16£àõ ÌÅ^úî1.žéÝÓ7Ši;4Ð`skþ2²YspáhÇûé  S­–tÜ�©`dú¿ºhû»"š¿;|ýYOø?ÑÛVÁ?2#ãÏ· È&ƒ8>�†øŠ@ÿì»Ç¸|¦·æÛAU·0·RÁìZ¬ëâh§‡b4P'sk¾º[„j8xÿxGúÂ~_i€­.Ú‘®ë"Ÿ‰ 7ÙUm3Ñ _ÞžÇï>Ê!õw¢·-‚yCÇç7 PLàÔP‰ˆ´«Ïûãµüðí<˜ô)+æVÊx¼"Ó|@�M/+øÏ»E8Ž‹÷Ž%é   =ßE›K…Г®­‹¶™LÌnBÑU|zÑß­›[:ø÷RÖÙÉ¿_›Á�Þ>àél?Í4Îô²‚/ffiaY¼w4�×{šcâŒÔf{ífÅD>B.iù°ßÎq]|uk?:“Ä¡ÿ,-üOË:‰ ޾º¬³“ÿ{eÿpa n ÏÏʇpr0ŒÁn (/M.(øËhÇàÝ#ôÐJÝÆýyw§d¬• t§‚è©Cm3YÝP1:µ†?|Ü Þ§ŽÞ– þ•¢Ž?Þ,@5\œ<˜A2º»²ÎNþíÊ~rá`C& ·ææ×ʰ]ÇûC8Cóžq]àþ|_�Y|p"�Á.zhFšá`r±‚±Ç̯éè~²Z;‡ýó®�/ã`NÂǾ<~Ë¿nV›°j-ëìäß®Lá§ïløs¡ù€úÙzøêî:B‡O¦ÐŸmŸRA«²l“‹ îL•1·¦ùÒEÛLTÝÂWwð?˜G2ÜøÁ_KÿÄBŸ ¯#•pl0íIS†ãºø÷«3øÉ»ƒ¾=¯çç¤%œ¤ùO8Ž‹±YÝD2ÌáÃIäÓôÐHÏwѦ£zºüí¢m&æ7`ëþåý®†?vS¡là³ë”5'†2Hí£¬ó<ÛqñÙ·3øÇ ƒ~?M4P/[oߌn æqéT ¹¤wßGäY® ̬(¸=UÁ£ÑhsuÑ6Çuñõ­y|üwi¼–6ô±›2ø ÓŵûEܘ�qè@óû/ë<Ï´üùo³øñù¿Ÿî 4ÃÂBAÁÜJ¦íTçÆ�ŒÒ|@­lÇÅÝiߌ­£;!áƒ)äͳiV+Ûꢽ÷XÆØ“.Ú¾L=é0$Úîü{­UŒÎð¯÷6´äÕtÁ¿½¬Sëj�Ý0,_ܘÅ'ï4_ðoGóÞ²mwgd|3ZDwRćǓè¢;€šluÑŽNÉàù­.ÚèK÷¾";ûnl Gzƒ84Þ°Çlšà/” |~c%ÕÆÉ¡4’ÑúÖc·ºè>~»ßï§¾+;ÍãH_|NŽí—aº¸3]ÆÕñ ÈðÁ‰„ïÝ”­`{-à"—Š 7Ûz]´ÍDÑ,|}{¿ÿ¸ñPc^G߃ߴ]\/bxBÆk½ õx_ÖÙ‰fXøúö"~ôö?Ÿ~Mž™¨è8”£ù€Z–ƒá‰2®=ØÀ`WžLÒÛç+&Æ+¸=]†a¹mÓEÛLÆgŠ`\?·»!�çkðO.(øÓð’ÑŽ ¤Z¬h®�.âoµ^ðoGóÞÐ-7'ÊøvbC¹>8žD"ܹ%‹í]´Љ\*La_G¶ãâ«[søÉ¹tCúO| þbÙÄg7 جØ8q0íË7SE3qmt?x«¯á�]/eÅÀÜj�—i> Všáào60ü°ŒÃ}a¼{,‰X°3^¿—wцh7ÔX,(˜œ+àÜW÷ˆü/–u¢¾uê•×ï/ãò™ö þ-ÏÏô¦$ ãp_Í슢۸1±ùô àýc D‚íwðBm�'»óݽ%í à�ɺ>N«¬Š8ùZÑߢ’b`øþ*.�éõõ:êÍ´,,¯U°VÖ¨?`�ÝÆw6p둌ã\8G¤ÅW­˜¶‹‡;uѦÃÔ8賊fâ¯wñû�{­ã�f݃¿(›øüÆ rµ¬“M4¶Qáe6dwpñÍ¿/¥avšxó`”V³ìBE·ð·›OßÞ=GXj�7€­.Ú±Ç2&—T¤cäÒaê¢mB÷fŠX ?{'[·Ç¨[ð›¶‹«÷Џ1QÆ@.†7úuÛ³EYÇÈÃ>è àßnk>`n¥‚p€Çé¡0Žö‡[*ÌüPªXøvb£32NEpþp�&mRzYmo&\·þ²¶ãâË›sø§óÙºí3U—àŸ\PðùÍ5D"N e^y¦­ÖKÆfŠxÿdÞïKñÕÖ|ÀÜJKë rI oEh>àJŠ…+÷60>[Áé×"¸p$ IðäüLí\က|:B]´-f~­‚é… üþGy°¬÷ßWžQ6ñùÍ %«©Ê:;)”4ŒÏñ^‡ÿv/Ìô„pr€æ¾Ï†lâÚýM<˜¯àÌPç'|yX*ê¸3]ÆýY<Ï —ŠàuѶ´k£Kxs „·Þˆyþµ= ~Ëvq¥‰Ë:;YÝP19¿‰ Çý=­Y©†�ÅBs+eX–ƒcƒ!¼9Hó/S(¸2¾‰©%ç%ðÖ±ºß1muÑÞ�ª€aA]´m¦¬˜¸2²ˆýq¯çK²÷ü[e�p@ÄÉ&-ëìd¥¨âÑâ&Σàšؽµ’‰«ã˜^Vñöëqœ}#æé–…’‰ÑÇeŒÍ*O»hû²‘]Ÿ3MZËØô:‚‚�|ÛÛ‰Þšƒ£báóëkX•-œL#›lÞ²ÎN–×L/—ñÎÑÆ´H·ƒíó‹ë ò4ðR+:®ÜÛÄ|AÃ;‡8}0Ró1{%ŃùjmQ¶Ð“ !O]´Á²|ykÿíB=ïþ½÷üÖ“&¬ëÊ8˜�áõÍ_ÖÙÉb¡‚¹Õ Þ>ÒøCÚ�í¸X.*XX‘i>à{,o¸:¶�…u çÞHàÌPtWÛïR-Ù2·*cveÿ뇽žýÛï)ø'*øÓÍbA LJҾ7aíÇÂZ … Φàß/U·0¿*ãÑB ÿò^²­u÷× kþ:¾�µMŽ&pj0üÂj ê¢%/seto½Æ™!o&zw�Üÿç›%,mZ8y0ÛÔ«uvËqÝ–¼SiFA‰Çë} ”dÝöûršRO&€ÿþ~sk¾-âÚøÎIàhSKêÓ.ÚL,ˆîLGvS-yêÄ`_Ý]ÄáÞ°'½»þ•MoÎ!Ú ý¢ëÍuA·ÌDªæø}M­/À/?ÌczEÁ·Öñç›kèJ‡�OE)ìÉKÅÂ"zÒa|}·ˆOÎföýõv=Û”ŠŠ¨h¦ßÏß34â÷žÀsP þÝì !pì`gßèFo†öÉ!ßïð@ ã –Öõ}­]W\€¬~?wÏЈß{’À¡¢Q©g7dÕÂôª†ÞLÄïK!-BàX9�ć Øo÷Õ®ƒ?ÚjÄïº.M˜yL8T4ËïËh ÃeȆ!Ըēt¦þî( ™)ïëëìú». «í4â§à÷ZuÄO¥žWqw•џ󾟴¿“3øâö:4£ö»ë=ŒøElÊí3â·]€z޼%ò,T“J=¯2± "(ñˆ…hû ²w‰ˆˆîT_�kþ»~I`!ð 4£Mnå É4OI•jü¯t}¢„þ\ÔïË -ìè@c³ VеMôî©À˜ŽK(+í1êwöúäÉ+‰Ít÷=ñÔΊ²‰ÕMùLØïK!-LàYêKâ³áBMŸ¿·à� mü®ã‚¡¿§à9ê>j�ínx¢Œ¹(-%&û6Ø…f£�÷>Ñ»§àïŽ Pôý¯!m4â¯� ÄB¥îÝY¶‹;32º¨ÌCö�a€CiüÇí"tso‹*ö”}©8�r…Füä垃BÁ¿£ÑY©¨D‡£Ï$¢ºâAüulcOŸ·§àÏDE”•ö˜Üuá‚¿×$�§ýz^bx¢„ZÂIØU¨‹ Â"‡H�G*£7! ¶…:ÖÃÅžƒ?0WhýlÚ²¡>D�CIVý¾Œ¦rgº‚®T¢àí�ÙĦå@3¬j kÕò‹iÛPuªn¡¢Z`yö™Pˆ†H„9„ƒâA¢ÐØ,Úsðg¢Æçµ†^d=Pãn}HíÉÿ¼áÉN¾¶ÿ=ÔIc=êšaA·ª#tÝ0¡¨6X–A(P õxˆC6Æ!”�‡ª¡šr>´†R�¹Òú›µÑrÎúyŽVõl3µ¬`Z¾4ÚnlÇ…nبh&4Ó†¦ÛP ãi¨W4Žë"à�‹ˆX$C‘"‘ ‡dT€Ô„¡¾{þDX€¦[°·¥Ž åœõ! têÜ}êÆ$-ál´çC]×m¨ºÍt ʪ Ûy6Ôã!™m¡ ­ê»±çàg  «&âáÖÝ]Ðq¶}ÿ]}³}¿žNŸB)«6fV4üý٬ߗÒö LέCV-0` òˆ„8ă<’a Ñ�€XˆG,Ä5eù¥‘jj!LǪ§qµrðÌÇÚæüàf²}¿/…ne·•q ÏuvÈÔÛüªŒ{ÓüÓ….ä’R[�Ô½RÓ+”�‹(«­½²§+DP¢Öùz ýzª‡­Ü~H‡­ÔÛܪŒ{�×ñé¥<º‚ú»T[ðÇD¨-ü¤~Džƒ¢wöÊž‰Á¶RO3ËeŒÏ®ãWæ‘�Óë¼5 yS1¥6:†‘xKyTôöØÓ©VÕÃVh´_/ÓKe<š/â·—óHF¨d»W5�øÓaeÕ„K'n�ˆ|gï×óô°•tÈïKiK3K%L-ñ›�z(ôkTSðó<‹p�‡Òá£:²³N߯çÆd‰[©“‡ó›x´¸�_]Ê#¦9ºZÕ<’�ˆmsñ–$p�ÕΜܵlw§+tØJLÌmbnµŒß~Ô‹d˜FúûQsðW—tR𓉹CïGgÊtØJÜ\Äb¡„ß\Î#ììeÂ^¨9ø3 ŠN¼äE�¼_Ïõ‡eêÔõؽ™"Ö7üî£D)ô=±�R�€’BÁO^$ ”ܶaiÀ¢Ña+^›ZÆ\Á§—rß襚ïGS1¡mÎß%Þ’x®#¸nLl¢?G‡­xetj 劎__êA@¤Æ,/ÕüjDîik>!Û‰ýÉ~=�bë°•�®ˆß—ÒF­AÑ üúržB¿öõŠfb"d*÷�çlí×£›�Sç¿3-Óa+p]àæä 4ÃÄ//æh †:Ù_ðG«»tò¼ Ä¢¢uÎÊžáÉ2iRw_\¸=¹×¶ðË‹Ý-»×}+Ø×š³l\ÄÄ2�ø;‰e;0m¶åÀ´�'v`šOþk9plšá@Ѥý¾à˜^V@‡­ì�뺸ù`:l¥&¶ãâúø2’a?{'K¡ß@û¾OE«;u¦¢’ßÏ¥cUtç߈!A;6Tõ°• ÎíöûRZÎVè§Â,~úN,�ƒÚPû~µ3qZÒé'Çu¡b!Ñ7Úƒ¥zØJ AêÛvñ·ñ%tÇyüì|…¾öýŠgc­ c+Su ‘O?<>ž�é°•=2mWÇ‘KðøñÙ Íùdÿ#þ˜€ŠFÁïEµ£Cã®(›XÙ4è°•=0mׯ–p +âÎf)ô}´ï:&@–©Ôã—Šn"íŒe“Íäú¶²¦åàÚèõHøèÍNèîhnûñ'Â4ÂítÐÆ,MDQ-¤#Tßo$Ëv12C‡­ì–aÚ¸2ºˆC½ ý&±ïàg P¡:¿/4ÃBœJ= 5:SFš[Ùݰqet ÇûCøèTÊïË!Ox2#˜‰ 4ÁëE7�ˆRð7Òõ‡ešÔÝU·ðבEœ áâñ¤ß—C¶ñ&øã"Ê´¤ÓÕBÿTTBY¡:#iº�x˜J=�0½¬‚C›î`³bàÛÑE|òV '¨·¡xüÙOÇ06˜ªÙˆ‡hƒ°F¸1Y‚ pXZW tБ’¯²!ëøöÞ>9›Æá¾°ß—Cvɳáb&"`¥¨ùý|:Ь›HP×nCˆ`i]ÇR¡Œ±iªn# IˆEDC"âa±£Î¥(–5|7¾‚ŸžËàõ<íYÔJ< þt\‚È!Ÿ¢%­­ÎÓäÈ$L,ÒÖ � ™âuµ£�ËE. ²±«rQ,,Bò°\´°VÁÈÔ~q1‡|’B¿xü騀;S¿ŸSGPUÉ0uHv –e^Z.ZÝ4°V2±²Y-­u°,ƒXD@H�JOïöZ.š_«àÞL¿¾”G6N=#íÂã¿„M•š[AVm$ÂTãït’À¢/@_&`§r‘‰…‚‚ù …²Ž°Ä#’ ¯,Í,—11Wħv#£Ðo'ž,ÈÁ¶\˜–ÓQ�,�fÛ.LÛF„Öð“—x¦\t¨ú1Ûv±Z6±¶©ceÃÀr¡Œ±²Ër�ˆˆEÄB¢!S‹›øí¥<’´`Ûñ<9’1eÕ¤=Mꨢ™ˆÑq‹d�8ŽA.!"—��ÿú¸¢ÛXÙ4Q(éX.ꘘ-Á²€ß\Î!Iw•mÉóàÏFDÈŠAÁ_GŠn!N?�Ä#!‰Ã`Gëò;ˆçõ˜lB@E£Þzªh’´G!¤Fž*&Ð.�u¦ê&’´3!¤FÞ—z¢"Ê*­åß Órà°,¶ãÂvX¶ ×uaÚlÛ…ãTï:.Ö6œLù}Ù„�åyð'"4Õ‚í¸¾·˜{Á²8n5”Ç…åTÃy+ˆÛ…ýäãÛ?æº,Ç…ë†]ý¶ëÀ´\À©®Ê1Ž ð,–c ñ,8ž�À°ùêÇ –ŽAHàÀó º‡bȧ¨K©�çÁÏ0@<*ê<)? eË�íVCy+œMˆãºpl6ª¡kÚN5¤ŸŒª-Û�e¹°\†éV_$x<Ë€çÙ§¿ˆ,8Ž�ðäÿ  …XžgÀs xxà9<ǀ ÀCàˆ|u/Bi”ºŠSaeA‘¯†²û$P·•/Ç…mWGʮ㰸à86,Ç@·«Ÿk;lkk”mò]ØN5�Yž…ıàXÇBplu¤ÌqÕÑ´$°@0̃e]ˆ‚�8–EàÉßxÇ€ãØê(›a ­ÇB!Ïc\×u½þ¢_�ñÝøX¾¢ [-cðó4ˆ9–� 09WÝÖ™a‰ç¶…2 –e ò̳¡Ì"5ˆBHMêü„Bš › !¤ÃPðBH‡¡à'„�CÁO!†‚ŸB: ?!„t ~Bé0ü„Òa(ø !¤ÃüT ':¸éó%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--4jb6xfakep.png000066400000000000000000000460111524103652300220150ustar00rootroot00000000000000‰PNG  IHDR–Þ„&# cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ü’ŽuJéIDATxÚíÝçç•àû_uÎ9  ˜s”D‰Ê’%{짉;OðÜ»w?÷sÿšûbï~vò®g¼¶ÇÏxmÙÊY"Åœ ’‘»�cuW¸/`Ê¢‰Ð誟ï+‘"€§ Ýuê çI×uAAè›ÑA6XA„®�EAè*XA„®�EAè*XA„®�EAè*XA„®�EAè*‡ÑxÕe…™œL®Ü&[jSi*T[JGCV4ìvpJ6|^~¯�DÀE:ê¢/â"u#IF¿ A„Ï'‰’.ëO×a2Ó`|¾ÁÄB‹º¬ z ú\„ü.|n;n§§Ã†ÃnC’@UuMCn«4Û õ¦Bµ!S¬¶i) #I/»†}lðã´‹(#‚yˆÀ²ŽòÕ6ç&j\¼]Ã벓ŽH†=„ük›qÈm•l©Éüb�BMæÐX€‡¶‡ xÄTã‰À²r™w.•¹�k1œ 0œð9×ågµÚ 7gJÌ,Ö9¼%Äc»#b#‚¡D`é¢ZSáÕsE&šl 3šaïÑM¾ÕV¸v ø{vbN„Þ�eZm•¿ežmCQ~£‡³"óù7gòüõ‹ƒËš5hšÆGãUNŽWð¸Œô‡HG}k:í&·U²å&sÙå†Ì¾ÍŽl ñ‹ÄNAØHD`Y�ÿõNvöŒ%Œʪ|py�Cc>�…îùïf[üòt‡ÍÎŽM1"�îŸtk´:ÜÎV™^¨±cØËñÝ1B^ûÚ¿± †�e™.Þ®òÞå*Ç÷÷›êô×J«-.Ü\ä?eè 7ò?¸RæÄx™Ý£ñžÌÊ:ŠÆ�ÙS Um ñø®0±ñ/–&>ÁË +¯�/²gKܲA ô`sHLdŸùš¦óÓ÷³œ»]çñýƒ=[ês:lì‰ñÔ¡!¦ÛüÍ˳Ìd£/• k Ë2|p¹D2â%p=”5ˆ¹x»~×ßé:üìÕ†Æc{ûñ¸z¿$åqÙ9º#ÍÖ¡ÿëí o_(}©AX%XîCQuNߪ±m0jôPº¢/æåv®u×ß½r&O±¦rxGÚ°R4w Äý<}p�ëó-þõ½ U¬Ô ‚ÕˆÀr§ªÄBn|¤$½Ïã¤ÓѨ5U®ÏÕ¹:×àˆ ‚Ê.§�Göô!+ÿôÚÜÇcÁD`¹�s·êŒ¤CkÿF& ¹™/¶hÈ*¿<¹È¡m)œ&Û0·I·¦ˆ…üüË› 4d\Á*Ìu71™V[%_•‰‡W–Thv¯“bµÃ;—‹ ÄýÄ‚æÝ;Ú1!ññ/oÎÓjkFG„e�ång[DÓ,u‹$ÙÈW:\ºÝ`ë°ù÷ŽvnŠö{ø×w3ˆÃñ‚`~"°ÜC¦Ü&´N‚}šÃ.qqªÆ¦t·ÓI‰»F´U‰×/ŒŠ ÷!Ë=kžõi)l$I’P5N�Ê Æ ‡¶%¹4Yg|®¾öo(º�åJ5eÜP5�+“%&æ*„|n^kM—ÓΡmI~uº€¬ˆýaý•j ?ý ËOßËQ¬tŒŽelœ»æ=(ª¾ªFWº.±QvWtÞ>7K¥±ôáhu®Þ.°sdm¥ô{-ò�{xëB‘/Š=ÁÄÚŠF³­"ËwCZmI’p;—ž©ívp;øœÒgJ å+mþñÕYÚÊÒŸoeê|÷Ù’aã»ÄšÝ† ,åF‡‰L‹L^&WéP¬whµUT îóõºìø=vúc.c^FÒnÂ>k=µ¯VµÙ¦Öúí—®Ã|¡n¹À°s$Îgg8¼%D<ô`üþ„Ïjµ52%™|µM¹®R®+”êjM•f[Åf“ðºìxœ6l¿9€ãqJ¨:t”¥S UEnëKÿ^’ð¹í}vÂ~'ù’üqP�¥¯ùðj™¯=’4ú¥›ž¥K©®pæF…ñù:�–N:ê!ð0Üçg—Ï…ËaûøD—¦ë´;*MY¡XmsaºÉkç ÄBŒØ;üL�ËF{ƒ,¹¸vl’„Æo�UÙmÖØ¸ÿ4—ÃÆætˆ÷®ù݇SFGè�vGg¾Øb6ßb6/“-µi+‰�‹dØEÄç¤oÈMÈï äuàsÙVÜï§­hÔe•jC¥TSh4t:w­Z,”ZœºQa0á!v­KWÖ�À’Õ�o-49qµÌB©Íp:À@ÜOÈï^ñ/YÓu²Å&ÓÙ*µF›ã{"ìñܯä¥SyÝÉØÀÆH�¼>]b|º„ªëx\Ý“&è³æ´¾£j¼þÑ4õ !ÑÏeÃÑuX(ÊÜZhrs¾A®Ü&ùm'ÒTØE$°¾³UMÓø—·2Ìä[H@2èæðöóù63‹2•F‡á¤‡-i›û½D×yßÀï¶³¥ßÇæ>Ãq¯aGïÜ!?ýàÚjkLf›?·ÓÆŽ!;‡¤ð}K¹£ñòéEnee¶ EØ” ®Ûtb¾Â�é_:#tòãw³£‡Ó—'ò ÅmÛiþÒ4Ôš �W97QaSÒË�± ›ÓÞ {Ãmwt®ÌÖ8s£‚ÜÑxx[˜}›ƒ«J°SMÓùÅ©nKZ.ȼwiž‡·H†\üljEß?hô�º¢ÞêpâÊÿ÷W7Æ>ØF +?y'Ë\±…Ãn£/êb¾ sxkˆ‡·…ñ¸6æÍt¹òÕ6ï\.s;Óà‘�Žl m¸Œ©4Mã'dQ5‰‡v¦MqónÉKRŠª:Ó‹5‚[ÂFmÙ²Å&ªª°o$H­©ÐhoœÞ&~�“jCEÓô�“àc½tr‘Û¹&Eåv¶Á_>?$2Ö#tñõG’ä*2ï\,sj|š§÷ÆØ=0zh]cªG‡ŸŸÌSk¡m)S€\¥Å]“: Ùèa-›ªé\œÈóü�’~��vGE3×DuMþä©~Tºh4í対4@CVø‡WæÈ”ÛFiE ý4Nf[Lge¶Y'¹m0`8é¥Ñ–¹4aÎàr}¦„¢©|éÀçÏHú£.*ueCTn®·:øÝöÏôÒÖ�ªé¼t:Ï;WJüáã}Û6õìݪ<.;ßx4Í£;ÂüàÍyÎOԌҲöiÔuøõ©»7Ç ÏUY‰þ˜ŸÙ¼Ìï?ÖG½)sæFÖT'¬æòuf3þàxê ¯«ÃacsÚÃBÞú-~Ë5™tDl ÷Jµ©òý7æ©6:|÷Ù~úb¢”ÎzÛ3à;Ïôóáõ"/�ZDÕÌs¿ù"†–+S5ì6ýqŸÑ×`Eœ±�›LIæ;Ï à¶ë|xiÙ¹!ùJ‹K7óüÁãiÞ{ï7ìÜäg¡`ÝÍÁ; •&ÃI‘Ñ óE™|u†m}>þàñ><®¯¸¢QâAß}v�†¬ðÏoÌÓ��¿ßÜ‹a�å½+eƆ¬“døIÑ ‡©l ‡]âÛ�¥Ù>èæ­ssä+-ÃÆT¨Êœºšå�%IEïÿ¹¥ßG¾Ò¢£Zw9L×uæóÍÏÝGºëÖBƒ¿“áÅCIÝ1z8$·ÓÆ·ëc4åá_�'_5ヒ!�åæ|M‡tÔZ³•;âaS¹¥ "IðÄž_?–àÌx–K·QÕÞNU‹Õ]Íð{Ç’Œ¤–wÂí°±)éaÞÂËaÙR“pÀñÀ´—6Êéñ ¿ø(Çï?žfÛ 5?³É{c<º+Ì?¿±ÀLÞœ •†–ó“U†û¬Û•1äw‘¯Üý´0šöò¾8„Ç¥ñÆÙfr5z±õ’-69y%Ë×I0Ö·²“um 19Wéå¥ëª›3%Ží°æ¬×*Þ¿Zää�2öìý˘ ½qps�¯>”à'ï.0™5ß’vÏK[Ѹ5ߤ?nÝå §Ý†Ãn§T»;ÉÐã²ñ»§øæ£IæóÞ>;K¦¸>¿t]_:ýuîF–ß"Íæ¾•?Iަ½8l�+Zïèq®ØDÕUvŠe°uóÁ•2'ëüÉÓbVhBc}>¾ùhšŸ}�ãú¬¹VzžQvc¾A"ì±|¹è€×N©ÑùÜÆDC þì×çê¼q®ÀÍ™2#ý!úã>l]8—YªÉ\œÌpÙøË†­¡CÝ£;ܸQîy¿›µP5� “y^<C’–þ<�k2•“Y,wÈU:(ª†¬hØ$ð¹í„|’!›’n|n±ñ|/oœ/2‘ið§Ïô‹kebÃIøx?zg»MbK¿9–*{žyÿó9$‡›Í^ 8s#Ç�{G‚÷üwº×f뜾Q![ê0”ò3” ò­ü$S¹Þææl‰BµÅ“{£Ü\ñ÷ø4MÓù¯ÿ{šÛRÄBÖ8¶{y2�]R9¶=ĉënÍ7ñûÄC>Â~Ÿ‡Í†ÓaCÓtdE¥)+”mJU™B¹I*ìæà–Û¸œÖ9îÞ ï])reºÎŸ<%‚ŠU,”Úüð­y¾öp’±U¬^t[ÏËûÅ ¶¥ù­}DôÒD�á¸�c;#ËþšR]áìÍ*§ªhÄÃ^b!± ¿×ù™ÙŒªé”ëmKM²¥:íŽÊ‘-AŽl�tõfxu¦Æ«çÊoKâìÒìÂçqph[ŠJ£Í‰ñE®Î6øêCÉ5í[YÑ|Aæå³yþø‰>T,ìÊtEÑQhÈ2ÿøÚÿå+›z^IJ§sÿJCÁç6ÇMk­$Iêj)IZ:Uñ;ˆø=_Ûù<} ÊGײ(&IšœÉÖùô„Úå°u-¨Üýú]<¾¯¯×Ãß½<ÃdÆ|G8×K©®ðãw3üîÃËK®Ìk¾(ßÕA¢ÙÒÈ•zŸëÒãÀÒÁ½AÊ@H˜»¨ÂÊØd,íæÔ5sÔ?‹ï¾ÉI,%§®I’Ø>áÈö4ÿöá"&­Sôoµ:ªÎOÞÍp|gdUGÖs‰|ªu„$A4Øûýìž¹­ã°oŒ REÑqo�×òI/NñIœ¼²Ðó Ÿ´Phpk®Œ]’p8$v£}!6¥Ö~î~â!�íéç�K%Þ¿R6ìô¯N/’99¼íÁÝ[ÚH¾v,É@Ì…Ã>��€ÇÁ5r\Äbê*µ; AŸ5Žç®„$Á×�¥øÅG‹¼{iŽ£ÛÓøzØ@«P•¹>U$[nâ�$?0@Ø€„¯“ã{ûyïÂ<·Ä¡±�wã==^!WjógÏ=¡K|n;ß}nðã?ç+þçsôG\=]æÜx�Ü=Ò”;¦Ùäî6›Mâk'9:äí sL.TXÏúóù\Zàܵ,»‡Ýxœ6ŽìLTîð8íÛ�æí‹%®Í˜+³y­+Þ¾\ä÷Ž%-×�PX¾xÈɳbüìD¥‡+= ,.§Í4ÃkÕ쨄7øÉ¡£ÛC|ç™4År�7ÏÎ2•­v­„®/ϼ4±È«§¦˜É–9¶=ÀÿõÕ!&3-†S!S)õyœ<´«�—>ʦ>œU©ªÎ¿�åé}Q⬿ ½µo$H*âáµóùžýÌž.……ýnl€Ó6º®Ój)ıÌdÈÍŸ>ÓÏd¦Áת\ž(Ðó’ˆøˆ…žÝß÷ñ îüD•JSçøÖˆÑ/ýca¿‹í#Q~ò~Ž¿|®ßòÝ*ß¾X p||Ô]Øø¾|8Îßýz–[ý�ždæ÷ôÎò9hÉ�µ#ƒ•ëmB~組0šö1šöQmªŒÏÕ¸¹PçòdUƒ Ï�ÛåÀi·}\»KÓ4M§£hTë\N‰€“TÔÍÖ-^F’ñÏdv7d•×.xdW?’É’�FÒAò¥¯ž+ò⑸ÑÃYµlQæÂT�¿zAì«: Ld¬ñ^(ÊÜZh­º·°±H< Îç‹tÖ)·Å�OòÑí!nÌ•ŒøÑk2»X#ì·3”Ë`Ýtñv�Méõ/ÕÒMcƒ!>¼V1zËòæÅ"�ïŠàvZ#p ëo(áa0îæÔøú”,2ä�¶$„®h,¬“ÓÒQ5®Þ.ðôþ˜ÑCÙP+dE'´V°H˜Ë·¨5Í]Štf±I¾Òaÿ˜µ·°þßãÄõ2²Òý¤uC‹$Áó‡b\šÌÓ±H&þå‰E¶ z ï̶Ñ\žª2÷=Œ³Û$ÒQ/ãsæÞÄûb‘ã{"ØmÖ=Þ/¬�DÈÉhÊË©ñîϼ ›�¦½lï÷q~ë€pÀË|¡÷­_ïçôõ2FCb–-Ü×P‹Ïmg|¾{û…†€€×Î_<ß�Û¡óî…yª�ß–'ï¨ZO“)çë¼un–ˆWâ/ž"â5•ÖËÌ¢LÌ¢Ë`wDnfóæ)§¯i: YåâT�C[EéayŽ…8w«{ “=½kêúÒñÇù‚L¶Ü¡ÔPiwTtMÂé�ð{ìÈr‡7ÏΑŽ{Y,¶P4›Mb÷H„Íýáu×B¡Á­Ù6IçÇ '½½¼4¤|¥ÃŽMÖž úO¥¡êB;�ž–Ù‚Ì™Æçš¼v"7¯‡á”—ÆÎR©u¹£âp¹¨VÛÌæëÏTTUçêT‰MéPW�MVmëLçj¼vžÜfû  ^¶ MÓhÉÚ²ª›™Ïm§Ú2>—%_msn¢öÛFl*üò£E¾ó´õŠe ½ç°KìÚäçÂD•ã{Ö^¡a]Ët®Å[‹j #ý!ž<]vc¨üÉ)šíß~`UUçÚt‰TÄK4è^q€Ñu�¦¬�¯È,–äŠ-Ü.[û½üÑ㩞öƒ !ë86Óõ]Y)—ÓŽ¢©(ªnhžf[EÕîÎ ët¬‘#&˜ÃþÑ ÿñaμ�EV4^;—g|®ÅŽá(·ûW|IÇüLf* ƒxÝf²nÌ”°I~¯��ß…ÇiÇépàtÚ°±ô34]§£j(•º¬Pm¶iÈ ~—�þ¨›=C^F�D‰DA>£¨º†mƒ4JsÚì´ÚÚg—õÒ@ÔC"èb±º´ß#I:ûGÄ‹°|ýQ7š®“)ɤ#k{Ðîz`Y(Êüø� ɨ—§ â\eaÁý[â$Â^¦sUÒ1#© Šªqc¶ÄÔ|•=Ã~úcnªM•z[¡ÕRÑ4 °Ûmø½¾°�hÀK,è$âw`ß 7²�@ÓMrr¤$c÷3l6‰¿øÒÿíÓ„NžÞe(i­29‚ñv¸2Õ0W`Ÿmð¿O.²oK‚þøÚû*$| $~û}œ»Fb &œÏQ¨)|õá„(aoAn‡ e�*«öœ:Æ?´ÔeU×ùÓ§ûÅ>¡°*;7ùùÙûžÞ¿¶å°®Ý‘/LÖøå©<ïNw%¨ÜKÈïâø�ÚªÄ?¾7ç×v/]S`‘�Ÿ~�cß–3¨ÓQGv¦ø·÷²Ì,ŠàbÃI vý¤fK!è5~¶2_h 8ñ¹­�$o4åef±‰¦­þ¸úš˯O/ zÖ}Oe9âa‡¶'ùÑ;Yrek??(¶õûX(6zZ²§ÛJu™¾¨ñÕfrm6‰^ABx\6B>™òê÷YVXnÎ7¸�k³w³yz”$#^ölŽñ£·3´Ú"9Ììâ!~��lɼ=Mî§T“Jš °ä› Š2DB— %ÝÌ.®~ßzU�E×áÕ³öŒÆL—2” �ŠùùÉ{YK? ?(ÝææìúôÝî…b¥Å@Ìø|‘Ù‚Ì@ÜøqÃpÌ»¦m…U–s“Ulv;é¨ñK`Ÿg×H Y…×ÎŒŠp»6Ð4�ù¼¹[ü~žbµ…×m#jp‡J]Á&I„ Ìü6–tÌM¦Ôˮû‹ì‰ýÚ¿�$Áám)®ÌÖ×|lNX_’_9ãÒd�¶b­åËÙ\�=ÃÆ—MÉUÚ$EÏ ¡‹b;Õ¦ºêî¨+,ãóu\N‡éÛÉ:6ömIðË“‹È»a=h†“^ö�ø8sÝ:Ë—ª¦3·Ø`— úÉgË2éˆ,B÷Øl6âA'ùêêB­8°|4^eSŸ5Ú�&Ã^ba/¯�-=á>žÚÃíй4¹hôP–åv¦ÊpÊcø2Àb¥C;åúê*c¬(°ÜœoÐóvµÙÖzsÚmìÜå� %£‡"܇Ûiã;Ï ÐVڜϠ™4º\Ÿ)1w¯¹l·”ëÂ]èú'Ÿö»(×W—˲¢Àrm¶I"j�Ùʃ‰•†*J¾X€Ûiã�ŸèÇï’8qy¹m|wÆO*Õdf2^©&k<Ãk• OÐg§Ú\çÀ’«vðy8íÖì}2�P­+,”D¹+�$xjo”?x<͵©"çnd鍯�îS5�W2ìö±sØ<³öº¬âu[ó3)˜›ßm§!¯î3·ìwd¶Ô&äµî‘FI‚¾d€+S5£‡"¬À`ÌÍ_i�XÐÎë§f¸9WéùÞKGÑ8yu�tÈγûÍ•¿Õ”U|"°ëÀ尡묪!߲ߑ E™`�z­¬—Á¸ŸË3æXV–Ïå”xñPœÿôtšF³Ágf™[ìÍï±!+¼wqžþˆ‹ß}Äû*ŸÔj«xÝbEX^·DS^ù>ç²ß‘ùŠÂ`Ò7 …6l1z$ÂZ ÅÝ Å“4d• “UÎM,Ò”5ÒQ/±�—XȃϳôÏœº–EQA’Q7Çv÷KÁ¤Tk1_l²°X'à±ñÔÞ0Ûý¦?m¥k Ù¬ÿ¹Ìç—§rä«Þ¾\â�«EžÞåá‘e}íò‹¬àÚ3ŸÛÁB^¦ÜH|n;�ìˆðÈŽÅz‡[ó ngê\�. (:AŸƒjCýxR²Å'¯, + •Z‡°ßÉŽ!�ïHÒµÎlVÕÀn3g"©`]rGãÊTÐÑuÐU8y½²ìÀ"u„�E_š�¨ÚÝS�OO<>þ³¾ô_úo¾NÜ¢á ¬`ö¾ì‹Çí Ý±þ ”fK!¼‚µBÁü²Êù[5ÎMV‘;阗XÈÇæÁØÇKa¹RƒWs¨¿É…ID<<´«¸³&³PhpñÝ~��c;Ãì°ÀR˜Í¦Óî˜|�‚å¸�6v�8{« HØ%‰‡–9[�•§ ¹£áµÎ*Áçª4e¶÷[7Gø­™Å&§nV¹1×d ácïX‚hðó»(&#>^8:L®ÜÄ뺻íƒ$A4è&t³sS”…Bƒ·.”øàJ™¯>'2ï›Þf“Ð5s•½6†/N0•“Ù·ÉÏÞÍA‚žuؼ÷yì´;Öç‹2ƒ{­Qö_ø|“Ù¯�ÏÓjklJ‡yþHbYÇ��ñ{™—$è�ûè�û˜ÌTùŸ¯gxlgˆGVð´ÖKNÉFG[]Ù A¸°uл¢ +,ñ�ƒj³mÉZaw”ëm°é⨱EeK2¯_(²XVØ1½o�X«Ñt�tÄˉkò…/‰c3Yeo—KZu—?A¸ŸVGÁãXùÖÁ²7ïû".ªµÕ÷@6ƒ¹Åº)ZÉ +ÓîèüêLž~#ƒßçã©CƒëTîðºßÓO¦Üá?>Ì})>;>—�æ*ë9 Âý´Ú:^÷:–TÔM¥iÝŽºs‹5vmò=afò2óò,…ªÊ3G†ëaëñŽºÃnãèÎ>²U•×Ïç�¾$wñ:m4Úb)Lè¾;3aÇ**;,{),tRo)t­ëå3zav±F4àË`¡ëðÖÅ"ç&ªìÙœ ?nì�Ý&ñðÎ4ï\˜#­±Û$3_¯ÇNKÌX„uÐê¨x]«»×/û«ƒ Ù’õZüê:\›.ñÄžˆÑC–AQ4~ò~†[ 2Oì4<¨ÜátØ8¼-É˧óÔšæ8Èô:¨6US·r¬©ÒPzW—^²¢p´cÐO®h½êÀ³‹5">;#)ëë�óEÕÆîÍæk¦õyFÒA¦[k£‡B2ä$_3¡»²å‰Ðꪔ¬8°lé÷!« …ª9–¾HGѸpk‘¯<”ÀmÁSl’©\‹ËÓunK™z¦òIv›Ä`Ì÷› °ÆJ„�dK"°Ý£ëP¨tH®²ъ︒Oì�påvÁè×~Ï‹rz<Ë®A?c}æ8Q$|>MÓøÕ©Ev�Æ,wŒ} àâTÍèa� ¹È–E`º§Pkã÷ØW݃kU_µ$šÆBÁœ}M®ÞÎã¶Ã³Å˜Ù]�n`³ÙéïQ&}7EƒZÝðå°HÀ‰¢`š#ЂõeKRáÕwN]U`‘$xî`”K“Õ\ÉY3¹Ùb“o=f�e•Ùû×ËŒ š³ŸürDCnæ�_ˆ»˜-?ac˜^l2_ý�§U¯=ŒõùM»¹FÒ¢«,°&¬�]’Ø0ÛÌ:€±ARÓtþîå9j²N]–ùÁ›ž=ãè¶�ÑWG°�«3 ¾öprÍßg]¸Ý_>’`ïH‹·/–¸6Sb¤/Ä`Â�o™kê™âo§ô:Ðlu “Žz‰V~bA×uš²B¾"syªÁ[‹Ø[û¼ Ò·†£uÂÊÙ$ M5þ)¿:šjxÞÔ\±E¾Úþ8¼iºÎ…‰Š,²eÊmU§¿ ÷ÂuÝ9Jxø“§û˜/Êœ½Yå�ó³xÝv"~!¿ŸÇ�ÃnC’@QuäŽJ£Õ¡\“‘Ûwá´Ù%v GV}N’$|'>�“áÔR[Ùj£ÍB¾Á�ÞÍâóØ8¾+ÂŽA¿¥ó*¬Âç–h+º®[zŸ¥ÝQqØì†/ëù]6é®^I.‡¹š¤ ævi²Ê®.µÜîÉ‘œþ¨›þ£n¾|$Ál¾I¦Ô&S”™ÉÖ騪 .;ø¼fsMZ�þ„Ÿ\©‰¢.-}íÚ´ú òE‚>AŸ‹mà ޹Tâ�‹%ž?e4eÝlp+°ÙlxÝ6ZmkŸ kÈ*!Ÿñ7ðhÐÉ¡-AÎÜ\Z>FÒùòÃq£‡%X„ªé\¼]ãÏžèÊ÷ëé'Z’–JO %>»©(+?ÿ0‡Ûíä‘=I‚¾¥ý�Žªá°ÙÖ}ÑóÑó1Ÿ¯óóyFÓ ^8Ãe±Š»V9©ÔÛ–,õV‡°Iöêž?çÙý1m•ÿþ«Y\vãž` ×gê¤Â®®�°5Å]³ÖRø‡Wæèh6Žïëÿ8¨8íëT>©?îçɃÔZ:ÿò¬á•k7²¡„Ûô}}î§T“Š›'ÉÓf“xìòsaÒ ùã��¨±,صïgx`©Ë ÿüú<}±û·$MÑçÜa·±K’át„zuެ jAmDQÕ†µ¯m¹¶¶*°ëå¡m!Nݨ¢(æì�°N²E™BµÍÎÁîµ®04°¨ªÎßÎ’ŒØ61r(Ÿk´/ÈÞ±ÿòÖùªh¤Ôm}1…Šu‹ªé”ªmú"æ;Q¹HGœ\2A#2ÁÜÞ¿^áèö0¶.îaX^>WÀa·³c8jä0î©?îgû¦?~;C[<ýuUÀãÀç±S´èrX¶Ø¤/æÅå4~–ýyÚáäxUdâ _¨ÒP˜Xhpps÷–ÁÀÀÀrk¡Éø|“ý[מŒ³ÞFÒA‚/Ÿ5o;f«Ú=ìc.o|Û…ÕXÈר3bÞÓƒ›Ó^¸:-f-Âç{ïJ‰ƒ[‚«nAüE ,º¯ž-°g$¶¦’/½´g4Î͹&3¢çEWíÞdÞ‚�EÕt2Å&ÛÍXžÜã­KE4M̶…»•j®ÍÖ9¶=ÒõïmÈ]ýÂd›ÃN_ÌÜÊOr:lì‰òÆù¢ÑCÙP!'§D¡b­€=—«1÷à7ùQé±>/~��KÓÖ ÞÂúzçJ‰#[ÃëR5Â�Àròz…­Öës>˜Pn¨Lç¬u4»}›üLg«FcEnÍ•9¶³»ëÒë婽1Þ¾XBÙ %t„µË”d&š<´N%zXæó-m�DØz•W% FúBœº)òºéÀ– ùíŽñ�—#SlàpJ–©Î0œô0ssâzÉè¡&ñÊÙ�ï‰v}o厞–«³u“AËÖãN¸9ß'ĺÈç¶³mÈÏÄœù¶®ÃøT‘'vGŒÊŠ<»?ÆÉë* ã’ ƺ:SGnk]? öI=,·dRó%”-—Óa#t3± ZÀvÓã»ÂL.TL?k™ÊTñ¸$vu/™¬B~‡¶†xõ¼8Ùø “�×Îxî`l]î{ºó(w4ŠÕ6‘ ùÊV"õqs¾É‹Ý\ÖC­©Rj(Ôš䶆ބË.awØp;Àé´öÙ xîýV‹œì 0>SdÏæ„Ñ/ësu�k3EþäÉ´ÑCY•ã;#üÝ˳\Ÿ­³½‹YÖ‚u¼u±ÈhÚËHj}·"zXrå6á€Óe[Ö"tsiÂüË6ë¡ÚP¸>×`|¾ÁBA]Âïµãq;qÚ%�@UA×tM¥ÓѨ·TE%v1u3˜t3’òôÞ]$ñÉ=þ楆R!Â~óÔߺãüÍ»‡}¤M˜i¿v»Ä—�ÄùÙ‡Y6%=x\¢Håƒd¾ seªÆ_¿8´î?«§�¥ÒPð¸ÍQ v-B~¥ZEÑp< Õ�'|x½Â\^¦/æ% ²m8‰w™7'EÕ¨ÔÛ”jmÎL4ùõé¯��C>vo ’9ñ¹í÷ú?Pô4°”ëʲ;Hš™$Ix<ª-•h`c–lIæå³E*u•±Á0{·¤W5ãtØmÄBb!Bס\—™[¬sö�B>;m ±{8ÀåÛu®MØ9bŽ~"¥Z›ëSEþì¹¾ ñ ñÜ�ÿÊ W¦ëìKb‚WÏ-Òs±kSwyÝOOïò펆Ã"™ö÷ãwÚ©4”®õ/0£¯•xïj…Ãn vu!I ¸‰Ü쉑)689^áõ‹EŽl ròF…hÈK:jì‘Þz«Ã‰« |å¡ñ ù–çVÃ唸ú±?|{�Á¸›�Ïú{»9ßdr¡Å_~i°g?scÜå àò8©47æÑMMÓù÷³œ™hðľFûBëº,%IK�ÖÞÓÇám)®Î¶h´TN]ËRªWUºÕVùðÒOï‹°Ãä¥[Vª/êæ¡­aþýÃ,š&'7ªr£Ãÿ>™åk'×-gåóˆG•Uò8Ôæ>»š¦ñÓ÷sTš:Ç÷ôcïq/÷HÐÍ#»ûÈ\¼•ç½ s �„Ä`"Àþ­½Y«5–f*G·9¸y}²“�öèîó¥¯�ÏóüA±ß²4d•½µ@®ÖÆe—p»\Ûa(ÑÛ�žÎXÜ. E݉…v‡Dg–ÈxéL�rCã¡]éž•OJG}lé£h:ŠªÓQ5ng+LgÖ¿ôËb¹Å{—çyz_”c;#†]ƒ^ø�£InÎ7¹,ú¶lÿþaŽùRE�†¬S®·Ø?ÒûÒC= ,!Ÿ“†¼A–�t½«�qÌàÌ­ ·³2Gw®nƒ¾Û µ»û´è:,®c±J]×¹6UäÌõ ß8–`ïHo6:�äqÙùÖci^9›gNTî¶¼Ï,ÏëEšö8°8hm�À¢j`“º7cÑ4m)Ù°®Pª+Tš½]f+7:¼u¾ÄÑ)Ó°Nù?¼;…Î:Ìz+õ6ï^˜GîÈ|ï…AËÔë†dØÅ×Nò¯ïg)V;FGXƒ�¨›O¦Ôû<6’ä]õt�%tRm´Ñu,[+ì]gMOõÅZ‡Û¹“ -æ -j²‚Ûf_Z~ÒAÑuÚŠJ,èb4ée¬ßËæ´wÝ®ÛK§òlá÷˜ç”[2âãð¶$W¦–Ê� %ܘ-ñÆévŒDNÖ|¨ ÞêpmªH¾Üäéý1¬cý$3ëóñøž(?z7ÃwžéïI®ƒÐ}Ç‚\›®ãpIDn¾q,�À%힟ێÏí Úh2afõÊèH¶•=ÙkÎܪriªŽ®é$Bb/GwFðyŸ Tª¦S®·É—š¼z®@«£qd,ÈÑí!\]̧¸:S§XUÙ;f¾V ?‰ßæZø=NN_Ï1“©p}ºÄh_ˆ¡T�sù7BM×ÉÌfkä«2Ƕ‡øÃãIÓ¶î•CcAÊ�?|;ß<Õ×ÓSDÂÚe‹2?y/Ã7�§ë3¶z¼¤ë½íˆý‹“‹`s1Úoí“6gÆsìõ°ï>cº×f뜾Q![ê0” 0œô­<°VêmnΕX,5yr_ŒCckºÖ4�ÿú‹nK Z£8èå‰6[‡ÇvDøèF…ks ^‰���ßEÐëÄa·á°Kè:´:*­¶B¹Ö¦TkQ¨´HEÜÚdǰß�':3{ý|�éÅüd_W`„õS¬vøþ›sšâÏŸï'ìûìžÄÌb‹WÎhutvnŠ‘ŠvZªëpc¶Ää|™o?ÞÇP|utóÒ,Û6ÅHF¬Õx-Wnre2Ïþò�å÷ëÌê×g™ËËüñ“ýëÒ¾VX»\Eæ‡oex|o”£æ*`@æ½Ë)1Öça>ß0úµ¯ZG]zþtPiÈ*?û0ËO?È1˜ ñÄþÁu *°tøaÛP„ƒ[Süøí ·V~='3M Ë€dØ‹ÝnçʌȿX//J0wóƒ7çhÈ/Øêæ[üË þéµ9òäCŸïúl�¿—á«¥LÙtÎ�À2ÖçÅa[ênE…J‹áôR`Ñõ¥æ9??±È¡m)voŽcïqâd,èæ¡�iþýDŽÉìò’ÜdEc:פ?n¾7år¥"^*u•RMä^¬§'÷ÄxlW„ï¿>ÏTN$Qí£ñ ¿>³È>ÑÇ–~s®6¶pz|w„[³Ö|Ú,VlJxé¨:?~o�ó-ž:8@7¶¦LQWëŽ�¸Ÿát�¾³€¢|~éEјȴè‹Yw쎰ßE¶,–gz%tòÝçPU�ÿñúE± ¹înÌ7ø‡WçØ>èãÛÇÓ–H\5t„›’FR®O�¾Ë6“­q{±IÀëb÷¨9:~ÚÖÁ.‡ƒWÏ>÷ÿÏeB~džÈOð{œÔeõ ƒ¨Ð}.‡�o<šbÿh€zmŽs“bil=(ŠÆ¯Oçùõé<ß8–´T¥mÃï,ÏŒ2›¯‘+­ìD“Êõ6‹•ýQ{ÇÌÝ¿bÿ–$ã™Wg>»ÿ0³Ø"4ç¦ßJI8vZ"°ôÜ‘­aþäÉ>>º^æßÞÏPß fÍ`¡(ó¯ÎÑh«üÕ—NZëójøB�ßíàë�$ùÙ9ŽïÄë2~¯âÓæ u.O�e¯ËÆ¡m)£‡t_N‡�ÃÛ’¼tj�¡„›€ç·¿êÙB‡pÐúË`w¸r[#`�Š4J*âæ/žäíËþöW³<½/ÎÞ‘¯Ÿ/pe¦†Çmãë�¤H†¬^°7:ªÎ;—Š\¼]ãÙQöl2W~Êr>cIyyh[�S×2¨&k“Z¬Êœº–£ÞTP4¹£1_°Æ)¤HÀÍp:Ä˧ówý}¾Ü&è5OcÁÚìv‰§÷Åù£'û8}³ÂýÅ'ÇËÔš*‹¥ßmžV[Ì(ïg|®Îßþj†ZKá{/ Z6¨€I À£»¢ôEœœ¼²€ÖÛ*3÷4³X¿«'¸¦Ã|Þ�`ûP„ÙB‡›óK§ï4M£ÜìðmœÀ"·uÛŸêSÔê¨ÌÄ‹/²Xéðƒ·xã|‘Çù݇S–¯egªOã׊òJœ¹žÅ,±%ñðÉ3_³Ðþ„Ý&±osœ—ÏÐu¨·4\N»©N²­U«£á5Áqol6ƒñ»?6»D, –Â>­ÚPxétŽï¿1ÇÖ~ß{a�Í}ÖO“›ÍÆ7Mã´iœ¼º€²�WÊã´ƒ$ý¦ »�¡d�1‹•AIF½8ìv.Þ®Rk©–ú¤z«CÐgßpm¢­ì+GŒ$½¸—�� ›ÿùú'¯WÄé= ÖRxåì"ûò,»�ÿãÅ!Žn m¨÷pÏ«/‡¦é¼t*ÏÌ¢ÌÑ]}x ÚÐoÈ oŸ›Åá°óÜá!£/Ëš*-ÎßÌòÂáï\.óð®~£‡Ô³¹•zƒo?fþ²lQæíË%æ 2G¶98ÚP8Ë‘¯´99^áÊL�ý£AŽí áw~~j]˜2°ÜñÁÕ2'®—Ù¿%¹nU‚¿H£¥ðá•dYel(Ìö¡ˆÑ—cÍ>¸¸@*l§PW9ºÓ:ýWîåÒDžá¸ÝRgüd‹•'¯—¸:Û`×p€Ã›¤L\šd­tn-49s³ü› æÐ–à†ª¦,S¹??‘%ô²gsGj[UêmN\ÉðØ®0o_*ñä�¼àÉbv±Î™ñ,é˜�‡vX»ÑÚ¯Ÿšæ÷ŸH‘ŽlÜ›ÓFTk)œ»UãÜDŸÛÎÁ±;‡|†­Nt[±ÞáâD•ó“5^Æ‚ìöãØIÉËaúÀ w4^>“çÖB“­CQFÒ¤uÚ|ž˜¯0>]âËGãDN~òn†§ } ºBÓu^99MØïà‘=FgÍJ5™s7rü—ß±ö2åƒL×a"ÓàüD•‰L“ᄇ]›ülðã¶ØM¸RW¸2[ãêtƒr½Ã®Mn’ ?x,Xî˜/ʼv®H¥®06a áïZ‰úBUæÚT‡Mã÷I 8ùh¼Â�…6û·˜;Ë~%.ÞZ¤\oq|ŸõoÆ—& ¤ðÔþ˜ÑCº@V4nÌÕ¹2Ý`*Ûd æf4íe¬ÏKÊÀé�;ä§Ÿe5Mg&/ss¡ÉäBƒJCaû€�]›üŒ¤|tgSK–;&œ¯2»ØbS:À@"@Øï^ñ/RÓu2…&S™ �F‡Ç÷‡Ù?úøû¼t:�¢9-w 싌O—¸6]BÓu<.Çv§ ù­ù4ÕQ4^;5Í÷^$ä·þ2¥p·vGçv®Á­ù&™&mEc(îf0ée0î!rár®ï�[Ótþù­yæò2:� ;ybwŒ¹¢Ìl®É|±M,èd¬ßÇXŸ�ÁØÊïA•%ËÅz‡ó7«\›mÐ�5RQ/A¿›�ÏIÀëÄå´<£Q5�vG¥)+”êmŠÕ¹b“TÄÅþÑ {F>;ûùÁ[Ò± é˜õÏ–Ëm•WOOßUê<pñÄ�A£‡¶*ãÓ%ì(|í‘�3›¾Xµ¡0�o1““™-´ÈW:¼vÒa7± “HÐAÄç ìsòÙ±ÙV·Œ¦(å†B©®ræV™ñ¹æÇyl:õ;Ø=X rq�%* ÁÒ�zQ¿“§öÇxjŒJ]a"Ûd¡Ðf6Û _m#·5MÇn_šÎú\ü^;ý17‡G}lz8Fð} Zm §ÅÖy¿ˆ¬¨Ÿ©hбP»‚OjwTnÍUøîóãd›pAŸƒÝ¾»‡ÀÒç¹Pm“-µÉצ3-.6Ê�Õ¦ŠË!áuÛñºì¸HžO]¹³Ô³¨ÙÖhÈ*Ͷ†®CØï äsP­+ŸIŽŠ{xrOÔèËaz–,Ÿò;8°9È�ÍŸýŠ¢=0§1¾HÐëÂïqRm,õÏ�€A‹¶%¾z»ÀþÑñ 5—ñ„µ“$ˆ‡\Ä¿ ¸¥ÜÑh´Tš²J[] ²òÉ)ýã@ãq;ð¹lxœö»–×òÕ6ÿðÊ,�ßmv:$Ží ýÒ-aÖ{¾ÈU»¤cÍgúÏ’$xòÀ ×§ÊÌæª86vŒXïÉ+_i±XiñÍǬ¹„'ô†ÛiÃí´ ®¾&^<èâ{_æ­‹4 žÚ#x n™k&®Ò=„ý-…øÆØ»Çn“Ø5Á锸œ °óîÅyZíÞÏÎZm•SW3Üš-ðGÇS<±7bô¥a•D`Y·ÃÆ3£\º•ÿL½-+)TZèšÆhú³y 6›Ä×�%98êã­ósÌ-Ö{2¦¶¢qy²À›ggNºø«/ Ò÷¬ý ‚`KW7îµ}wUw°wÌšu?¸¼Àá1?Ç‚÷üws‹-~y*�d·³kS”p û½0ê­·ªLgkìöq|w” WlÐ ÂF Ë È�¿}yŽ­ƒ†’£‡³"sù:³E¾÷ÂÀ²JŠë:œ¾Yæý«e¼N'#!ÒQßš«µ:*Ùbƒùl�JSfßh�Ã[‚DÖ)+#Âý‰À²B¹r›ï¿9ÏÁ-)RQ¯ÑÃY¹­òæùY~ÿxš¡øÊfº×f뜯�)ÉDƒ/!Ÿ‹€Ï…÷ z”«šNµÑ¡ÚhS©·ÉWÔ[*£i»ýlê^÷OAÌE–U˜-Èüø­ ·'IFÌ\4]çýK ìì÷ðľµ•C‘�É…&™‹•ùŠLGѰÙm¸’n££k(M—ˆ¤ÂnÒ'C ƒq�Èœ„€,«4³ØâGïdÙ5cSÊœËbºgÆ3x�ðíãéuùU§£h´]Óq8lx\6œâ˜° <°D`Yƒ|¥Ã�ÞÉyؽ9Žd¢Çñ;™ëv›Æ<–~à� ‚Ð;"°¬Q«­ò³s”ëû·$ù�ïj(·U>ºž%°ñõ‡“"¨‚ÐS"°tÉ¹É ¯Ÿ+2œ ±m(ŒÃnÌÍ�IDATxÚí½ç“gžçùÉDÂ{ eYU$‹žE'Š)‰-/µ4ÓÝêÙžY7w»;»³qq÷êþ”�‹3ëæöfwv¶G3Ý-µº[­–½è=Y,oTÁ#�tϽ (‰)U0eò¡Ð 2óû˜Ÿ•„›¶ ·{66ë[€66mÄ �M±hcÓFlÚØ´[€66mÄ �M±hcÓFlÚØ´¥Ý°¹G©j�-™äK¹²NY5)V-TÝB­T4�%ݦ°0Í{Ÿu8À!É �Ç)#I·ŒÏíÀç’ñºd^aŸ“ˆ_!äwàwÛ�~% Ù¡h­%WÖIf5Ò9�¹l•t^§¢š<b>a·‚ßíÀ§È¸$E–pHI’�Å—ÿÿÖ5Å—ÿ!°$ 0,�n�n *¦I¥j’×tÊEÕÀéq¹è�9é »é »ùla¶[€MDÓ3™*3é ãÉ ÉŒFÌç +ä&îuv9ðÊàhÓø,$*–EQ·È¨:S… ªEgØÉ@§›¾¸‡ÞN‡Ôî[¹f±Ø@„€é… wfUnÏ•)u6Å}ôÝtx<ÀJ•…U ª&Óù*£ %B~'›z|léñÒÓáAZé?ba p™Tu‹ÛÓenÌ”™Hªl»Œøèô:pK ­ò»+€ )Õ`,Sf:¯1ØåfkŸ�á^?nŶã-[€K@3î‰îÊT‰ét…-q?#¢™µ};-$ò¦`"§rc¡D"âa÷�Ÿán?.§½4Ö‹-À:KV87Z`l®Ì¶„ŸÍa/aEBZÇ·°`ÂX¾ÂÕd‘Á„—}›ƒ &¼íÖªÁàc(ª&—Ç œ»S$äVØÝ á’‘íÛöuÁõÅ©’ÎȦ#ƒAÞv™˜V¶Á|Nãäõcseö÷† ºp¯ñíe£0€±¢Î¹Ùƒ]>žÚ¦3ìj÷°V$¶¿ÅTºÂ§Wrä‹:Oö‡èö(öj·D�6,¾˜Îƒ"qtG„á^_»‡µ¢°ø%·fJ|t)ƒ_q°¯;DTYýÌ•DÞ|1W¤dš‰2Üc l2•®ðþÅE‚²Ìþ® >Û�×TJHœ™ÉQ‚gíqý p6Så½s‹x<ÑÆo ¯¥œœÌc9/í�ÓYŸgÄu'À¢jðáÅ,傯ÁÞ~ÙV^;Y0ŸŽgèOx9¶;ºî¬¦ëF€¦%8u3Ëgײ„½ntùéó(\[T™)Uq;dvƼtx�L”tnfTr·"Óçw±+æÅeÇE6!IŒ NMå8´=È¡-aäu21® N-Tùõ©$²,£‚ƒ[‚¿ž£#èA’-žÚ&_6øðR†ÃÛ»™Í”HfJÛ¡'æ¦\µ8?Z`|^åµÁ~§~Õ tIâbªÄLQã�Cqzbîv©é¬iê¦à“«.Þ-²s0FU7ñ(/ïëào?™g2¥ò¿ýh§ro¶=?Zà‹»%4Íà_¼Ô‹ç[BûüZ–[“*¯ „ÚýÓÖ4Y¸“a°ÛÍ‹û:Öt¼éšMþ›/óΩ4/ÏïëǩȔ+Ÿ]ža*U¥T5ñ¸•¯Äò)¨�çG¢ßÀSÛܽ] P5 ºLªÜÊk¤K:UÃÄít÷;Ùö°Áïl÷-XµD$øÉpŒ+¹ ÿá·S¼þd‚¡„§ÝÃj kN€¦)øðr†+%önî¤3òu\¢Ï£ðÜþ~ e�°ßÅǦ¹:Qdç@Ýœ¸‘Ã0yäÖG–$º".¦u‹±ù:‡·†Lxðº”5“ñy•7ò\[”ùA_÷:9Ë4ÁHØÍPÈû§Rlðqlw Ç»Ÿkj º�×ù‡ó¸'#Ã�¸³uÉ—5ÎÞH"KP©šôvúÉ—4^?ØA_ÇÃEøŸ~?C©b²kÀÏs#±‡æÆ ïŸ_àîl…7†Âkî¥i5–$q.]fªPåÍ#�k*¬mÍðâݸ�aÛP”ÁD°®Ï–*:.§§Cææd§lðÆ“ñïü]2«ñ×̲µÏLJ:{Ý_žLAEp¸ËßîÛ³&˜7ÞÎðüþ#ƒõ=ã•ʪ?Ýš¦à�Ó)>½–ãèHOÝâð{œ8÷nÅÆÞcó>¿šÅúÆÜ”Ìjüü³y‚÷uÔtÝ—öŸ“Q©V»oÓš K‘øÉŽ8'¯æùíiLkõ¯«zÌ«&o}6‡$9Ø·5ñ•ˆ–KE3¹p'E±¬‘ˆ¸)UM %ƒḊÏ)øñS�_ýîóÖçI…-áµoRo–$ñEºÌ\¹ÊÏžîZÕ…¤V­gÒ~~<ÉPW˜áþpS¾£\Ñ)”uœŠL$èæÆx†þ‡·Õþ}Ÿ_˲˜6x²ÓNRm4c“““Y~ötתõ®Ê©ãÆT‰wÏ,°oK'‰hó^lŸÇ‰Ïóµ;A@݉dY´ó›Â�ÇAx8Îß~”äµClë[}�Ý«N€§næ9q=Ç¡�ÝD­µ†y\ ‹­®Ï¤ó:>××·Y5,ʆ…n ¼ŠŒß%£ØeÆ–LTüxgï~±À|¦Â±Ý±v©.V�…€ß}±Àh²Â3{zð¸Z?ôDÔˉ«Y^Þ/jr-¦àÎl™[|ºPb.SÆ´�—"Sª˜+&.¶FÝȶëÆ+¼µƒ÷ÆrTô4¯ì�/ÿ¢-bUœ…€·O'IfMžÜÑ…Ò cËR8s}žá7GwDû·_Épe¼„¦[ØdÇ€ŸxèÁUÛ0có*çF $3Ov ­?W+1%‰�¦sþèÉ΍_ºâhY‚¿?ž$W¶xrGwÛ�ÚjÕà³K3¼¼¿ƒíß»8Vä÷çØØåå‡OÄñ¸?iL¦*üòdŠÍûã«ï<³°$‰ãÉ"B�7w®ø¬Š-@ðxëxŠªû·%VÌö,_Ò8scžÁN‡·‡I|#2c>«qüzŽ»seö yq_}g’rÕäo>ž§ßëd¯-Â%a!q&UBÅâOŽ&p¬à²+@Ëüü³$š%±¸i…ˆï>†iqw&Ïdª€a ¼nµjáTdd 6u{yõ@mûoSª˜ü§ßÏp´;@_‹ Mk!ÁÙ´JQ˜üìhbÅ®„+R€BÀߟ˜§PÜÞµâÄ÷m4ÝDÓ-\N™\QãúäÿæÕ¾e­ØwçT~s6ÍO6G‘W|G‰•‰�$ΤÊT$“ŸéD–W^à×ÊðΙ4¹’à‰U >—ÓAÀçÄåtpk:Ãs#Ñeo—7v{ ù�ÜÍÖçö°ùIvúp™·O/°ò–š(Àß}±À|Fçàö®sæ«•ŠfRT ¶4¨Ò×Þ�ÆK¶—ƒ$OuúQK&ï]Xh÷p¾ÃŠàÉ›9îÎUxrGWÛ­�K!•UÙØåmØÄ1Üãc&Wm÷ÏZõÈBðl_ˆ¹”ÆÉ¹vçÁ±µ{÷¹5Sâä�<Ûìç[åªA,ظ�KÆá�¨š+pï´ÊpÁ‹ÎÞ*psªÜîá|ÅŠxÓg3U~}z�'·wá]ŽËuÃÄïnlY=Ÿ[FµÓ™‚",^ßÒÁo¾X`&]i÷p€ ÀBÙà|:ÏÞáNÂþÕmrW2U½±b©h–] ±�x…Åk[:øùñ$EÕh÷pÚ+@˼u"ÉPw¸©Y ­Âír�-7– jXxWé–|¥–ODù»ÏæÛžÔÛÖ'ûÛ³i2Ã}ÍÉçk5!£sjî76¯Òp­Š˜ÆÕF¿[¦Ççæýó‹mGÛxñn�±d•ý[m½�$äs!�˜]lŒåòÚd‰þU¾-_ÉŒÄ|̦+\/¶m m`:¯óþÅ Ol_½ÏG±©'ć—3˾ÎbAçö¬Ê¶ÈÚ¬‡¹�¼8å£ ‹,Ô™çÙ¸1´ÓüÃñy¶F x×^ñÚÁ® ™¢±¬YÕ´oŸN³»+``šŒÁ ›:ø‡ɶœ[.À/ep:•%U/[ H’ÄÁ­]¼a‘ÉTý¦n!àÝ3i$ÙÁ¦® š)(ëší l1‚^>º´ü�K½´4ûî¼ÊÛ§ÒÛÛ‡s ×ûHç*œ»™ä¹=Qön¬m²©h|ž…‚�,I”ªŠ,ápH˜¦À0a¯BÜç¤Ççd0àZ•C+K’ø‡[‹¼~¨ƒÁDë,ò-`Õ°ø÷ïN±û[åâ×2EUçÜÍ$>·Ì±ÝQ:=µhV4‹ w |v5KÐçàà–ýbAç3LÁBAg*]áÖL™ÙÅ*›c>F¢|vǦe3/$>Mó¯_Ù€ËÙš‰­eüÍÙ²e‹=›k¯©¹¦ÒEÆfrT4“ !Ÿ‚Ç)“/¤rÉœF<äâ•ý1ú:j7ºT“S7r\/²+îgOÌc»,–�¡8øx&OgÈÁK5_^.-àôb•¿ûtž|Ù¥h½R®d UªšA¹b0Ÿ)ö;øÑ¡‘ÀÒCð²%ƒ_ŸN£iÏ÷ñ¬ã{¼,!q2¯11—ãðŽ‡·6ß?Ýô'eZ‚·O¥Øµ©c]‹ÀçVè‹û‰‡½Ì-–9¼-ÌÿôBï²Äñ+ü“t³©ÏËÛc9ŠšÙ*¹•UÉ—T^ÜßÁgW2d‹zÓ¿³éŠ8u#‹Ïå¤'f7(�{Õ¶O]›ãåý1mm\£OI‚c»¢Þâw“9Ûjºò†ÅPÂî�AŸ““7²MÿΦ °¨š¿Y`ûÐê*–Ú,LKpúz’gwG¿·¢Úr8¸%Ä–^NçWdøJ&öñÅ�ÿîW“H’̵I•b¥¹ÛMà—Jñ{ÖžÃ})\CÜÅþMÍõ�¾¸¯‡[æ|zåä½­t>O•¹<¹ÈP—ÄB6tøøR¶©ßÛ4Îe5Fg*l^#�ÖË%[Ԙ˔xió­k’|(ÎõE•‚}|,³E�TIã/_ëç'O%ø·?ìc~±D"âåæl™¹Lóª4M€¿ûb�mCÑuox¹Ïí© ÏîŒ<´÷|3zžqq¡qÙk•tÅ`K¯å˰?—"³¹ÛK¾¬³­?Âûš!Ó”·áî\™’j²¡sm†›ÕK¹b�)VjíýxrKˆñ\Å.iñ|'Sé¯W9!`j¡J¿”áÿ<’®1–lN}SøÑ¥,[¢¶SøK¦REvnð5ö �Kfc·�»va§ï¥«Ã�nIü×�æ8q=Ë_8‹G2ö©ÈÂä…>ƒš´ 6\€·fJTta»¾A:§²µ¯=÷c[Ÿ�iÕ.mø(FsUÞ»>Ïb¾ÂTZåäÍ·›×û¿öe�¸Skh²õ}^é“+¶ÄìÕïK„d Uú:ÚÓÁuC§‡ßž]yõ0WÓeF‹U^?g Óƒ÷ª¼{6ÍUYfoäë¿}²Ëâ×—ÙÔÝ×Ð14t�SÑ ‰î˜ÝTä>¥Š�ß«´|ûyŸ€Ç�@ØçÀo‘­Z\[TùçÏõ0Ðy/þV’îU$ÿgÏõpj^¦ ýÌ‚R•˜brw¾±«`Cxâz–ͽ¶Ûá›T4“€§±¥ ë%àQ(ë¶;â›Ü)VÙÄÿ�gö+lï÷s'ÿàñpÂhxa߆ 0•ÓHçuzâöÙ–…³Í©BŠ"a´¹ú×J£¬[ľ'7t’5 É¢Z!Ù@¿`Ãތϯå쯺~ÍF–ï%Ó¶Ë+¶=W»ð)ÙÒ£ÃÌ2E¿òÝçöT·àÔÍBÃÆÑU“ÑÙ2C=¶ßïÛ¸j›£QÊš…Ç®-óQ/F ¨Õï>›‚jp}²ÄÖàwWºN—ÆLº@©Ú˜цXA/�èŽûp®± g�ÀïQÈ „ -–aͰ¨ê&>¥½çÐvS6,îäª$+:C 8e^'ýÁ¯ŠÓ»g¥žLUxçLš}�açw«œKBp¨ .�–xjÇòí à¹Ñ"{‡×W¦{­(¯ÛA*¯=ÐʺUÌ,Téð¯ïâ¾*\M—ØÖçãàP¿ÇAE3™HU8?Zào?™!€Ï)q8¡³5øè\À��¿¹›_¼¢# ´Çϵˆ‡½Ü™SÛ"ÀÑy•®u\Ü÷³ùÃà/^é#è}p°¹ÇÇÑ~}&ÍBÁàù� Ýæã+e+Xôù,&S6t.¯në²÷ŒçF lè²Ï~ßGOÜÏå±ÖW_®Œ—Ø\Ÿ¼•«²XÕù§?èùŽøîãvʼy$AÔ¯p}®öˆ¡=qÁ£ùe�qYÔ ‹ÑÙ2: ¾uk‹Ž�üeÑJ®M ºDÜ2m5 œK–xã`§òøý÷vpkÑ¢¤×¶W�)U¦çKèË´p/K€·gÊÄC;娆û#|p)Ó²,uÓ|t9ËÞøúŒJšWuün=±ÚŽF>·ƒáwòµ½Ë’ŒtÊÜž.-kœËRΕ‰=¶ã½úâ~,Kâì�åo[já“«YÂ.…^ÿú¬F�­uÇßöÇݤôÚ·ë›ÃW'—Wu`ɬê“É ]ës†] {†ã|z%Ë\¦¹Ù 7¦J\¾[äéîõ;9j¸ë,®ëR$ª¢öízX®’Ì”–Õ”uÉVÐÛÓeâa�íû«¿ÇÉȦ8ÿãÓ9þüù"�ƯNs�wÏ.ðÊ`dÍÖÍV ÆŠYÍ¢¬›^§ƒ�Kf(à"îQp¹2åúÊ æË>¥¾3Âî¸Ì�™2;—fY²oΖIØ«_Ýôtø0¬(ÿïfyóh‚ ñƵ»=[æíSiŽöéhsx3˜/éœN•¨˜Ûz}Œlðô*H+&s�Ϧ ˜lì 3>“Ç´DÍý3nL« ×·; ¾˜U[+@!`|NåX ­E6tñºÞú,ɳ»"^^}P!àøõ,gnxi L§·áižmÅBpz¾ÌT±Ês#Qv<üeßÞï繑(£s*¸°ˆâ�8}3ÏSÛï0�S)Wtúê[5#ŠÆdR^r¤Ó’žÔôB�×�ǵöfÙV{9:ÒÙ[)®N–xaOŒÞ%$íŽ'UÞ¿�AðG›"ø×ضÓBðþTÅ%ñ¯ôá®!³dS·—ÁD/¿8‘æókYº£.†ºÝh¡ óöé/÷juEda1‚¹Lµf‹ë7YRoˆ�.eHaÇ`tùwx�#L$ Ü™Îö)Œ îñð>zrË• nÏ–¹8VD­Zìê±Ý¿6'Ããs%*²ÅŸ=Û½¤æçŸÎ3™ªðÄÖ‡·†°i .�ùør†£]:;ÂK+E?Võ±¨„xvW¤îÏ.I€ÿá½i¶öwжÛ'7 !ó•Ùt‘T®‚K‘ˆœ¼YB3Õ`± cš—KFFÆé”q8$܉€"vÊtºbn¥mñŸEÝ$S1Èiœ²DÐ)s9Ö0S28>—¯yå{–%øÏïÏ2Ù¢FgØEÀë@Õ,æ3U~‰g:U➥;h˸x{Êÿ|©·îÏÖ½ÕtA¦  Ù±Ÿ�D’î•ò¸_ΣPÖ˜J•˜Y,S(ë¸�â!'#Cº£n¼.ù«Ý”«&¹²A:¯sc®@©bÒp³1àb ÔüFž™ŠÁÍ\…‰¼†… 3ì"tâU �®[Œ5NÍkKÐò°5ä"î{´%øLªÈ {bKÜËÇ|í@œ¿û<ÉOw¹(ËT �ߤ«Ã¤Çe/…’„n œu¦}Õýõ3•hÀe'Þ6‰Šfrg&Çd²@OÌÍÓ;Âlìò>´tÂ÷QªÜ«_ri¬Èñ›6ǼŒÄ¼ø|F\¬œM•ÉV öxzŒŽÐ÷»W2E�k%>º[Àçtp°ÓG§÷ÁÏ,TL K°½=4z;ÜÄN Ûý�ïx$ÃQs‹6tÖ×|¶î-ègW³Ìå-v Ø W‰nZÜšÈ0•*22äжÁY3 ªÁÉy.�Øõ²/îõÌ] ÁÙ¤ÊhVåÙ]Qöl Ô½ÊZBpe¼Ä— y8”ð}5±Ÿ]Pñe^ØÓ˜÷ììí<ãS9^í^^èØ£¸£ú(yBÙ©ësuO‡ã)•hÀ>û5’™…ž›ÂçüÛöóâ¾XÃÄ÷ÊÔ¿´/Æ_þ°Å/ów+,½®‰f ~3ž§$YüëWûØ¿9¸¤-®,IŒ øË×ú1�ð«±y!Sq9YÔ-ú–`U|}› ÷XL¤ë¿§u?幬Ǝ!ûü×LKpåîÙb…Ÿ=ÓõUVv³ð¹üð`œ™…*¿8™b¦dp8á«K^ØÛ˜ÕÉã”ùéÑŸ]Íò»; ÝÝCE3< 9(iK{Ig6½„I¨ž?ΕuYÆí\›&ïV¢é&ǯÌâu þÕ˽Mß7éípó¯^î7¼;‘«¹f¨i ޛ̱uÀß0ñ}“§wFØ»1À™Ɇ—ð�%hf"Š“  åújÅÔ%ÀTV'´Ž³«…Z5øüò,Ûú¼üø©N\mpžßODÝÜïã�±LMuCO$ËDÃNžižÿ÷™]â!†iQ¬4®˜UA5ñ¹š{Ÿû#2ó¹úBÙêQ2[%೸4ÝääÕ9žòƒÝídxnw”Ã!~ó˜•p¶l0[¬òÆÁxÓÇôG‡:1L‹ùf�$saws-÷ ¯Dº™œÏi„½ë3¿¬˜–àÔõyv ú9¼måT?¼-ÌŽÁïMæ0QÀ÷ä|�—÷w,Ë'W+N‡Ä‘í®N6®þæõ©›ýÍíq æ2õ¹9꺛é¼NÐÞ‚.™+wH„�+båû6ÏíŽ ;9™ün‚éDQéÈlík]öËÃ!ÊUÁDjù}ù2E�ét…MÁæö{(&©|}"¯ÏS4ð¹×V¤}«˜Y(‘-VxýàÊÍ yã`œ¹²ÆháÁmÔ�\•C[——±Q/’û6øÝ¹¬eÖñxÿÂ"{;,Ürsë�x„F¾Ô$#LQ5Q2Š�€[7ºiqõî?:܃K­¸�2?:ÜÉéÙ"ú—[QÍ$óU¶µ¡¿á±ÝQ %ƒ÷Î=¾Tà£8q=G6We¬ùMJe,¼N(Wk7Õü6äTŸ×v?,…›“¶ôúZêjX*}n6÷x9³xoë—,ktGÜ5Uk4²$ÑßéáÖL™÷Ï/Ö]Ðêä�gnæøã eZ5ïÅý2¹:\µ °¤ãsÛ˜z©h&ÓÉ"Ï5ÑtßhžßånºÄ¢ä`NôÅÛ7q &<Ä£>&4þëG³$³�·2fK÷Y’K£9~¶±L*<’ˆW&WÇ6´æ]¾lâ±Ïusg&ÇÈPï*ªÍés; pu±ŒfXlhcaßhÀ‰6]áµ!‰;I•¿ùh–®˜‡íý>ú:Ü< ² …²É|¶Êõ©2)•½/ V[¶òÝ'ì”Èk·„Ö¬¨RÙ´#`êÄ´“ɯ½Úضƭàж0ÿáwÓt„½8Má!`s%�€G©;“}%ð8P™d¶ñYäµ’ÊkÄ\í›êÅ) ÊutD®YQš)PVy›ãñ¹ï¤xóh‚öÄ–åÛ x¼y$Á3;#¿2K:÷`ÈT¾T¥'¶úÏÌ=Q7ã©Övuú&ãó6xš[Ê¿‘H’xd<íèY€¦)Vu˜ñ¹wg³üùó= ,³©â7 ð'Gœ»•$Wü:Ú¢¤êt†V¿ß´¯Ã�¡ ’uFù7‚|Ù _Öéö­ž-¨,–Yûxk e ¤Utþ&©¬Ê­é ÿôÝMéǰ¡ÓÃ㜹‘¤òe^�ªDÖ@g¢hÀ‰ÛåàÂhã2jåâÝ"›Â÷’iW ‚z6̵ PX«rÔt“ó·Süøp¢)â»Ïp¯�'†ƒœ½>�`˜î&'€¶·SÆí”¹2^¬+Æq¹h†Åwòˆ.?¢•H¬:º%Õ¾µX•¼>‘a×@€ÁDó IÝÁç–ŸËc˜Wâ'�K‘°€þD�.fZö½Ÿ^Í2DÜíq¨/ 0êò꟢¿‡¢ª3Ÿ)slw¤eßùê�·¦²-ë„Û dañt¼ÈèœÊè\ó 2cI•Ëw <ÓÙ>ãO«¨Y€™eçeµš»³9žØj©û$rÑ÷`YZ=Sá E3nÉ d•y¥¿Ê¯N¥ÈÔëX/™¢Î/N¤xµ_kHÕêvPÏÆ§æ7S–äU%@Ó̤KìÝÔú˜¥ý›ƒè¦Eµ‰eðZEU·¸_…¢ßkp¨Ëä¿}4Çb¡ñ"Ì— þö“yžL˜ôû[wÞl$�ë(ÛQ»e Q‡£Ý,æ+t„\Û�Ã8Ô塪›dJís`7ŠLQ'äüú¹ï W9·ø/Ìrw¾q[Ä©t…¿z†�ƒ½‘æ'Ï6 �L=o\Í‹¼Ã!­ª0S¨0ÔÃËÃ�%‰ˆßI*·ú˜Êëô¹ü#a•°ÛͯN¦Ø¿)È‘‘%iX–àäÍ<§næx±Ï`£õ8Ýú{GU#j Ë!aÔXÀu%PTu¶÷¶¾ŒÂ}zbn&’«ßˆ0·Pe_Ïw·Òž*ºQæÃ¤Ìÿ5^äév jîd˜‚k“%>»–%à„Ÿ U»Vÿ–ÝD®+{¤fz\ºa«Ã¹\©„üí;Å÷DÝ\›,Qª˜«6´X1Q5ƒŽGôÎ :-þ¸·È¬ªpz4ËÙØícS—‡DÄM$ àùò‰¨ŸHàëàgI’XBó߆a �Kqpi¬¸jxén‰‘Pí¯;£;£kgE«—ª)ÕU~¤f½2…:Rí…0™,pk*KÈë`ë?‰�— OÁ4ÅŠÉTºÂ…ÛI™í1âaNE¦ÒÆ»ªYý.¦ÓEòeƒ�ou9µòeƒT®ÂP÷êÙõ¬ª–„ßÓ#Œ×­°Pjí ¨go$q*‚ôt‚žG”õÛÒëãù=1®O–øÃʼnˆ¯[![4ØÐ¦|Ø…‚NÀk1ÔååÔÍ»4ÃÆnÿü¹žGŠï›lßàç/^éÃ0u %�ÙÅöù“æ2‰Î,»·æ¸eíIšM¾b©Ãú^³#~%µ5³øÝ™<¯Ì±]K+f+IðæÑBÀ¥ñbKÆüMnN—éîPp|¹Ù³­Ä�¹2Ó +?Âcz¡ÂØl‰Ã�öê·’E³®<Кèw+¦…QG¶ïRÐM‹;39^^æ™Éã’yaOŒO®´~å9}+ÏÆ¾¯w .EðÄv“_žLQ]Á®œªnñË“iŽuk´  ÙšCH%CÂSGh]·9äW(Wš{œ[(3Ðé!\¾Ã÷`M·kaDÊ­™2ºi2Ðó`"é`o•Î(üúLºec©—wN§ðél­žóêJBG!X§µ».v†]äKÍÝš$3%¶÷7¦�$Á¶¾{-®Z�fX¼wn�;.ø'wY(VùðòÊ;~pi‘\®Â³]+›¼R)š ‰H}…¸ê`wÄE¾Ü\æËzMÏZé�»Ñt‹S7rM·ðË“)ºb=ñ‡o3xþÉ2×& œlòxêáÄõ7' üx@µÝË _…®p}ïn]Œ‡�Õæ P­˜‰ô:ð¹N\Ïq{¶¼ü >‚O®fÈWªÚýýÛ]·Sðâ¡2gGs+b%üàÒ"çïäøÉ€Ú¶~ k…Å*$"õ�ê`WÄÝô-¨à^]�†!�C¶8vÐà�Ói.7Ø**|t9Ãå±Ç”‘j¸£>¼zDåöl�·Ž'Ûb˜©êo}ždlºÄŸ©-máµV™ÈYÄ›¹†| º%ÐôæÒ½.ÅJã®_TM<A<¢ñÒá*_Yäêoöø04ÃâçŸÍ3:_àÕ£eó™Æ]n±J$pÏ%˜¼vTer±Èúýò^úS%þŸßLãpª¼t¨Œ{ E°8´[eÏv•¿û|žwN§›1Sª˜¼}:Í[Ÿ%9×x¡«lŸùDÉrÒµ„Jè’¨3eàó«fs‚ƒÍ‰mŸ+ é~|¸³!×û?Þ™äË„þÌÑi…‹7�Ä‚nl2Üã{lVwE³¸>UâÌí@X‚‡DGÐI¦P%^ZÑ£ùL™ ·Ó<1âGßêÍ—Êi|r%ËDªÂ'—³<»Ä¢ºoŸJ CO¼¶È§ú}‰•épÀ`�É`O! [�XÌk¤‹‹ª:躌%†‰e�ª™Ä »|}2§LE”«&çÓ2ïå€çF¢\Ÿ,¡(þêýYú:Ülë÷‘» xX–  Þ+IqcºLA5Ø»Eg¨oel#›Á�)/ç®K¼z ÆŽ K/»ò)üñáNîΫ¼}2Åþ¸ÌþØÚ½oÍÂÄÁ´ ݱ¥Ç–$@I‚¡N7©L™�®ÚK¿§²*;ê´ö¹tGÝtD+ŒlÕ˜JZ\�Ò8yS V² >·L8d±c£Fwܬ)eµrsÌǵ»þ|7 jþ¹±ËËÿüR/óñº�8Ôac×CÒð0Øé®+iü›,ÙοµßÇÙ[õ °R5ˆ¼u}O4¨ éÜ.ƒÍý›ëÛõ®ÆfÜ\•øózêʸ®…�OáŸ?ßÃþý a—`[Ð^ kåv^b놥gï,y½îõ“ÊWÐ�:š:$Ì:«k¦@QÖw~Z¾,s檃?}¶«áâ»�Ïíà=ÓÅÇ3 ÉÊÞF4 ™ëó&Ã=m [‘ìt3·X{†�ßãd.[ßì:ŸÕû×·ÿêäE/OïˆÐµ?S=$Â.^Ùã½ëûŽ×FÊô°¡Ë³¬ÐËšêv˜[¨½ðQOÌÏåñ"f�]–æ2UÔªIGdý¾³.,Sæà–PK¾oç@€ ßÅ¥E;=âq\[”Ø5°¼þ#Ëàp��t®ömhÈï"ìwóÉ•ìcÿÖ0ïž]`×f±äîZàʨ“c»£-½Ï�D9—vÚ«à÷ KNn-Xlîi£]ŠÌæ^/©ÚsìF6upe¼ÄgWÝÆ¹¢ßKóñ¸-¶®ßØÅÅœŒ®ß+<ÜJzbn>'ãû,ø(fªn6õøjîõ(–}¢ß¿)ȯÏ,²¹çû·H ù w¦²,ä« Áw \/rd{˜þ¸�S¦ ÜžQ9{'Ï`·Ì��­/)¸’Ÿñ´­¯ÄÈ�Ÿ[“ƒëwü>Î'Çö-¿ûò²8˜ð" A¦X%xxhÙä|�[ÓY^ÜcSwÜž)óþùENß,òùµšaâuK$¢/®>4ƒa½1Ÿ‘Ø·¯>·M£ØØíåókÙvß‚IyM¢?¾ü° ±iïÝàî|žhà»9|jÕàêD†ùbÏ%»w莺ø/ÌñÚS.‚�õ½Ú}›{Ø&Ý ,PUÑ€ÝTL ��1ÿWs û6/õƒežï³{0ÈLºüPcÌtªÄîÿCëåÇC.¶ôú˜JÚÑߦ\‘p;Ë>c,‡ˆßIV[ǰ‡`ÈNÎϘìjÌÑ ! xlíó26—ÿο©šNgøÑþ«®ˆ‹rÕža¿�f€·Ž ËÍÀã’ia?žUÁ˜êfk¿ï�ºåа'|xk˜ñ¹<Ö·L›NÅA¡ü觘/x\öSþ6¹ÍþE–¨3piMcI2ŸOšÚÖ8Ÿl؈¸‰‡]L§tÌwÇü\+¢=d{ZÑ,®ŒÙн¾C͆¢€Öä>�£jX´y^QÌè>¢!7�¡Æ�Ëz{�n3:ó`ÅçHÀE"êã¿3xi_GÓ¾£i슸îóqg2ƒ¢ÈÌfª\º[b ;ÄÓ{ÛcXX�xÜ‚‘a“_�La՘ȼT,!øåÉÛãQ—}þ»Vð²¹×OW¸y•šjäz~O„±ù"UMçs� �nt3‡,Ûç¿zØ6TEqMoµýþùE ÍäéX{ ?+ UrsbÚâØîæœýîÓTúÝ »ý¨U“ù¬FA5ñzš×¥v-óôþ2“i•?\lLoÃosâzŽÛ3eþ¨¯´®+ÜçxÒÉS;" ‹ù|Mwó¼¼?~q"…Ç ›úí­ÍRp:àÅÃeÆS%~þÙüCCû–‚i Þ9•æÂÝ"?¨à–í³yÒô1W–xr¸1)GßÇ’JÓ×Ëìb•¿ýdžW‡çšþ£Ö2‚SWü,d%Þx²“¾Ž¥Ç%Ž%+¼{&…at"r…>·F·o}Öâ1%…¿¾éäÍgº¿·wI£h‰Þ;·@AÓ9´;ÛŠ¯[óŒÏ(œ½î¢¿ÃÃÑáº^–KcE>¹šA­˜lêñ‘»ð¹¦E^5›S)¨;:Ž–q®£Uñd./ìmNÚoÓ2j†Å¿ÿí/ø}¶‰»¦Ä­ '7Ç8¶ôùØ÷:ñ{œŠ„aÞ ê^,茧+\+"€÷DÙ¾ÁÿÈ”§LQçãËY&’e^í×é[Í[…�_ŽÂ_¾¶¡e‰Ð- ÀdJå½óI^9RÉvò6’tFf&í`!ë$_¨ºÀ0‡„ÇéÀçuRVu†^2^ssÕ±y•_œLñL·ÁöÐÚµ^›8øow\¼údC‰å×z©•– àçÁ•gë í l–¡ðûÓ~†:ÝKÚZ-äuþ¿gùa•>ßÚ4¢_ôã øA“ÝߦåÁîÏí‰2>ã"_lÝ,³Þ¹xÛ‡ß-óüž¥�k:BN~|¸“ßN¹Ñ­µg™™ÖýL”dž­£l£h¹eYâG‡ã|pFÂ0[Ÿç¶Þ¨hpkÊàÕ˲juyHx9·ØÜþ­¦‚‹ßŽ Þ<’@®q[ÞHÚ’îÕtñÜHŒ“] ÖÞŒº’¸5áa{Ÿ¯!I½ÇvG¸¸ 7% IæÝ …ç÷EÛ}¹Y´-ßr×@�ˆ×ÏÕQ{+ÚLf’2;—Ù@ä>ÑÀ=ëꜺ6ÒtO,xéîò³{°ù÷GÑÖ;ùòþsiÉtk{¬„€Å¼Å†Tp¾ÏP—‡ÙòêßµŒVý̨ži�¿ïQ´U€²,ñ摟]‚b¹=%Ø×2MÂã”z¶ ùŠæên]–µ<|<?}:Q³;¦Y´}/ô:øÙÓ]¼wt}mðÛ�a‚¢4ös)2ú*Œ©H.~yGâ'G<í7¶]€ÝQ7¯?ç÷§,«¹Ñçë �[P®6V-EÕÀÛþ÷vI’Â/F¼x N_›zn|›!@€Í½~ö E8~Ñ�X9ÃZÕ8à�ihM™T^'âZ}K %ÉüvÒÉžá[ûc”j+êM?¼5DÔçãä…{e,l–Ooü^+¸F`Y‚±y•!kÊc4 !I|2念#ÈÁ-�-¬»\VÜ[þÊþ8>·�/®ymaè­rn4¿ü ×&KDý >eõ8p"íÁôxya_{-žcÅ à‡âXº‹ó7|¶—IÂÂÂäêÄòê°¦à£Ë6÷E˜0CŒ•œ¤Õ•߼勜�œäá�žL¬ÈüÆ–c׊e þÇçIÂA�]Ãe$Vä0W Y‰Ïzùóç{ˆ—æBøûÏ“ÌåtÔªAЫàs;P5“BÙ`0êàh¬Lй²Î†çó>fªnþäéö„™ÕŠ €i ~~ŠU%@€37󜹓á•#.§Ý<¤†DE( �ûë×áÚ]/zÅÏëã5_ëý ‹È…‡â­{6 ¿s²ks„'V˜Ÿïq¬H7Ä÷qpkˆç÷tòëOeJe;•©(Š àãñ¨ªL4P_ÜYÔ¯�­ ¬/ÿý¶“#{â«N|Ð๭b[Ÿ��§‹·>Oñäž½q»×`3p(F�Ž>ÍX³J¹Å†iqYôù̆ŸÉfu/¿—øéÓ]-©áÙ VÝô›”«&o}>O8h²w{Å6Î4˜ñ9S3!þìÙ®š?óÖñ$¥*¤s6ÄÝøÜæ2U Ýä‡}*1÷ò_7�Ä…œ‡Û%'r$A`µF‡³Ê÷ö¿;·ÈL¦ÌsO˜¸\vµµF¡›ð‹?xø—/÷®¡¤E±bò¿;Eȯð§Ïtò}ý™+ãEþpa�?ݬp,}¢ÔPøÍ¤“x<À‹{£Èòª;E=Àê=÷’z_{¢ƒC["üêS™Ål ÝCZ38°}£É»gÓ5Õ�y÷LüÉÑÄâØ5`×P�ϳ* U…)ÕYWnaÚôð7·œìÛÞÁËû;V½ø` ¬€ß$SÒùÅñ‰ƒ‘a I¶]ËEøðŒ¿ËÇŠãR¾ûÒë¦à7gÒL/jxœÿâ¥Þ‡^k>«ñÖñ~·BQÕx²%�—û |�ΰ°�9�q3VRxóp‚èÃéV"kJ€poKúáå ·¦ üà ™€ßîu·\, Î^u35ï`ÿæC]¥ªÉØ|…/î茺éŽy™M–ø'Ïu?ô:Ù’Á_ý~†þ¸‡7�v"K© ÿp<Å;\ä3Eº=!×ׯdo�9ØØâØîÈŠ�l©—Õ{z}²,ñž›º}üút’MìÜXA¶WÃ%#Ëðäî*Ã2w&àÆ¹"ÍÂë‚XXpì€NG¤DIusþ–üçSü6)§"³oS૞�ÜNxûªF_<ÀÇsU~¸QÐáÜÊÉœO Þ8”`CçÚ¬´æVÀo¢›‚O®d¸>Yà™}2±ˆ½6›Oψù¼¼ràÁ¾êÕä¯ÞŸ!äw±¥ÇÑí÷|vÍâßýj’�„‡?}¶‹/-2µ`²�UÙ>àãù=±‡n{× kZ€÷™]¬òΩ4]q‹Ý[5œŽÕ•ѽšÐ ‰?œòàw»Ù¿)ˆßí`6SåÄõÛ‡dz; Þ?-±SˆH@áÌ­Ÿ›Ù…#C.�q)ðæ‘ÕëÛ«‡u!@¸w6[å÷ç3T �§F hO Íz¥ª99yÉ�n^Ú×AWx}Ö„]·¼ÏTºÂ‡—‘{·JDe{El"jÕÍåÛ2ù¼“c#Q6v­Mëf­¬{ÞgtNå£ËÀäÀˆ…U$Éξo(¼\¸ UÕÉs{¢ ­sáÝÇà·˜JWøüj–t±ÊÁíºvþRB&�ñröš…ËáäèŽýv#žob ð$³UNÝ(0š,±{³ƒÁ·ËN®Ms16«péŽ`¸ÛÇám⡵>ÖHl>†RÕàÒX‘ £\.صI¦»£‚lû@ 7Wï E{7Ù3XwVÍz±X“©{q�wfËlp°©Ï$¨®Û³¢@&_p36ëàö„ÉÆn6éo`?µŽ-À% ›‚ÛÓ%®N•™ZTÙÚç` ×$ä_ûbB&_ô0>+ssÂd îaç`€áßCã?m¾[€ËD3,nO—¹5«2ž.3Ô-ØÐ# j(ËH<]IT5é¬Âè” ½(1�ð°µßÏæÓl¶ˆ0—©r{NetZE³T6t;èé´ˆ «@�BH¨š‹lÞÁl&ç ./ý6w{éŽyVE½ÍÕ‚-À&b˜‚ÙÅ Sé*é*é¼JGÈ¢;. AÀgârHípü ÃRP+òE™L^"•1YÌKtG= vºé‹{艹í­e±Øbò%ƒT^'•«2—ÑIå«T4�°_ ;>·ŒË)p)E‡ÃÂ!Y IÈòwϘBH $2ÂKȆ„nÊhºDU—P5PU‹\A°X0¨T%B>'‰ˆ‹®ˆ‹Î°‹DØIзæRDW4¶WåªI®l�+äÊ:EÕ¤\¨Uµ*(k&–%Ð ��–!0¬{�N‘%dEB.EB‘%<.^·„Ï£àuÊ|2aŸ“°_!ìSl÷À Á �M±MX66mÄ �M±hcÓFlÚØ´[€66mÄ �M±hcÓFlÚØ´[€66mäÿ]êå~JŠ%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--5dia2xrljuq.png000066400000000000000000000515071524103652300222310ustar00rootroot00000000000000‰PNG  IHDRjøÅ¬ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ü’ŽuR'IDATxÚí½×sciš§÷œspàAAÐ&™†I2½)“U]ÕUÝ=3ÝÓ½Û1;;kB³±ÒJ«ÕîèFwú3Š�b¯t±’vbgg43;v{LwùÊ2é 3™ŽÌ¤ ï�ÓÅ@fÉd& G~ODI |p¿óž÷{ß÷'Y–e!‚¶Enõ�@°=B¨� ÍB-mŽj�@ hs„P A›#„Z Ú!Ô�@Ðæ¡‚6Gµ@ ´9ŽV/@pp™Y.ðé­K™2X »øðt7‡¢îV/M h+$ÑB.hW¦ùÕ�º¹~™H2üÆ…çwµz‰AÛ R‚¦³–­ð÷/ˆ4€˜&üÍÕURy½ÕËÚ‘ú4�[O²Ø²,m~Kâ³»IÞ8fGÕ.UF’$T(’Œ¢H¨Š´ãÇ:!Ô‚¦³’Ö1Í­…Ö´àöLŽÛ3¹mïG’Àå°O m1Õ!¡È2Š,¡*ö�Üjõ6 I–PeP²,ã”e�©ßÆ©JÈ’„"ƒªToã°×êv*ömömŠýŸ`ÿ`YO—1MèîRq:Ú#é „ZÐtyÛx PU‡bItÝÄ ÃÂܰ¥bYPÒìüIíg+ØxÀp;íŸ;:`8dÙÚpÀ°p«öÁ ~àQ샆R½=¸]/0dp´‰ t2×gùèæša"K2–iqöH€ž�´ü€,6Mc5£ñå½wžfÁÚúƒ/ËoOƈ†<[ÞÆ0-LÓzîwÃ47ü^ýim¸�a=[ký¶€ý{í6–õ�ûìû°,tâ¿:ö�Á~mk)"EUQêg öåò ·±(Š$¡* ÇúÙ‚C‡"ã�¥õßë�Q»oû~œ Yî¼³Œ/ï¦øl*‰ñÂñÞ¡Èô…U~÷ä>-Q ÎZFã‹{)î>ÍaY INUAÓ Ì´N‘e"A×¶"mßNB© ‚ÚÂçöâ�Á¾¬™ “�Ç cÃý m\is7g›yÀ¨ÝïÆÇu:@–wv–‘.h|:•ÄÜä¤L7L–R·Ÿf9=hêk¸!Ô‚†±–­ðù�Ssùª@Ã`ÔÏøp�ÓÁÍG«ÌÅóØß1 ôŒz9s´§ÕKß1µF;,LËx€Šnë‘Mð-ËN%h† 覉iY˜¦}�Á­v›êßõû1-tÓDª?ß9XÔÖÔê†,ƒS‘AZ߃¨mL;pȲ ù²ÅvçFºnrg&×R¡©Áž“Ìi|>•âÎl®.ÐýãÃaÞç%­¤¤²eÂ~®ê†� ó¨0¬jj ¢Ï]W?`˜nc˜H–-ø&ÕëLëùF5'a&¦fõlÖo³Ùc¯èîRù7?jÙk+"jÁž‘ÊÙ9è[3¹zJ£?âcüPˆ.¯sÓãVúº½­^º`ؘŽrV�ÇÞHLý P�ê­ Ñÿú™�aÙ…åd‘…ÕüsÕÏ#Ñík­T ¡ìšL^ç«i®?ÊÔ7c¢!“#aB~W«—'8`l<`ÔØ.ˆ†<,¬åÙ*ÿ¡Hg[Ü)+„ZðÚäË:ßL§ùf:[ÏGFC&… „@ :§ªpöh7®~'ª–e8Öïel°µg}B¨¯L¡lðõtŠodëyÆî.7“‡ÂD‚b ’ óîõãRn?I�+Vê—wyüÖ;±V/Ol& vÎV=q(L�hÁ>AÓMŠ��®Ïƒ¿÷ÓaºDŽZÐîÊW¤ùæA†Š¾Q Cô=»¼w� ½P2ªÃI4è!ž*rw.Ï¥ñ`K×$„Z°%¥ŠÉ7Ó)¾}˜¡¬U:àbl(DLTjö9CQ?ñT‘[3!Ô‚ö£¬›\{�åòýT}†F8àâ¸hÁ¢?âåæ#‰µŒÎJ²Lo¸uäB¨u*ºÉÕºËëäø¡_«—'4‡"Ó×íe~5Ï�gy!Ô‚ÖRÑ,nÎdùb*I¡,Z ¨1Ôë·…z6LJ§»[6˜Iõ¦&Ð_ÞK‘/Ù­¾¯“q!н!.§B®d0»R`4ÖšÔŸêˆaXÜšÍñé�d] ý^•±¡C=þ–ŽsÚ I’ˆøx²˜áÎÓœjAã1L‹[39>»“$WhŸÛÁ±Á‡b!ÐÁ& õúy²˜áþ\�߸`µÄNõ &ПßM’-Úíu; q(æG -lIØïÂïQÉ5,ä91ìoú„PïcLÓâÝIÕ]½½.cCB ‚Wa(êçÞÓ$wfsB¨{ƒeÁýù<ÝJ�ÊÙíq98:d´?€,Z x%jBýx©H®hà÷4wnºê}DM ?¾• Yh·ÓÁ±Á #}�ïŒ~;Ãëv¸IfKÜŸÏqñXs;…PïjýÉí$‰¬í{äTŽ 9<Ð%Z ؆z}$³%nÏæ…P ^�‡ >¹�d%m�f-4†¡?w'XL”YËVˆœ»¿Ó"„ºCy¸PàÓ;I–Së}¸/ÀÑÁ egîË�`稙ް‡¥D�;Os|ÿdwÓ[u‡1³\à£[)–’¶!¬Ó!s¸¿‹#AT‡h� ‘ õúm¡žÉ ¡|[ “,%íÚ¡ÈŒö ¡ŠZ h ±°U‘ItæVK õ4Ç0Cu›3³\à£ÛI–B ‚V£È=>f—³Ü™Í ¡>èÌ­–øäv’§ñ°A C"Å!´�¡^?³ËYîÎåùµs”&´” ¡n3æV‹|z'ÍìJE‘‰Ùír6·È^ |—H—¯ÛA¡¤óx©Ø‡r!ÔmÂÜZ™/§’ì'xµF˜}!Ôc•éù"²,ñÖd ousK˜ÊîžT®L*[F‘%õZ½œ}‹$±¾�ºƒtf-R/Ul±Ö4“’¦×E¾TÑ«—õ¼zŽ—çÕÕj.ÝítÔÓ.>—Zÿ½v¹àåè†Éüj°›ì/x²bñÍý?:åÂØÎ¿O/Ô_U‡ú¼1ÞK·˜7±§1ŽtO©è& Õˆ`TTËt$Š"áSÔ•PVt“R¹¥ë”ʶˆ«9v;—n§] %�Bik1—% �Ër¯Ë�Ûe »-èöê>Þ-UtV×ç ½ˆeÂ'·Œþp`G÷×±B=·ZâÏ¿²Go 2º�ªÚ…ÙeÛÀ7pò‹4Ò~ÇžÃâ¤k›Ùd–eQÒ6zeýg±¬S(Û‚nZù’N¾¤³¶Å}©�Ë�ÏíÀëRíŸn¯Û�×í@îà„y2[A‘Ÿ/jxîu–•ß_G õZ¶Â}¾ŒaZ öø˜énõ’ö–e×Nƒ¨=¬#I’¿$µQªV³Ë:ŲA¡¬ÛW½\Ï�WÈä7,·³*ân>�Šß£ð8ñ{;î-k‰LÃ0éò;éò6+àxù3ùfÓtœPçŠøé2¥ŠI¤Ë͹±¨Ø©n+©ù’ŽKUˆŠñ¯‚WíÚU&!ÿæ{F–eQ,äK…’N¾¬S(iäKöÏõÍR�µFøH’„Ïã àup«|Nü•.¯ZpË‚©Ù$�ÒUA´0-»Àà�‰ØK4»%pc¼d�Y¬{ç�ŽêŠfñGŸ/‘Êëø½*oMÆÄÄ´QÛD< tô)¨ =‘$©žâØ Í0)”t E�|Y'_ÒÈ4²…Š]ÁRÐÈ47üY’úœ„.;å’.bZæÁLç*|vs�œlhÓ�Û©ëö°”(lz½,ǧB;¾¿ŽêZ­ôR²‚KU¸4Ù'ªD¡¤O‘$é%y‚æ£*2AŸsÓÛrÅ [¬�-jäòšý{A£¬$se’¹­G›Õù.O3Œ …¶þ²f�)Ø) P$ Ó²Pd “Ÿ\Œ2Ô³óæ±Žê_\[ãáb‡,óö‰Ø–GbÁîy²˜Å² ¯Û‹×%^gA{a×›{è >/tŲN*Wfv1K<]Ü2Kl˜ «ù† µiY|so…BI§; òáé03KŠšE4èäÔˆŸ.ï«}¯:â[xy*ÍõG$$.ND·Ì{ v�í5iץ粒‚ýO­ì/[ÔXͱ̭o«æÎïø¹þp•D¦„Ç)óOÞ‹ö«ÜÝ>OÛ õÝÙÝNpæh„XXÔJoF® ±˜, é^—Ê@Ä‹S}õ “ùxM7ñ{ö\Açâ÷¨H’ l-ÆþULÏ¥˜[É!ËðÛïÚ"½´µP?�—øËoíZ鱡�È—n‚eÁíÇ«Ì.ç�òP™;OÖ8?e çÕŽä3Õ’¼Q’'èPba/Š[MA‘%8Ú€³Å…µ<÷fí¼Ÿ\ˆ2ݽ³K}Í�x¡ö‚µŒÆ¾ŒaR­•·zImÉýgIfWr˜–…Qmƒ2 ô¸ú N"SÚößˉåúï‰l™T®bÏõˆúž»N èYâÍÉŠ"}§bI–%Ž „öül1•+smÚ*/M9sØ¿§÷ß–B�+êüÁ§K”4“ž ›óÇ£­^R[¢é&�æÓ˜ææÛ&–iqw&¹å¿W¿ú\ùPžN0[�¦‡zýø®ü®¿ú¿Qž=hõÓ^™H—›]¦?âÅé�ë½Gú»81º·A_±¬óõ]»o|ÐË'÷¾¯íRÝä�>["SÐ x�¼9u¼[�Η±Ýl¶j ‘-ñp>]gév®;Œ`Y`™8?þS ïýœù¸}ªvvñ”Ç7ì‘nÆÎý‚vÂíT¸8Þ ÀÃù4wg$³å]Þëóè†ÉWSË”4ƒXØÉ?x»·! xm%Ô¦iò§_.³”Òp;.�ˆíëÁ-»Å4ÙчâîLâ;—É’„S=Á…ž<ëÓx>ý/ Å.Ñ_^Å“z€%IÞùÒÈâ0)ètõú¹7›d-S"WÔð{v¿ÉgYpe:N&_!àQø�ïõ¡îÒÄv+ÚJ¨ÿæZ‚ÇK¥j­tQû-AŸsË¡/5œªL_ØWqYw©Û#-K�/‚ç¹X19–yÈ¥å/«ñ¹ÄåÞK<]öÁòLÝ´ÕUm v¹”úày·Z›S,ì¡í‹SUèëö²°–gv)ËÉûOOÜ�I°œ( *ÿø½>žÆµ¥·�~1•äúã,’$ñæD¯úÿtÃÜ4RÞˆ,Kœ>a0úüƆe±ÁIDgiíC¢ßÆ VÒÌE'Yí9‚R±GZÖ�º_‚"K¸�ëîvÙ®!µ™Åµ¿_Å]\ Ø+Fú,¬åyÏ19ÞUJuv)Ë£ûûòó·{é 5V¯ÚB¨ï>ËñÉí§�t ‹úÝíHeË\™Ž“/iH’„K•Ñ s}Œ$!KöÔ»Eºzu}hNÐçD½ü‹ºH ¯N›Ã�Ä0­º Ûƒrª£-5ƒRÙØàùg‹z¾¤‘/½ž“ˆ[u ª²½¶êìb¥ öŠhȃ׭R(i,®|ÅÒÕké·ÛÃ[?<fl—ã;¡åB=»Rä/¿¶ËZއĀú—ðx!ÃÝ™¦eáu;¸0%p1Ï3ÏSÖì�U£±."ÁÔq~þ× Æïc!Qx÷g¸WçQ¦¯áüôϨŒNn;<§†=CÁDÓ�º=TÍȵT¶ÿ.Uìßwê$57‘ª W£rU‘Ÿxá("Ø!‡bv®úéRöµ„:WÔøúÞ2¦eqf$À¥‰PSÖÝR¡^ÍhüÉ+v­tÔÏÄ!Q+½¥ŠÎ•ûqÖªuÑgÇzꛭý~†{_­vS½ü �n`!1uü‡>vŠÊ±S8á9±6F'_z_²$Õ«J^jµ!J¯Eæ[ùýÙn":…’þÒÇw:¶wåv;m»¨�Î2~]4ÃäþlŠùÕÝÄ¥*îósd0$¦=¶˜‘Þ÷Ÿ¦ˆ§‹äKÚŽœojhºÉWw—Ñt“¡?~#Ò´u·L¨3Eƒ?ød‘’f y¸0ÖÓª¥´=‹ky®?\EÓMTEæÌÑȦ)�WÅBÂB⋾wžÚÓÓö™¥ iW7§7Û�¤Žiع+wM¸ËÕÜyY7(–íª–buS´\6ìÍÙWI»¨ .UþŽëôFLÓbv9ÃÉÑnáJÔB¢!~¯J® 1Ͻt_ìá\šÙ¥,²ÿè�XÓEZ Ô}%ÎÌr‡"séd ·³åû™mÇ£…4S3I{ÃÐåàÂñ(Ý]{7à ‘)‘ÎWp(2C{�FélA— °ýYI-�^ÖtJs=ÝR16\n§bj5é¥x•†…¦¯5ÙP°wéróÑ*�2Û õâZž©§vì�/ö0Ú»·ßÃ�ÒT•üôv‚[3ùz­tóŒ&;ƒrÅàêƒ8ñT°‡Q�9ÖÓ�3Ž'KöÌ顨O8ålÂNóè–ÍìD®Ì­‡kX/16UÄdËŽú™šM�+j¬$‹ônRœÊ•¹ú ŽeÁÛãAÎnÝôΦ}bî<Íòù”]«{îX�˜uüñT‘�¯ÏOQd‰S‡#\ïmˆH—5ƒÅÕ<£Â`WH’½AÕås2 ¼´™'Òå•m€¢HŒÆlá}¼˜þÎõ%Íàë© ÃâHŸ—O·v_¡)B=³Râ/¿Y`âPø•ËÈö3†iqûÉ_ÞY¢¤ý.>'oïÅïmîôÖã5ž,fˆøxc¢·Õ/Ë�Å0-¾¼³D"SÂãrðþ™~ÑOÐ"·/£^ýè¹Ëº.]"òᇭ^Úsìy˜ûÑíwfíZé7&z¼H犟Ý\¨‹ôH_€÷Ï 4]¤uÃd®º‰uXl"¶E–xûDŒ ÏI±¬óå�%4}ç­í‚½£8ñK�áúß©®XÛ‰4ì±P_”árµVúü˜¨•ž]Îòñ�yR¹ .§Â¥}œ=ÚÓ’:Ú¹xÍ0 x�;*h(ªb»yݲ�¯î.a˜M»s ±,‹…Ï>£/û¬~Y(³Ì“¿ý´ÕKû{&Ô�‹üâš=LûÄHø@µ%¿ˆf˜\™Žsãá*†a yøàÜ`KwùgªåG‡û[×]%x·SáÝ“}¸œ ‰l™¯§–7æ$h Ë_|ÎÄÓ/È�¿É³ÃoÛW\ùœÔåË­^Þsì‰P/%Êüéåe,Ë®•>6jõój‰l™O®Ï3Ï!K'Fº¹t¢w g;¬¥Kd ö\�Ážƒ{mG¼n•wNö¡*²½Ùü`¡Õ�'ñõ—~ô™co ¿ý#üo¿ÏÍžs$?ú¨­Äú•w0n<Îðíà ©œ�Ë)s¤ÏÓ…šn {l­´eYL?K1=—²ÀïU¹x¼=¼Ÿ,ÙÑôp¯_ÌõhCº¼NÞœŒqùÎóñªCæÌ‘ƒù=j+É"ÉÕ4ƒÀêáóøÞý5ÜN™c¹aYœ]»�e¼Ü'´YìX¨- þøËež,Ñ«Þ|ZÑäÖ“,ö‡íâxô@ÖæÊ:W§ã$ªî+ý~Îéi‹ñ%Í`q­Øg;‚ö¤'èæâx/ßÞ_ff1ƒ×éàØP°ÕËÚwd ®L¯ Çq bôì‰ç® òQ|‚5oÿôüùV/·ÎŽÃ«ë�3ωt �°ÿwk¥Öò||mžD¦„SUxk2Æù±hËEÚ´,Še�™Å,–eÑôÐÕѽ`kú#^N±�ŽîÎ&˜]ζzIûŠrÅàrÕJ«7ìaä̉ïܦËç¤'è!îìáÊÃöyýwQ=�úŽH×°°ËÐ2ùÊ�M7¹õd­^òÖôpþxO‹MV˃[OÖX\+Øã6«oYD´‹w£}Ê�ûÏRÜ|´ŠÓ!Óy=·lÁ:µÎÃbY'àU¹8޻堥cƒAVÓE®?ÎðΉ ®6Hîx©üöùY’È•´Þ[g“È–ùäÆª"Õ£k ‰ÉÃÝûr}Í}åÛû+h†I8àâƒsƒ ´á措ÊÈ/É¿–…»ÅytÁ«áPd.�ˆá÷¨äK_Ü^B3Ä\�—‘/é|}oÓ²èñ½–aÉh¬ §Cf5£ñ`!ßÒçóJ!a_ÈÉÿô›Cü³ïÇ81jw¸…»ÜÙ‡"�Ê•ùøú<�2H’Äøpˆ÷N¼Ôì´UÈ’D4ìÙV¬=NÇŽòs‚ö©*öfµËA¦PáÑj¾-šnòͽe*šA8àæÂñèkÝ�¢Hu‡ò/§ZU¿ò¹»$ÁP�‡KÇCdóå}×òúx!Ãg7É5¼.ß;ÕÇø¡p[lnÇé#EÚr�¥ŠQw8t—ƒ·'c¨™Õt‰+÷WöÝ÷n/¨UÊdò¼noOö¾ôLs;Ž Q‰…D™gñÖUß¼v’µ; âtHh†I~Ÿ”åÙñKÜ~²fŸ2E||pn�î®ÎØ$õº|ÿì ½©+Ù^}’$ô9é y0-»‚ Ö©(è,º|N.�èCQ$× Ü|´Úê%µ·¯±œ,àPdÞšŒáÜ匧CæP¯ÝÑ{ù~ªeÏëµÏƒ% baÏâ%Ò¹rÇ»T,% \¸JE3p(2'G»›ê¾²WøÜ¾wºŸŠnR(é¸� n§‚eÁõqžÅs|{…sÇz„|¸xc¼—¯§V˜]Îâv*Œ ·zYmÁã… O–2H\�ÒµG³ð� ™YÊòh±ÈRªB_¨ùM}»*[è¯.8•ëÜÏÚ†á×SvN+pñÁ¹�Žé�82!¿³¾y(Ipn,Ê¡˜íÙwýaœ§¢E¹#‰…½œ?f·šß–ª»ØdV’EîÌ$8}8B,¼w�¸—ƒ¡¨]@ðõ½TKžß®„º/l×$¦ò�iÒ™-TøôÆBýƒ~d ‹÷N÷ãswöÙÁVHœ;ÖÃÑ»ëíúÃUñ%ïP†zýœéàÎÌ «­­Jh%Ù‚VÍÙ[îïjHÚØ`I‚©¹<É\óS½»‹¨»m¡Nç*·±1»”å“ d <.ïžêçÔáÈ®6:…“‡#õr¥ÛOÖ˜®6:‹cCAŽëhñäÁÛ(®h_M-£&Ѱ‡S‡»ò8~¯JoØ‹eÁך_²+¡T\NÝ0É;#ýQÖ ¾º»Ì�G«¦EÄLJçé9`öT‡ÂõˆìÞÓ$wg­^’à58y¸›C½LËâ›û+¤r�yvû:Ô-J~¯Êã½ ³\ nn>Α+6·ql×­u�”§Ž§Š||mžådE–8u8›½v˜þ±¡`}@ýù4·¯µzI‚×àì1;'«&—ï.˜á[7®’È–qª —&c Ÿ5ö»ˆt¹1L‹o57e¸ëgÖ×]êö=’›–ÅÝÙ—ï.QÒ º|NÞ?3À‘�ýרóªŒöwqöh’O3Üx(¬ : I’xc¢—î.7ÍàË;K÷ù¨€ûO“ÌÅs¶£ûd/Þ&í+ÕÌ®>ÈPÖš×!ºë6µ¾°È�n±P§reÎ¥IæJH’DoÈ˱¡ ¦iqåþ é¼ñèâÄh÷�ÈE¾EâêƒUf—³è¦Å…±žéÖÓ©(²ÄÛ'b|~k‘L¾ÂWSË|ïTÿ¾<[\XËs¿º¯röhá&ƒ‹…½}NÒù ×g¹4Þž]¿‹±°Q§ó{r ˜]ÎòÙÍEyŠeƒBIçér–_^™ã£ó¤óûôèDß�Ù0|U£~Þš°»¸æã9¾©ÎItª"óö‰>¼n™|…Ëw—0Œýõ¦såú¸ÞñáC-è8ZÖôõýºÞœ¨z×Bö©x\2†i‘-4?7–-hÜz¼ŠiYÏ�²›–eÿgXô„ÜüàÜ ½aOÓ××Iĺ½¼5C‘%–¾™ZÁhƒY¼‚�ãqÚsAœªB2[æÛjÙZ'’/iöÞÉ£5ΧYË–¸<µŒaÚ]íjôìñãu«Ê&·Ÿ6§,rO΋b!»L/Ù‚ôÇÌRfÛœª,I Eý¸ÄÔ¸Ñöðö‰Ef9Yàë©å}•íw|n•KÞÃ;o“øþÓ$¿º:ǽgIž,e¸ÿ,Éç·)W Â~ç_sÐÒ^ IptÐÞߺ|?Õ”=�=êþê†bº•©ìöC¡,,2ùƒ± ¾Wô=¼sÒÞE�§Š|yWŒÖì4B~oŽÛ©¬§+Y¦f:§ürf)ËÃù4¦EÝ]Å0Ö­åFb¹µéËC½\N…TNçÞ\ã£ê½êv(*Žíß0I’p´øMíDÂ7O¡™_Ü^¢Ò¤|œ`oˆ†=œ³+z̧y´Ðúø/ò`j6±mÊíþ\ªÕËD‘%ŽTG ^nB[ùž u&WiúT_Ø·íÑÕ4­]OÐ:¨„ü.¾wª—S!�+óEõÔSÐ9 Fýœµkåï´þóÛ‹û¾Fw¿qd ‹ãC!Àžï²œl�1·ù’ÎR¢Àô\Šoï­ðË«s|rsþ¥ßSÉ’h‡mU‘­oûr*ÕÐÇ’¬=R¯?ül‰G‹EÎíiúä¹bYçë)»#ËÂvu´€�ˆY‘xºdO‰ û]\�6­8~?Q(ë|y{‰|IÃëvðîÉ>ñ:v7­2»”E‘%Þ=Õ×´úcÝ0É4²ù ™|…t¡B6_yí}Õ!ó›o�4ó¥Û’rÅào¯<Ã4-~÷Ã~†£�yM÷L¨?½�àó©4#}Îíiê‹Uc-S"•« HÐt×çÑÆSE®>ˆS®tö¬éVS®Ø]o™B—Sá�}tùš?›WðzX\¹¿BfiKuñæ¹Ñï¼R.N7–óõ§T1HçÊd Ùb…T®lP›¨Œ,Iø<B~�“€W%pñp>ÓŠ†ù]!—e‰ÉCáz-s;pëñO3îóðÏÞïkÈcì™P?XÈóÿ}¾BÐçäƒsƒM}¡vB¹bpíaœ•ꄱ�ˆ�³ÇzöeçV#Ñt“/ï,‘Ê•ë^~A!Öƒ•M!ÿåÿKIrðåÈ�xëÜẨ”MâúÅïc¹½T~ýŸc¹¶î;ÐtÛÙ)[ÔHçʤr•j~yó(Ù­*|¶ý.B>'~�sSÛ8Ó²øvj…•t«Ú!I¶‘ö`��scѶ²Å+–uþþʦeñßþÚ@}Ïn/Ù3¡Î þ�¿xŠ$IüôÒHËËg¶âñB†»3 LËÂërpáx´c¬¶ÚÍ0¹|g™d¶dwÃ�ì£;°÷NÁÞ#åÒ8ñûÈù4)Wˆ¯ÿ:o�Å]ÎàúÅï#²˜Ý±ç„º%§6DÊ;‰’ƒ>—-Ì>çkmè/% Ì­ä(Vt¼.‡zDÛ´iíúÃUž.gq©n§Ìä°�K!\êîƒÁ=j€ÿó/ž’-¼v€°¿}¿¸©\™«ÓqrE I’8>äøpû›×¶†añõ½eâ©"Š"ñÖdŒh°=¿D‚çÙ(Öµ‹©Ñ÷xsþSäB-eæÂÏIé2©\…t¾¼eÓ[Uú]|*¯sÛ(y?cY_Ü^b-ó¼ù­C‘ñº$þåñ{vWy¶§BýÇŸ/1½PäÌ‘HC\öÝ0¹õx­^®érsq<ŠÛ¹ë9UôøæÞ2+É"Š,ñÖD¬m#Á:–eQZMàÿÕÂYÊb"!c‘t…ù¸ÿÊÊóA–ê� x�ty�}N>']^GƒÇŠv æÒL?KnZû-Ë0uóϾ߿«ÇØS¡þb*Å'·“ ÷ú9?ÖºÏWa~5Ï͇«h†‰ê�9w¬‡þˆ¯ÕËêLËâÊý8‹kydIââx/ý‘½ó«쎊n’É—Iç5²;�œ-T0L‹hq…,|„„…!ÉüíÐ�Ñ»"}Nºªÿ¼N|n¼lÇ/¾~Jy›ºnY’ø·?¦kQõž¾}&éu ƒ=>Â~W¦ã$³%¾¹·ÂH_€S‡#m›go'dIâ�ñ(×HÌUÎ/Œõ0çÍIJì¡hÙ‚]þ–ÉÛ%pÅ-”ÂVžwW¿BÂÂ’ÓàÝ¥Ïy4ðs&Æ{[ýt:ô¶iE±HdÊty^?€Ùc¡®v(*†…¢t†ÐyÝÞ;ÝÇýg)Ì¥˜]ʲ–)ñÆñ^Q~¶$IâüXE‘˜]ÊrõAÝ´‰‰ÈFPÑ Òù ™B…LÎþ™-h›vKøKD°9£}]8d™kWy²”ÁÄâÌ‘ž}'Ö¦e‘oq”¼×œ;ÖÃr¢HE7ª™×õÁý%Cç³Û üÚ…a1‚»�n5]D‘áGç"vÙܲ{.Ô.U&äw�Êédò"˜§~I’?¦;èæÚtœl¡Â§7˜éæÈ@{7ö´š¡^?’,qu:ÎìR]7¹p<Ú±§Î/FÉÛ Ú,Jù]a —Ê•ÑÍÍçvXØ�©�2Œ µz©-gºêˆ~ú°¿!" j€¾�“TN'™-ï ¡® zøðÜ ×Ø3}o?Y#‘)‰áN/a°Ç‡,I\¹¿ÂüjÓ²¸Xµ‰jWtÃ$[ÔÈäÖÇrf¶Íév:ê]{Ájçžß£vì)ž.Á6»W¦i±œÌx¡Îä+,% H\oœÙnC„º?âæÞ\�t Ìn�SUxûDŒÇ ¦f,¬åIæÊ\‹ Ò^ÓñòödŒ¯ï-³¸f›æ¾9k‹ÓýBI']M[¤«µÉ…²¶Å.¾„¿:×"àµë’ƒ>ç¾;P›¦µe¹ÙÆÛtÎÛöf“C>B¾Æup6F¨kŠ-0»mGºˆ†Ü\¹'S¨ðÅ�E÷wqr´»c£¨F {¸t²�¯§ìù —ï.ñÖD¬i"§f½.¹639�+oéù*£9÷AŸY’0¶( “$©iÆíJ¾¤3·�mß™ 5ô±“ú¨V~äKšnî»h£FÀëäý³LÍ&x¼�áñB†D¦ÌÅñ(>á~²)‘.7ïœìãò�%ÖÒ%¾¸³Ä;'û°L‹•T‘²fÐåu ¹wuÀ{ÝöµÑœ]>ç®»É:™X·Õ¡`T 6Ë�Hpà›™ͧ°°ð 6¶° !BítÈD*kY�T®L4´'ª)²Ä©Ã"]n<Œ“Ê•ù䯧Gêó.6#äwñ½Óý|y{‰t®ÌGWç)ë:Š,Û’`�C‘xs¢÷¥MS¯3À^Œæ|9²$ô;)% uk;°#iI²8w´ç@—ç•+O«“7ßoü«aI•¾nkYû˳Ÿ…ºFÄKw`ˆ«ãÄ“¶õ×R¢ÀÙ±žŽ/Ql¯“wO÷óÉÍEJšÝ½Q\ ¾¸½Ä‡çñ{U,ËvÒ°»÷Ö#ålAÛôþŠŒß£V×»êé ç>=»Ûkž,fXN�%‰á^©|Ó´\8३�Ò˜¦ÅH¯‡¡žÆ§€&Ôýawfs$;h’Þn©ùÖ\dÖò¤òe.�ø|ÞfxœLskƒSÓ‚ËSK¸�1À¾‰¤²eî<±»JO‰Ô�¶6šn2S5Ì~g¢9å¹�‹¨ÃöiQzt(¾*Gºw¹¸r…BIç³[KuCN!ë$r%¤çN¬_Ä¢PÒëCˆTE¦ËoW[½NºüNº<ÎŽ™ÒØ hºÉ·÷W0-‹Á¨_ˆô&¼n•X·Wˆtx8—b9YÀ¡È¼1V[›0»œ¡¢›DºhÞ€¶†¾ý!;/›Ú‡�/¯ÂP¯ŸÎ ÒÝ妢|=µÌµñ-s®Ÿ[%poÙ¡¨Ècƒ»¬Y¬eJÜ{–àô‘È�®èØ Ë²x´�à�‰PSÓ˜ êú$½.Ô^—ƒï�êc|Ø~ƒŸ­äøøæ|GÙ–5‚ ã½8Uå;ŠŠ,Ñ×íeDäHN¹bpåÞ –‡ûºe¥›òt9G±¬ÓåU81ÜÜר¡B‹ØŠû±•üu¨ wz÷T?n§ƒ\Aã³› <®¥"§Â/ rt0ˆßãÀ¥*„»Üœ‹rQx÷5˲øvz…’fô99qXÌ ß ËZo¿4ܵÀ«ÒÐÄ_¬KE– X1(i†pH©éróƒ ƒÜ|¸ÊüjžÛOÖXN¸0íˆÉj{�C‘™8fâPó6g6S³IÖÒ%T‡Ìm2{¥YXË“/ix]2gF›?1³¡µÃ!×[+b™Þv¨ŠÌÅñ^ηMaã©"¿º>ÏJu¹@Ðh–“…z”xîX_L ö �æS¼5ÂÑ‚rІoëöw×4 ¡ÞŒá¨ŸÎô9©h—ï.qûÉÚ¦. Á^Q(ë\›Ž06¢?",æ¶b9Y •«àR%ÎkÍžIÃ…:v&éí¿Gåý³²b/døìæ"¹¢¶û;^À´,¾½·BE7é º™8à3¥_ƃ9û¬ãÂÑ .µ5%‹��¨EåÇŽ�%‰#Ý\:ч[UHåÊ||}þ@o4 íGk¤re\N… Ç{ÅXÞmXM—HdJö�°ã­ssj¸P÷�(²DY3(–õ–=ÑN!òðáùAba/†iqûÉßÜ_AÓÍÝß¹àÀ3Ï1»œE’à˜è’}ª¹ésGüx]­{­.Ô², ÚÅó"ý±3j.2§G�%‰ÅÕ<]Ÿg-SjõÒL®¨qãÑ“‡ÂbªånHç+Ä“Ed Þ<ÞÚÆ«¦$\jŽ/¢žúÕ82ÐÅ÷ÏÐåuR,ë|q{‘»³ ,±Ñ(xEtÃä›{Ëè†I,ìåØP¨ÕKj{ÔLkGý[ܩ١®u(&óB¨_•.Ÿí"sd Ë.ºŸKóÙÍÅúD9�`'Üz¼F¶ áq98<Úêå´=¹¢Æb¶Ùz« Æ/£9B©ÎüµÔ¯EÍEæÍª¿`2WæãóÌÇs­^š x²˜áÙJY’xk¢W˜'ì€s), Ƈ}D­7IhÊ;ÖÛåDU$4Ý‘à.è�xùðÜ =A7šnre:εñ-m§‚çMº ú]­^RÛS,o0­mƒhš$Ô’½!Ñø²x\Þ9ÙÏ©Ã$I²‡;]Ÿ'!ÎV/`Ì«&=>FûZW^ÖI<œOcZGúÜô…ÛãÀÖ´s ¾îj+¹ê]#IöFãûgúñºUò%�Ïo-rÿi±Ï(¨qíAœ|IÇïQ9s´§ÕËé*ºÉÓ•šÍVûÌžišP×_’¢DoÏù]|pv€¡^?–eqÿYŠËw–(UŒV/MÐbâP, >„ &•+su:N®¨!ILJ‚‹×½ È4>º>�¹Å×TuÈüúÃ8”ö�Û‘d®Ì§7Pdøw?ÆïiïrƦ õN°,¸ó4Ë'·“d ö`¡�ßÅÉÑn"Aå5Ý0¹õx�g+¶AOÐÍù±(W{€÷;·¯1³”Ù²‹WQdΉ0ÜÛžeeíÊWSË,' œ;ÚÅO.´w4 MìLÜ ’§Fü›Ÿ óá©n\ªD*WæóÛ‹|=µL®(*…C‘9?åâ¸=Üi5]â£ëó,®å[½´ÍËF-˜†)º{_‘L¡Âr¢€$ÁÛãí[鱑¶Š¨_¤P6ø|*ŵGL$$FúüŒ‡q ›û†Q(é\}'Qu=é pêpDì4‘T®ÂÒZÞ»¹Mùª,I 21Ò^ÓÞÚ™+Óqæã9NŽøù‡ou†d[ u�LAçãÛIîÌÚ§åŠ"q¸¿‹ãC!‘›k–eÏšzj7Æø=*Ç{ úÄÈÌF`Y�ΗYN˜_ÍïøìQ–$Þ9Ù'Rƒ;¤PÒùû+sXXü÷¿>Pwžjw:B¨k,®•øå­$Ïâv¤çTŽ…8Ü…þ "™+såþ …’.6÷Ë‚d¶ÄÂZž…xž’¶nø È=A}=^îϦ(kúwR ²,ÑÝåæÝ“}­~*Ã�G«Ì.e9>èá·ßíœ×­£„ºÆÌr�¿»ž`5cG~�ÊÄH˜�ˆ¯ÕKÛ—hºÉÍÇku×óhÈÃù±(n‘~ze Ób5Uda-ÏÒZmC½ªÓ!ëö2ñ {�«GÃBIç«{Ëä‹XvmZѰ‡‹Ç£â¬r‡”+{å¦iñ/~8ÀP¤3¢ièP¡0M“›3y>½“$_²#‘pÀÍ©ÃaÂqØžÅsÜz´†n˜¸T…sc=ÄÂbÐËÐt“xºÈr¢ÀâZá9×x�ËAoØC_ØKoسí™ájºD*WF–$"A·HC½"wž$x´�f´×Í?ÿ ¿ÕËy%:V¨kT4‹«3|q/IE·ŸÊ@ÄljÑn1ê±äK:W§WHV]Ï� tqb´»ý l*šÁrªÈBº™ •·Ç¨ý.Nî&"rƒ{ÊìR–ÛOÖ0L �ËÁù±(=û¤¶wcÝâjžbå»etQ}Ý^TQ�ÑV˜–Åß}ûŒRÅà¾åähg¶Úï{¡»$êÚ£,ŸÝIRÒì÷hÈÃÉÃÝ>¯º—d Wî¯Ô]Ï� tqr´»#kÜketKI»R£²¡ÆYuÈôu{‰u{é yDy\3»”寣UB>ÿæ'ƒÈrg¾WB¨k”*&—ï'ùf:ƒaÚ§ªCQ?“£Ýâ4u�0L‹©ÙDÝõ<pqñx´#r´†a±š¶kœ_,£s© ½aßKËèí�eÁ/¯Î‘/iüøB„óG;wÿä@ u�­ZÒÇCbpþ±”(pýAœŠn¢:dNŽ0Ô†Þ*ºÉr²°i�Ïí¨7 ˆ2ºÎc>žãÊt¯Kæ÷~v‡Ò¹×)Ô5DKzc)W ®=|ÁEf¬§åyÜBYgi­Àr²ÀjºôœÉ¯(£Û?|tmžL¡Â‡gÂ\µz9»â@ u�™å#A<-ZÒÁs.2nÆšï"³±ÆùÅ2º ÏE,ìa0êÇïiÿ�àå,% |=µŒKµm¶\jgŸ) ¡®²YKzwÀÅÉÃÝ¢%}HçÊ|{?N¾Ô<™l¡ÂÂjžù5ÛiºÆset=>1³dòéÍE’Ùïžòý“Ý­^ήBý¢%½qè†É�™DÝõ¼'èæüñ^<{$”ÏM£[-Pª¬;Û×§Ñu{é‹xE·ê>f5]â‹Û‹8‰ßûÙ0^Wç¿×B¨·@´¤7Ž…µ<7®¢é&ª"sæXƒ=¯—f2L‹D¦ÄrÒn@)o¨qV™hÈC,⥿Û+Êè_ÞY"ž*òæñ ?:ÛùÑ4¡~)¢%½1Ê:W§×]dN¹³/F±ìMÁÅ®C$ßþ)}‘ÀžU‡ö…rÕ´Ö²øW¿>@¬CLkwÊþÈ´·¯KáGç{¸x<įn%¸ÿ,Ïìr–ùxž£CAŽ Q:¸mµQX$2%–öL�By½Œ. ™HÖúæ iš”JzÇ7,ËÃù4–eq¤Ï»ïDDD½§ˆ–ô­ÙÎqÛ¡HŒôº9áHàû쯰t÷ð0ù…ECgÎ?ÄÝ#?àüx¯è|‡Šfð7ßVMkÐÏPÏþÛ³BÝDKºÍvŽÛn§ÌÑ~/“C>Ç/Çú½és×g›å2Ïþý¿Ç,•ðMLÐóóŸ×¯+Ḭ̀üŸÿLƒ«=x£?âãܱ1éP€¦›üÝ·ÏÐ “ú~Œ#}�g³µ„P7˜ƒÐ’^Ö V¶pÜù°#çíNI‹³³änÝ"òÓŸ~g¸{af†ÂÝ»Ì}—_ÝNb˜vû…±(Qy ™žKqo6I,ää_ýzç™Öî!ÔMb¿µ¤oç¸ér01ècòP€ž®½Í)Ç3eþìrÜN+Ipl0Èä¡ð�ß8ˆ¦Åß~k›ÖþÖ;½L íßÔ¢ê&³–©ðé�TG¶¤oå¸ 0q1Öïc|ØKØßØ ?ݰøÕ­WØ.2a¿‹‹ãQ¼¢¶úÀ`˜Vݧ³; ò?v¨iíNBÝ":¡%};ÇmE†á7Ç|L {ñ· �s¾À_}§\1q(2gŽFжŸ‹Œ`o(”4nÍ$ˆ' ˜H’„eYüä�çïï f!Ô-¦ÝZÒŸš§TùnÝä°�±_[Ô6gò:þM¼^9Üëçô‘ˆ˜”·ÏÈä+|zkÓ´žK³I@_ÄÅ¿ø°¿íÏHwƒê6À0-nÍäøøv‚b¹ù.éÛ9n»œ2Çú½Œ x9óâTÛóËðíƒ ¿¼±†iÙ^‡ç�÷ÒØ�•_^™#WÖ`µr(ïN†xw2Ôêe6 !ÔmD¡lðå½4W¦×[ÒûüL ï}Kºf˜,¯XLXI0Ì ¾�…±A/ǽŒD½m“Šyskeþâ«RyY’˜ sl0Øêe ^Ó²0 Ý´°L‹D¶Ìõ+˜Û(UÀ#ó?ÿƒ‘V/½a¡nCRy��n%¸÷ÌÞpt(2Gƒèzî”^3L’™2†ið:_ÚµW®õJ�M]Ã~ãC^Æýôwwn$ZÖLþëÕ5¦žÚóÑ�‡óÇ£¸U…t®Ìüj�²¦ãó¨ õøÄä+`Yºaa˜¦iÙ L–EE7mq5m�­]g™šiÿÔMûßZÕëL³z{Óüο{$Iâý�ÑV¿D Cu³˜(óË ž­ÚùW·ª0~(Ì¡˜Ÿs)¦çRÈÈ �aštÜ\œèŽ¡Ü/_Òë35^,£ë ©ò16è%Úչ⼷g³üÍÕ5*º…SUùœ¬V+ULÓB–%Àbr¤›£�u[–msfX¦a¡›¶jºi_WCÓØ ®†‰iÚŸ›çÄuƒ¦i‹«e=gÎÐ,Š„C–P‰BÉ`;¡r«2ÿËo‰ˆZÐB^lIw:tÃ|®±@–Á­:x{²�xºøÇm€¾°‹£}nNŒø÷Õ¼ÞÍHå4þüëUæ×J[ÞF–%.�Òß öþZô¹þÓDÓÍõ¿«‘¨YGM7lÁÝøoj×Õ#Ñç…×0›ÿVd U±EÔí”PEfÃeJýwUE²oãpØ·w(2Y¡ØgŒEBQìϯªH8ÔŸ Ãâÿó§T´ÍЧGüäBOÓ_‡f!„ºC0M“�s|r'A±²Í[fŠudE=L ù8ÖïÅï鼿šÝPÑLþ·ÿ2ƒem�h÷º¼1Ñ»=f]8 ÓŽ<+Fí~ý:Ý´#VM·´¹šºaÒìoVM8ÝÍá˜eCçŽ$Ù¹ã‹cAÎŒZ½D�`[DÕG‡²–©ð«› fâ% zº¼3âÄ!1”h+/¸;›'WÔ u©œñÓó¬í�j�@ hsDêC Ú!Ô�@Ðæ¡‚6Gµ@ ´9B¨� ÍB-mŽj�@ hs„P A›#„Z ÚœÿRòð*+l%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--5jgo8mhcjsw.png000066400000000000000000000337431524103652300222310ustar00rootroot00000000000000‰PNG  IHDR›F#S cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ü’Žu6ÃIDATxÚíÝw�eÇ}è÷ï97ç|'‡�™Ý� ØE" "!;v{ÿ΃%Q ¸;”ëóun¦[,g¨ŠAÀïÀçvâó:ð»¸6l6§]Æn“°ÙddIBÓ TÝ@× 4ÍDÑtj •ZS¡ZW©45tÝd$êâÀ ›‰/!'’…w¡ë&+¹& ©7R ²%¯ÓŽßëÀç¶ãó¸ðºíoôE›MÂn—qØdtÝD{£?*º�®›Ô[Õ†J³¡Ri*T*�ƒ 7ƒnƼ.[§[Ø4Í`%ßd#¯°šo‘-©”ê*n‡ �ˆÓiÇi“±Ûe$Y‚7Þp&ªnbè&ЦÑT6ŸËN<è r‘ :Œ9‰œ�~Ì=!€ZÉ6¹¸Pe>ݤ©$#¢!7±�ŸÛÚ»¢êäJM²¥¹RE1Oº9:áçà�›˜�õ½zKçòr•kk ÖrMB^‘ —DØC$èÂ&[×GLÊu…La³?æÊM¢3C^ŽMøúf¶&[V¹¹Qcn½Áz¾EØï$äwô: ú�øÜŽõOÓ4©55*õÍ ´ÖPÉ•šØ$“ƒ¦½Lxp9zs•@{¬\Ó¸°Tåõù*ÉAßÞxME']¨³ž©Q¨µ˜õrb2ÀhÜÝé‘°‡ Ã`>ÕäìÍ Ké&Q/1ñ°‡mï=Ó0)T[¬çê¬eª„|6NptÌ�ÛÙ›ƒ¯ðÞr…³ó./Ö1$HÝ$£^â!Ž6/ÛWë*©bƒl¡N®Ôd ê䮩³£~ì=4YÀYH7yáR�TAa$ác, puºY4Z«é*+™ ’$ñà‘wLø-�ñ Ý¥©è¼r½Äks¼;£‰ Ãq_ÛÖ­0MȬ¦+¤ò fF¼�¡éüð½1‘#°]_­óÍ39"‡Æ£ûêÅÿN†i2¿^áÆr‘;§ü|ðH§cÿ�õ)M38=WáÔÕ"±°‡Cã|îýЙ&¬åj\[*òÚøÈ‘}5FŠÀB—Wª|óµ/GİïaU»¥òu.Î狹øø�1üqd«ÛU:ϼžc9«p|:F"ìét“,£hWs¤ >v"Êñ §›$lÑJ¶Á?¿’Åërrh"ÚÑý}«˜&¬dª\],phØÃGOF÷ÅÉX R×øÆ©4ÕŸ‰ö÷楦\[.²’©ðØ= �ì¿%¯~qæf™ï�+21äàhy?/C½‡\¹Éù9‚6~侤81ÐÅTÝä¹KÎÍW9>c8æët“¬FÍàÚRž�|�OÞïú1R»´�ªó�—³Œ™ ïëåþ­*TZœ¹–ffÈË']DÕMž>�e5§p÷l²«ü¬b˜&—æó¤ 5>óࣱýŸ�ÝkRuþùt–ˆßñ©XWœ6i§\©ÉësYÆâ.>qW´k‹\‰`^º\â¥ë%î:˜è©åÕ­P5ƒssZŠÊ�p€H ÷_4Ý®PQùûï§ñzœ˜Jô]`–Ê×9{=Ã=3>t,ÚÁø~ðÜ¥"goT81ï«qR7L®.Hªü؃ F»/0À´4ƒ'^LSm˜Üu8‰ÛÙ�ÑÝ^˜_/3·\äÓ$˜èŸ?însmµÆS¯ä88ar(ÐéætL£¥ñÚµ aŸÄgè©¢-ûMK3øÆË 5ƒ{úxœLå뜛ËòÑN访MlS½¥óµçRx\N!‰iùr“ÓWÓüÐÉÇ'º«ƒ÷ƒs ¾{®À}Gû»o–±× ÓäÜõ š¦ñ¹ м€ÈUþ¿çS|n÷lÊVU*§¯¤˜L¸yôžX×Ô‚À6Tó½ñ�›ÙÉX§›ÓUªu•S—689åãCÇ¢�nNßxõz™ï_-qÿÑÁ¾Øïߎ«KRù*Ÿd�Pdšï é&O|?Íìd”ñq:ãMªfpæZ‡lòÀÙy"Ø¢BEå«Ï®3:bz$Ôéæt¥¦¢ñò¥‡=|ü.´Û÷θ°\ãÁcƒ¸�û÷l;ÝX-³°Vâó$. µÝÍ�:O¼œåÞC â}´ß¿nd©5>ÿáίN‰` Ju•¯|{ƒ™ñ0b‰û½¨ºÁ‹682ìæ‘"h—ï�Ësy­ÉGp:úsou«–ÓU®-øé� ö‹  ]n¬ÕøÆé÷Îí’{NºÕ¥ù¥jƒÏ?2ÔÑ�_ƒèr-ÕàkϦ™‰—ÿ8l2àÂJ�—®”:Ýœžtæf™óËuñòߢ±¤Ÿ©¡ÿï³)ªM­ÓÍéIW–k|ãå÷‰—ÿ–=#òñ•ï®Qièk‡Xxšfð7Ϧðyœ{þÛÒT4^8¿Î#ÇÂ]—ùºŸÝX«ñϧsÔ‘Ê�"x¦ ÿùÅ UâîCÉN7g_ªÖU¾q�OßçÀ`wWÄÚÖ²Mþöù4÷ $²ýwäÂ�,ª¶¹ÿ*.·Ú½�¢ÂWÿuƒûŽìùõæME'Sh�.Ô)TZ¨†A8à%äwát8°ÛddYF’7ÇsÓ4Ñu]7h4UÊ•¥z“€×I<ä!ñ ºöüd×ù¹,º®ñï?œÜó>)€wñÜ¥"×VÜl°ï�°ìF¶ÔäÌÕ?ó‰^‘¨¶Sµ–Æÿý/럎1ÁÔN™&¼ryƒñ„“�‰•])×4þê;뛊1Û›>©jKé*+© -Õ`8$ô`·;0 ‰í¾Ì$@’ š-…\¾J®\c ìeb0@,´7—ú˜&œº´Á@Äο»'¾'ßó­çÀZÎ4ùú‹i>9Ò·Å+¬4·\"_®ñÓêšó¯ûÍß>—Âáprx"Òé¦ì{ªfðìë«/Ç�as¸1:¸Q­±X„£3#Ì­•9}%�¢¶çè^4èfl0È7NeöäÙDð†¦bðì¹·ƒÃ!þåL®ÓMézÿz®€ËioKA´J]áÙ³ký^L ¡›Ýùj2Lpy¼œ84Ê•¥"— X� IwJòÂ¥"™’ÒÖçéΟòÛ(*\^­qdB j7‡]æÈd”'_ÉZþ‡ÓK¾y6ÇÔPŸ[,ý·ÛÌhˆlYãÚjûöw÷»T±Åùå*'f–öz®Î‹ç78t`¯Ï¿/ÆÍ”9<5B­©sêr ÕâmMŸÛÎìD„'_Ͷõ9D|óÕ,‡Ç"8ºàv¦~0–ô£#sq©Òé¦t¥ùTƒõ¢*.�Ú#²$q|*Æ3¯[?›ëÿòZžCm#7*\Z(pÇáQ�÷WeKÝ€Á�8¡€—ïŸ_·'6»Ärf÷ce_¦ ˹±PEÙo¢!/ó©þÊXLÕ‰D@Ú�¢A…ºJKí�<Ó„¹Tƒa J£/§« Ä‚=[ðg'â± skeKJŸFü\[Ûý*@_Ù²‚×!ãrˆÙV7Šø]¤ Ö×»îfËY…¨X‘êJ²$ô:È”úãtJªÐÂë´YR‹âÆj‰XDœ´º•nÊ„ünÖs»qÇÃnÓb`[r¿ÇÕéfïÂçq�¯öW�¯¨<ý™!½ø\Nr•þ¨R¹˜iXréO¡ÒÂép`ô×ëeK†!–Ó»?^¸(ÖÔ]_?ÜW¿¡\YÅ+Û®åqÙi¶´¶Ý}ÝmLÊUŸè“]Ëçu’¯(�nÆžXL7-I�^IWwúqº’$;(VZ»¾2X–$"7«»¼³¢¯€lYƒm“$ð¹¬õI"`±¦âvÙÅùÿ.æ÷:XLõ~`š°’ß}~”iš¬åk8�b¥õv Æìew¿  ¸YLï.Iµï±ÜÚÝŠÁ —¬½ð¢[å**~¯è�ÝLR¥Õ†µ·°u›t©…ÇaùËü¨\©EÄïÁ‚Ón=+ô±fA@,´û<€¾ Šu±ÐÍLss‘)µ,¿ö²•jQ�ª«•ª ¦iòìë®víF¹²Šß‚»Q²å±ˆ8ú÷^LÉFµ®ïº&@Àë$_Ý]~J_šjâ°õÕ#ï+庂aš4U“g/æ;Ýœ¶k©:q"¥«¥ ›ÇRo¦=”f+*>×î'GÙb·K,ÿ¿'QÅÊîöïv›$Qmî<è›·¡¢šØdIl·v­�\í­¨øÆZƒ¦ÒÛÉ€MÅÄ.÷ÍŸà¾cš›A@µ¡ñ\¯dK*�]nGé†I¥®böÏkeÇBA/Y . xíäwqJeÇ¿©S§Ïð•¿ù[–Ú󲘢ëØÅl««¥ ÿöQ©ë<{±w\€–¦cïÑ©³¯¾Ì“ÿø÷¤Së�nÊŽ•ëÊÛîrŸ[«÷lPš¯ªøw¹=Z®nÖ´ÛÿïÏépPØå l�Ζw~tzG£Ïßx’Ÿÿ¥_ãÿøã?çßÿ‡/í‹ @UM61ýïV¦ÉÛÏ´J0·VÛõ9×nÖRÀnï½>ù�¯�?üO_æ«õçüO?ÿErÙt§›´#¹ÚÛ€ª¢óÂ¥b§›Õ¥š†×½» ÚP ú»³¨ÕÕ³Ïñ¿ÿÏÿ5ÿ×ÿö«èJç«�ʲD¡ª�-î2‰O¶ñâ¥�O”v|ý‰¦Qo¢i:ª¢ð¯Ï¿ØÞŸ–Zª!€.Vª¶Ðõ·Ï®*M�ï_)vºim£ê½¹ðì·ž¢Õl¢ª*†¡óúk¯tºI;r늀iÀÕÕ­«SÑT $ÉÄaß]_¬6UÜäXÍÔþæÏþk‹\=šyâ+�n2šªsmyw«œÙr“ZKßq~ÊŽ~ãÇŽÁñÆ/ÚátrhfºÍ?®Ý“eÄÑ”.¶ž¯ÿ@ Ó€+˵ž- d“dŒì”ÂáxãE ÉŒOLuºIÛö+Ro¨4µ]͸º‘¢8l»ß­6TK>Çr&ÜZ€?ìüõÄ&P¬*húÎÆ7Ã4i4U ÎÞÜÙ%C;:ƒôóÿíÏ¢©:ç/^â3Ÿúa>øÀ½{öƒÛ)—SF볫f÷“LáöËrÕºÎKWK|øX¤ÓM´œÃ!£½Üü7_úìvK 7ùä�|†™ÃG:ݤm+U[húަ—k|ðhç.gÌÝBÑMì¼·[ŠŽl“Ñ»l˜•ìNþÃ÷¿ðŸÿúÿdhtЇ>ùã�n¥Òæx§+é“C�mÆz¶ö֪饥<Þögì(p»]üÚÿø?ìá�k÷\vÊ#-¡½LÓ|×Y¾œ_¬òÁÙ0öÛÂqÙ%­ËFK x¼^~î¿ÿÕN7cWÖóuTíö˪µ†ÆËWJ|èxo¥-Ͱd+JÓ $ºóotúøýüêÿz§›ñ–Tá�» ‹åókå·Vµë-•t±E2¼½#˜½Ân�ÓNO¶½ XÙ̶–$ ‡MÆã”‰‡$‚^;�–Á©k½WÐí”w¼ü'´Wæ�ýÿ7ë4$Â!±€¯ËÎ+7*h=²5¥ª:v V3tàKßÿÝÅT©Õþ­¼tKÕi´¶w”OÑ ê·lQÕ[&¯Ì•·Ý”¾)C&Ë2vÉD7LQ{½Ë¬çk˜&ÌŒ„Ðu“ñ¸Ì³a`sëîÆz�Õ|ï]ÉêtH"èB¦aRi(„ü.ŽˆðÒÅ ¾ð‰Ñ·¾^mh¼tµD¡¦‘í¾z^§µ4°Y° ê¦xÿ¿»ó+¹Í`é -Ega½Ì‘É­ç&,mTPÞ‘£²˜nbšl«ÖM߬xuALóíG¦ß<õæ•"õ–ɥŭ_5Ü#í"'�¦˜qu«ZC%è�Ùÿ›"~Õºè“ݪÚP‰õø–”]–ÑÍÝ¿¸=.;š.‚ÙwS¯7Ñ4ƒxØÇ�‘(‡�©á /^·EÓÙÈ¿w.@¶Ô¤©}Nf'"9#ê·óøýI�zq;%^½±õS½½¶õñ€ƒBUÝv¦¤°7òåC‘Þžm½S2ä¤RWˆ‡Ý�nŠð†¹y îí>i—¥·e¥ï”Ïë ©¨x<½ýóÚ)I–9qd °´^àè�(²$a&7ÖJ”k-†â¾wý Ã0øÀáQ/ù:¡€“ÙQ³£>šŠÁKW·ôÕ €ßcÃç²Qy]©P®39Ð�—‰´ËxÒM΂kAëåË-¢~.Go“·Œªì~ äuRÙb"[?r¹\˜lÖ•�1ñ¹ÈoÌD%Ybf4Ìá‰÷> 8õ¾õò‡Í#„׿•qt;e>rÇÖOLõvϾ�ñÙ¢p»�n˜« £±þš O xÈ–˜,Á ÖÊL&½»ÿ .çvÚhZp5äs’-TÅQÀ-Ð ��÷+% UÇïÝyç¾ ¦=äÊ"è6ùJ“XÈ…ÓÑ_£‡×e#äqP¬ˆU©n“/7˜èý€Ôe—1Ln›�¾­ÏqÚpØelâ$ÀûªÖDƒ»ï[Š¢¾m`»ú.˜H¸È›»î삵rÅ&“‰Þlog2é!#¶ºŠn˜k #ñþè“n‡„ªî> ö ´D0û~Ò¹*±ÐîûVS1xwžÊ×w€Ûi#t�+7;Ýá¹*3#½¿Üz;†lËñq?빆¸ˆ¥K¬d*œ˜ìŸÁö�dYæè¸ŸåLµÓMEÕ)–›Ì í~�Þ/">õmÞHw;’Ã1JKœ¸XKŽï~µ³ZWû�»:ÒÞ—€×ec,áf=·½ 뙆Éz¦ÎщþloçΩ+é*"5¥ó–ÓUfF|}•�Øi6­Ù»NøYM:ýH]I–u4Ý Øýþ¹®’Øe�о Nð³"¶:n£Ð ²ÙÅ2V/H„œ¸�2¹’ÈMé´Õt•;&û+%âuа¨$u$àÂ0td+ê ÷˜l¡ÂÄ`À’Ï*”›ŒÄD°#3C^ªu…Š(ÃÚQó«%î�vº]áî©K©­Wñ¬—)6�$ƒ‰DÑ �rÕºìýƒ£aVÓbàV›ÉêF‰ñ‹€Js×uSú6�e‰û…™[�´Sr¥&Ц1;Ö¿ûÿ·ºc2@¾Ô¤\Ǩ:enµÈCGÃ}W*<êwÒRuT‹ò¢c>jõ&2"ÏêM¥b…ñÁÀæ­‰»¤hõ¦Î@dw‰Ó}Ü3$[jPÙ×1·Zäá>lß�Ó!ñ�C!n¬;Ý”¾T¨´hµTŽŽõ_>Š$A<ä¢dÑ*€$ÁÁ±0k©¼( Øe“ùõ"ÓÃ!K>/_n2Û] ôyàtHÜ{0Äu± °çJ5…ZC娄˜ýßêž™™²J;áúj‘fCÈr‹ƒa'% WŸFâ~*õ&’¹ûÓû]>_fr(€Ë¹óª}·ÊêL ì~›ª?{ú-î=$]hŠw�]]Ìóàá6q`ømœ‰ûfDPº× •åj‹ÖìÏîGƒ1'e /ó‘$81çêB [¿il’Îj¦Ì̈5³Ó„T¾ÎáQìšË!óÀá—çó�nJߨÈ×iµTîšîßÁö½Üs0H®Ü¤Pg©÷‚iÂÅ9>v"‚Ý‚ýÙýj2é¶ü¢´xÈMÔï¢\éÏW0·˜áŽév‹¢ |¥‰×i#âßýÉ©þíí·¸ÿpE×XÏÖ:Ý”ž§&çs±àî ½ÕÎNý€ºÑ�Œ²ž¯“ÕØ,g˜&¯^Íðáãa‚k2a{]ÄïàþƒA^ŸËŠÁm°ž«Q¨´øðñH§›Ò5¦‡¼+- n|§ÓqŠ•:Z«·K°KÀz*Ë@ÔÃ@ÔÚ•ÎÅõ2÷²®pšnávÊ<~’³×Ó4-*‹)lº²�'á·s÷Œ¨ú· ã¶Á5q*ÀRMEãüÍŸ¾/ŽË!†Á79l“CÞ¶Ü“b“%î=2ÀÕÅ,N¹7Wµ$ R)c:‡Ç­ ,+u•ZKåаuA…èùï0™tsçT€3×Ò˜bÚe‰t¡A*_籈}Öí’$øô㬤ª¤ Öfh÷+Ó4yõJ†gC Çw)K¯9>îe¥M7Sz]vóúµuœ¶ÞË·Ò”é\…»%-ß긱Ràžé€¥ÉÓ"¸��àsJ\],vº)û^SÑ8{=çˆãu‰¥ÿ�ð¹ì|úÁçæ24•Þœ9í¥+‹En¸ÿ�5ç²{Íô —ZC¡ÖlOm”�¨—Ãca.\_Ãeï�I–d´¸¾˜á¾£ØlÖ¾ý+u…l±Á½÷Y܆$Áã$XËUY͈£�;¥j/]Jñà‘£qO§›³¯�'ÜÜw0Ä+WÒhÕkïG‹é ©\•ÇHvº)]K–%îž2¿VlÛ÷˜ p`(ÈÅëk¸lû?� …K7RÜl�Ënùç_](pÿÑ.‹ëTˆà]x]6>÷p’‹ Y±ôº›Ii¦“n1Ó²ÈGBŒÅœ¾’Fõ¶-]hpm!ÏùÈ€X�z÷ °š®·%ðMSÃA£^®.làÜÏ+Z‹K7R|ðŽ!‚>k²óo•¯´¨Ôî�²¾N…ÞC2ìâ'ä̵ ù²8°ç®gùd>y·Ø÷·Òc÷$ˆx%^»’9*ÛPª¶8s-Ã�?4@,`ý Ýk|.;‡F½ÜlsŠ#“"WæÖ÷_ �©6¹²�桃ø=»¯Ì÷N†irq.ËGïŒX¾­"x_#QŸ~ Îé«iqMë]¼‘E×u>s_¢/Îüî¥Íí©$^ŸËvº9ûB¥®òòå?z_œQ‘ô·e<fq£B«Í'¢Žˆ2œôqþÚ ®}’(IP¯U¸¾”å¡ãƒøÜÖ¿ü®/‰íoÏ¥i"Ø‚©A/Ÿ¼+ÊK—6(TD}öwcš›3ÿº¢ð¹YŸ#l²ÉÿŇ’¨ªÊësâ´Ê{)VZ¼xq�OÜaÆÂãSý âwpò€ŸËK¹¶¯ƒ#!fÇ"œ¹²‚£Ë�Êd2y²¹*ŸÂÛ†™?@¹®°´^áÑ{ÚW8M[ttÌÏgîOpúrŠT¾· Yì„aš¼v5…fh|þÃâlu›9í2?ù‘!l˜¼|qC$ÞF¶ÔäåË)þÝÝqŽ�÷w�ÿ�zøh˜\¡E~&>£I?wLpöʦ֤§›É�…uì²ÉïÄåhO.‰¦¼v-ÃGµpšdŠéö¬æ[üýs�21(Øì¬¯^IôÉ|æþ„¸âw†Á“¯æYË)|àè@Û¤ýf#_çüõ,Ÿ}(ÉxB,ûïÆåå*Ïœ/ñ¡“Ã{ò·]m¨œ¾’&ò‹Fлä %*ol0;nëØošpúò!;?|o{˦‹`r…¯}/Å@ÜÏìx©�7ºßüc�Jºxôž¸Øóï�ï�Ës~©Î½G’½ý›äfšp}µÈRªÌç`PÔø·Ä?¾œ¡®Â‰éÄž|?Ý0¹¼�'WnqèÀ šÑ¹EY†B¡L&_æ®C Âþöö©Ë‹jõ&ÿÕGÛp‰`‡j-�o¼”¥Ò2¹çp·Óú³ŸÝn-[ãÂ��œˆpWލÛsq©Ê·_Ësp,Ìäpÿ•\V4ƒ3WÓØd“Ï>˜$ Œ¢ü?ßZåÀp„Ñd{Òng9UåòBžC°9ö>˜“Ѹrsƒ¡˜—Ù‰r›g8óke–ReþãLJö䨪véÔµ2ß¿TäøtŒá¸5w4w;Ó4¹º˜g-[ãÇ`(*fYÝ"WQxâûiì;wLâ°¸pH·*V^»’âШ‡:³´\ª°)SRø›g6¸÷h’H`ï¶UjM•×ç²H6;“Cq4³ý¿[Y‚B±ÄF¶Ì݇DƒíÞ›ke–ÖKüäG ûÛ“XøN"°ÀJ¶É/¦ID½ÌŽG{zÐ-TZœ»‘%°ñ©û¸�b–ÕmtÝä[¯ç¹¾VçÄtœD¸w«0ê†Éµå"+»7ΡQ‘éßNóužx9ËýGö6ð_JU¸´X`f,ŽÛí¥/. P”&s‹&ÌŒ†ö$ïan¹ÄJ¶ÂO=2Hзw«É"°HS1xæõ×ÖÌNFÛÃe²½ jW—òldk|ü®¨ÈªÞæÖë|óÕAŸ“£S±žÛ¦Êœ¿™c8âä“wEñ{zëùºÕÜZ�:�åþ£ƒ„ÚPùî½´� 7s”ê*Ç`wbE$ sË;G'#m)éûNºari>K±Úâ'Úóm+Xl=×äÉ×r`Ê›Šµ¥4ä^[ËÔ¸4ŸgfØÃÇNFq;{w…£×hšÁ‹W‹¼2Wef8ÄôpiŸ/�7�+ 9 Õ�ÞcfHÌú÷ÚÕÕ:O½’åøLŒáØÞo}*-./æ1L™É‘8¦´Ã§¦®±´–Ã4 ŽOEöl{£ÖTyõJš�°ƒù@gVŽEЦ gnVxöBžxÈÃÌhx_ë¹×—Š8ðè]Qq¡Ï>V¨ª|ûµe•éác�}w\³©èÜX)°’©qr*ÀÃG"8ûëzÉFQáë/l�Œø™�ŒväP¦ØàòB‡ÃÉØPS¶oiE@–@Wn¬äp;$�…‰…öæÅoš°”®pe±À#ÇÂÜ=Ó¹„]´‘¢œ½YåÔ•¿“™‘0‘`÷'Ì¥òu®/�døÐÑ0³£ý‘ÜØ6Š /\,°œk1ž 0=êúœ•–¢sc­ÈòF•c“>œ�ˆ ÿ.Qoé<ñb†ªbpü@¬íGäÞÍz®Î͵ŠF¢8�®¨ 6Ù Zm°°–'ìwrp4¼§¹ …J‹‹7r¸\ðØ]1’>¦*€= é&¯Ï—yéJ—ËÎhÒÏPÔ×Uo½¥±šª²”®pÛxøxX,­ö°t¡Å WJ,¦šŒ$¼Œ$¼oÇ4MÒ…Ké ¹R““S~8·û²Âö�_¨ðÝ×ó$#^Žˆud9 \S¸¹Vf=Wcl0D4äÇf³ÓRZ¬¤ŠTk ã~ÆxÝ{×—J5…›«Erå&;áøDwäP‰`†ÉÜz�ת,¥ F}Œ$ü$ÂîŽÒtƒ�|�•t•rUáè˜�S~Q<¥�j*ççk\X¨ É026àëXÂ`¹¦°’®²œ®õ;99íçȨO”–ÞZªÁ³ œ[¨2šðq`(„ß»7ÇÙÞ©TS8s-ó¶ ܦFB�lÿYþ7™ææ6êâZ™†ªqït€»quÑÄORoé\Y®qv¡B±ªzˆ†<ÄÃî¶Ur3M“B¥EºØ¤P®S(+Œ%=œ<àçà�W\ÞÓçV²M^_¨re¥†Ça'v {‰…Ü8lí´šŠN¦Ø _¬“)5±Ipl"À|âÚÞ}ªÚÐ8s³Ìks‚>C ɰ·­G†Í PnR¨´ÈkÔ›SCn�øH�\_¯si©J±¦ xˆ„ÜÄn§¥“/U7Hdò56 â÷qh؃,wÏ‹ÿM"èµ–ÆRªÉB¦ÁBªE£¥ ¹ñ¹ø=oüÏëØV�÷FK£ÚP©ÔUªõ E%WRˆL&=L z�»±‹—¾ð¦ ù&‹™&7ÖlZ}vüÞ7û£Ç‰ÏcßòlJ7Lª •j]¡\W©7UʵMÕx«?N&ÝDö¨ŠÐ~ºarmµÎååK©n��xØKØçzkLÛîlÜ0MêM�zS£ÖT)Ušª-š-ƒÁ¨‹±„“I/£q÷m“ë-�åL“ÅLƒÅL‹RU%âwâõ8ð¹�øÞèßn§ »M~×ÄFM7P5ƒjC¥\S¨5*u…J]e8êáðˆ‡é!ïžžéß t¡rM#UTÈUU²e•lY!WQ1 ‡lÃn“p:¤Í*Ëhš�¡¨†�¢è8±€“xÈA"ä p’ ;÷¤¼¤Ð[tÃd½ �++ä+ ™’J¶¤Riè8`·ÙpØÁ.ËØí2¦¹yüPÕ TÝÜ쟦IØë t;ˆ�Äýa—¸?¢l.‡7¹‘n’.(dJ 妊ÏeÇë´#Ûd6› ìv†f ›&ªn¢&†®Smê4�€ÇNØg'âw0u1q’í¬5ƒT±E¡ªm޳e�\Y¡©¨ª�MÚìßv›&(†NK1±ÛÁå°8‰‡ì$C.âA;ƒ‘ý5©À>¢ê&Ц£jÐl騺�n˜Øm2N›„ÓiÃi—pÙe±œ/´�inîû*š�¢™¨ªNK30‘ð8ev ‡Ý†Ó†¨)üÃ0)ÔT*uí�þc¢&­–�l§MÆí”qØ$ì6‰ ÏNÈcÛÓ¥ô[Ç\I2qÙm=UE‚ ‚Їz'”AaËD ‚ }H‚ ‚ЇD ‚ }H‚ ‚ЇD ‚ }H‚ ‚ЇD ‚ }H‚ ‚Їv¤Ói®]»F¥Réô3‚ ‚°MÛ¾ªè[ßú¿ò+¿Â¹sç°Ùl<úè£üñÿ1SSS�~A:¤ÙlrîÜ9NŸ>ÍÅ‹Ñ4�O}êSüè�þh§›&ô¡jµÊ“O>ÉSO=ÅÜÜkkk$ xà¾ô¥/qäÈ‘N7±ã¶uÀ?ýÓ?ñéOY–ù±û1¦¦¦xþùçyþùçàÔ©SŒ��wú™AØcO?ý4�?þ8ªª¾íßë·~‹/ùË�nžÐg4M# Òh4p¹\¸ÝnJ¥N§“?ù“?ág~æg:ÝÔŽÚò@½^çç~îç0 ƒ¯|å+|ík_ã÷~ï÷xöÙgùÙŸýYR©¿ø‹¿Øéç¡êõ:‘H„Ç{Œßø�ßàãÿx§›$ô1Ó41M“/~ñ‹œ:uŠZ­F±X$•JñÅ/~EQøÒ—¾Ä¥K—:ÝÔŽÚrðw÷w¬¯¯óÐCñùÏþ­—$‰ßÿýßÇëõòõ¯�•••N?“ {ìñÇ'•Jñä“OòÛ¿ýÛÌÎÎvºIB³Ûí,..òñ|àÀfÛ¼Ž:™Lòçþç<üðÃhšÆ_ÿõ_wº©µåàé§Ÿà3ŸùÌ|-ó±�} Ó4yê©§:ýL‚ ì1»}ÛéD‚Ð6’$‘L&ßõko®P---uº©µåàüùó;vì¶_óß/\¸ÐégA„w•N§ìtS:jËÀêê*Ñhô¶_�Åbb @AèZkkk|õ«_೟ýl§›ÓQ[jµðîÀ›ÿ^­V;ýL‚ ‚ð Ãà§~ê§( |îsŸã¡‡êt“:jË€$Ièº~Û¯kšðV²… ‚ t“_þå_æ™gžavv–?ýÓ?íts:nË@  ŸÏßöë…B¿ßßégA„·ùõ_ÿuþðÿ�±±1ž~úi"‘H§›Ôq[&''Èf³·ýz&“yÛ'‚ Ýàw~çwøÝßý]FFFxæ™g˜˜˜èt“ºÂ–€“'OpæÌ™Û~ýµ×^àÎ;ïìô3 ‚ ðÀoþæo’L&ùæ7¿Éôôt§›Ô5¶<þøã|ík_Ã0Œ·}myy™çŸ§ÓÉc�=ÖégAþè�þˆ_ú¥_"‘Hð�ï|‡£G�vºI]eËÀ§>õ)Ž9ÂåË—ùò—¿Ì›WÔëu¾ð…/ i_øÂľР‚Ðqù—É/üÂ/‡yê©§8~üx§›Ôu¶uÐÙ³gyä‘G(—ËÌÎÎ2==ÍéÓ§I¥Rœ8q‚çž{Ž`0Øéga�éºÎý÷ßÿÖÿ_ZZ"“É044Äðð0°™HüÌ3Ïtº©BX[[cttÓ4dddä¶ÿÝ=÷ÜßýÙŸuº¹³­àæÍ›|ùË_æÛßþ6ù|ž±±1~â'~‚_ûµ_'¡Oiš†ÃáxÏÿ&¿uZHÚiqqqK éùÈGú:(Ýv ‚ Âþ·åAAz‡A¡‰@Aú�A¡‰@Aú�A¡‰@Aú�A¡‰@AúÐÿ�˜,´WæA%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--7dzkrwuhlfn.png000066400000000000000000000401351524103652300223370ustar00rootroot00000000000000‰PNG  IHDR­è\´»\ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ü’Žu?=IDATxÚíÝw\\÷�ïÿ×ôaèm’ P³z²Š-«@rÖÉæ—ûÈ®óËÆÙÜÜ�S÷æfóKvã”u¼©wãd³‰-j¶%K¶ÕPï¨!ÔPCïLŸß²+n”ΔÏó/ƒæœyÏ1‡ÏáœïçûUy½^/B!DP+@!„è+)ZB!‚†-!„ACŠ–Bˆ !EK!DÐ�¢%„"hHÑB4¤h !„R´„B m__øÙÿñyÔ*Ш”Ž,Äs:Ñ�üü¿@£Ñø|÷6›�¢¢"¥?¥Š1 l.)éÓkû\´Z­Ì+ú.«ç˜‰3õy3!‚Zwm­oïá_OŸÂétú¥h ýíOșȰÄH¥?¶CBÝÖDÄ;¯ð¥wÞéó6ýª>ò²9PÙÎÿ³ÄŒQ/wEh³5·ÒsøÑ ×Á™3~}/•Jņ¹þtÐJ„^C|´Qé�/„_©z»Ðï/&þñÇ¡E«_•gdJ4Éq&6—Yq¹Bø�Ó�þ�b¢'O&f„~mÚï?—ò2Ðé´”kD懡ÈëvSSº×ð1¸ÇNÒ÷ÎabVN'¯Zq8ÝJ !|ÏëEäuŒÃRHž;»ß›èߤ¬$ºm^Þ<×¢ôÇÂçjvîÆ¥‹À99_‘÷Ÿ�CΰHN^µâöÈ•¡-ºSo£ÃMêŠeÚ~@EK­R1-×Ìk/G*Ú•>BøLÝÛq´µã˜·TÊ •]:%žä8g®5È 2´—O k¬&}ÃjÔê��‹ðh �Fͬ< govpñn·ÒÇBˆAkÛ­O§µÈ�ɨ§¸LF<‰Àæõx¸_ºWR®¼JÇé“ìT#óÆÅs²¢^z¸D`{·KKÚâù>ݵÏçbz,+ »ÛËÎSMCv|„è¯ê]oáôhpÎx¢O¯÷H¿Ô´ìhrÓ£8QaÅíŒLBü5Ý™}hœ½ _»ÂçûöyÑR©TLk¦¶ÙΡ+ÒÃ%O}Ù1õõج�öŠ(iÉäx̱ÒÃ%“¶â4Úú;Œ,Z�ÊLûåŒÕiÕÌÊKá­ÎÝêôûA¢¯š/VÐ{¡çã@§ïû†¶$ÏÚYIhÔ^.UÉ 8457ÑVœdXQ!êAôb}¿]fõfæY8t©•*k¯ß’}ÕqûíûßÁ¾¨¯)Zé8ƒ¢V«(š—L{·�ªZ¹£!”§n®Gtæõë1ÄÇúï}üù!¢Mz¦å˜yíx# 2âI(ÇÖÔDóÎ8æ¯Æ?ø^‘@`Ôkxz~ ·ëÚ¥‡K(JÕÙ†þ@)qO.'*}˜_ßËï7ôcŒŒ•@ñ¡::{dÄ“zŽî^ꊷâœú8žÔ ¥ãøTL¤–‚9.U5ÓÒ!=\bè©6ôûŠ1ÍœC|^¶ßßoHžB§%G‘nŽáÕÃõØd¨®B^—‹ÚâR\£ÆáÝ¿u{‚Ej¢�3Íœ©”.1Äs ÇâB¼zÿôвõ³’Q«=\¼%=\Â÷4÷«Ð•—‘²qºÈ¡_ÆG‘éŒ: ³rS8t©…÷¥‡KøNWm=­»wa_¸o”ÿzE™Z­bÓ< ]vnI—ð!us=ú#¯c^·S’2Ëø(6‡M”IÇ´±fÞ8ÕH}«¬Ã%ÏÞ܆µ¤Çœåx’üÛ+è z5›Z¸]ÛNM£Üу§êéDp±K—5B¹e|�x-1ÖÈøÑ‰”©§½Û¥däÜ6;µ%[qO˜ƒ{¸ÿ{E‚A¬IËÆù*n·H—‡ý¾"§N'aüXE£(>[hZR$#-±¼z¨› Õàõx¨.ÞŽ+-WÎT¥ãK¼�3“¥‡K œ×ƒáÐvŒiiXæLW:�òE +=–ø˜6—5â�% Dð¸¿s.�ç”…JG HÙ©ÒÃ%LwìM´z-i+ú¶Œ�¿DÑ?*•ZÅk²—臺ýeØ›ZpÎÚ^‘`393ŠÜ²—èmùatm�Œ(X0çWÀ­=\fÛ�ì¿ÐªtÏ]¤÷jŃ¡íÚ¡í FK&Åc‰Õ¿ÛÃ%…K|<Íí t·/3üS…CÞ‹õq¦hhÔ*fäX¨¨îæÌ ñ$>ZWÕ:¾¸¯qè{E‚ÕÚÙ‰hÔ^.V5+E0�õº³û¶±Md¤ÒqPE @¯Ó0+ÏÂኮI—ø½�M4ì܉sþj¼1 JÇ *jµŠM ÌttÙ¸y_z¸Ä©ÛšÐÚ�yÕ* I‰JÇù`>¥|“QÇÌ\ »O7R×"=\â/Ü]]Ôo.Æ9} JÇ Jz­š§óS¸S×AMƒÜÑ¡êíB¿¯˜ØÇ5*0ϯ€,ZqQ&e%QrTz¸Ä»�êÍ%¸ÆNÁ�9Né8A-Ƥåé| Wn7ÓÔ.w4àt ßWBÔ”)$L¯tš�°E %ÁDfj,¯–ÕcsÈr&aÍë¥vç8ãRpŽŸ¥tš��«gÝ<3ç¯IWØózÑycªóÜÀ>¿ºhd‹%1&‚âÃ2T7œY÷¾�ÝîÆ9ëI¥£„”ŒäONää•:éá cúSocP»H]±Lé(Ÿ(à‹@^F"•†�'•Ž"Ð|üÝwïa_°ÔAñ#TÆ�ŒbRf '+ëåÂ0 i/GÛXMÚúµ¨ƒàü ü„<èáš:&™–n/JW8鮬¤ýô싊@gP:NÈZ0>މÎ^·JWÑÜ­DãéO¡6ÇùE ôpMËIáʽ.ÎÝèP:Žð“÷ÿ´ÕÔиg/ŽÅEx#c”Žò–MMÄ …ËU2+MX¨»ƒáÔ^† �ŽV:MŸMÑ‚Cu3â¼ô³°ÿè%¥ã?øÓŸþĹsçp¶¶R·}öy«ñÄ›•ŽÔjëçšéêupó~¥|‘Ö&«ÒÑ„u´·ðç_~Ÿ×÷#,kÖ ·X”ŽÔ/Z¥ôרQ£Ñxºyñ…æ­7'R¸n5S§ÊÌÞ¡ÀëõrþüyêkjHŒOÀ5a.îa£”ŽV Z5ç[øï}uU½Ü¹y•}oSðé/)M ’ÝÖË�=%œ*Ûƒ­·›}î9"22”ŽÕoAW´æ-ZŶ?ÿ‚Š‹çùÁÕËŒ;–Ù³g³bÅŠ x�(>Ü�¨ªªâÞíÛÄL›Áü1“•Ž–¢"´,§áû?x�¶†Z¼7½=]D˜¢”Ž&Àé°sð­­\8]F“µ€±iiä,^¬t´ ÊßðÓç.%}DN§“{÷îQ^^Nmm­ÒÑÄ ”••áñxp¸Ýì9sšÿ—稫¹­t¬°óÛßþ–üŸoÒf½ @s“•ýo+K PÅÅS\»töaÁX²v­Ò±,(‹–J¥büäÙÄÄ%2éñÏò�o|‹ôôt¥£‰ºyó&/\@§×3jÌ8VþRÓåöàPûüç?Ï3Ï<ÃøñãѾ;{þù“q:eJµ`4iÚ|þßç_`zöƒ½GŒÁ’%K”Ž5`Ay{`Þ’5œ=±ŸÇ¦/ ~ô$¶�h¤p®%P–|ýôß¿ù �‡19“È_VÀèœIJG [*•Š%K–°dÉΜ9Ãþ\Bõík”½½ƒÅË‹”Ž'Àpí,“�M£ÝNÞøñh4¥# XÐ-­VǤió™»hz£‰“W¬¼u®…'§Ê¬ßÁ¦óúuMMüÝß“ŒÇf*G¼Ï´iÓ˜6mÿµó$ÏáõzQÉ•aPÑÔÜD_q’aŸù4£ÿðÖ¬Y£t¤A Ú¢°dåÓÿ{Z®™#눮lgNN¬ÒÑDÙëëi~sû•ÿOÒ0¥ãˆ�ð™Õ3)MÌàrUF'+Gô‘º©ñݤn*BË?üÃ?õ_Y¤Ï´>ŒN£fö8 §®upéž,· ÜÔ–nÃ>s™¬§RÁêYÉtöع!ëpUgº¥$>µ }J @Ð,¡¢`Ôk™‘ká�³-Üm´+G| �ÝÎýâRœ¹3p�£tÑ­šM R¸gí ZÖá h*{/†}ÅÄÍ™CôØÐ:¿BªhÄEé™<&™­Ç¬4´Éh§@äõx¸_º »y$®ÜiJÇéyŠó@T„–M ,\½ÛL£¬Ã˜Ü.ôûK‰›MâôЛx!䊀9>‚Üñl9Ò@w¯,·hj_:œS)E @rŒžu³Íœ½ÖHG�\ý±71ÄE‘¼h¡ÒQü"$‹ÀHK4i‰‘ü¹¬§K� õ�`ohÄ1 ÒŸ¼Fš#X:9�W¬Ø²²x Ð�=€ÁÞΰ5«Böü Ù¢�32žH£žâ#�Èj Êkºp…ž+—±/*ÄûnÓª^FF1it§®Zq¹åÂPiÚëåhk®1¬`=jmP ÿX!]´ËJÂæôòúIY@RI·ïÑq`ö…ðFD*GøÈãããIO4r¦²AÖáR�æ~Úò2Ò6nDc2)ǯB¾h©T*¦�5SÓâ ì’ ÕUBoCÍ;wà˜¿o¼ôø„šÓ1êT\¼Õ¬t”°¤n®Gô R 6 OˆW:Žÿ?¯Ò†‚N«fV^ çowpîV§Òqг³“ºâbSáIÍP:Žð• ç›éîµs£¦Mé8aEÕÓ‰þÀVžxSzšÒq†DX-£^ì< ‡.µRUgS:NXð:ÔoÕýîÑ㕎3H¡ùPÛWtÕƒ®†Néá*;ú}%ÄÌœAl^ŽÒi†LØ-€h“ži9f^?Ù€Uz¸üËëåÞö×pÇ&ãš0Gé4bDEhxz~Šôp ¯CÙvL#G�4sºÒi†TX-€Ä#y£(.«§½Gz¸üåþîwpö:qÌzRé(b%ÅêX3˹Jéáò'ݱ71赤>œ 9FØ-€´ä(†[bØrÈŠÍ)…Ë×ê�œÄ^}çÂu þ¹ÎDÿŒ²Y<9‘“ÒÃåÚòÃè:I[¿:d{±>NX-€1Ã㈉2P|¤� Õõ™–K•ôœ;ƒ}q^½Qé8B!3"yl”ôpùšææEt·/3|S!*½^é8ŠÛ¢0!3�GÅÎMJG ]Õµ´ï{ Ç¢¼‘1JÇ ËŸOZ’‘3פ‡Ë4Ö{èÎ"ucšÈðíu 뢥RÁ”1ÉÔ·:8p¡Mé8AÍÖÒFÃöm8f?…'Á¢t VNKĨCz¸IÕÖ„þàvÌ«VaLJT:Ž¢Âºhh5jfŽKáâÝNN]—¡ºáîé¥nóœæàž­t@T*(œk¡«×Î�ê6¥ã%Uo†ý%Ä.ZLTf†ÒqöE À¨Ó0+/…£W[¸V#CuûÃãrq·t;®cq��¢tÿ ¿çÝ>£Óªx:?…êÆNªå°_œôûJˆœ8™„IÁÞëèR´ÞmÒ1mŒ™]§©m•¡º}U³c7� çä|¥£ˆeÔP47…ŠÛ-4¶É…aŸx½è¿†1Å‚eÁ,¥Ó )Zï“kdÂèDJ×ÓÚíT:NÀ»¿÷ÎŽóV†åÐ[Ñ?æx«çÈ:\}¥?õ6•›Ô•Ë”ŽP¤hý•´¤H2Rbyµ¬�^» Õý(�gʱ߸†}ázЄî2·F›�,™” =\Ÿ@{é8ê–ZF¬C­–_Óï'GãCd¥Ç’mdóáé1ùm×oÑyô0ö¥ÁÚË ß›˜ŤQÑœ¨°â”óë4w®¢½qžô‚õh áÙ‹õq¤h}„ñ£Q«Uì<Ñ¢t”€Ò]ßHËî]8®ÇúË ÿX8!ŽôDg¥‡ëjk5ú“oaY¿}¬ô:~)ZáA—™æNoŸoU:N@pttbÝZŠsæ“x’Ãcá?«f$!=\©Û›Ñ—í ~Å"‡I¯ãG‘¢õ14j3r-TÞïæô�ðªë¶Ù©Ù\ŒkìTÜ#Ç*G„€‡=\6;×Ã}.{/ºý¥DÏÏ'nL†Òiš­O ×i˜�gáhE Wkz”Ž£¯ÇCuéÜIi¸òf(G„­VÅÓ R¨ çu¸Ü. ûJ0å�#yÊD¥Ó<)Z}`2ꘑkaÏ™&ª›ìJÇrÕ»ßÂíUãœñ„ÒQDŠ2j(šŸBÅ�0ìáz·KGêãó”N¤hõQ\”�IYIl?f¥µ3|†êÖ8г®û‚5 Co…Ÿ˜cu¬žõnWwøôpéÎìCë´‘¾f¹ÒQ‚†üꇔ™ÃbÙ|¸ž^gèÕm¹x•ÞËp<¾t2ôVø×蔿ôpõÚCÿÂP[q mÝm†®C­•^Ǿ’¢ÕO™ÃbIŒ�`ó!+nwèÕí¸}�¶ýo?XfÄ­t&&fF1qtLÈ÷pijn¢½zšÔ�ј"”ŽT¤h À¸ŒDÔ %G•Žâ= M4íØŽcþj<ñf¥ãˆ0óøøXF$8}Õ’ ´ª›êÐÝMʆŒñÒ‹Õ_R´@¥‚)ÙÉtôºÙs6´z¸œ=½Ô—”âš¶Oj†ÒqD˜Z9= “^r=\êÎ6 JI\¶ “ôb ˆ­z¯‡ëF]7ǯv(Ç'¼N'5›‹qgŽÇ5z‚ÒqDS© pž…›ƒë!²—ÊÞ‹~_1ѳæ›;Fé8AKŠÖ èµjfå¥pòF—ïv+gp¼^în}wd<ÎI2ôöÃÈtCCK§Uñ©î7v—Û…þÀVLcÆ’4sªÒi‚š­AŠ4j™™cá­sÍÜk°)gÀj÷ìÃm³á˜»Bé(BT†ÅÈ’Ç8~%¸z¸´×ËÑU_#}Ã:T¹ ô)Z>42%sœ‰WZqAWOm=-{vc_¸oT¬ÒqžJ®’5!#Šicb8~%8z¸Ô÷o¡-/cئ�h"#•Ž2¤hùX^Fzƒ–’c òs{Gkõ%%8f?…'i˜Òq‚Bÿï óóbÉL1r&À{¸ÔÍõè�¼Ajáô ²îœ/IÑòƒÇ²’èéõ²ç\`. é±Û©-ÙŠkÂÜó•Ž#D¿<55‘(£Šó×›”Žò¡T=�èn#ù©§ˆH“uç|MŠ–¨U*¦åš©ªïåèÕv¥ã<Âëvs¿d;ÎÔL\92ôV• 6̵àv9¹h=\;†}[ˆŸ9ƒèéÅò)Z~¢Ó¨™=Ι\  .ë®Ý8´œS*%øîݨ°£Õ¨(Z`¡¾)€ÖáòzÐÜFô¨ âgLS:MÈ’¢åGF½–é9Þ9×Ìíèáj>XF·µÇœ•2ôV=“Aæü®H—îè.L&ÉK+%¤IÑò³¸(=SÆ$³ãXõ­Êõ˜t^¼HÇå+8áÕê”>,BøD|”ŽÂù)”_o¤]Á.ÝùC»šI]+½Xþ&Ek˜ã#Èù ‡«Ë6ô=&¶;wh:T†mÉF¼F“Ò‡CŸJM0ðä´DN]­W¤‡Ksó"ú{WVT€J/ëÎù›­!2ÒMzR$›5àpÝÃ{c#õ;v☻ oL‚Ò‡!¨ðë°—“ɬœXNUm—¦þ.ú e¤¢‰ŠRú0„Y.s匌çØå^|ý.‘F ùãã7·?è»�†×^Ã^_�>9Gs Žé‹q§ŒTúã=¹ëØfމ宵‡·Nß%B¯cܨx,ñþiêU7Ö¢?úªÎV¢§NEŸ˜¨ôÇò—Öjî°ÑÒáÄíöÒÑíb×éFnÖùörÝ«¯Ò{ëžînlwîàq{p�¯ôGÂïnÕus§¡·ºz�œ¾Ú@K§ï@©ºÚÑ¿³UG x½tž=Kç¹sJü°!EkÕ4t=ÒÅïñÀ•{¾®ëõxpµ<ÚÐìu9ÁãVú£ áw—ïõàñüåÏa�ª­¾¯¹[‰Êù¾A^/Ýׯ+ýñÆ­!”�Jýè=¦ÉŸí_¥V£þ«9ÎT­ÌÜ.ÂBz¢á‘V:�áó÷ñ¤ õ_~uz­Ù¬ôÇR´†PZR$‰QzÔ*Ði`bf$“3c|ú–‚4qq¨t:4QQ¨<.ÔMµJt!ünjV ‰Ñ:T€V£–ôdß?Óò$Ã9q.^�T*Œii$æç+ýñÆ ÄB÷›ºéµ»yö©áÄDúçÐëñ쳿î¹u‹†]¥ô>ùi¼Ñ2qç È@Œ€v´¢ 5jžš5­Æ¿×㮉sqMœ‹ÚZ�ªl;Φ&ô‹Ò‡ ,È_ZC¤¹ÝÆå[MÎ7û­`}ÓèÑ$Ì[€q *‡ò³ráw»8_ÕÉÔ‹ß Öûy,ñÏx‚ºâ\��J†° Ektö89{­�ճ̤ÄûîV_ÅLyŒ¨¬Ñèö—Ê ŒA�?´Ó݆^Þ.ofFn ýÐ?¿u�ÌÁ>f*µ›‹ñØíJŽ�'EËÏlN7'*êY8!�Ñ©¾(ÜWÉKaŠ1¡;ò†Ò‡DŸiì°³ýx“ǘ‰ŠPnz2×„ÙØÓ©Û¾�'ð¨ fR´üÈåöpòJ=“GEóØh…»åU*R×®Foë@[~XéC”¼2%F@éìu³¥¬�¼‘‰$ùa”`9g>�Í­¡a÷¥£„4)Z~âõ¹ë�¤&X0!Né8¨´ZÒ‹6`¸{íõr¥ã1`v—‡-euŒ°Ä�n�é“T*ìóVÓ]g¥ùÈ ¥Ó„,)Z~r©ª­ÚËêé�5ߟÆd"õéMè.A]wGé8Bô›Çã¥äH‘&#Yi±JÇy”N�cQ!åçi-¿¬tš�$EË®W·ÑÑm£h¾µ:ð±>.óÚ5èËv¢nmP:Žý²ëLN—Љ™�9ߟ7" û¢BÚî§«ê®ÒqBNàýF r÷»¨iìàé)èµ�{x#G'ù‰'1ì+AÕ#CuûB%3æ*îà¥6jšœLkèÿž¸$ùk±¾¶[S³ÒqBJàþV BÍ6®Ün¡p^ ѦÀŸ:)z\ÑS¦ ßWNåТ/Êowrñv'³ò,h4�[°Þã¶ŒÀ5} u[Šquú~Äp%EËG:{œ©|Ћe‰ØBp üçþ'¯¼òJŸ^_ZZʯ~õ+ª««œ;iÞl"G¤£/Ûñ`_!P•ÕÆ¡ ­Ì7ð^¬–Æ:^Ûò[îÝڧ׿ýÚŸymËoinø4hîQy8G�§fs)^§S‘cjd'°9Üœ¬°’?!žÌcÿ¶µÙسgåååܸq�Çà /¼Ð§móóóùÇüGÊÊÊÈÌÌdüøñ¬ZµŠ¨~.F—²l)ÕÅ¥pr/ŽÙO)}8…x„µÍÎÎ LÏé/–­·‡eoróêîWßD­Öð¥oþ¬OÛNœ6Ÿ_þèkœ?y�´YdåLdÖÂåû¹ú·ë±ù¨º;¨.ÙΈ§ ea¶A’¢5HN—‡õLÔÑÑ}Þ®££ƒŸýìg\½z•žžž‡ß7 üú׿îó~\.½½½\ºt‰K—.±mÛ6ÆŽËW¾òûº0�JEÚÚÕÜûã+x®œÄ5n¦Ò‡U:º]¶2.#�„˜¾_v´·Pú_/r·ª»í/kÖé FJÿëÅ>ïÇãqc·õp³²œ›•åÜSʈ̱lüÜW‰Œêûd×Î9O¡~§˜ûoì!m•\†­Aðz½œ¹Ö@Z‚�ùãú7ô6&&†O}êSlß¾�[·nQ__�×ëÅh4²~ýz4šO¾âõzyñÅéííÅëõb6›ÉÈÈ`ãÆ�}/XïR ¤?]Hõþˆ7" wæ8¥¯sv‡‡W׿;[{ÿîÄÄ&°hÅ&¿½ƒºšÛ´µ4àñxˆ0E’ÿä†> âp»]Ôýþßq:ì¨T*bãIžÉÒ•O÷«` RcÏ_{ÿŒõè),sg(}xƒ–­A(¿Ù„Q«bõ̤mŸ��Í×¾ö5<‡æäÉ“TVVR]]Íš5k>qû·Þz ¯×ËìÙ³™3góçÏÔ{mT© ©ýó«x£bñ˜Ó;¶"¼y<^6—Y‰1=l`½X£sÉ�‹Çã¦üT•—ÏpïÖUZ›˜1ï‰OÜþð;;Pk4ŒŸ<›IÓ0~òœÁ�XÔp,.¤ûÍÿ¦%.†„q9JÞ &Ek€*ï¶Òcs𷋇 úµZ­&??Ÿüü|zzz¸wï^Ÿ¶=z4¿üå/1™úw�ýã““I^¹’Æ7¶a_ö Þ˜ÀjŽáaë‰&<¨™8z`„ï§Vk˜2ëq¦ÌzœÞž.šëú´]Fö8fÎ_†ÞпçÔÇkŠÆ±p=íomAMÌÈ4¿ÃP%£வ“š¦.žžŸ‚^ëÛ‡ª&“‰œœ¾]��=Ú§ë=ÑY™Ä,ÈGÿN1*[Ïàw(D?¼]ÞJSû{½X¾Ýw„)Šá#³ûôÚá#³}Z°ÞãILÁ1oM;¶ÑÛÜêóý‡:)ZýÔÐÚ˵»­lšg!*z±*iÊ$"ssÑï+Aå’¡ºbhœ»ÙEeu³rƒ£k Üi™8[@ÝæÍ8»å°?¤hõC[—ƒs7Y=;süÀz±‚IÊâ| ‰ èŽîz0°~t½¶—²Ë-ÌÌSf]¬¡æÎž„{d.÷K¶JW?HÑê#›ÃÅéJ+K&'’iQ~„¡’¶f9:g/ºó‡”Ž"BX]‹�7N62m½XÁÌ9e!.SÕÛå°¯¤hõ�Óíáø+SFÇ0qd¤Òq†”J£!½`-Úêëh+Ï*G„ Î%‡­LÌJìW/V¨pÌYŽ£§—Ú·*%(HÑú¯—3WÈL‰èw/V¨Ð˜"VT„öÒ14Õ7”Ž#BˆÍááÏ­d¦Å2,1¼.Rkp.\GïÍ4œ8£tš€'Eë\¸ÙD„^Ͳ)á=ôÛ�GrA!úc»Q7÷mȰÇãñ²å°•¸h™ìÅ ^½Çâ"ºN� ¥âºÒqš­�Qq§»ÃIá¼d™. ˆNK!nÙ ¶¡êjW:ŽrÛ�7âñª™�9ø^¬Pà�ŽÃñxí{vÓU}_é8KŠÖG¸[߉µµ‡MóSÐù¸+˜Åçfaš6ýþT›ÒqD�z»¼•ÆN—_z±‚Ùƒ®•4îØ�­U. ?Œ­amíáÚÝVŠæY0åý5Ëœéè‡g ;° CoûkøòÅh# è�îR:ÊÐ�ÑÈ>qã~/G¯´†M/Ö@¹ÆLÆ•šAMÉ6<.—ÒqŠ­÷é¶¹8Yiå‰)‰Œ4”ŽØT*FlX�¦»ÝÅ£J§A ®ÅÁ®Ó�LÏ ¯^¬�rN[ŒKAÍŽ0¹0ì#)Zïr¼».ÖÌì8ƇY/Ö@©u:Ò7¢½u MÕe¥ãˆÖÖí¦äH=2‰�¿^¬Q©pÌ[…³½ƒºý‡•N0¤hn�—SW­Œfbvn?×É sºH–‚ôg÷£®»£t€lv7›Ö3jX©IrAØ/-öEôVVÐtú¼ÒiBØ-¯ÎÝh$Ö¤áÉ0ïÅ(“%‰ÄÕkÑ~ U[£ÒqDñx¼l>Ú@\Œ‘ÑÃä‚p@ Ø—l¤ãØQÚ®W)�Fqa_´*î4ãq»Ù0GzE#fÔb_‚áÀVT½ÝJÇbÛ‰F¼^52û·’¶x”7*GþZZw½NwmƒÒqÖE«ª¶�Æö^6η Õ„õ¡ð‰¤IyDäMxÐÃ%Ë™„½½çZiê�^,_ñ˜ÓqÌzki Žöðíá ÛßÔõ-=TÕ¶³i~ &CØŸK}|.zK úC;dÖê0vúf'×j»¬‹¥–Šå+î‘9¸s¦rK)»]é8ŠËßÖm]vÊo6±~n ÑZ¥ã„œô•O ñºÐ�Ø«t¡€k5=¾Üʬ\ z�ôbùšsü,\Ééٺ�Ç£tœ!vE«ÇæääU++§%“žú 9*A¥V3¼hÚ–Z´WO+ÇG䝯¾¨ou°ût3¥˯œ3–âðj©ÛµGé(C.¬Š–ÃéæD…•ùãã“> 9*Ac4’¶±íÕÓhî^S:Ž=nJ×31Kz±üN¥Â956k#Ö#Ç•N3¤Â¦h¹=^NUZÉÅ´Ñ2ôv(ècbHݰýɽ¨eÖêPfwzxõP݃^¬p]kˆyµ:�o ûüyZ/„OsX-¯Î]o 9VÏ¢IqJÇ +©)$®X‰~ÿVT�­JÇ~àñx)>b%!ÆD¦ôb )oDŽÅE´îßGgÕm¥ã ‰°(Z—o7ƒÇÃêÒ+¢„˜ìLb,Àðöf°õ(GøØÎ“�¸ýá×¥‡+œ­êäju³ò¤+¸GåáÊœ@õ漇Òqü&d‹Vs»�K·›)œ—Bl¤ôbŠ”UËÑ;:Ñ•—)¥_¤Ä>êV}/‡/¶0kœôbç¤y8c’©Ù¶#d/ C²huõ89{­�U3’I�—^¬@¢ÖjI+Ü€¾úšk甎# ¾ÕÁk'˜–›B¤Qz±�sÎS8ìêv‡fWÈ-›Ó͉Šzò'&��*½X�Hc2‘¶©Ã¥£hjn*GôCg�‹Ò£õL�DB´,”�Tjìùëè©®¥õT¨4÷ÿEH-—ÛéŠ:¦ŽŽbrf”ÒqÄÇÐÆÅ‘R°Ãñݨ[¬JÇ}`wzxµÌJFŠôb<½Ç’"ZOŸ¦«²Ré4>2EËë…óבddî¸x¥ãˆ>0FâÒ¥÷—¢êîxø}�[F�Ç˶£V’ã"¤+HxMÑØbÝû=55JÇñ™�(Z÷ïÝä?~ümÚ꯱lªôŠ“è¼\â¦O%bßpÚééîäO¿ù¡Ò±PWWÇ¿ÿû¿°ëL aÌp9¿‚‰7>™»�ñ¿žž}o¼¡tŸêau·o\áØþ7¸\~œˆÈ8ž-š‹Zu8¬ÄÍž…««ï`og/÷n_££½…˜Xù©¤-[¶píÚ5vŸ¸Kc§Žé¹©Ò‹„R¦/À±ý¼ôÿ/ûŽ£  €)S¦(kÀ‚î7¼×ëåÒ¹£ü×/¿Ïïÿã»\:¯×êUOaÐu kIK–pæþÎ|“®Îvíݪt¤°ÖÞÞÎÅ‹¹ÿ>[~÷3²ÌjéÅ bSòWàñz¹|ù2?ú·ãŸÿùŸ¹qã†Ò±$èŠVG{ Ï¡öÞ-ï.‚6løŠ Ö+M Pgg'ÿó«_eË™3tôöpój9.YýX1[¶l¡©© €Vk¿ùñó¼^üŸJÇ4wÑ*Í©ôôöÒØØÈþýû•Ž5 AW´bãù›Ï?φÏ}�È8 3§ME§“~‘`Í׿þu.\H\\ÖºjŽìMéhaÉn·Svø­ŽÑc'²då§XQð9¥£‰Òéôdf� #1‘ÿ¹|9ÿ÷¯t¬ º¢`s¸¹×Å“Ë×’œœÌÆ�•Ž$Él6óÅ/~‘_|‘%ùùhÕjΑ•�•ð߯l¡³³“ôÌ<þö ßâó_ù>3ç?)Ï‹ƒÜì…+0EF³ôégÑÕÔÑqö¬Ò‘$è9]NVÔ3-;š™c–¡÷´c2™”Ž%|$>>žç¾úU žx‚ßþüç´Ü®$aTŽÒ±Â†Ýéáê½. þþ_˜:i¼Òq„ žIFV.£ÇϤwäXš÷ü ML ‘ÙÙJGë— ºtòz½œ¹ÖÀðDsrãÐh4|êSŸR:–ðƒa&ð¿¾ò†]8ˆª7´g­n�—Ò£Væ,Ý(+D}úÙoà�ŽÃ¾¨€Æ]»±ÕÖ*«_‚ªh•ßl"B+f$)E �¨¼ Š¢u×ÚImK7Oç§ ×ÉnRW­@§r¢;œCtÝÙ›�TÜëaêXY+¹Æ<†35“êâ­xƒ` µ€/Z ­½TÞk¥h®™(£¬ÛŽTj5éëÑ×ßF{õŒÒqBÊ�û=¾Ü¬q)d]¬°åœº§ÖDíÎÀŸê) ‹V[—ƒs×Y?+sœ¬‹ÎÔ©E…h®œ@sïºÒqBBm³�7N52]ÖÅ*Žù«°·vP·ï°Òi>VÀ-›ÃÅéJ+K&'2Ò"ëb ÐÇÇ’ZP€þÄÔMÁ5â)дu:)>ZÏĬdâe], Ñb[T@oe�§w�Ö€,ZN·‡V¦eÇ21CÖía–Büòåö—¢êlU:NP²;b%;-žÔDéqïcˆÀ¾t#�Ç�Ñv£Jé4*àŠ–ÇëåÌÕFY"˜›+ëöˆŠ“Eô¼è÷—¢rLj§@áöxyõ°•¤8£Råüä�ŠÃ‘¿–Ö7^§«6ðh ¸¢uáf‘*–M‘e)ÄGKšö¦Q£Ðíß žÀñ(¶�hD­Ö�;BÎ/ñÑ<æt³ž¤¡´{[ÇàwèCU´*î´`·»(˜#½"â“¥>¹CTú#�?â)ì9ÛB[§›ÉÙÉr~‰O䙃+gµ›‹qÙìJÇy(`ŠÖÝúN¬­=lÊ7£ÕÈ%ú@¥"}ýj´=hË{Ä“ÒN^ïàV}3r¥Kô�kü,\)#ª‡+ Š–µµ‡Ê»­lšoÁd�^Ñw*­–´MÐß©@{ý¼ÒqÒÕ{Ý»ÚÆŒ\ :m@œò"ˆ8§/Á­1PýF`¬º øOp{—�ó×›X7×LbŒôŠˆþÓ™L¤<]„¦üêº;JÇ (ÕMvÞ<ÛÌŒ‹ôb‰�Q©pÎ_�³±‰ºƒÇ•N£lÑê¶¹8Yi剩Id˜�J ÄŒññ˜×®ÁP¶ukƒÒqBS§‹ÒcVËN’^,1(^­Çãëé½\Nã¹ËŠfQ¬h9\NTÔ3=;Žñ#¤WD ^tÆb—>�a_ ªžN¥ã(ªÇîfó¡zƤő’ ç—ÓL[¯›Éc¤Kø�;#OÖDê·”à¶í�!-ZUµí4¶õ²iž�ôb R©H_¿uK=Ú+'•N3$N\ë ª¾—9ÔR±„Ÿ9'ÎÅ™˜Jué¼CxGcÈŠ–µ¥‡[u<�oÁ$ëb‰! 1èIßTˆ¶ò,šª+JÇñ««ÕÝœ¬lgV^Šôb‰!㜹—ÛKõ®·†ì=‡ä§»­ËNùÍ&ÖÏ1%½"bè裣HÝX„þì~Ô 5JÇñ‹{Í6Þ<ÓÌ´\3&£Vé8"œ¨Ô8ò×ᬭ¥öÈÐÜÑð{Ñê±99Uiå©©É O”^1ô"ÌIÄ/_�þÐvT-JÇñ©¦N[�6<èÅŠ’óK(@§Ç±¤Ûù³4•WøýíüZ´N7Ç+¬ÌÎ�#g¸,ä(”—�IÌÜèß)FeëQ:ŽOôØ=l)«g¬ôb …y#¢°/*¤ãà>ÚïÞ÷ë{ù­h½×‹•3<’™ÙÒ+"”—4mcsÐï+Aår*gP\n/¯”YIIŒ$Cz±DðÆ'㜻‚æí[éilöÛûø¥hy½pîz 1z–N’^8†-]ˆ61ÝÑ]~PƒÔÖcM´r¥KwZ&ÎÉùÔo)ÆÙåŸ.¿­Ë·›ñx<¬�) ͉À3|õ2´Îtç*e@vŸm¦£×Åä1Òë(�;{îQyÜßR‚Çéû;>/Z7kÚiî´±i¾­F†ÞŠÀ£ÖjI+\‡¶æÚʳJÇé—“×;¸#½X"À9'çãŠI¢fû>¿£áÓªRÛÔÍ�ºvžžo& K.]DÃ6¢½t Mõ ¥ãôIEu7ǯ¶3Cz±DpÌ~ g¯�š½|º_Ÿýä7·Û¸p«™‚y)Ò‹%‚‚!!žä è�íFÝ\÷ñ/Vøñ×½F;o�mffž“Az±DPk°/\‡ãÎm¬ÇÏøn·¾ØIW�“3×X1#™a‰zÅŽ‘ý�žJì²lCÕÕþ‘¯S+¸D}k—“íG뙘•Dl¤œ_"ˆè ØÐ}ú­×|²ËA-›ÓÍñŠzæå%�“&½X"ø$äfaœ:ýþT›ÒqÑc÷ðÊ!+Y#â¥K%oT,öÇ hÛ»‡Î{µƒÞß Š–Ëíáä•z&dD1=;Jéc#Ä€¥Î��adºÛÀãV:.—‡Íeõ¤&D2*Ez±Dðò&¦`Ÿ·’Æí[émjÔ¾\´ôb5b‰3°h¢ôŠˆà—¾l1ºH#ú£»>ðoCýHËë…’ãMè´ZrFÊù%‚Ÿ'm4®Ió©/-ÅÝÓ;àý ¸h]®jF£†µ³•>Bø†Jňõ«Ñt·¡»xô‘òq#ò›g›éêqK/–)®1�áJͤ¦d+^÷Àîh ¨h]¯n£­ÛFá¼$é!E¥Õ’^T€®ê2šªËùþþœ¿ÖÉmk/3r¥K„ç´E8õ‘To{}@Û÷»hÝoìâ~C'“Ÿ‚Q'ëb‰Ð£‹2‘Z´Ý™ý¨ëî<øæý¥uå^7§®µ1Sz±D¨R©pÌ[…³£“Ú}eýÞ¼_g…Ëa£âv ›òSˆŠ�‚%B—!) ˺u¿†ª­‘¡X»¾®ÅÎÛ盘‘+½X"Äi´8Ð{í*çÏ÷kÓ~�‡.5°až™Äi¡/räp–.¡åàVT~ŠáõzÙ¼¯ŠœŒ$ô*½=¥?¾~çž¿’Ú··ôk›>-�ÞÀá?}�c¯È=vfÜn\N'jµn×iµZŒ¦HŽ—þNªTþ«N…ÿF9úk ʃ̾ÿ�¢R�Çã›ÌCù<ó#3àUzRŸ ¯×ûȳZ¯×Cr\\ß3xûøÓh³Ùp¹\C”„Z­£Ñ¨t !Â^Ÿ‹–B¡4ž$„"hHÑB4¤h !„R´„B )ZBˆ�ÔÒÒÂÞ½{iooüÎ>ÄÁƒ¹~ýºÒ3ìHÛý´µµñOÿôO�|/""‚ôôtV¯^MNNŽÒ…i{öìaëÖ­¿6 X,òóóY°`V«•_üâdffëó /¿ü2‹/f̘1Jް"EkÜn7V«•Ù³g3eÊš››9|ø0ßøÆ7øÁ~@nn®Ò1…Y]]]X­V>ó™ÏMgg'ÇŽãÇ?þ1ÍÍͬ[·³ÙÌg>óe%ŠP"Ek²³³yòÉ'~½|ùr>ûÙÏrðàÁ-ZMMMØl6, :Ýà§Âòz½X­V""">öJ²»»›ÖÖV¢¢¢ˆûˆÎóÖÖVº»»IJJ’&Z4òóóIN~°|Ëš5køâ¿Èo¼ÁºuëHLL¤  à#·íé顽½³ÙŒFóás©¾wŽy½^’’’>ò¼íêꢫ« ³Ùì·™SÄR´|(&&­V‹Ãñè¼qW¯^套^¢¦¦£ÑÈúõëÙ¸qãÃiQ^~ùeŽ9ÂË/¿üȶ?úÑ�hllä…^àøñãüð‡?äÛßþ6üã¹wï¹¹¹<ÿüó$$$<ܶ±±‘_üâ”——ãñxHMMåûßÿþÃýúõëüò—¿¤ªª x0óÃÊ•+ùìg?+'Ÿ*:�Žœœ<ˆÓéäæÍ›<ÿüóüä'?!;;€/|á äååÉo¼�ËåÂ`0ð…/|�E‹=²¿×_�âââ‡ÏÄôz=EEE=|�ÛíæW¿ú{÷îÅãñ`2™xî¹ç˜3gŽÒ‡#dIÑ»ÝNWWðà9×®]»p¹\äçç?|�Õjå»ßý.iiiüìg?#&&†={öðÊ+¯`4Y»ví€Þû·¿ý-Ï<ó ãÆ�£ªªŠŸþô§üùÏæK_úðà*ò›ßü&n·›¯ýëäääÐÓÓÙ3gîãþýû|ûÛßf„ |ùË_&>>ž3gÎðë_ÿšÈÈH6nܨô!¢Ï¼^/555ÄÆÆ~ì�Œ£G�2yòd~úÓŸb0øÃþÀüÇ0a„‡s;wîäw¿ûË—/gåÊ•DEEqçÎZZZÙ×[o½ÅìÙ³y饗P«Õüæ7¿áÅ_d„ DGG+}HB’­Aزe [¶üe†b�NdzÏ>Ëc�=öð{o½õ‡ƒçŸ‹ÅÀ§?ýinܸÁ¶mÛ\´Ö¯_ÏÂ… HNNfáÂ…œ>}úá¿¿óÎ;X­Vþíßþíá­Ê¸¸8V¯^ýð5¥¥¥DEEñüóÏ£×ëX²d 555ìÚµKŠ–xwïÞ¥½½�îîn<ÈÍ›7yê©§>v›¨¨(¾úÕ¯¢Õ>øõ÷ùÏžãÇ�såÊ.\ˆËåbóæÍLŸ>�gŸ}öávï?¯ß“œœÌsÏ=÷ðŽÉç>÷9ž{î9*++™>}ºÒ‡'$IÑ„åË—³dÉàÁs£³gÏò«_ý �ÇÃòå˸sç#GŽ|X°Þ3sæLÊËËiooÐȦ¼¼¼G¾NII¡¥¥¯×‹J¥âÊ•+$%%}ì€�Ë—/Ç�ù~gg'mmmtvvÊÕ¢hßûÞ÷þw||lØ0àÁÀ,áR´!))‰¬¬¬‡_Oš4 «ÕÊþð–.]ŠN§£££ƒ˜˜˜lû^1hmmPÑ2™L�|­Õj>·‚E4î¦ûïêêÂívsøðáüÛĉ±ÛíR´D@ûùÏNRRz½þáÝ‚Oñ�ïi4š‡«Xtww|èyû×þú<|o@‡¬ˆá?R´|,55•ãÇ�ÓÚÚŠÙl&))éá`‰÷{ïJÌl6~Ø�Nç^×ÑÑ1 qqqܽ{÷c_Czz:ßùÎw”>lB Hdd$QQQ>Ýç{‘ïýå%‹ ó!·ÛMyy9z½ž¤¤$F�Muu5·nÝzø:¯×Ë¡C‡HKK{x¥f6›iooä¶Bkkë€;î§M›F{{;Ç�ÿÈ×LŸ>� .PWW§ô¡"`Œ1‚äädöîÝë·Å/ÅÀÉ_ZƒpöìÙ‡·l6åååÜ¿ŸÏ|æ3‡‹?õÔS¼ùæ›üË¿ü Ï<ó 111ìÝ»—ªª*žþù‡ûš5k¿ûÝïøñ�ÌêÕ«éîîfûöí¾=7þ|öîÝËO~ò ;v,===œ>}šÂÂB† Faa!'Ožäßø6l`øðáôôôpëÖ-ªªªøßÿû+}ˆ…r*•Š¿û»¿ã‡?ü!ßúÖ·X¶l±±±Ü¹s›Í&”&Ek4 YYYØív.\¸<¸Õ6qâD¾üå/?2�Sdd$ÿú¯ÿÊïÿ{^~ùel6|ó›ßdÖ¬Y_Ïw¾ó~ÿûßó“Ÿü‹ÅÂ3Ï<Ãõë×ikk{dYYYh†Œ��}äùšF£á»ßý.›7oæí·ßfóæÍÄÄÄ0nܸ‡·Sbccyá…xõÕWÙ¾};---ÄÆÆ2|øðô¬HÈÊÊúØ¡íF£‘¬¬¬Gšåßû+ê¯�=ú‘Ç™3gò½ï}�-[¶ðÒK/0|øðGFßfdd<²Í{²²²ˆ��Wú…,Y¹X!DÐ�gZB!‚†-!„ACŠ–Bˆ !EK!DÐ�¢%„"hHÑB4¤h !„R´„B )ZB!‚Æÿ÷¯Õ�ÁÞô%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--7ktoom0527a.png000066400000000000000000000267321524103652300217600ustar00rootroot00000000000000‰PNG  IHDR<àžŽÚæ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ü’Žu,ºIDATxÚíÝùw›×�çù7¶ûJܵQԾؒlÅq¼Äqg©$U©JWª§kjºêtŸé§gzΩ™>}æL*Ý'Ý'•TÖN¼ÆN$K²lI–D‰w @ìx<ëü@YŽm-Üß×92e‰„î�Ü{Ÿ{¿×aÛ¶�Btg« „ÛEOÑ5$ð„]COÑ5$ð„]COÑ5$ð„]COÑ5$ð„]ÃÝêˆOjhŪNI5(ÕtjM“ZÓ¦Ö0¨7mšº‰aÚhº…íÛ²Ñ�•Í2N'xœNl(.'N'ø'~¯‹€ÇIÀç"ès¸ˆ=DnB~7G«¯Zˆíá�­e­QmäJ:éB“LI#[X 9‡Ó&èsðyð{Üx7ŠÛ‰âv¡xV>ºœÜn'å”ǽÒQ7-ËZy9uÓ¶m4ÃBÓM4ݺÿû†nPoè¨Mƒ†fò¹IF<$£^ú ɨ‡DH‘ ;ŽÞ60M›ÅB“¹åsÙ& Ë ,ÛA,è!ôxˆ‚~×öÎ2X¶�Ú0¨Ô4Jª†ªê”êMÔ¦AÔËp¯�‘¤�Á/¯«ÕO¥"�·EÒE�ÉE•Û *™R“hP!ò ûé‰xñ)í=›`˜…j“B¹I¡Ú PiðºÙ×ïcÿ@€]I?n—tEg‘ÀÛ$†i3±Xcb¡ÎÝt·ËA2ê'’ˆøpux8Ø6”U�¥¢Êr¡N¾Òd¨×Ë�¡cC!"~éý‰ö'�·†aq7SçúŒÊdZ%òÒß  ôµwn£tÃ"Wª³”WYÌ«$#Žìrp8Hh‡_»è\xë0ŸorùN…[s5¢!/ƒ½AOwör,Û&[¬³�­’.Ôé�{yr4ÄÁÁ`Ç÷lÅÎ"�·J ÍâÙ*—'*4u›á¾0»R!¼Jw†ÜÃX¶MzYef©B¹ªqtO�'÷Eè�xZÝ4!$ð§PÑ9«Ä�™©¸Ÿ‘¾½Q_«›ÕÔ†ÁÌR…¹l…Þ�ÂÙCQFü­n–èbx‘.49³Ä�t�ádˆÑá~éÍ­‹mÛ,æU&çKè–ÅÓcažØ‘»¼bÛIà}ÊôR�7®¨Õ-öôGé árÊæfÉ–êÜ](S«i«26cï@X‚®…r¥×§—ñ+¾úDý o«›$v ® <Û†÷&Êüþz�ÁÞ G÷7ߋֲm˜]ª0>]`lØÏ Çã½²ˆYlž® ¼¥B“Ÿ_È�Óű==„²6¬é†Åí¹"s¹ /�HpbO¸ÕM;DWžaXüáf‘KwªÜgOŸüu‚²ªqe"‡_qðõ§zè +­n’èp;>ðæ–›üì|–°ßñ½½²3¢ÃØ6ÜY(1±Pâ Gb<=iu“DÛ±�gYïÜ(rq¢Ê‰}½ ôZÝ$±jÃàò­,?üÙÓ)ÂR�E¬ÃŽ ¼bUç§ïf1MOŒ¥ðI¯nG°m¸3Wbr±ÄWN'8<ju“D‡Ùq�w}¶Êÿ¼”gl$ÆÞþìD…j“Ë·³ŒõùxùT�ìÔ«¶cϲ,^¿RäúœÊSSD‚2Á½“¦ÅYLÓäϟ퓤bUvDà©M“Ÿœ[B3œKɺº.2¹Pfb¾À·?—dOŸÌÓŠGëøÀË›üøí%{C‰Ëþ×.”-Õ¹|+Ës‡cœ> Óâá::ðî,ÖùÙù,ÇG{ì‘=˜ÝLm¼{3Í�A?_:Ù#o|â�:6ðÞŸ,óÆÕ"g¤HD¤ §X™×»tk‰�¾ó¹>ð,Ëâ'ç²Ô6§öá”Ûob�¦—*Ü�+òƒ/öJèu³¶þòâ2eUÂN¬ßîT˜}Ã1þéµEJªÞêæˆjëÀûõÅéÂÊœ�„�؈ݩ0»úcüð� Õ†ÑêæˆiÛÀ{õý<3Ë:Oé“ӬĦŠ0ØâGofhêV«›#Z -ïâí2ã *g�ôávµeE‡:0#ôñßÿ�Á²ÚzúZl�¶K“;‹*ï\/òÔ¡><vb ÝÛƒa8øÅ¥\«›"¶Y[%J:ßägçsœ9ÔGÐ'wÓÄÖp8àÔÁ>ò:o_/´º9bµMàUë?~{‰“û{‰‡åLR±µ\NOìãò�*7窭nŽØ&mx–eó“sYFúÃô'¤¦™Ø^ÅÅS‡úøÍÅ<Ùr³ÕÍÛ -ï·—óØ¶“±¡X«›"ºL$¨pxO‚ÿñvVîÜv�–Þµé é:'Ç’RÃL´Äp*D<ìãççå&ÆN×ÒÀ[®h¼z¹À™ƒ)¹#+Zêè¾rUƒwÇK­nŠØB-K˲ø—ó9ìŠÈ�;¢µœ§¤xçf‰LIkusÄiYà½q­'»ûí~„ àssdw‚þã†)‹’w¢–ÞL¶Áµ©*'÷'[}ýB|ÂH*DÀçáµ+Ë­nŠØÛxšnó‹w—81šÄë‘òÛ¢ýœØ—d|®Îl¶ÞꦈM¶í�÷æµ<Ñ��TÜßêkâ�¯KN‹»Ç¯¸ØÝæíë%^9#˪:Õ–Þ›× ‰ãè¢Û¶©k&õ†�ªÔ�¦A]3¨5tÔ¦‰_qP\øŸ¿â"tâ÷zð+Î{¿\ø'N§Ÿg¥wìt‚â^[OÙ0?IͰ°l¨7MšµÒNÍ¢®Y¨ �zÝbùÞß©M“ZÓÄçqô{ð+n|^7~ÅMÀçÆï]ùØM�¸(ÊkïÍñÌá(±à–þèˆ-â°m{Kfbï,ªüör�çNíÈ:w¶ jS§TÓ¨ªUU§¨j¨ ƒ€×EÄï&r¹‰ÜD‚nb7á€û~�«ÝÙ6T¥Ú½_ªA¡jP¬”UƒjÃÀëv zûB…HP!ðìØ ¼9]@q|óiÙÞ‰¶ìmê�kÆFâ;"ì Ó¢XÕV­®Q®iTT�€ÏM2â¡?®ph(H*'tãì�@{‡Â~7a¿›áÞNI5È•4²%�L±ÎL¦D±¦òyˆ<÷C0òîˆç£ÃQ^»8G¡¢˪ƒN³%=¼É´Êo.xþÉ¡V_ߺ44“|¹A¡Ú PnRQu’Q…þ¸B*¶ò«7âYóð²[˜–ÍrY'[ÖX*j¤‹éå&^ÅE"ì#ö’ˆøù;30nÍñ¸ ¾q¦wã&¶Õ–Þß\$ 3œìŒ›Uc¹Ü¤Pm�/7°L›Á„—])ý>úãJÇ CÛ•mC®¬1—k2›k0›k 6‰°—XØG"â#òvĈ@7,^»4Ë?¼2DÈ'sy�dÓ/[ÒøÑ›i^:=Ò¶ó8¦e“+ÕY*ÔÉTœNØ•ô³+ée¨×G� U¶E¥n2/üf–”ë©x€TÌO2hëôÕ;9úã.^8&ëK;ɦÞÏÎg± cÃÑV_Û'45“¥R�l^e©X'ò06àgl(@\ÎÁmjÓänºÎ­y•é¥:AŸ‡TÜO* j¯×HmüþÊÿá#(žö|cŸµ©�W­›üã¯çxéôž6xw®5 æ³U2ù Íd߀Ÿ±Á{ûüx=­oŸx8Ó²™É6˜XP¹½XÇ4mú{ ÷†ˆ¶Iø]Ïp|w€'÷É1�bSïÜ�"“9�“£­»e¯ó¹ ¹*µ†Î‘‘ Gw…HtÆü�x°åŠÎ�™W§«`Ã`2ÄPoˆ@ çЖ uî,äù·_îÌ›sÝhSï?ýrŽ“û“Û>ü°l›l¡N:_#�Wêñqboˆƒ�³DD|,WÖ¸:UåÊd¿×Í`oˆ¡dpÛ� °mxõò,õ…>úcrò^'Ø´À›ÌÔùÍ¥<Ï?±}ïvõ¦ÁTºÌL¦B*æåÄž†2\í–es7]çÊT•©L�þž{ú£ÄBÛ>ã3EŠÁWOÉ•N°i�÷“?dP|~ööG¶¼Ñ…J“ÉŹb�{Ü‹ Èò€nÖÐ->¸[áÂí2~¯›=ýQú�-ŸÆhho½?ÏøÖ.<.M´»M ¼¦añÿe–—ÏŒlYUÛ†¥‚Ê�…šnðäh„'GÃ÷÷™ +ß'wUÞ½]¦PÑIEØ=ÞÒj=ï^Osö`˜Ã#RÍ»ÝmJà]�®pyBåÌá¾Mo mÛLe*Ü�/¹9{0Êþ�­ç�o!ßäüx‰©L�]}aF£[²½mv©J¥ªò½/¤Z}Éâ16exc¦Æ@ïæîª°mXÈUŸ-Òqó—_HÉz9±&ƒ /ß}&EY5øãͯ_žcw„}ƒÑM]ÔÜŸðáÝešº%óÇmnÃ=¼†fòüb–—OïÚ´µw™‚ÊøL¿âॠF’¾V?Ob(«ï\/rs^et0ÊÞ�Ȧm|÷f†§ö8ºKÖäµ³ Þ•É*L©œ>¸ñî|¡Òàæt˲xñDœ±Á@«Ÿ±ª:¯}P`±Ðäà®C›p’Þ\¶J©\å/Ÿëoõå‰GØð�öö¼J*±±`jê&7§ó,—¼x<ÎÑ]!™£[&òðϦ˜Í5øíå<3™2Ç÷ö ¬u_"ÀÕ»9 ÃÂÝ»ŒÄƒm蕱,‹éå:©¨Ý�1�®ðÖóôE]ü»¯ sl·„�Ø#½>þîåAžØä�.rsº€i­oÀãq9‰…æ–›­¾,ñ ¼ùe� ×�WYû�¯†fpþzšL¡Â^è祓 æ–d¯]­;ð—›$ÂʪªçJuþøá"ÏŒð­³I™«mÏá€Ï‰ñ�gR|p;Ëtº¼ª¯K„}Ì,˰¶]­;ðfs ¢áÇg§3.ßÎòÝgR¼n› ãK]¯çp@oØËB^zyíh]�W¬x=·nÀŸ-Pªªüë/òuþáËB¸œþâÙñ€“÷ÆÞÓ ½,µV7W<Àºo©Ø$ü�ª²“é2éåß®¿"[lÄÎât8ø³³IB~ïOä8§ (dJÒÃkGë <�°ï³�·°\cr¡Äß¼ØOPzvb‡r8àÛg“Ø–ÁÍéügþ>TÈJ¯-­3ðtÂÁO^¹¦qõî2ß{6EDÊ­‹Îírð½gûX*ªÌg«Ÿø»pÀC±¢¯{_®Ø:ë ¼lI#ò'•%tÓâÂx†WN÷H‘NÑ5|Š“ï=›âé÷†¶Ÿ‡buõ…ÄöX{à©:¾{whoÏÙ×`°GæíDwó{]Â~Y`,ÄŸr8àÉ}!frUœ€fX›zè÷NÕ4,ÞºVàút•Cöøz]”ë&Sé:o]ÍóÌ‘O�E7ôï¬=ð4«Ùä…c±V?GB´¥c»Cœ»9�¢¸©k¦Þc”Uƒ¿�f0áåß½2‚ïS{ðOì S¬üìÜéå&ß:›Z÷Ñk~%MƒŠª3:°þ£…ØÉÂ~7=§êM©‹÷(jÓ俾•æØž¯œI~&ì> ºù›P›&¯~�[÷¿·öÀ³l{|÷ !>koʇ ¦ì§}”_^È26àì�Øc?×årðÝÏ÷qk¾ÎTf}Ça®½¯m[ìí“êÅB<Êž>? t ¼‡º9W£¤¼plõKÛ¼'_;ÝÃo/ç[nÿAÖx.‡“”œ#+Ä#%c Ý”Š)�ðö‡^:‘À¹ÆÑâ¾þ^ÅÉø|mÍÿæšnZ44 ðñJaO!É4mœN'…š,MùS¶ ?=—a.פ©[¸]ëdÚàp8øù»Yþða‘/ŸJ0’\Ý=…Uÿk—'ÊüÇŸÏ`X6?|}‘7¯äWû¥Bt•·?,ðþbÍ0yíƒ,ïÞ.¶ºImãâí2·æTª Ý´ùÝûËk~Œ ·J¤—¦ÍRYãÕ5<ƪï�ãÅû°¦eóÞdYæ'„ø˶¹4Q¹?”µ-ço”Zݬ¶Q¨êüé}ëõÜÔ)Ö þôË´5<ƪï3„¶ó‘ÇÕ Ñ�l°òç‚§F‰Þ«ˆnC‰µß}j„�e×…Çå`¨wõ�±êÀ;5¹ÿÉN‡ƒCÃYP)ħ¸œŽì ñÑ<¼ÓáàÄÞкÊî4± ›¿~±Ÿ§Dñyœ=´ö�ñˆ‡c»CôFܼrª—oœI®úköºiŪÁÿõ«9þîKƒô%äN­“-iü·ß§9¹;ÈsÇ{ZÝœ¶ô‡E²e�oŸ]}`†ÅúÕß®�Tlm¥éÖÔE‹…Ü(nø¥BŠ�’Œ*˜&$北‡:³?ÊÂr“‰Åµ-"þý�#½Þ5‡¬gžËÁrE'âQ4ÃB3,bA =ŒâqðͧzùÕÅËåÕK�ʨ\›ªðåSëë5¯c᱃\I*¹ ñ(Ù’ŽÇå$à•yîGIúøÒÉ?zs‘¹\ý‘Ÿ;•©ó³óY¾ûL’ w}•šÖüU~¯“Ɍʙ±H«Ÿ+!ÚÖt¶ŽnYø½2ýó8Gv…ð).~òÇ,cC~Îì�ÑùøTÄBEçÜx‘»é:þù>†×pWöÓÖx‰°‡ÉLãÞjçV?UB´§ÉÅ669ÜjUöõûù‡¯qþV‰ÿöÖ"¦e x¨Ö pØßáß~eø¡ÕTVkÍ�ö»ñz\Leêìí—QB|šÚ4É”šøCYÕè‹ÉÚv´®Àë�y(Õ><¯ââôÁ?=—¥P•¢;¦Íÿxg‰Ñ¡ñðÇû;«ªNJÊBµ¥u^<èÁÔWÊß|$ñq`8Î�ß^¢¡ÉR±³­œ¾•%àUØ;ðÉBeU£/*=¼v´î½/©¸B¡ÒøÄŸíîÓõó£·ÒŸC!vš__ÊQ®[ýd]6Û¶É— öÈaõíhÝ�·+åc¹ÒüÌŸÞ�ÀïUøñÛKrª™Ø‘~{y™¹e�3ûp~ªdP©ª ºñzdm;Z÷«2Üë£T~ðMŠãûzq9ÝüèÍ4MÙ‰!vÛ†_^È1�mòô‘>\(ý”¯67T¯Ml­uÞPÂG¡ª=pý�Ã'ö÷â÷)üð�Ej )2 :›iÙüôÜ™¢ÁÙÃx\þÑ)•ìJJ൫užâq)0¬ýÈÑ==$"AþË« ,•d7†èLjÓä‡o¤©6ੇôì>’+5¤‡×Æ64ѰÀÇRñÑkïŒÄ80’àŸÞHs{am§ ÑjK%�ÿò»ÂA§¦>3g÷§ŠÕ&^¯“È&×p›gC�7: [¬=öó†zƒ<}¸�ß\Zæõ+yÙ†&:•© ÿôFš±‘Gâ�ýü¥b�±þ@«›-aC�7Ôã£^7iè�Ÿ£‹…¼|áäÓY�ÿïõ4eÕhõµ ñ@šañów³¼s½Ìç�0Ô\Õ×åŠ*£ƒ2œmg <‡Fú|d «ÛR¦¸�<}¸�x8ÀþíW&+­¾~!>a&ÛàÿþÍ<Õ¦ƒ/œ$XÝbݰ(UuFz圗v¶áɆƒCÞ»[c$Zõ׌EIÆüœÏrsNå•3=„ý2ï!ZG3,Þ¼ZàÆ¬Ê‰Ñ^RñµW:¯²«Ï÷È¢õ6¼:rl0H®Ð@7×¶Þ.Txöø ŠâåÿùŸ œ/ÉÜžh‰ñùÿøëy–+6/<1´æ°X\®qtxuC_Ñ:îVy=N†“>2Ë*Ãkèå8ŒÄJ¹vw™«ÓU^>™`OŸ ÄÖË•5^ý @¾bpb’žÈúæßtÓb¹Ô`ÿP²Õ—$ÃaÛïV]Ÿ©ráV�§Žômèqs5nΈ‡Ü|ñxœ�„Tœ›¯¬¼u­À�t�Ñ¡{ûÃ86pªüL¦‚ªªüù³ûþ[oS&ÎFüêÒ2ºaáq¯”<Ф¿'Èb¾ÆÿÃ=a_~"A2*¥²ÅÆÕ5‹sãE>¸Sa¤/Ì‹O?tÇÄZ,æk[#PØ3# lË÷Àt¦Ì“£›³ÛkS{x?;¿„íPŽmÛEè†ÅB®ÆB®JEÕ88äøž�”éÙ¡*uƒñ9•÷'+Ô›ƒ½Avõ… ú¶ï‰j]çܵþ÷oîÂ-»+:ƦÞR±É�ÞÈðÒ™\-8—³ÖЙËV™ÏÕPœŽï rdwˆ¨”ìéh Íb|¾Æ•©*Ëe�ÁÞ C½!âáÖÜÀú`"ËP�›ç�>¾ŠŠh›xÿõ­4ñHhMûk·B¡Ò`.[cq¹FÈçbt0ÀØ€Ÿ¡Ÿ {;@¶¤qg±ÎíE•lQ#•ð3Ô"÷oh¡ðFiºÉkïÍñï¿>LÀ»9Ë[ÄöØ’À›Ê¨üêRaÓ—¨¬—mC©Ö$Wj�-ªTj»R~öõû ôÉ7m;0L›¹\ƒÉL�ñyôIFý¤âzcþ–Œäæl�€Ëäkgz[ݱF[xÿùwóìNÅXe-±íÔÐL2y•lQ%WjÐUØ“ò1Üëc¨Ç+'NmôIšÌåLg›ÌçÄB ½±ýñÀªK3m'Ý´xýÒûòñPûµO<Ú–ÞÝ´Êo.xþ‰¡¶>Z¶Ír©A¾Ü PmP(kDnv¥|ŒôzîõIÉîMÒÐ,ær f—Ìf›,›Dƒ ñ�—xÄGoÌ¿)[½¶Ò�é�É+Ò»ëH[xÿï« ôFJ¶v.o-lÛ¦TÓÈ—+M–Ë \.ý>úc ©˜BoÄ#!ø Í"SÔÈ•5Ò�ùå&ÕºA"â%ò‘ˆx‰‡:«~œfX¼~i–ÿõ+ƒÄƒÒ»ëD[xSK*?7ÏŸjé$óFÕ:ùr“J]£RÓ(×Vާì‰(¤¢ ýq…dÔCoDéºá°iÙäÊ:Ù’F¶¤‘.®|4 ›hH!èWâa/‘€ÒÖ½ýǹ1�'äµøê)éÝuª- <€¾¾H<bOßΪ&¡›•šFEÕ©54J5�bEÃé„hÐC,è&pò¹‰…ÜÄ‚naÊ-ÈÞ*–e£6-ª ƒbÍ P5(Tu UƒRM§Ö4 ùÜ„ AŸ‡pP!ì÷ì¬ 7õ¦Á›Wø‡¯ öËM®Nµå�·ThòO¿ÏðÅM*ÅÓîšI½©£6 Ô¦AC3¨7 Ô†A­i ¸WŽñ z]ø½N^~ʼn_Yùÿ�?®ü~³µš–MC³¨k&uÍ¢Þ\ù}C³P›&jsåc½iQ®¨M“€×EÀëÆïuãWÜø}¾{¿÷º:º÷¾Zï�gØ�RxNÖÝu´-<€_^Ì¢6�Ù+%º‰Ú0ÐuͰЌ•�†i¢ëºa¢éMݤiX˜¦�ÃÁýž¡Ë鸂·§Ã�ÃNXØ@óÞ)r¦ƽÒû†icZ6N§¯Ç‰âvâu»ðxœxÜ.Üî•�ŠÛ‰âv¡xœ]h�R¨4xïv–ÿÊ0žšsŸµ-3ï/Oð�¿šgW„�¿»'{}¾5Öb³í�ƒË´m,så=Ê0-,ÛÆX6÷çÇ÷Êã;Üß<ïr9¤²Ì:Ø6|8™çK'ãv;À¶^Àëâs‡#\ŸZæéÃý­¾æŽãpp¿ƒçþÄv˜ÎTð*pd¤sVˆ‡Û¶Iµ§Æ"X–Á|¶ÚêkbUššÉ­é_“âž;ƶžÓéäO%ùp:ŽIˆvvõnŽScaúbRa{§ØÖÛ¦}1/Çw‡¸>¹Üêëâ‘2•ZSç󇢭nŠØDÛ¾NäùcqJµ&™‚Úêkâ�tÃâê�ßzªw‡­›�¶í¯¦ÇåàÏÎ&¹z'GS“¡­h?Wïf9²+(dw –¼} ÷ú8¹7Äw²­¾~!>a:S¡Þ0xñ˜,0Þ‰ZÖ_îh “ÉÅr«Ÿ!P:7g |癤 ew¨–½ªN§“ïœMq{¶HYÕZý<ˆ.gÙ6dz¼p4F2º³ö‹�µôm,òðÕÓ .ÜÌ V«Ÿ ÑÅ®LäH†�œÚ/§�íd-ï· qx(Èå[Klý®^!>k*]¡¢6øæY9P{§kyà¼t2†Çeqk¶Ðꦈ.SªiŒÏøÞ³ý]W˰µÅ+ìt:ùÎçú˜ËUIçe}žØ ÍäÂÍ ßxª‡žˆlPîmx!¿‹¿üBW'rä+ÍV7Gìp¦esáf†§ö‡80Ô~M‰­Ñ6�ÐSøæÙ$Ç3Ôz«›#v(Û†ËãK %<‘Àé”y ±:;.ðʪÁOÏeÑ,OìOâ—!îŽ`Û6 e¦‹|ãL’ýƒ2„k³#V†¸¸QàÂD…ã{{è‘»¸�¬ÖÐyïv–¨ÏÁ7ŸNÉbb±.;6ð>2ŸoòóóKø½ ÇF{ñy䥓ضÍ�…2“ó%ž=ã̘£(ÖoÇ€eÙœ¿UâÜx™±á{û#²|¥”kWî䈜|íT±�ìªÓ�÷‘lIãçs˜G÷ö È óíH7-nOç™_®ñò“=Ýju“ÄÑU�+s{ïß-óÖ‡úŒ$ðÊ0·-Ø6L§+Üž+p`ØÏ ǼòÚˆÍÓu�÷‘†fòöõ"W§kŒ FÙ3Á)ãÜ–É–êÜœÌ ¸xùÉ}Qé}‹Í×µ�÷‘åŠÆ«ïÈ5F‡bìî á�àÛ6ùrƒñÙ"†nðâɇd©‰Ø:]xY*4ùý�óËMƆbì’àÛRåšÆÄ\‘r­É3GbœÜ”SÄÄ–“Àû”¹\ƒ7®æ)Õ,vDØ� ã’2C›&[¬sw¡„ÚÐùü‘'÷„d§„Ø6x‘Î7y÷V‰‰Å:éû‡¢øÙ¯¹–m“ΫÜ�/áÄâô�(ÇwqKÅj±Í$ð£PÕ9«Ì�é*ɘ�‘¾½Q¿¬ã[…ZCg:Se![¡'êáó£ìí—9:Ñ:x«ÔÐL®ÏÖ¸ÝO1-›ôr�Ù¥ åºÆ‰]aNî Ñ‘»®¢õ$ðÖ!]hrùn™ñ•PHa°'È@"صuø,Ûf©Pg1W%SPLøxb4ÌØ`—Ìω6"�·¦es7­r}ºÆ�t�hÈKO€TÌ¿ãÒ ‹l©N6_c!_§/®pt$ÈÁá ,mKo“†Åd¦Áí•»‹*8¤b~’ñ‰°¯ãÏѵm›RUc©T'[¬S©5îõ³ÐÇ�¡ !ŸÜÐíOo‹dJ“‹*‹ 2ÅAŸ›DØG<ì#ñá÷¶w@è†E±Úd¹Ü tïc$àf´?À耟‘^Ÿ,×GoX–ÍbQc>WgfIc~¹ŽiA<ä!P¼Dƒ ŸgÛ7-µaP©k”kµ†F©¬ÑÐMú #½>†z} ÷xñu饨9$ðZ¤Ö4È5–ŠÙ’ÁbA£T×Á² úÜüüŠ ÅãFñ¸PÜ.·ÅãÄåtâr:Vì:ÀãZ IÓ²±¬•—S7,,ÛF3,tÃDÓ-4ä©Y4tƒFC£Ú0Ñ “°ßC2ªÐó�Œzè‹y‰=²ôFì8xm¦©[”ª:EÕ ¨Ôë&µ†IM·P&MÝF7LtÓÆls¥œ€Ë .§àu;q8À¯8ñ+.ü>'AÅMÐï p xˆ=„¥r°è"xBˆ®ÑÙ·…b $ð„]COÑ5$ð„]COÑ5$ð„]COÑ5$ð„]COÑ5þ Lf·ô¿¨r%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--a3v96rkrp7b.png000066400000000000000000000256571524103652300220660ustar00rootroot00000000000000‰PNG  IHDR‚Ú«PE§ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ü’Žu*�IDATxÚíÝÙsçyïñowÏŽu;�w¤IZ²lÙZh™–âØ:±-[›Ï©,哜\%ùR•»TJJU*uÊ©¤R®ØblÅv)¶�HÉÚ©�$(€W� ˆ}öÁìÝï¹€�  g¦ŸÏ%g8xèîß»t¿¯¦”R!„p,Ýî„BØK‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!ÎewÂ¹Š±3o¾IîòeT>�»©‰ú ®¯ÏîÒ„¨E+Ç@ì=ÆÒgÈäã\ ¬¯ëc[øô¥_Þ5YbBØ!?9É•û7T±ˆ¶ðt¹¨ûÜçh~üq»K¢¬¬‡Fÿ•Y+�RæÕ74užf¾Úþ?—24$l1ù«_¡ ׇ@±Hª¿ŸÌ¥Kv—(DYû,ü&iu}˜ªH2ætüý%–�Xs…xœb<΢]QÓ$sú´Ýe QÖFÓ§±,󖯙ªÀ¥Ô©%–�XsÅh͵x—UÙ©)»Ë¢l™Ê$genûžL1¹äÏ“ kÎÕЀ²¬Û¾ÇÓÚjw™B”-C3ðè�Û¾ÇoÔ-ùó$Äšsƒè>ߢ¯kn7�-[ì.Sˆ²ÖèE[ä5Cs³®vë’?K‚@¬¹ÜÔªP¸é@Ö\.j¶m#ÐÛkw™B”­¼™%V˜ºå<›¡»ð»êÙüÊ’?Ož#k*?9ÉÄÁƒ¨\_Oš®“E ¸ƒAê¿ðê÷í³»L!ÊVÁÊñöÄAâùiîš<ë˜Ê\$o¥ñ¹jèªÙI_ðaÜšgÉŸ)A ÖL>füßÿ+“Á·q#íO=…f¥•M»· D•+X9Þ‰h~‚ZW#û;žÇoÔ Ph,ï’ k"3ñÓŸb¥Óø{{i[ ! ÄÌ÷"ù ®znöjË�9±æCÀœ�ÅßÓCë�! „¸­‚ÊóîäËDrãŒzmžZwãŠ}¾ôĪʇÃL¼ôÒµøÞ÷Ð]rØ ±T¦*ðÞÄËÌd/0êÙßñ5+ A VQ!-…@*…¯§‡¶ï}ï¶’ !®gªÌtn¿QÇþÎç©q5®øÏ‘³R¬ŠB4ÊØO~‚•Jáíê¢ý»ß•â.˜ªÀ»“/3�»T �ŽÕ � « �3qðàµxúi4ÏÒoeÂéLUä݉ÿ`*{ ŸQÃ#íÏRë®ÚÏ“ +ª˜H0ñÒKãq¼ëÖÑþôÓèB,™©LÞŸúSÙ‹xõ�vJÒ1I:W¤>`pÿÖöôÔË�ŒËTL$ÿéO)ÆbøÖ­£MB ê�NñÉÙ8±Ù~�‹ÝÜш×-7$.‡¥L>˜ü™ xõû;W?À¡ÓMÅ¿¾q…hÒÄ4¯-~æréljóñ�/·Ù]bÅ)&Lüä'âq¼��´?ó º×kwYb½úÑ4C£³Ík—]ר÷»øãÇ;ñº$ LÞŸü%ã™s¥hŽzoËšülGþ¥Þì�M¯ €bÑâüD†Á‘¥/ß* ˜L^ w{{i8HB ª�½’¾),K‘ÈxýÓ°Ý%VK™|05~ivÍB¦¥8:Ç4oÝ*šŠ†bv—Y1ÌTЉƒ)ÄãxÚÚè|öÙÛ®,*ªÃûC±›B`žeÁàh’|ѺËOu&KY|0õ+ÆÒçðè~íxžFïÚ.Ãî¸ HgM4uûI€ø¬¹ÄOs63•b쥗(„ÃxÚÚèxî9 ‡ˆ§ ·}Ý¥é$Ór݉BñÑô+Œ¥ÏâÖ}<Òþ žµë Ìs\ø¼wØ�ŒmÞQqv–‰ƒ)Î…@û3ÏH8ˆ×sûs¤PTø½²ŒÈí̇ÀåÙ!ܺ�GÛŸ!èm·¥G]ñ³E~óé wZ›i6kòów'ˆÎ–öÁc¦ÓL¼ôù™<­­´?ó F pï,Ê^¾ xg rçsCƒŸ½=Æåé¬Ý%—¥ùI�­yy¸í‚ÞÛêqÄ]Cù‚âÃÓQŽœN`Z ÝИßÑÁ²®}}C×p¦iQ´,tömªç‘]A¹bŽ™N3þÒK¦§q·´ÐñÜs  Ž$yóD”Ù¬‰¦�Û00-…¹ ‹­kš·N&WÚÔáçë{›h¬uÛý5Ê‚BññÔ«\šÄ­yy¤ãYB6†8 †Fg9|žÊqâB„h²Ô½m zøúÞ&ºš�7nf³LÏ2p!L"]jTmhñòؾfÚ*{åÚ£áÿÇùÄQt ¾Üö:›í.iQ–¥8z>É;ƒr…¦iôÚtð.T4-Î_‰sv´t�Ï­ó¥m�|ak=†QY÷›ªB¡##UêÜXšCÇÃÄfW(u©æUƒÃò U�í R³Bók©?ü;Î$Ž £óå¶§èl²»¤Ûª˜ ¸8™æõcÂÉÒ�¥ƒ7DÀW>©Ìf œºe,< @°ÖÅ£»Cl缾»´%Q…ã/¿LîÒ%Œº::ð\2T5‰‡úà Od¨ ¸ÙÝÓDKÐowiWL‹³£1.\I\ߨÚVÓ­©åê³è› Å>DGçÁ¶ïÒYÆ=�yeáDžÃýa.L”îå¯õ»ÙÕÛDk¼7šŽgŽ�˜›?èiõñØž­�å;  &_~™Ì\t<ÿ¼ôªD6oñÎÉ赡T—ζîàš¥Þ�T¦Ààp„Éh(5ªìmbSGy?Å>ù§â¥žÀƒ­ß¦³f«Ý%-IÙÁâoÝM~•#¥#“)NŽD)J�äïé­ã‘]Ae¶—*™xùe²/¢tþปVW$±º,KqâbŠ·>‹�É[hšÆú¶Zv¬âq—×1¸˜éX†�áÉôµFÕ×ö…h©/¿FÕ@ä-NÅ?@CçÁ¶ï°.°Åî’–¬ì‚À²,N\œå­�™œ…†ÆúöZ¶¯â­�ƒw¡ùå*†Ç’(^�ÎÃ;ƒ|~S-ºnÿ­rÊ4™üÅ/Èœ?_ �çŸÇÝÜlwYâ]œLsèx„™Di(µ¥ÑÏ®Þu�Ê›€UJ1<žäôH”‚i¡k°os=�ôËfKÌÁèÛœŒ½_ �Öo³®BzóÊ*†'3¼Ñf:>wð6øéÛ¢¾Þ¥2†ÃskA¨ÎÍ�½!6¶Û×Õ•¨>ádž7ú#œŸ›ð»éë Ñ,ï!•¥˜oT]O€ŸGç¡�AîÛlï×@äNÅßCCã‹-OÒ]»Óî_Õ]+‹ ˆ& ¼5eh´4ÉZãs³£'HgSeL²Þ�ÉHšÏ†#¤³¥°ÛÔáçÀÞ&‚k¼2£2M&ùK2çΡ´?÷Þ–µßC¬ŒlÞäÈéŸI`Zà6t¶t5²q]=z ¥Þ�TºÀgÃLÏ5ªšêÜ|moÛ×~Þðtì'¢¿CCã�–'Y_�!6A¾hñáPŒ#§ã˜¸t�MëêÙÒÝXuïBó]Ý¡‘(EººÊ4™úå/IŸ;‡î÷—B um·Æ+c~yè7ú#¤sš]-µôõ„*f`¹J�ª0élé6ØM~¾¾¯™Æšµ¹Ýt(v„ÏæC ù[¬¯ë³ûW²l¶ÁbïÎ !¼žê>xÊLΌƸ0– Ægðð*/w­,‹É_ýŠÌ™3è>íÏ>‹·Ýž]‘Ľ¹4•áðñSñÒDjsƒ�]½MÔ×TþPêRYJqqa£j�ö9û�þè›hhÜßò-zj+7À† ¸ÉqèX˜ñ¹µÍ›|ôõ6Ñà ƒ÷F±TžÁá0áDéÙöFwieÆ•^îZ)&ÿó?I IT°Äl‘·¯-í÷ºØ¾!xO+ìVºlÞ\³=DNÇ>âDô hþêvÙýõïÙšÁR×6w²[vuWjg'¥˜~åR§N•Bà™gðvØ»+’¸;7î´g›;ØÜÕX1[­¶X*ÇÀp„Hbá"!ºšWfþàlü#ŽGJ!p_ól¬Ûg÷W^«SqäT”Ï$(š¥µÍ7¯“ƒw1¦¥V~g'¥˜ú¯ÿböäI4¯—ögŸÅ'!PQJËC‡I¤KË/t6ÕÐ×Â_�Ë/¬…±ð,'‡#¤ì!òÕ=AËoT]Hçә߰¯é 6×WGÀ*Áj¯m^ÍVlg'¥˜zõUfѼ^:ž}Vzd<œåP”+áR ·±ÎËîÞÁ:çí’w·ÝCdG×]®v>qœ£áR|>ô8›>o÷×[Q«ÑÒ§W涉l¨-¼«±¶yµ‹¥r \X°³SÈÃã{šè\Êü�RL¿ú*©ÁA4�‡ŽgžÁ»ÎþýQÅ�%3&ï�Œ^[zvÚsª{ÝCd8ÙÏ'3¿`oÓãl©¯®€eA¾ 8{e–d¶ˆ×c°¥#puÉå[¼Ûº×fmójw§��. OsåäyŒÙ8žÆ›ì#÷ÞÛ$�Gs»i{úiüÝå±?ªÓ)&Ò„St46´y¯.™°Ú;í9Y4•cà|˜hªÔ¨ênñq`oˆ¶¹5À¦IŽ_"mFð�ìnßBָ̧áRì }�Í ÷Ùý5VÅ]ÁÉË)~ýñ h ËR蚎¥ö6aZÜ´¶ùöõA9xWÐ-wvÚÖ€ûÄG´Œôciº2±4ݲбÐ\.Ú¾ÿ}üÊkk<§šŒçù�÷¦ÈdŠ i”N?Åö ulïp¨ÿúå¡wml¢¦Ê·q\K‹í!heÆ8 4ÝBY:šn¢ë¥ç~>Ú϶†/Ù]þªYrŒÎdyé­ Lëæ·kÀü¿–ÃÚæÕnár×çÙ>ŽË*Þô>x¿þ-ÖÝWù··UƒlÞâÿ¾v™l±tñ_HQ:�`n§½ž&šd(uµ,ÜCÄí�°nûa4ݼå{kÌ­üþæïÚ]òªZòÕúÍþ¦uë× ë_ÜÞVVk›W«Ÿ›û··2ÏÐþê¯n%ãÇOI”‰£ç㘠n ¸;6„ؼ®A†RW™ËÐÙ¶>HWk-C‰wÐ4kÑ÷&Ìq»Ë]uK·™Œç¹Õ<ÏRЦFiÁ¬¥F3�Ë*,úº†¢&Výq¥¸4™£`.~ÁqÁ:�„Àªñ¹ñÔ„A[üÚfxR$Ò»K]UK‚2X1YÜÀ2\¥AÏÛPؾ¦ ˜ã¾cÿ[ ,)…nT÷y´äË{gÈwÛ…àêüîª^(®yȻߠÃÒtŠM�v—)æt·pßææ K)jËoÕj§ ·_fÅ,ÔRë­üe¼ogÉA°WpÑ.«®kôõÈŽVvHíü2¦¾HSSÓYÿø~»KsöõÖ¡/²¦¢®klìh¸mPˆÕ±ÞÿJÝú£,�mõûí.qÕ-ù¨kyyò�\ºÆü±ªi`èŸ+ó=„«YÍÞˆoºKÓQZécj:9·ŸÚ'Ÿ¢±Sö(·Æóû;¨õ»®{²U×5Ö·Ö²cƒìm‡Fo'Íæ“(Ë…e¹P–ŽeºQ–A·ûöuTÿÍwý@Y6oñÛc3œ™¥©ÁÏÛ[q¯âr¯biT2Fáõ_Ð�š"ÙÓÇ®ï<Žî•a†rdZŠOÏ'xãx¯ÇàáÝ�r»u0ÉqfòÓ³c4úB<¹g5ng<É}×WpŸG§«©t�©¸%Ê„V×H®¦Ô¢4ZZ%ʘ¡klh-õ ½.CB Lx©Õ6ßA�µÉ1!Ë!„ÕE‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@!N‚@8ÊÈÈ™LÆî2„(+ÂQ:ÄÖ­[ùñ�ŒRÊîr„( ÂqFGGùÃ?üCöïßϱcÇì.GÛIÇzûí·¹ÿþûùÓ?ýS¦¦¦ì.GÛHG³,‹ú§bëÖ­üÝßýù|Þî’„XsBñxœ¿ú«¿b×®]üüç?·»!Ö”� œ={–§Ÿ~š000`w9B¬ !náðáÃìÛ·�?û³?cffÆîr„XUB,¢X,ò£ýˆmÛ¶ñ÷ÿ÷‹E»KbU¸ì.@T–£G�òÏÿüÏv—±l§N�ºëÿ‰DøË¿üKþå_þ…^x�Ç{Ìî¯!ÄŠ’ wåìÙ³üã?þ£ÝeØâĉ|ó›ßäµ×^“0UE‚@Ü•ûî»�ø‡°»ŒeûàƒøÉO~²¬ÿû½ï}�¿ýÛ¿¥§§Çî¯!ÄŠ’ weóæÍlÞ¼Ùî2–Íï÷ßuìØ±ƒ^x�'žxÂîò…X2Y,Ä"B¡/¾ø"Ÿ}ö™„€¨jÒ#ân·›?ÿó?ç¯ÿú¯ill´»!V�� 8p€_|‘¾¾>»KbÍÈÐ�ÀöíÛùïÿþo^ýu á8ÂÑyá…8qâßøÆ7ì.G[ÈÐ�p$Ã0øáÈßüÍßÐÜÜlw9BØJ‚@8ÎþýûyñÅÙ³g�Ý¥Q$„£<õÔSüÉŸü‰ÝeQVdŽ@8JCCƒÝ%Qv$„Âá$„Âá$„Âá$„Âá$„Âá$„Âáî:ÎŒÍòéÙãáYF§R(e÷×p6+Ÿ'ûÚAZ¦Îàùôú_y˲ì.MÜÂT4Ç›ýf³Î^ŽR(ÊßÊNJ)Î�Æpêr’×>™&�3í.mMhJ-ý2þÚ'Óœ™¥h^û/†®QððЮ C³ûû8N1• ð«aX7o¬žö7Ò÷ÿÇîÅ—’üú“Ì×}ÃÐÐu�‡wwRëwÛ]¢#}xj’™XÓZxm¿Çà‡OtáóT÷àÉ’¿Ý…‰ôM!`ZŠd:ÏàŰÝßÅ‘Œß¼e21N½ú¦Ý%Š9éœÉ¯?_¦©(,>š´»DGº<�b&~}˜dò¿>:cw‰«nÉAðþ©ØMð<ËR\žJq� ±ÌLš@:rÛ÷'?µ»L1§ÿBµH§Yé¬I4•³»LÇ9%ŽiÞúÚeZŠ3£³äª|ènÉAKn{¡W 2ygŒ§• 3šÎ™¼ùY„Áá$š¡cYжz7ßüb+u~rô\¥ÀíÒÙÖ¤·£M“îî½R¦IâØÇ„NÁcfQšF¼s[ž<€55ÁÔ+¯`ó€(L-ÝÿëxCA»K X–Ňg¼2†R`¡ðy]<±¯‰-~ŽžOòî`”lÁBÓ4z;êØ¶>ˆÛ¨îéZ™Že¼¹:rÑÓêãkûB4×yùðLŒ‡âdò.Cg{W€{Cø<Õß ½« ˜—+XÄÒEê|ïõ¿¤p"Ï¡þÃjýnvõ6ÑôÛý]+VòÜiüGߤ. ÞÐIû_£}ãºëÞ—‡)„Ãøºº0»Ë·aZŠH*�Ç¥Ó¸þÙ�lÞº®QåqélíÒÛQ�´©–g6[àÔÅ(cáY‚µ.ÛbKçÍól¦¥0tgý¢—Kqn,ÍëÇ#ÄgKÃmÁ»76ðUwk%ef¦±Ž¼Asd€YOž¾ÂÖ‡öÚ]šXáD�×�‡¹8YjT5Ôxèëm¢¹Ágwi£`Zœ�qþJ¥>·Î—¶5ò…­õòì«Pšü:z>ÉÛòE…®iôtÔ±­;ˆ»Ê'_î…•Ë“üðmZ/EW¦áfvãnvþ�¯âvË“§Nsn,Í¡ãab³¥ùƒ¶`€]›¨‘FÕ¢”‚Ñ™'‡#ä ¥ÛCû6ÔòØž 5^ù½ÝhUƒ`^*SäÝ“1ú‡“(>·Á¶õAÖ·ÕIWwe)'>%xò]¼Å, �XÛF¶üÁÔ…êí.OØÈ´ÇnѨھ>xÛ;‘œ(œÈòÙ…ðÕy€õ->ì Ñ”›&³&A0o"’ãP˜Ñ™ÒÓ“�µ^võ†ÕKWwvä®�^§1]zœ=YÛLÓ�¬ÛÞcwi¢Œ$3&ï�ŒrüBŸÇ`[·4ª2¹"C#Q.O¥¨ó<º;È® uv—VöÖ4æ�Kóú±0ñôµ®îîMMØeËÅ£Þ?LËô9²îúý_aÛ£÷Ù]š(cãÑ‡Ž…¹.5ªj½ìvh£Ê´J+‡ž½DzJå=°µž·7Þña1QbKLŧg¼7¥P,ÍÒ÷vÖ³µ«Ñ]]+Ÿ'yämZ.ÃP&EÍ ½y;¾µ�WîK34:Ëýs�ªÎ¦úzCøÒ¨ Ï28!“+}ÿí]5<¶'D}ÀߥØó“·>‹0x©Ô�óy\ìè ÒÝRk÷ïfõ¾ó@?õoãÏ—ne‹µl`Ãï?A¨#dwi¢LÅ‘SQ><“ h–U›×5°¹«±joƒŒ%s|6!šÌÐôp`o]ÍÎë­Ûƒ`Þx$ÇëÇÂŒE®ÍìÞØD°®z&xfGGp}tˆÆTi±¸T Dã×ÐÝ·ÑîÒDH¦‹ün ZÕ�ªlÞäôå(—&“  ÖgðP_�=½2Gr/Ê&æ \Jòæ‰(³ÙÒ-_Ý­µìÜÂ[ÁO÷åq²GÞ¤uâ4ЬÛ�µçv<öEt½ú‡ÁÄÚº)ÍŒÏ5ªš|ôõ6ÑPS¹Cަ¥Kpúr Ó²p÷o©ãÁÁª_h-”]ä ŠOG9r:QzÊÏÐØÜYy]]Ë,’üäÍg?Äe°4�ÄúlòþZyÒZ¬¥`p$ÉýÒ9 Mƒ®–ÊlTMFÒ×-·©ÃÏ�}Mk䙚•R–A0/š*ðÖgQ†FKcé5>7;z‚t6-aùe›%O RÓÿ&5ùR7=êfÓOêh¶»4á ù¢Å‡C1ŽœŽcZàÒu6­«gKw#z™�¥Ägó ‡ ÇKóm�ì ÑÝ"�¨•VÖA0ïâTšÃÇ#LÇKËU47øÙµ1D}®Ì˜�œÄúà·4%ƘõÕxø16Þ·ÝîÒ„ƒE“Þ¨ŒFU¾hqær” c |�‡v¹o³¬µ´Z*"àZW÷p„LÎBCc}{-Û×ñ–Ár×W—‡¾2ˆ†"¯{(ìú}¿÷Z g‰ê6<™á�þðÕFUKƒŸ¾Þõe0 ”bx<ÉÐH”¢i¡k°os=�ôñºe`5ULÌËæ-ŽœŽòÑ™–UZîz˺F6®«·¥««,“ÄÑ� �þ�™C¡ß°“mßü�zYT”˲8qq–·®oTÙ¹‡Èt,ÃÀp˜dºP=­>ìk¦¹^æÖBÅÁ¼p2ÏýÎ�_[7D[pí.¾É³§ }ƒÚ\€X}�¿ÿuÚz:íþõqG7.wmÇ"©L�ÁáÈÕ]ÙBunÛbs‡4¢ÖRÅÁ¼‹“i^?&œX¸³Su�ÕkId¦¦PG^§)v€´·ßWö³é�>»Bܵp"Ïáþ0&J“²k±‡H¡hqöJŒ WX —‡ÞV_QwV‹Š¸¶Üõ;ƒrµj;;3if�¼Mëè teQ0<ä¶ícÇ7Æå–GÚEe»õ"!¾•kTÍoyj$J¾`¢i°§·ŽGvoÚäJ¬�ª‚yéœÉ{§b+¾³ÓÕå¡ßÁ;7kÛÈ–ï îâtãvÚCßÓD§,]ÖóÆf²ÄþõGø‹éEß“×ÜÔýÁStÊ6‘BÜ$1[äøÏ^eÝôYtëÖ�©¢f�üöÿæóÛí.W,�ãžÛîlòÞ6tMÑ´i½Ý¥ Q–êk\„㋆€®iÔå£v—*–ÈqA`™&KéiÈd–‹Ñïp~XJaò\@¥p\è.™šà¢¯+4â�f4 :{:ì.S,‘ã‚ ø•‡09ˆ-M'ôØ~»K¢¬mxì!¬Ez¦f�Ür¾U\æE¬,GAççûp}ñÔÕ'c4LÝ…©»àáßcãλK¢¬š}÷iŠÆµ‹}Q3°Ð˜íÝÉÞo?fw‰â.8…ÆúS²##d×õbôlcýý}øüÒŠb©bï½Gô�w(44cmÜIÛçwl Þû‹5娧;,Ë"71ÀÖ?øF½<+ ÄÝÊ^.­À»nÿW¨Ù±ÃîrÄ29rh ?1�Êçq‡BB,ƒeYdÇJ[²z»»í.GÜÇAæÒ%¼ëåy!–#76†Êçq55᪭µ»qÙ‹ðoØ`w)BT¤ìÈ çP5pd(Ó$7×¥õK—VˆeÉÍõª%*Ÿ#ƒ 7>Ž*p77cH—Vˆ»¦L“ì•+ø¤1Uñóó~™bYrW® ŠE<­­Ùh¾Ò93dlSˆ{’ž¿ÙBΡªà¸ °ŠEòs]Z¹åMˆåÉÍ7¦äª Ž ‚üèh©KÛÖ&]Z!–A‹¥ç4M†W«„ã‚àê°�ÀB,Köòe0M¼mmè>Ùy¬86|2¶)IJÈ9T}ªP 7>š†·«Ëîr„¨HY¹ë®ê8*²W®€i–æ¤K+Ä]³òùÒb�Ò˜ª*Î ‚¹e%|==v—"DEÊŽŽ‚eáíè@÷zí.G¬G�L qoäªNŽ ‚…]Zߺuv—#DE’^uurLdGF¤K+Ä=°r9ò““ ëø:;í.G¬ çÁÜNJ>éÒ ±,™‘P og'šÇcw9b9'æny“.­Ë3ߘ’ù�ê㈠°r9rs]Z¿ti…Xy~ z9"2—.�RøÖ­“.­Ë`e³ä''Ñ Cž¨B΂¹.­ìO,ÄòÌ÷<]]h.—Ýåˆæˆ ˜ßR/ k£±,²™Su«ú °²YòSSh†�Gæ„XÙÌ©ºU}Ì·d|]]èҥ⮙é4…™4— oG‡ÝåˆUà˜ �-õ„Xžì\oÀ»nšaØ]ŽXUó[êɃdB,�,+Qýª:г³ä纴>éÒ ±,2?Pýª:®öºº¤K+Ä2S) ‘šÇƒ·½ÝîrÄ*©ê HÏuiýÒ¥bYæçü]]hzU_.­ªÿ²YÙ[Uˆ{rõf ™c«jUÅTŠb4Šæñànk³»!*RNzÕŽPµApõù�întéÒ q׊‰…xÍëÅ+�©ªVµWȬl©'Ä=¹z·Pw7hšÝåˆUT½A0ß#�ù!–åj¯ZSU¯*ƒ ˜HPŒÅÐ}>éÒ ±LWo¿–ù�ªW•A�™›àò®_/]Z!–¡‹QŒÇK�©–»Ë«¬*ƒ`~~ ÐÝmw)BT¤Ì¡UiLU½ªéÒ ±ÆJ¥ÐÜÒ˜r„ê iɱ,9é 8NÕAzn£zÙŸXˆå‘ù穪 ÈON^ëÒ65Ù]ŽÇ*ÉÎ5¦d¡9ç¨øM|­b‘è»ï’:~+›@w¹(¦R¸jkí.OˆŠ�õMQ½*:г³·}])uÇ÷ád…hn3:¬éºœCPÑAp§É`¥FM�Ýe Q¶ÜMM¨Û4×"7>é:µ[·¢»*þÆ(!VM]_šaÜò5MÓн^ü]]v—)VYeÁç?�Ó¦›.öºË…QSCèñÇí.Qˆ²æik£ñÁonPé:¸\´~ûÛ²T‹Tôí£–e‘øè#’Ÿ~Zzv ¦†Ú]»¨ÿÒ—0|>»Ë¢"¤Ïž%öî»d§§ÑÝnj¶l¡áÁñȃ™ŽPñA „âÞTôÐ�Bˆ{'A „'A „'A „'A „'A „'A „'A „'A „÷ÿÓ2¹X‚G!%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--cgvkcjlnr.png000066400000000000000000000246251524103652300220430ustar00rootroot00000000000000‰PNG  IHDR‚¬v+«{ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ‹•¾ã(uIDATxÚíÝYlgvàñÝ}ç]¸h!ER¢n"e·Ú-µmÙ²äžÁ$3™×4‚ @‚ È<æ!€� y’‡tä%@HÏ`žƒä¥­Å–wŶ$Š«6î;yòîKUÍMµ$KIÝ˪"Ïï©ÑÖ­{ªXß=Uçûꔢ뺎Bˆ}ËftB!Œ%‰@!ö9IB±ÏI"Bˆ}N�Bìs’„bŸ“D „ûœ$!„Øç$!Ä>ç0:€jKfÊÜLR(©¼×£¡ÎetHBì é\…�‡’$Òe.�‰q8ê6:$±EÊ^i1Q,k|1šâ›ûk¨ßí‘bƒ×Ž…x«+‚Ç%7?BÔBYÕùr,Åͱ5Tí·?'ýGƒ¼ÝÁç¶¢x‰=‘†¦Ò\H�+j¼NºÛ£¸œv†ÅIfЏœ6ÞîŽðÚ±6›$!ªåá|Ž+·WYË©ø=N:Û"øÝîŽ'H¦ ¸ì ç;#œ=ÂnWŒW¼€¥ÁB¼À•�óñ"N‡�ã‡Ã=¦lœpº³«F&Ë*± “÷ú£=à3:t!,m1Qäê@œÙÕ"v»BÇ¡:Ž·„�=€ùx–á‰ùb…hÐÁ»§£?ä7:tñ–Lé¼Êǃ †§2´4ènÛ¸ xž²ªñ`6ÅøÜ:š®sì —Ëgê û÷܉5•+ª|>šâÛëÀÆØëj�âv=쩪Îùç6ÊFm�Þ;¥!$ófb©DPQu¾¹¿ÎçcIÊ�XÈCï±!ßÖ&„3ù2à –’9ì ôw„x»'‚Û!å"!~ˆ¦éÜz”æ“¡¥ŠN8à¦çhŒhpk?èùb…±é$3Ë™ÇswowGp;eì™�eÁF-2ÎZ®‚×íàTk„–†À޶µ’Ê34‘ �+á÷Úy«+B_{EJ˜B|ÏäRŽ«·¬¦Ë¸]vºÚ¢;{«k†'â¬eKx]6~ÚáõŽ�Œ=ƒ™>Ä×Ë\¹gr)�ݦÐq¸ŽŽæ0vÛ«�9º®3±�fl:IEÕ8qs©?Js½Çè]Ââé×JR(ªµÈö(ÑPm¯Ö²%†ÆãÄ× 8 oqîT‡Ìˆ}B×ax:͵�ù¢FÐ礧-FCÄ[ÓïÍäË MÄYNnÜõŸ=ä|g—Œ½]cªD0±”çú@‚•µ§�“G"iÚÝÚýR"ÇàDœ\¡B8àä�Þ§šeÉ›ØÛ¦–ó\ˆ³’*ãtØ8Ù¡ýàîÖî—9†&dóe‚;NGèi }höS$‚dºÌ�¡$c³Y›Bû� '["8 º"P5�‰ùuîϦ¨¨­�^.õG¥]…Øs6ÛB Oe°) -M:�D^¸»Ö¾7wuñ~_ŒC2wWS†&‚RYçæ½$_Þ[CÓ6j‘½G£ø<æ¨æK*cS f–7Ééö€<2/ö„²ªóÕh’¯î­£j: u^ºÛ£„üæ¸Ø)”UîM'™ZLÐÝàÝÞ(¯Œ½Z0, M¥ùèn‚la£-DO{ŒÆ×"w*•)2ø]» �ËÆ›]Ò®BXרl–�âOµ…83gù3•)24‘ ±^Àe·=ž?�vÕµë‰`!QäÊí8ó‰ç·…0«çµ«¸ØãØAs&/!žµ˜,rõη…0«'ÛU„Þé�ÊÜ]íZ"XÏ«Üx¦-DW[·AµÈ�ª¨�æÖx0»&í*„%l·-„Y©šÎÃYiWQ 5O›m!¾MQR5êë<ôÝz[³ÊÊŒN&™�gÛ®B™&²ÙâÓáÅòF[ˆÞ£1"[l aVÏkWñVW�Å›™Ô4T³-„Y=Ù®"à±óf·´«Æ›\Êñá�‰õ2—�ÎWh aVñõCãí*—W3 &?Âcáw„žþ�6žú«Ú'?˜^vå‡O›bc&3ÆPògëÿ‹Ñ‡m_r;í’ªÈnWð{¬lós%µÀ@ò#Ü6/>Ç3?̶§Ëä/{Š¢`S~8Ù;3Ù{ÜI^ç|ã¯Ùñ�Ù J|Šœª{§m—úÆè:“éAŽû‰º}„0ÄèÚç”Õ=á·qÛ}»ò� 6ÆÓwXÌMpÀ×^“ï�Ë{‹I—™Ì Ðâ;¹{I8à=†ßâÛøt ©�».SNò`í‡ýÇw- 4z[ :#ÜI\CÓµš|‡$‹L\Çc÷qÐ{lW¿WQZ½¤Š‹L¥ï}„Øu·ã×°ÛœòßÕïUØ{éò*ÓßÖä;$XÈ|ö>K…IŽzP”ÝÿÓÕ¹ˆº1�ü˜²¶½y !¬l9?Åbþ!m�®—ΩÕBÐ¥Ás„‘øgÕ\Õ·/‰À"4]ãNü#Î(1÷!Ãâh vSÖŠ '?7ú�±+tt’pÖQïi1,ŽÖ@7š¢1”ü¤êÛ–D`�ҷȪIÚ½†Æá¶û9ä;ÎÃô7¤ŠËF!jnbý.©â"-þŒ{~ÃissØ‚‰ôñÂBU·-‰ÀJZ�áÄg4xŽpFŒ‡fß \6ÉkF‡"DMU´CÉDÝ »Œ‡CÞcx~îįTu»’,`$ù)½D‹¿ÓèP€�\ZÝ,秘Ë=0:!jf,õ%%½@k ÇèPPm�Ó$JóL¥«¶]I&—)'y´~›fÿ ÜvóôuйtƸ³z•ŠVyõ a2¹Jš{©¯9à=ŠÇnž¾Nu®FÂî&׫¶hC�É݉_Ãisqp——¬mű`?9m�ëÿat(BTÝ`ò:v»B³ÿ¤Ñ¡|O{à4%½ÀXò˪lO�‰-&YÈ?¤%Ð�]1_{¯#H“§�‘ÄäÊkF‡#DÕ$ŠsLgFiöwáPÌ÷ºK�ÝÏ!_÷×o’.Å_y{’LJGg`õ#|Ž:ê=ÍF‡óBG]Øì6î¦nŠUs'ñ^G€&O›Ñ¡¼ÐaßIœ6·ª0q,‰À¤Æ×H•—hž6tÉÚË8'Gü�ÌdFX)Lޝl&3B¼0K[ ×Ô­ö튃–@×Få ÷è•¶%‰À„*Z‘áä'D=‡ 9cF‡óR�Þ6|Ž0·ã¢iµé…"Än¨hî&>&äj$ìj2:œ—jð´rÕs;þT]Ýñv$˜ÐÈÚwKÖü]F‡²% íÁ^ÖJ+L¤ïŽ;výkòjšv“,ÝŠ¶@/¹Jšûë_ïx’L&[YçAòz�™jÉÚË„œ1ê=- &oÔ¤ŠµV¬d¹·ö�ÞV|ϾçÃÄüŽ:<­Œ¦>'¯¦w´ I&3˜ø»ÃN³ÿ„Ñ¡l[k UÑJ~jt(BlÛÝä'h¨¦yps;ZƒÝØPŒ¼£ÏK"0‘ÕÂ<3ÙQš}§°›pÉÚ˸l^š½Œ§o“”>DÂBŒzÏGµ8'ÍþSLe‡YÉÏlûó’LB“×ð™|ÉÚËòÇc÷s+ñ£CbËŒzÏG55yÛñ:긽ƒ—GI"0‰ÙÌ«…9Z§M½díe6z¡ô�(Ì1“1:!^j¥øÀÐ÷|T‹‚±àiÖÊKL¤¶õYëîõ¢ØTFÒŸv7v5Î+‹¸v5r'y�²^2:!^LÑKß à2ö=Õtƈ¹›¹ÿx[‹6$˜@¸é5M›…–¬½L[ð4E5ËXª:½P„¨…ºÆä*)ŽúOJÕ´z¨è%FS[y”$£)*‘ƒ£Ô»ãµ�ަj÷ÐèP^h&3ŠŽNWxûËEŸ%‰ÀÄ"î´º™ÉŽQÖŠF‡ó=ÙÊ«…º£oíhÉšfrÖs4x†Ùì=S¾ƒ;¯¦Y*Lpªîþ*¼_Y�ÉõDßAѦ³£F‡ò=“™A|Ž Ç‚gŒEˆªë‰¼�ÓîaʄǓ™!\Š�á³UÙž$“óÚt†Ï³’Ÿ"SNÎcñâÜÆ’µØûØv¸dM3sÙ<ôFÞ"^˜g­¼bt8�­•VH—è�^Ä©¸ª²MIp¢îÇøía&ÒƒF‡l,Y›ÉŽPïiá�¯Ãèp óÁpïÞ=£Ã5Ôì'âjb|Ý‹6tt¦²ƒD\M´»ª¶]I`Sl¼Vÿ32•+…£Ãa!ÿˆB%G_ô=£C1Ô‡~Hoo/ú§ÊÚšõ»ÆŠïSPè�]¦ð]MÞhKùI²åuúc—Q¨Þ»Í%XD“¯�ƒÞ¦³C†öB)kEf³÷i œ&ê>`ôa1\¹\æïÿþï9qâÿôOÿ„¦iF‡$ª¬ÞÓ̳ÙQCmüö=§ªþžIr¦þµÂlÖ¸>D³Ù1P g÷²ååe~ùË_röìY>ûì3£ÃUÖ½ˆŽ�i_`³ñž�RMÞó!‰ÀBüŽ0'ë~ÌBþy5³ëߟSÓ,&é �Çë}8LéÖ­[¼õÖ[üîïþ.“““F‡#ªÄãÐYwŽ•Â´!‹6Šj–…Ü#N„LÀ©úö%XLgä<{�‰ô�]ÿî©ô]|v?ÇÃ;ëp¸Ÿüû¿ÿ;]]]üÙŸý™Ìî'mQ}'êÎâwÔ1‘ÝýES™œv7§êjóà¦$‹±+Nz#X+­’(.îÚ÷&‹K¤J+œŽ¾‡]q},!ŸÏó×ýל:uŠù—1Ū±s6ÅN_ô=2¥«»¸hc7ÞóáØµ½UÓèâÑúm¦2wÉ<óžU^:™¬é*šþâIMí™md*kD]‡hñw½û–377Ç/~ñ þñÿ‘_ýêW¼ñÆF‡$vè�ÿ8|íLe†ŸÛªºòŠcôï�߬š&èlàh¨¯fû%‰À¢^‹]âÆâÿ#^X@±ÙQt]ÿþr2›Ý†Ó¶ñЉ®ë(Ê÷o]Š E6·ñă*vÅNÀãD¨ú?`ûé*ùæÍ›œ?žŸÿüçüÍßü MMMF‡$v ?r‰�ÿ‰Â"Øl¯4öœ¸@yzìÙŸ3ö:‚¯Wu¹è³¶•²…2¹bŸ[òG5äK*™\iGŸ »›øo­ÿËè]x%¿÷{¿Ç¿þë¿Æ®Ò4�_ÿú×üÛ¿ý|ðüÇŒÓùòR[¡T![(ã÷HY®Je•õÜΖa]1þë‘?5zªjËsmM^Ò¹2Ýšel:‰ªíŸ+¹jS5�û³)®ßša-[¢¥ÁƒÝV»l/¬­½ÉK¶Pá£[sŒL&(WäY…�Òt�Gók\ýv–Äz�ƒ17n§Œ=E߯½ùäRŽ«·¬¦Ë¸]vºÚ¢´4È2ÂíXJä�“+Vx¼Ó¦§5htX†±rièüùó|õÕWÛúŒÍfãç?ÿ9û·Kccã–?7¹üÝØ[/ãrØ8Ñ¡ý`h£¤ ¶d%•gh"A:WÂïµóVW„¾ö C¶™4MçÖ£4Ÿ %(UtÂ7=GcDƒµ™ÍÞ+2ù2Cq–“yœv…Ÿq®3‚Ã.g¡U�;wn[‰àÂ… üÝßýýýý;ú>MÓ¸;™å“Á¹’F8ࢻ=F,ä1úP˜Z&_fx"ÁR2‡]�þŽowGp;eÑä¦m'‚M¹¢Êç£)¾}°1sÞÒ «5ŠÛ%�(ŸT®hÜ›I2¹�FÓuŽôòþk1ê|R뵺­&‚ææfþê¯þŠ?øƒ?@©Âåg¡¤ñéH’Û7Ω¦ˆ�Þc1™»{FYÕx0›b|nýñØ»|¦ž°_ŽÓ³vœ6-&Š\ˆ3»ZÄnWè8TÇñ–0¶}~¿¥ë:ÓKF¦“”Ë*M—ûc4×ËÕÛ^ñ²Dàóùø“?ùþüÏÿœ@ ú%Ôøz‰« &óØm í‡Bœhã°ïï+]]‡ÙÕ # Še•XÐÉ{ýQŽ�—'½È+'‚Mçs\¹½ÊZNÅïqÒÙáPÌoôþbum£¹ž-áuÙøiW„×;¤ž»×üP"ø�ßùþáþ�¶¶¶šÇñp>ÇÕ;qRÙ —ƒÎ¶È¾�»KfŠ =Š“Ìq9m¼Ýáµcl¶ý�_¦j‰ ¬ê|5šä«{먚NC�—îö(!u^ž`vÙB™ÑÉ$óñ,Š ^;&µÈ½ìy‰àµ×^ãW¿úo¾ùæ®Æ¢j:·¥¹1” \щ…<ô�Q·OÆ^¡Tat*ÉÌr›¢pº=ÀÛ=|n)UoEUÁ¦t®ÂÇCI†§6þ(-M:�Dp9÷æEUuÎ¥x8·†ªé´5z¸t¦žú�ÌìeO&‚ÆÆFþò/ÿ’?üÃ?4ôê3�Wù|$É�ñ4°÷çîTMgb~�û³)*ªFk£—KýQêöG¬–š$‚MÓ+®Þ޳¼VÂé°qr.y›YÉ02™ XR‰\ì‹ÑqPj‘ûÁ¹sçøöÛoù£?ú#þâ/þ‚ºº:£Czl!YäêísñN»�ãÍaŽí©¹»¥DŽÁ‰8¹B…ˆßÉ…ÓN5ïÏrô«ªi"€�‰›áé4×䋟“Þ¶ ¯ÑûþJRé"ƒq’é"§ÂONF8{2$†í#|ð¿ÿû¿ÏÉ“'�å…Æf³\»'�W x�t·GiŠXûB%•)1<'¾^ÀáPxãxˆs§Â8R‚Ý©š'‚M…’ÊW÷R|}oUgcÉÛÑ>�µ–rJ*£S f–7Z w·¸ØÁ/K÷„I•Ê:7ï%¹y�Š a/=íQ‚>k•OJ�û3I&ÖÑõ�±÷îé‹ý†˜Ñ®%‚Mñt‰ë -ä±ÙÚ9u$bú%oš®3¹�fl*IEÓ8ÒàáR_”ƈNîþ}l>ÑwßÅê”Ñ¡Š`éD  $?ý”ôíÛØC!‚}}8#‘§þ�šÏ“¡0=�·µ•èå˸Œ]KÓK%’7o’úâ á0ÁÞ^\ÑèSÿF+ÈŽŽ’ŸžÆ}䱋q75ºxk&]'=ü�Òâ"žöv��(έ·…(ÎÍ‘A¯Tˆœ;GèìY»Ô0…x™ââ"ñ?¤´°€»µ•`WŠkëK±‹‹‹¤Q‹EÂo¼AøÜ9lŽ=3Mii–I•L†ägŸ‘À]_OàôiìÁ�½%LWUòããdïÝÃ}ç©a ñZ¡@â“OHߺ…£¾žÐéÓ8B¡mK×4 dGG±y½„/\ ØÓcô.î{¦Oº¦‘¾u‹ä�(.�®.܇WeÛOÖ0=ÍÍD/_ÆÝØhô. aO–`m6‚��/-ÁnyÓ¥Ù±1r¸‰]¾Œ§¹Ùè=Þ·L�r““$>ü�òÚþãÇñ?^“2N9•"³YÃìê"öî»Ø¥†)ö±Âô4ñ?¤�o”`»ºPjPÆQÓiÒCC”––ð�p€@o/ö]XTQZYaýî]´B�Ðë¯9Û6æÄ«1U"Ð+’_~ÉÚW_aóùõöâÚåRÍãæØ6�Gj˜b_xªëvèíÝõ¥žº®S˜š"3:Šât}óM‚}}È«ÊjÏ4‰ ÷ð!ñßü†J¡@ðÔ)+€f‘X­ÈwV©ýéŠb™X…ø!úæE˜EÎgEQ¬WA°s\’[äd”ÛS±WXíGU.ÂjKJCÛ (ŠÜžŠ=Ájg±”ekË¥!«Ü(Š‚¢Ét±°>›ÅJCº®o¬5aŠKr«Üòéšf™X…ø!V[>j³Ù,«›,V§”9±Wlö²ÊÙ,sµeŽD`‘?°,a{Ž…Îg¹«cç6ÿ‡EþÀ²„Mì9{rGP;æh1ar{*ö ‹­ØCQ,SƲ"CÏ«­\�%lb¯°ÚÜ€¬Ø«!sÜXäd”%lb¯°ZY¹¯)‹ÝK–°‰½B·XiHQ¹«!c'‹7—°YäÇUæÄ^a¹;¬×ÃJäÉâíÆl¡X…x!‹ÍÏ!w5eì�Ñ{¿M²„MãÈØ«S”†,uUbt BT�%ÇžÜÔŒ)ž,¶È©¸²œŒb/°`YÖf¡X­Fž,ÞVÀR{‹eÎfyMlM™ã9‹�%lb¯°Ü «Åk1¦˜#°ÒU¶œŽb/°Ü«*EU�cÏ2ÅS%å•ÓŸ�…™Š‹‹–{GˆçÙ¼#(­¬˜þB¬8?OaaAÆ^ )º�g�¦i¤nÜ`í›o°{zp54}LžRY[#30@)‘ xæ Ñ °y\“ïÒ 2Ãæ§ñ´¶Rÿ³ŸáŒÅŒ>BB¯TXÿæRŸŽârèêªÙØÓËe²££ä&&p77Sÿþû¦›'ÜL›6UÒi7n�Ýœ?èíÅ UeÛº®S';6†Íç#zéþãÇ�Þe!LAM§I|þ9™;wpÔ×êí­Úü�®ë¦¦ÈŒŽbs8ˆH ÖP¦O› $®]£47·1ÐÙùJ·Ž¥•Òwï¢ ÔýøÇ„Ï�Ãæp½›B˜Nqq‘ÄÕ«ææª2P^]e}h5�&tö,‘óçw.P<Å2‰`Óãf©„¿£cÛój6Kfd„âܾޢ—/ã4x•„V�{ø�Õ+WP3üÇ�ã;~Ånßòçµ|žÌÈ…éi¼Ä.]‰½[ &ب+®ûí¶j˜ºª’{ð€ìýû8Ãabï¿�·­Íè]ÂRtU%}û6ÉO>‡ƒ@g'ž––þŒ¦Q˜˜ ;:Š=$véÞcÇŒÞñK&‚M�k˜8c1‚/¨aI¢•ËÄÞ~›Àk¯m¼vR±#j.Gò³ÏHߺ…#%ÐÓƒ+ýÞ¿+..’B/½ñ‘óç·u!v‡¥Á¦ââ"‰k×(ÌÎ>UÃT3Ò”VWñwu½xQžL¢ŠÊñ8«W®P˜˜À}ø0�žì>ßF vp�ââ"�în"ヒ#0:\ñ{"lÊŽŽ’¸~�J>�»±‘âÂîˆýìg¸0:'‰@!ö9IB±ÏI"Bˆ}îÿt @?ÇÚè%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:27+00:00hÄH(tEXtdate:timestamp2025-07-09T16:08:20+00:00šôæIEND®B`‚doc/design/images/s2shapeindexva--ddonz2lz70r.png000066400000000000000000000411231524103652300221470ustar00rootroot00000000000000‰PNG  IHDR=àqL±Ø cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé ‹•¾ãA3IDATxÚí½ç—\çu§ûT黪3  9$ÀLŠ"l%Ë’å0¾ÏšugÝÿèzÍ,Ï�q�lKcS¢˜A‰œ;¡Ñ¹r®:uâýÐE�QÝ]±ë}¾P¡XýÖ©:¿³ßýîýÛ&Ã0 � G0·{�@ÐJ„è ‚žBˆž@ è)„è ‚žBˆž@ è)„è ‚žBˆž@ è)„è ‚žBˆž@ è)¬í^€`IÖÉUTò%…|U¥\U)× Ê’JµfPS4TÍ@Vt 3º�¢n4Ó˜Í`3›1L`·˜1›Ái7ã´›ñ8¬¸ìf¼.3>·• ÛFÐcÅë²b2µûS ­Ç$ÚÐZKIRIåây™DN&ž“É•T,&�ËŠËnÃé°b·[±[ÍØ­ì¶�ZÌ&¬V3÷µÊfÝÔ5Ý@×7¾FUÓÑ YÕ‘ YÑ7þ³ªQ“U*’BER‘ ŸÓJØo#p0¶Óï·öÙ… v4Bôšˆ¦¬eeVRU“5VÓša�¯Û†×í à±ãvÙ°YZ›iÐ ƒŠ¤R¬È* ¥ŠL¡R£RS‰œŒöÛës1qàvXÚ})‚†!D¯ÁÄs5æ×ªÌ¬UHdeü^A�ƒ�ßEÄïÀiï쌂ªéäJ5Ò…ù’D¦(á±[p²wÐÃXÔ‰Í"BAA÷"Do›¨šÁÜZ…Ùµ s«U¬6ý~ý!a¿k‹#¸FcP¨È$rUÒÙ ™b�¡ˆ“Éa7SÃn|îÎq�àóÑÛšf0¿^åúR™…µ ¯ƒXÄM,èÆíÜÙ" ¨:©¼D"_f-Y!â·qx——©a7^×Îþì‚��½M°––¸|·Ä­¥2¯�¡ˆ—�ˆ‡­7s^†a�ÈUYK•XËT‰œœð25âÁ"¶À‚EˆÞ#�d�›‹e.Ω©#Q/£1κ‡¡ë™ Kñ"ù’Ì¡1Ç÷zé÷;Ú½4�à„è=„lIáüí<7—Êô�Œ øé ¸Ú½¬® "©,®YN ûìœÙïgï »ÝË!z_`=[ãü�<³kUF¢^ö qÙET· Ù ³+9Uã‰I?Ç'üXÅÖWÐF„è}ÂR²Ê›×r+»‡üŒF}XÌâæl©¼ÄüjžB¥ÆÓûƒŸð‰¼Ÿ -ô¼è­¦$ÎÞÊÏ+ì2õ‰Ž„&R(ËÌ.gÉ–džÜïçÄ„_ˆŸ ¥ô¬è¥ 2¯]É�Ì+ì2õbj×2rÅw–³T%™ކ98êm÷’=Bωž$ë¼s#Ã�Å {‡‚ìòab×6Ò‰› \6xåd„��8í4—ž=À‹syÞ»‘c ÏÃäh»µ»»%v †KÉ"w³ìpóüÑ Þ^ä-h=!zñ¼Ì¿}”BÇÌáñ0>·½ÝK| ª¦3³œg1^ä¥c!Žîöµ{I‚ÈŽ=]7øp:Ϲ;¦ÆBŒÇÄMÔ *2WçR¸¬ðíÇûˆøÅCJÐ8v¬è­¦$~ùQ �ÃÆ‘‰>M¨µË$–E2‰ª¬a³š z E< õyÅ)ð60 ˜_+0»’ãÉ©§§âz ÂŽ=À³7r|!óøþX»/ÏŽ W¬qq6Éž¯ïEÍ‚-Ñõ5º®óúÕ4¯]ÎðÄ¡�¦ žn̯äùæc‘ºòKO RªÊäËr»/ÓŽ èsðÜÑ!R�ÿñæ…²Úî% º�®½JMã½�`1©ðÜÑažæžò¥óaŸ��×V×ë-f‡Æ¼¬gÊí¾T;«ÅÌcS1Â>þûïVXˆWÛ½$A—ѵ¢ÏËüíoWpº<±àÓÉ`ͤ$)Ä‚›ÖXÐN¥ª´ë2íXv ø8>ã_?LòñL¾ÝËt])zóëUþáÍu¦vEØ?jY)ƒ¡Ãf�WÌfØIÓ¤/àäé#C|4Sâ7—ÒìŒì´ Ùt�è]½[ä_Ï'9µ?ÊP_ãËQ¾ ·ÓJ¦´¹³k•†¼ßÍÅ2±�{Ç\ŸNc¸ßKØïä—çÄÁF/ÑÑË–~{1é©è޳RÚ3äíëYôm6ºÔ�óÓyцÖdíŽ�«hœ¿“k÷R-¢åŠ£ë:¿ø0Á¾Ñ ~÷Îkï 8qÚ­¼ws{濽”f 䯷¯Q'a2™8±/Ê{· $²"¿× ´\ôÞ½™Ã„eGG0Ç÷ösùn‘›‹[;üàV޵ŒÌÁÝMG’5U§CÛ¤»�ÓÊÁ]a~q.�ª‰k¼Ói©áÀrJâŸßOð±�ßD_(Ë||;Îñ O Ö•—Ótƒß^J3³RÅf3Q®¨X,&,šf ên‡• ×AØïd(âå, äâL‚¨ÏÂ+'#í^Š ‰´LôÍà¿þf…ý»ÂÄBÝ_žR5YãòLU×xþpˆ=ƒ®/5PP4ƒÛKeÞ¼–Áb‚Çö�: ûlØ?#jºn�-«¬¦kÌ®UXX¯‹¸Ù3Äç'¼ÛEÑtÞ¾¼ÂwO÷3u¶{9‚&Ñ2Ñ{ãJšµœÆ‰}Ñvæ–ÏV˜_ÉS¨ÈŒDœ½V\ eI#]�YÍÔð¹,¼p$ÌÔHýÃŽjŠÎŹ"ç§ó F<ì ueÏr'‘ÈV¹u/ÍþÆ0Ö.3¼ÔGKD/ž«ñ�ïÄ{b[ûUÔ�L^¢*kÔ•x¦ŠÅlð�Óý …·Þ�"É:¿»’a1!qr*º#ˆZÉÅé8ƒa;/ µ{)‚&ÐtÑÓu�ÿþú*£± Ã}�±\êvj²Æ‡7×Ù3èä¥caÌ ò ¼¹XâµËNî‹ ˆíÙV‘�·.¯ð“gc lãa$èLš¾úh¦€Ùl‚÷ šnðÑ�8‡ÆÜ¼|"Ò0Á88æåûgú¹8“ TUÚýQ»»ÍÂþ±0¯^H·{)‚&ÐTÑ«Ô4ÎÝ*pp\œ†Ýçê\ŠÁ �g7gë´+êâ¥caÎßZî,Û`,æE1L\¿'L vM½·®eî÷ˆÞÑO¸»V@Q•ºfæn‡Ã»¼õpu.Õî�ÜÕ�ðæ•ŒèÍÝa4MôÙÓ«Uö�‰d0läñf–s|÷‰þ–œ >$DUVˆgÓÜ‹½vú‚NÞ¿•k÷R ¤i¢÷»+&GC;®·v«Ì¯å9<æ!Ü`gå‡a1›xéh˜™%a–¹¦Æ"\¾[¢PîÕ;…¦(ÒrJ"]ÒØ‡°qxq/^äôþ@KÿîÞ¡ ‡–T^j÷%èZœv c1goäÚ½AƒhŠè½u5Ëþ± &á‰Àz¦ÂpĉÏÕz3У»½¬¦D2~;ìpgµB¶$NÄw ½ùõ*ŪÆPDDy÷Iå*L ·§õnrÈM2Wm÷%èjl3»c~Þ»™k÷R  á¢÷öõ,ûÆBÂøò3dŠ5FúÚS,òÚ00¨Š‰jÛb÷�ŸÙõ*é¢ÜICEo!QA’ †"õ÷�îttàRS {Û7ç"ⳋbåmb³šÙ=àçÜííù$ ÚOCEïÜ­<»Gv®OÞV�§ÍÜÐ΋Íâw[�dQ¨¼]ÆüL/W(UEÔÜÍ4LôÒ™õ¬"ÚÍ>‡¦ëmw>±[Íhš(°Ý.6«™á~f‹í^Š`4ìn|ÿÎÆ<K#šNÄl2¡ëíuãU5“ø^Âî¡ çŠÈªxˆt+ ½JMcz¹Â®l¿UlÖÆß,IÃní]K¯FâqZéó;¸~OD{ÝJC²ëWJ †]¸ü 6°ZÌØ,&ŠUµ-uz™’ÂØ`o÷?ë†ÁZºB2WA’TLfn§•XÈC4äÚÔ{� ø¹8“áäžÖ› CCTêò|‘]"Ê{AŸƒ•t{&mI²NYÒð¶Ip;�t^â­KˤrE�:yùdˆ¯ 2³3¿šåìµÕM�n÷]Ôƒu1=­+Ùö�°˜”Ðuù„iåÃû]Ì­UÙ¿ +øF1¿^!tölwL<[áê\ŠïžîgwìÁˆnWÔÉãûü\š/òÎõ5Ψ{äæpÔË¥ùßz¬¿ÝQ°I¶é]š/0*¢¼¯d¨ÏÃôJ¹-ã¯Ý+3îͺɪ¬qe6Å�Ÿ‰}Að>ˉ /óñíDÝCÚÇb>n-U�12²ÛØ–èÉŠÁìJ•Ñ~Q¦òU8íúN®Ümmò;U�YÏÔèÑbñ¹åÇ÷ø¬Ãòýà˜—þ �Åx}ß‘Ón!âu2»Vn÷Çl’m‰Þìj™HÀ)0ê`ÏP�÷oå[ZêðæÕ,C�ž,#2 XM—99á«ûß9µ×Ïzº~èópýž½nc[juc¹Ì`_oF›%èsÐtñÆ•ÖøÛÝY.“È+ìêÍÔCMѰ˜Áï®?m=v�+×ß[;q³œ”„³r—±eÑ«©:Kq‰�po în‡ÆÃ,$$.Í7w››.(¼z1͉½ý˜{ôCÕtl›Ü�Øm¦Må]­3‘�“™UíÌ®UùéÙu~u>ÑöÚÔ¯b˧·³«eúNጼ ¬3�MEyçúŸ�±þÆŸxWjÿôî:Ç#};s|¡¬h¬e*ä‹5jŠŠ¢êØíœv+ý}A›…ФaÔíøS¨h¸ì›+âŠx¹v¯Äá]õo£w"ɼ̿}” RÛ»|Yç/^h÷²¾”-‹Þôr…¨ˆò6�Çiãäd”Ÿ½Ÿà•aŽ5î(™—ùéÙ8£QÃ;0íP­©L/eYÏT�¹88êÂçòà°›©HÙ’ÂôJ�˳Iö ðºmÜKV�ÖW|<»Z¡?°¹BåhÐŵ¹$Šf`kÁì“NåæRùSÁ(TtÝh«ÑÆÃØ’è,$kÃrºÆ¯?JòÜÑ‘v¯¿«‘U�+3IjŠÊKÇBìÜüM“Ì˼y-K*¯p|_” ·¾âÚnâîZ�…õ<îÅb1ñê…é’Ê×�‡‰|îº.§$~{)ƒÃnãøDxKkŒÝ\šI´ûRµ�{üÜKHL »;Vð`‹¢7·ReÏèæŸˆ‚/'v »Iå%îÆK|xgÝ0ˆøìøÜìŠfP–42EIÑpÚ,˜Mf\+©|•|©†ÃfÁã²ãwÛúmAEÕÉ—k”«‡ :³ §ÝŠ×eÃï¶ÕÕ§j:WgSüè™Ø–ÍŒzHd®/Vø»7Öð¸,„½64Í YTÀ€½#AF¶Q`ï÷Ø©©:¹²ÚÑ7»`ƒMC²b�.)œÚ¡'ƒí¤/à¤/°q¢[­©¬$J$òòe‹ÙDÄgcß°›á�—Ó‚ÍjÂj6QStjŠN¾¢’*Ô˜Y*’)*„b!Ã}žM—olIÑXNYK•)K*ý;¿ ¿ËŒÙdBÕ6„paM¡XQéºêó2v?4ß6·šgbÐÅPd{¿µ§¹¶Pâäd«ÅD¹¦b6™´ÖÝkû("~'‹ ‰ànÑ�ÔélZôV³5B>{OVù·EÕYˆXX+pY99áebpóÛ…š¢³˜”¸~¯Ä2ÄÂn&†ø=�ÍùÉŠÆ�¥,«©2ûG<üÁã†"_eVe�™Õ2—çóÜZÌ09däKf$/Å‹üÅ‹ƒÛ^£ÅlâôT€éÕ"Çööð6þ�ö9YNI¢×ñl^ôRA¯pTi4ºa0¿šgnµÀÞþÂ}þ­ ”Ãffß�›}CnjŠÎ¥¹"ço­ö990ÆåØþ6l%YâÆB†£»½|÷‰Q\öú¢I—ÝÌÑqGÇ},§$^»œa9¹!H÷ו+ÕpÚ-_™ÛÜ “ÃÞ¹‘ãè&êö6CØïäÊl¡ñoÜEœ¿“g!Q%U�Ù ù:óPmÓ{ž{ IØH5˜LAâ�++HµÿñëC|çtÿ¶ïó8lfÎìðÿüÁ(»cvÞ¹ºÊìjžÍŸÛo`pýnš¹Õöü_;®[ð>ÏHŸ“¿ziˆƒ£nÎ^[%�—È—eFú‘ù\¹ÑªÜœ¡>~·�ФR©õ榥”Äû·rH²Nª ðËs�{°³é_êj®FXäó‚aÀÌrŽ‹Ó ^>æÇÏÄšš·ZL<}0È_}ˆb©Âù›ëÔ¶0%íò\UQøë—‡ˆ·/Î&œÙàûgú¹0� ™«"É>Wc-î=NkӦ™L[ÜÕLo‹Î¯W�>Óƒ\‘�¶Ï†y›½BEÅj2c·‰y ÛEÓ .LÇ)–«üõËÃìj]akÀcåÏždï ƒ³×V)Têo²Ÿ^Ê¡**?~6Öpw�]Qüt”˳IUkøé³Ù FoDŸÇN2×›ÃÀŽyq;¯ A¯­c‹“7õ«�çj¼½=k¡(ªÎù[ëø]fþìù¼ ŽhêÁd‚g‡xùx˜o®“)H�üwÖReV’Eþøé�SÐf0ÒçäÅ#!ÖRe ÕÆFe%IkH.óaø\vÖ{Tôúýv¾{º�ÓÂxÔÉ=Ù¹ŽÒ›½T^ÁÛ #þ^E7 .܉3¶ñ½Óýmîõð½Óý||'Aþ+l•dEãÚÝ4?|:†ÇÙ\‘>ºÛÇPÄÁZúÑB\/’¬S«i8Í[»ßk'™¯ÖÆNc<êf´ÏɱÝ>œ›4nh%›½µ¬Œ_ˆÞ¶¸<�$äµð�“}M9EÜ ã1ß:á£[ëTj_žè¿³”åȸ—�Pk¾ÿ?|¼�LI¡$5&Ú›]«Ðt5µ`Ûç²Q(Ëhm ¨ŸÍEz!zÛan5�¦«|÷tÇÞ}¦†=œž pi:ÁçÛ±%Ec-Uæ©ý­yèrX98?ݘ2�óÓ†úš[Cg2™ðºm¤J½íu›;È(«¸�¢Íf+äK5æWóüàÉhÇvŸž ôX¸½ø »ór¼ÄäˆW·†_Æ·Oõqi®@®¼½2“k %tcÃé¸Ù¸�6 ¥æ”ÅCÝ¢W®©X-f¬Â4tÓ\›Oñòñð¦ìËÛÁ>ÑÏr²ô@~o=SâÈxë; Â>¯•Ÿž]ßòl‘DNæõ+ïn�ŠËn![éÍHï·—R̯Uxëj–{ñÆåcMÝ V(k¸ÛpʸXˆð:- 5 m.»™Ž„¸>Ÿ6ì¯JU•ámö¿n•“ûü¨ü¯wâ›.ü]I×ø§w×9<ixûÝÃp:ì䊽éÝY©pån Y3ÈWU^»”j÷’JÝ¢—+«¸í¢\e³hºÁìrŽ—OlͶ¨ÛíÃdÒ‰g+Ê5úƒö¶9¶ …€ßãäo_[åöò£çQ(ªÁ{7süó{qŽLô3Ô˜§•\¹÷"½DNzàGQ;·8¹î½V¾¢àù¼M³˜(2vп óËNà™AÎÞÌ3Üï%ÜÆÚÌ�×F©ª29"pñÎ� goä80êa÷€ ¿ÛŠÃ¶aŸ))Ì®V¸µT&pñôá¡–ç Ý+¹ÌéßíçúB™|EÅd‹µ3­âa¢W©jØ­Bô6Ëâz�?|¢ûu§F<¼q5C¡ªó·/�k1›°|bMñ;yæÈ©¼Äj¶Â�Å4UYEQtœ n‡•¾€‹3‡ñºÚ#Ôv»…j“ZÝ:ŸÛÊOžàÙ~—�«w‹\š/rbs‡[EÝ*Vªé8Z|z×*tà �—H$ÊU™jMEVuL€ÕjÆe·âqÛéó9 œuŸ¾æK}˜£}ÝgÐ`2Á‘q/·—%í]¿ÅbÚØ*}òóû¬ï`§á°š©)�¹­k6!Ÿ�ožÜèĘqó÷o®ôXÙÛܰ¥fS·èI²ŽÏ³³NnË’Êݵ<+©2Ÿ�Ý1'‡F½=6¶�Ï*+ޏñœÌB"Ç…™á>C<ίŽ&VÓe�u¯­þá]^ÎO�•önÍeUÇÚdÔFa2™°˜7ü ïÿ†z‘ˆÏΞŒò‹sIþì…"d3U·è•%•¡b4 h:ÓKYV’eNìññÍC_YJ Ú™vóì¡ ÅªÆå¹ï][c0âaÿX衮ĩ|•''»ok{Ÿ�׆Õb"Wißv­,iح殚ÿá°Y¨Ê½-z£ý.ž;â§ïÆùË—†pwÈN±îo¥¦ wÕhÙR�w®¬àµü—o�ðüáЦjç|. Ïñ_¾=BÐ ï\Y!ý%ÍúŠªS®ª „;ç ·F"’¹öÙ%¥ 2þ6åç¶ŠÝn¦Ú£¾zŸçظ�©?{?Þ1íyu«˜¬MsÖhké2ߎóÍ“¾uªç�/œ63ß8áïãât‚•dé�ÿ?_–éó·¯Ô£QL ¸)ËåõÀn–ŤDÀß™ù»‡a3m rlð‘0n‡™¿Øµ{ußõšftõ œÌU¹q7ÍOžh¨wÝÄ€‹?a�Û‹YÖ3•Oÿ÷rU!âï®åˈøm8m¦W*Û³-p{¹B,ØY‰ðGa²˜Ð´­u�ìDL&øîé©‚̹۹v/§~ÑÓuS‡ÖÝ<ŠRUáÒL’ï?%Ö§ßÏÓç·ñãgc\›O}jÈY©©„}Ý_âôXQTƒKóÅ–ÿíµL�š¢î²HÏd2Ó)š§Öq6ê5_…Õbâ�ŸŠqq®ÀÍ¥º®£=¢xYÓ tý«/¤ªê›{P÷]©zWFzšnðÑí8_;b¬¿y7O,hç•^¿ç¹c蚎ÓÖý‘žÓnÆ0 jŠÎB¼Êx ËÎÞ̱{°uÎ.�Âl2¡êíU½¢¤ñ/ï®S–6ÚGÿèÉ(σ¿Çd^æ_?LPS n+?|:ú¼Ùõ o^É¢h:ý~?|*¶å¢c¯ËÊ==Àß½±ÊëW6Æ—÷óôÁà^ûë�’,%$Ìf8s ıÏõ~ëºÁÏÞ‹/*Ø-f^:db ¾J‰ºEOÓéJÑ›YÊ1qpt¼ùE’F=̯W™YÊ¡ëzÓgͶ›ÅŒ¢ééãµËþÓËC-©´_ˆW‰çdž�¶ûl“ÙD›5�×.&?uq.Jÿz>Á³C¼æõ+™OMO •_�Kòø”ŸšÊ§öb¯_ÍPüÄå¦XUùh¶ÈéIÿ–×e3ƒÙdP®n¼ÿÇ3y3.ÛïSñ¬ÌÍÅÒ§×ð�ëYl–ûúcà´™¹µXfv­ Ÿüko_Ï5^ôº‘š¬q/^à?s¤eóÅ£!þæß—éë²<Ô£ŒxXI•xój–—Ž7·�¸RÓø?§8¼»¯cm¸:ùsÒ™‚ƹÛùþ·üç,»Öò5ÎÝÎc·™0›6صϘÊ:«Ûë+®Êº¾!^’ªsw­òÀÜ�lIFÓ?Õ3j²ÎÍ{%¬–ßï:ÒEå÷/ÔMtþÕ-zóFç‚¥‹¢½…x�ƒc^¼M¶7ÿ,n‡…£>f×$”-Ú!uЦc³˜1™àøÞ~Þ¿¾JØokZ{‘®üìýÃ}>¢¡î|pº�¹ÍAþñ=~9…Ьáv˜yéxˆCc~gçnçùàVžšªás›ùÞé#Ÿëzírš+óEÔO2‡#ÛKÅ‚NÌf0`˜`$ìäGÏ <𚚪ó?__!UP±˜aÏ€ƒ<õàkre…ÿõö:¹²ŠÕ »bõ»Õ-zf“yCôèÑ[I–øñ³±–ÿÝ>.ω׭Hòï·é6«™Ç¦b¼s} ŸËÂÞÁÆšrjºÁ¯Ï§ “£Ávô-£FÛ#Ôý#">3«ö ¸ˆ…¾( göé³³”’80êûÒñ£/�0s’Ì+øÜ~w)MÔo#²…¹Ì†¿>ŸdÏ ›]ýNÌf‡w}ÑnÍa5ó/sc±„ËaæÀÈ_ôØø‹¹±T"ìµ²o¨~Û¶úEÏlÚŸ×EÕ�¤P‘±ZLDÛànòÚ°ÛÌd Ýï¶‘-©x>ãTâuÙx|Œû(Á“ gd!_–4þù½‹…cû:w’V=†Žµ¶åýû#Ý}Fú\Œô}uD½gÐÞÁOþ‹nâŸÞ]ç/^¿Éͯ]J#É*?~vË#j~�v3�íýêÜ¡×eåôdpÓ×¥î Üb1¡oöl¸�¤óRSOkÅHŸƒD¡ûÇfŠÊzŒƒ^OâÊB™Ÿ½ŸØváòÜZ…¿ýÝ*AŸ‹““�k§_/†f`Ù¡ã‡Æ½œØããŸ]G’ëßɼ+ÇRªÊžŠ=RðšMÝߌÝbÚv­N+)UšP“W/£}N2¹c�ëe5SÃû%®Ã.»…§‚ÉÆßüf…·®g7=¹l1)ño¯óêÅ G&úØ7l÷ÇmŠa°“ÛnŸÜb÷€›y?ŽZGÞúÆb‘«w‹üɳ1²îøÔa7£¨Ðµg5YÅïi_"¼/`Çf3±–•ÛfµÞî%ªœzÈÖb6±Wˆ±ó+yþæÕeCö º ;ymŸÎÈU5ƒbU%UP¸—”˜^.c6›ðsl¯S�= YÖq¶ðð¬¼t,̯Î'ùŇI~øTì¡ÓýÞ¸’ýd¨}g‹Ô½ ·ÓB­‹óª¦·Õ Áa3fæ×+]+z™¢‚ª�4ät;¬žˆp`šEÝ¢çµ[�Õö9G¤ ‰l…²¤ É*&L8¼N;±ˆ› ÇñéÇdbÓí)�D76R×J<{(´ý7l7K obV¬Ålb0ânɨÅNE7 tcãr§c6›øÁSQþñÍUÞ»™{ ³"WVùç³q¾y²ï‘%­¦nÑs:Í”k­�ô VS%î,eñ8-L¹ù𺬆A©ª±š©qc>…nÀÔXˆXÈ�ÕbnkdZ“uœ+ÕšÆRRb´�‡*[Á06æÅž˜l}ÉO7#+:.Çμû8¬f~üÜ ÿó�U4C§RÛˆroÝ+óä� S#�g¢[·èyf²åÖFzŠªsi6 ºÆ÷Ïô¡p€ìróÜásk^¿’a=]Æé°’mã¤ùLIÁí° ¹ùàN¾ëDïör‡Íºc· ÍBV4\Û°,ëFÜ ß~¼�|kÝØØe…½¶G–œ´‹º¿�€ËŠ$µ®îLÑtÞ¿¾ÆPÐÊ_¾4øå‚÷9ö ºù�/ã´¤s+™ö™_®ed|n;£Qk™ñ\÷”¯¼w3Çžá`»—Òu”%µãº7ƒ…x•û… †ªÆ#RÚEÝ¢ôÚ¨ÔZ9\œN°oÐÉ+'#›2:°YLüàÉ(±��ÅDµmy½…D•È'C„ö�yíRº= ÙWîÁdîÚ6°vR©©=ÝQáÐHBNlŸé½³ZÁÜî^¼‡P¤ç±Rª¶&Ò[Œ±™ ^:Ùò{|ç‰~6 ï·Á´p))a1›?=õÜóS©ÜX,mó�›Oµ¦ñöõ,‡'¶~í{I’ ûzOôö ¹9¼ÛƒÍ²áÁøÍ“�;¦nÑÛ8‚7P›ìލéÓËY^>a;¥[V‹‰WN„¹0Shy´÷ÑL�±èï›»M&8<áw—3ä+�Ýšö«�RŒD½øÝ"—·ªŠF ··ß8ÙÇžAÏut{Sñ§×i¥Üä¼^"S!´7ÄáxÏ ›Õĵ…Ö¹þ&r2K)‰±ØƒŽA¯ƒ=ÃA~þ~⑎±íâÜí<ù²ÆþÑî,±éÊU… ·7E¯[Ø”èõ‡ÊÍMÈ'r4ð˜ûð˜—wod[ÒfðêÅ4“#¡/í/œôcµZùå‡É¶Ö~w–ËœŸ.pr2º£º#Z‰n”+JOno»‰M‰Þ`ÐJ©Ú\Ñ+VdÃ�ë`îs&~Û‚ƒ„7®fÐ Ó¢¼Ïr|_?¹’ΫR#|wãUþýBš'Äp9D”²UŠ¿×Öõ† ;�ÍEz¥jsË@*5 Ÿ«q-<^§‹ÅÌB¼ÆÇ3…¦­ûú½·—+œ˜Œ~e.Òl2qj”ÕŒÂ/ε«{k©Ì¿~˜äñýQü¢&o[*2ýþîl9l ëË)‰KóÅŽnYÝœèùí-)ømäsò¾�Úãý[y>¼“ßÞ~ g‹¼~9ÃãûcØê°²ZÌœ>4@©ÿðÖ:ÅjëÛû Þ¹‘åw—3œ98@È×¹‰çnac—Ò›‘r2¯ð«�”$�ŤÄ?¿o÷’ʦDÏﱂfP“›w“ºì–M[}Ū†ËnÁí´òô‘A®Ü-ñëó©†DXºnðê…4çg <}dè‘�ùŸÅl2ñØd”€ÏÅß¾¶ÒÒ¹²¹²Êß¿µÆÜZ�g�á'µ ¡X–éôæÃãæRé_Å|UíX[µMW„dŠÍÛâz]6Ö³�Ë®gjx\7µËaåÉÃCä*:ÿõ7+,Ä«[~ß{‰*ÿíµU•§âvní ¿w8ÈcSQ^¿’åŸÞ�75’V4ƒ³7rüíïV øÜ— g�õÝÞg´ßÅS|p'�×iá{g:wtç¦ùÃ}.n,5î$Ô0 Ê’ŠªêØl¢!772¤‹ ‘mý/%%Ê’FØ÷ŧo,ì&r³ž©pq®Èo.¤é ØÙ ûlØ­&L€¬dŠ ñœL"'Ót2Üïçdس­âéÏc2™Ø3`×€�…õ"ÿøö:^—•£ã^ö ºy7w-$Eg1!qý^‰{ñ*7gâs‹rŠf�-JŒöõf”wŸ'¦,&«Ÿðoú÷ÚJ6-zCa¹¢Œ¦ooâSUÖ˜]βš*ãrXpØÌ”¥ ÃÉ€×Ák—Òüä¹�-¿¿®¼v9ÃÔXø¡ug&Ÿú¿iºA¶X£X‘YH(èº�ÁFdèrØts|ÒÙôr«ÅÌÞá{†¤òUf×ʼ+�Ù Cý~aïFDa·™±˜MÈŠŽ$ëä* Ë©ɼL©ªá´[ð¹íì pÛÛjªºÓÉ–$Ž�‹^e 4ƒM‹žÕb¢/`'Wªño-i›ÌU¹<›äø„�?<5ò©¥8@º¨ðþͳk~w)Í×Ol­ô·—2X-†ûêÛ~ZÌ&úNú:$m2AÐEÿ'CÃË’B®$“*),¥«(ªŽ¦êh†�ªƒ®kTk~—•��“àÈÆƒDÕ ª²Êj²ÊÅ™N»…Áˆ‡‘¨·¨Ék™¼ÄHŸèd¹o-ÕÉléW?1è"‘«lIôrÅ—f’üè™è—Žøl|çt?Wîn”�X,&^<®ûýuÃàw—2,$¤�Á5;�Óö…©dˉÓ+9ü. '&BìreNÉ06,¼¯ß+qöê*±�‹É±0®ÖÒÍäË26«™Pº«|Ý06åŠÔL†±ù¾€Õ”Ä¿~”â¹c#›ú÷ Þ½ºÂ ‡ƒì}töÆ• 7Ëôl|ýx„>ÿWÿ¨Ö25~{)ƒa2sboÿ§Cªw’¬ry6‰ ƒ—�‡ëòü<5EçÃé<f‹ì ±kÀ·é÷l0½œÃmÕxådo;Ó\œ)ðÎ�A�…ï?ëØä-­j0â¤ZÓ©ÖÔMµ-¥òUìVS]‚ðôÁ Wîq9�üý[k „L »Ùñ:­@±ª²š®qg¹B¦¤°o4Èh¿¯ãCì­’-J||;Á“~Îìnùs:lfž;â𘗟}� W’8º§OôÝn�L¾ÂÑ#½½µ]NI¼}3GMÑXÏiüâÜ:õõÍE­bK¢g2ÁxÔE"WeW¬þ!•¯²´þR‡ÍÌX¿ ·ÓÆ‹'FHäªÜZ®p~ºHUV1.§ŸËÎP¿Ÿ£û\;ºï1�—¸0�à{gúÙkLÒ<ì³ñW/ ñó\¸“౩؎}`4EÕɕ䶖ïæ×«4-”kºntd­Þ–ãϩ͔7%zRM%äÙ\][Øg¥PS±ZÌ E< 5 .®)K*§|ÿÉ~Æ£�=%´ZLüðé(ÿôNœ[÷2¯?‡Úë$²†û�X-�ws·’£..ϨÈ=·~�¥#¶Ð‘qŸ½CnR ¥Ž ç÷1™M›nÿR5k‡^¼V¡j:ߎóì¡`Ãï>fÓÆ8¿T¾ÂR¢óž;…Õt™Ã#�)¤ïfúN¾ýD”‰˜“#c~ødçNÑÛ²èÙ­fÆ£.Ö3õ÷Œz¶Ðb¶ž•7ÕÓº¹½˜e´ÏÁÉ&O—rÚÌüè™·îe�äÎvxîU'�“Ø;Ü»s~?ËÞA?~n�?8íèaçÛ:Þ<8êf-]T0öps©„¢Õí¥ ÊFgF‡ÔεƒRUa-]æëÇ[³åŒølœÜëãöb¶Ý½ãYÏT�9qØvf•ÀNe[ßÖžAé| ¹Î-®×e#âwñÖÕÌ#_«ÿ~!ÅÞ‘`Ç×ý4“¹•�ïõ·´§óôd€d¶J¥…#?»‘õt™Cc½™cîf¶u'Ùm&ö¹YJÖ히0³ZåíëÙ‡:˪ÎÏßO¢fvtæÀàV ¨:ëéJÓ·µŸÇa3sxÜËR¢u³Eº IÖH%öÑë6¶>œÜãcy­~Gb›ÅÌS‡™_¯ñ_»Âåù"©‚BYÒˆçd>¸�ãÿý÷e4ÃÂcSÑž.Ÿˆg+ŒF�mqî8¼ËËZºÜîKб,Æ‹ñb·õð´KÙvÉôh¿‹Õ S�×Ù–f·Y8}p€d¶ÊÍåïßΣ¨:N»…�ÏÉ©ý„u9é‚ÄÔP{šØcA;Šª#ɪ°¡ú–“%þø©þv/C°òk>¶ÛÇÜz¡nÑ»OÈEH8S<ŒB¹Æ`¨}ía±°ƒ|IÆÙ£è#™«â°›hà+AëhȾéȸ�µLµî A}”«j[Ç öy­”¥æÏDé6ãENí½ÊÝJCDÏí°05âaaµyÓÆz ÃEÓÛZárXăìsT$•T^âИ½n¥awÔ“ûý,¬Ú>Òp§ íï[´˜MlÁ„gG3·’ã±}>q€ÑÅ4Lô">;ƒ!;Ë›(_<œ ÁÙ¿v!«:–:FZö Šª³š*sRlm»š†þ¢Ïpw5�ƒËn¡XiýLÜûäÊ*.qrû) k¦Fm]II¼z)M¶¨0q2ÜçÀã°`%Ic9Y#ž«1Üçaïh—½wTñl…é{þÓ+CX­Âla'Ò2ÑS5ƒ¿ùÍ ûÇ „ÅœÐF`°š*qw­@Mјv³«ßI_ÀŽÏeÁa3£éUY'STXËÔ¸|·H¹ªñÔ� '÷ú°?䯮Ê:Nç¹4Wdÿhˆ];?·¥¨:ï\Yá{gúëïݱ£;�–‰ÀZZâ§gá£X‘)Uw΄´ës)"^3§ö sÐ^¡mgòSÃnîrsi&)ìå›H<[áÀXcÜRÌf“Ãâ™öxü5š¥D‰l¹ÆwN‹2ª^¢­…H_;ÁaÝØ~ šC®Xc¼�åãQ'¹R{ÜœI¾,s{!Ã�žŽµu̦ õ´õÛ6™àûOö³š*²*æj4©¦6ÔÉç¶R“»;%Q“5>¾ç§Âôù…ý{¯ÑöGœÛaáGÏÆ¸q7E¶ØýD§¡ê¶žHÚ­&­{óšnðÑí8'öxÙ?"ì³z‘¶‹@4èà;OôóÑ�eiç$É;§ÝB¥Ö¸È¬TÕpÖYØÜiÆFò`ÄÆ3E_m¯Ò¢01àæùÃA>¼nË Äã´’.4îA’)*¸»tî�»)lføƒÇDÇE/Ó1¢pbÂÏ¡Q7Þ\GÂ×"�ÆNT»½\¡?Ô}½ÓÓK9 å?|&йGÝct”è¼x4ÌÞ˜“oÅQ5!|Ûe0âffµ‚$oÿZfŠ ‰¼LÐÕî�µ)æV ¬¦KüäyqR+è@ÑxéD˜‘>î$ÐôîMšw.‡•¡>goæ¶ý^o^Ͳg(@µ¦’.HdK5”0ÝKY\Ïñç/Äð:»s[.h,-7¨À_|'_58µ?†YŒæÚ25EãìÕU¾u*ÂÞ-vf|<�çý;L€ÅbÂç´ êÙ¢B$àdßp� ÏÑî�ú‹‰3ËYþ˃bf­àS:VôtÝà—çd+�OŰˆfð-“+Ö8;Î÷Ïô3ÛÜöôÂl�w®gíwò‘}þß÷¨ªšÁ�Åo_Ï21d¢C\X»žçOŸ�ñ‰žZÁïéhу�ˆïÿ|œb5%súÐ6áf»e2‰ Ó Níõsz*ðHGIÑyûZ–›‹%ßà™CÁ‡¾¶PQùû·Ö™2Úæñ‘³ËyV’y~òü !¯(>fC­u-Ñ ƒksIj²Ê�Ÿ�Õí -è=ºêQøÜá0!¯�ׯ®qr_”¾€˜c°U‚^A¯ƒƒl†TÓ0›Áa³`úäÐ(_–q;,›Ú"îqóÞ­BKEOQu.܉ãw™øãÚv'Øyt•è÷âs™ùù ODîkŒmR/c6™pI9‡$«6iVðX©¶Ð� ,©|t{�©A7_;®{"œ wéÊS�ñ˜›?!ÆìRšÛ÷²Â�¯I˜Í›7P5£eór“¹*ï]_åô¤�—NÁÔGWŠl˜ü__¦&×8ws­ëíŽ:ŸËN*/£o⩲ž­µ$ßzw­Àå™ß;ÝÏc{…ë± ~ºVô`Öê'Ï °'æäìÕUrÅZ»—´£pÚ-x\6¦ëìÝ5 ¸4_d Ò¼”ƒ¢ê||g�d¶Ä_¿2ÂîMÖ ]-z°aDúÂÑßx,̇·âÌ­äÅv·�LŽyýr¦.{ª�f hº™X“ 2Åï^]!°ñ¾6ˆÏ%Nh›§«JVE¡¢òËsIdNìíÇÙ¥H�ÆôR–T®Â?{h;×GÓ>¸�ã©#C¸�½î†³«yÖr|û±~ö wŸË‹ sØQ¢7ȹ[9ÎÏ8´;Â�8Ým ëî,å88êarØMÀmEÑ Ö25.ÎÑt'&û.xIåÒt¯ÓÄwÎô ÓÁ¶Ùq¢wŸµ´Ä/Ï'qÙmÙÓ�Ó.¶BÛ¥&k,%‹¤óÕšºa<à¶3ñ4|KkwW L¯æyî@�S“�ÑÓ+è~v¬èÁ†aÁ‡wòœ›.°o$Èî¿(kè ™«3)\ß~<"  eG‹Þ}’…ÿöQ Y5sd"‚ß#n¢NDÑtf³¬¤J¼t<Âá]bp� ñô„èÁF®ïòÝo_Ë2v35Æ.Œ :À{ñ"3‹Yö »yáhHôÎ šFψÞ}$Yãý›9®,”Ù7`|È/ JÛH*/qën·ÓÌ+'ÃÄ‚�eD*ØyôœèÝ']”yãr–µœÌ¾á c1ï§�ö‚æ“)Ö˜^ÊR“U^<3h-£gEï>ñ¼ÌÙk9V²5öŽÙâ×L ™¹¥™r�g86îÅlîúyAÑó¢wŸå”ÄÛײdJ*»‡ŒE½X-âflÉ\•¹Õ<IáéŽîöµÌ˜@ ø,Bô>ÇzNæüí3kUF£^öDgÇ1 ƒµL…ù•<:�O82æÁ*,ÿmDˆÞCÈ•U>¼“ãÆR™~¿“±˜Ÿ¾€KÔùÕAER¸—(±”(Òï³ñä�¢uLÐÑ{5EçÆb‘ËóE*5�‘¨Ÿ±¨WDŸCÓ Ö3–ãE e™CãNLø‰ø…­¿ ³¢· Ö35.ß-r{±Œ×³Ñ~5ñàèÑ7Ý0Hf«¬¥K¬gª F÷29âù:AÇ"Do hºÁB¼Ê�Å2³k;aÑ� �sgG6Ц“ÌUIdʬeªDƒ6�y˜ñài°Ù€@Ð „èmM3˜‹W˜Y®2¯b6C_ÐE4è&ìsvýœ^ÀB¹F'!¿³áÖK�FÕt²Å™‚D®T#]�ð¹¬ìt³gÀÉhŸSœ¾ º!zMD× â9™¥´ÄR¢ÆJFBU >—ŸÇAÀkÇí´ao±�hºAUR)Te e™²$“/*H²J4hgWÔÉHŸ“ሧ]ˆœ`ç D¯ÅTjñœL2W#QPYÏÈä« †nàsZq¹l¸ìì6+v«»ÍŒÍjÁn5cµ˜±˜M˜Í&0�í“âiM7Ðõ�¯QQutÃ@VuUÛø§¢!É:’¢R•ª’ФjøÜ6¢~;Ñ �þ€�XÀNÐke9‚�½¡¦èäK ùŠF¾¢R®ª”%�²¢S‘4jŠ�¢jhš�j€¡o*XÌ`1›Á«“ \v3.»—ÓŒÇnÅã2áw[ ¸­dÁ2¢’¢¨õz2¹qÏ®]»øÃ?üÔ}þ·¿ó}††‰Å Äe ù�*ñž¸ *Õì¿“eP«îþÙqdÔÜú&Y%£’ß|]FFÅ쟙ùw3¿?ù+UâûÕñÆ0æ§ì îÌÔ¨IoBe0$. dâ* ®BÑQ§–Q‘¸Ne@Ž«÷• d•J…F&­š÷¿ï]§,”ÿäg\¾r�8 ˉ8âqòŒëú–kþ&ª}ӛȷ³³~Ë÷̓�ø{5 ÒhÁ˜‡96�²s$¸3RL&"©9qý #'~D–U ’A^앲8’÷p•Z†¸ŠøÍÑ�3}á©U2jµ ½ž|âíTVVÌë³ç­–$Ib×®]|ìc[у_6b1®}ýDöÜEÓÕã#vð–ûòEŽØ Òó­grãb«k•eÑô÷]M,.Ì“œº¾¬[·¢¾�Ú;¤t(9ƒæÒôv;¦U«”%íÉäå÷$RõFdÿ(cWn(JÎ�Œm?Atãn¥CY2rŠÃãªÌckJìÜ›¤w8ªt(9ÃD÷e¢“SÄ*j”eɨ�,‘SQ­ÕboÜ�ît«Ò¡ä²ŒþÜ!<{š•Ž$3¸W"a& V]¿ o[낞T‹gàð1âÅ«‘íbY?ÐiÕTÛ8Ðå# ž)3‚±Ö6¤M-wO&ÍæÑä”@plÛ†f´_¸ˆ+€öÒYtV+ÆòÌÌ÷Yq²DQÅÖnDå.âJ …£DOGÊ÷Û3RJ<&xXSâ`pd’«#ÂEL5—/™ «ÈÜ¥å™È ˜grN ªµZœÛ·¡k? t(Ù�,£;{P¸‡ ÕËk+†ZƒÔ°“@[›p8RLÿÁcÄ‹*ˆ;TÞa¥CÉZ4—Ï¡·š0UÌo·”€TÏ�+Š´nŒ2t¥_éP²–„{xŒè†&¥CY6ä+8… þ,+U¥Æ&¹<$)JÖ2qù*RpœØê:¥CY6âÂA¼;*½gãtg„‹˜dýÙ6\{ö(IF±Âå³R‹Zƒ´aÁƒmÂáH‡Ž/,GvehY¤Û�jÇy!ËkéŽN£¦¢ÈÆÑ >bYt\éÄèþV¢›³Ç=±Ie^8·nE;Ø+\Ä ¹r�É„yõj¥CÉ,²LHIk7¡`è²(ê»ÜDÂ"§ŽeÅÎ器R<#e›Žª*uÐ?2Á•!‘‹¸ÜL\¹†41‘Uî!,lšÉY�¨Òëq4î@¦MéP²‹›;—Ý÷ ÷0çÑh‘ÖïdüÈ�-kîÍÐá“Ä We•{dŸ‚K1:­šŠ";Ç.ø‘Ĺ[VF÷ º©ÔÙ%“RN-»Ž|�8·nE=؃Ú?ªt(Yƒæj:£N¸‡¤u›Q0|M¸ˆËE4%rêXÖì\ž‰œâ:…Ù³Pø&Ue®�NpM¸ˆËÆÄµkÄÆƒYçÂÂVËsZ ªôzœ;¶£k.â² Ëèδṇ‚$-RC#ÁC"q¹8t‚xA)qWæ¶üºª”'âfŸDÔkoæ"^ q™Ù×JdcsÖ¹‡p³gô<ɾ£_ ŽmÛP÷_AS:”ŒGs­�Q�¹²RéP2“,J„ž‰T³õp?Ãו%ã‰Üܹœ�î!��úmE¨.sr}hœk¢.â’™èí%櫬W:”” V‹%æùŸ½Ƕm"qеÀ³§Eé0é†F‹T¿ƒñÃ…‹¸D†Ÿ$žW’•î!€*Õ­ð²T€&]ÄcbGó}c¢îaº‡°°JÙyˆsÇv4×/ q h®v¢×i1¯Y£t(K–Î]Äj¶ èeäšè`´X"á(‘ÓG³ªîá\R_1{©.up}x‚žQá".–‰ÞëH>?Òš¥CI¢ÌÍQ 8·mEö Ò¡d,º3pß'ÜCÁ푵:¤úF‚q‘ 9EÜSŒì)R:””‘êK#žÅŸ^§¡¼ÐÊ‘ ÂE\,£¯ï'º);sƒ8 7±ïØ�¦·[¸ˆ‹@s­ �V�¹ºZéPiL¬v+ª¡>F{DíÑ…2‘�NÉÞÜÛ¤z‰Y­Îfñ¦‹84NÏHLéP2މÞëÄ|cIJØ=`cLÄ›¨ l[·b8wHéP2]{+n‘{¸d²×Û¸y|ZRý‡D]Ä…2tä1wñ,v�”‚lï ®×iXUhãèEÑ]e¡Œ¾¾ŸÈ¦fPk”%µˆÄÅáÚÙˆºç"ª WéP2MÏ´5–µk•%óÉöÙ ˆÕnC5ÐËèu‘‹8_¦¦$¤‡³Þ=„•ÈÌþ1V]ê whœ¾QÑ£y¾Œ÷Þ@ò�«Z¯t(i…ˆ3P Ø·ˆ\Ä… ?Ó†gO³ÒadÙ?uÍp̉ã]�Ÿ&î)$žW¬t(©'ÅKÀª,-%5ƒ^Cy�•Ãü"ßwžŒîÛ—xËv÷TNMÄ98vî@Ó×�*èS:”´GÓ{�:ŽeÝ:¥CÉ Ô90yÁM±¿ßõ¥CI{¦"1¤G�6æÆC˜*Å� ¹²êZ]æ.â< õ]'66†T½AéPVÑjoñhŒFl›6 qèÚài¹‡Ë…œ#žš¬Õ!Õmgì€c÷bøØipåå†{Hê—˜Õ9�Æ qU�•#ü"ß÷ŒìkÍ÷P-À¥ñ6¸v6¢¾Ö%\Ä» éëF'K"÷p9É�¹ ©vªþ«Œ ˆªwb*'zâpV×=\iäqé!á"^§ß'v4߉Ð�~¤ÑÑÜq…²—ŒÚhıE¸ˆwCwº÷}{²¶=œ,äÉ.ãÑé‘j·á;p@éHÒ–¡c§‰;<Ä Ê”eÅHu+æT/a§F½†²ü›¹ˆJ“¦ ¿±?ñ–#î!€F´Ú[:ŽÆF4×:Q�û•%íP÷]B/K"÷p¹É�¹ ¸é"ö^Á×/\ĹD"q¤“¹±syEIµM3Ö®rrµ?È _¸ˆs™¼1@lh�X¹‡, [‘ˆw@c6cÛ,\ÄÛ¡?½מá –†Þ€T»�±6Ñ}.ÇÛ‰Û\9å¨Sn!æÖS˜Q¯¡4ßÊáóÂè˜ËÈþý‰Í_­Ò¡¬, P}B ÞçÎ�¨¯ q&šë—ÑÆ$,55J‡"È¢uÛQõ\"8$\Ä$’'zâPnº‡â™sÙ©.spi ÈP@ìhN250Ht`iíF¥CYqòŒ$â]Ð˜ÍØ6nB/º«L“è¹Ü,ÜÃT�‹§To Z·�ÑV1Æ’ ? V'ñÂUJ‡²âä–¿·2˜ ZJó­è (JÚ0üÆÍ�˹æqÑjoùp5íDs¥U(¨t(Š£¹qMdkm­Ò¡d%¹¨¤ºÈ=݇E£XL&r¬�è¦Ü¨{8µ�ˆ)am™ƒË׃ E.âäÀÑ�Hk7)Š",$�CÄ{ 1›±mÚˆþŒp8t§[ñˆ�Ë)#ž«mô¢5[u8ÞŽluä¤{¸È9úf2h)ɳpP¸ˆŒìkCÚД“îáBq8wíBså\N»ˆêþ«hÃÂ=¤„XýâW» �ú”E¹s‹>zˆhŽtM¹¹T§p¥Y·ÊÉžc9ì"†‡†ˆÜ –£î!,,�CÄy 1›±nÜ€.‡sõ§àî¡ EÈz#±u›iÍ]qèäYâñ¢r¥CÉZT¹êÒó¦‹ØÚ‘»›.‡ßhEj؉¬Õ)ŠrˆÄåǹs'šKçPMŽ+ÊŠ£î¿Šv*ˆ¥®NéP²›×ÞRC#Òå LŽæ^.¢,ËL=DlSn·®T¥º^Ž�±u«œtßÇÊ=1<ƒj*„zàšÒá¤õpZÿ0–†¥CÉäTïàÌ ¢ëwíî âÏâÚ£²ŒïÐA$‘{¸bñMjÊœœ»ê'ÎÞÍÑÑQBW¯Y·UéP2!AÂE¬Esrú¿È¾ÚÑÆWÿ�Ã!ÜÃDÈÃLĪ70ðíç  )Ͳâ;|˜‰Ë—ïè@R鈕T*RÚ�ê27B¾‰Ù¤ÃnÖóãÖì_r,Æà /àkm%¾~§pg_À³ÿ‰MMõzA£Awñ4ªq?êÁ>¥ÃZ6Tã> /~9<…¡<·Kn¬4b“Êl¤†�Ä‚n<û,��J‡³|Ç52‚÷µ×ðîß/ÜÃ9ÄR,áÄCØlÖ”Ú¹16Å÷÷÷gM«ÏÈÈ“—.1úë_êé!,ÜÃY,d„ �¸@"ׯ3ðüó�ƒ›J\=6 tXË‚úÆ ¯üu` T*,kÖ(RN!äáld“…¸»$‰áŸÿo[›Ò!- R0HtxÉçCÓy}ë‹ +Vš�Z‘"Ò8fSè6£V«¸40Åw÷0ÍüM+“×®!G£ŒŸ8�Z¥BðWhz.(VÚ…²S‡©ªŠ‚÷¿]AÁôkª Oé°–Lr¢RùGP�苊”+§S×­HuÛ�£Q|mm ýìgÄã™=‰Å‚7SRdõè r^1è J‡•ÄRüŸV-\úY¨U*¬&* ghŠï¼1À�?ªtXKBò&:1Åi|U4L\¤qL³�g$!�¡ €’§žÂ¼f È2šÁ^¥CZ2ªxŒØš¸Ye^çp 6ˆIkEîÆ-Ä˪@£Mü ILõô0t3¿(‘ÆÇ‰Œ� ÛÝ„÷¼ƒhí6¥ÃÊ„ƒx+Vã›�E¼ãQ^88ˆw\R:¬EñùÿG­AªÙJø¡÷æ|÷”Å¢U:€LEm4’ÿÞ÷2øýï¾v ¦B`4+Ö¢‘êQ�`¸z}Eyê{¢ ó@Ö‘mNÔ¾QlM»p57£Öfîmkª·dÙê üÈû‘mN¥CJ+RÝèDÜÕnÅhТV©P!óÔýE¹2Ûˆô÷ßzц�J‡“~,`Œ q ¨ÕjŠ?ð´ùùèÏf~]DýÉ}8[š)xâ ŒbƒÊŠ£mÀn‹l4#•WC,–Ñâ`üÜ9Ðê˜z×ï q¨bˆÝŠÕ¬¥Ðc¦(ÏÂå�I¥ÃYr$‚‹¡®n ,ÄámYÈq(|Ï{Ð^:ƒ*2¥t(‹F5:€Î?ŒmãFÔŽ]»”)ç�³dárÙýÑ��h?ƒ41¡t8K"ìõ¹ï‰7—ͳÐ- ˆï¢…o¡4ßÊæê^9槪ÄAe‰MoÅ”-vbµŒƒÔ´­9½k�Ê2ÛZ‘6å®{•ý ߆úMl-ø$nczÜg Å+Cuú…P$á":;ÀÎuvôºô¾n£~?“. ½ûi¥CQŒ˜bD:‚7v·¶�=…'ßlYòçÎ[ ÞË|ŸŠ.ôúxæe?5ev×ÚqZÒû[Nt.¦ª*"N"­oR:œ»¢moŵ³1çÜC)Wo:†áxÂ1,Ó¼ûÎÂPa’B±ª°�îÁ‡;½9-e‹�ØêZ†£äáû”ç® u\)J¬¢FéPVœ¹Âp‹çi<eÃ{¡Öè©ÌÏçòP„#�¾œŠv‹—Ý@[W�ÖÛ•ç® ·$V» éym¥’YÂP×°dÇp.Ë® ¦—žo Åo¼Ò˺R»êìxrD(ºïkaòÙGªÙºÔnlX,*ßÚáØÞû„Ò¡¬·†åº'ÓVÎE­‚uEzª ¹<á` EiãnÂÓ.bzN qÆÈ9÷0*û•Žâ‹�#_¿‰òŸÆ­ÐRòBQ© ªPÏš‚® E9ØéåÕã}TçžP\WîâðÙšjlÒÔEŒ„/t}×'”eE™) =úzî÷|�Ŷìß3o�¸ÐËc¦P¼tÝϳ¯ôRSf§±ÖNž%»™Î帺‚È…ãH éé"Níǹ³•.û{TJq¸â»N÷…aºÜ"Õ*¨.Ò³¦°�îþ0‡»|¼|ÔOuiîÅD.b ƒmG)}$=]Ä¡ŽË™Ê÷p¶0ÜÈýyOã1§ÇRòBQ©`M¡ŽÊ‚zF¥ÙB±Ô�N“Ýs€Ã¢Çi3p 3ÀCÒ3qpÒº-Ýæv!̆ºzZ<¥ Â0IÊ×í=[ÖåO Å¥�ª+Mµòm™áÜ,OK SÏ=�´.ý\D•oÕ`ö÷<®t()e¶0£m\’cW¥×®>µ Ö•Bq ±n?¯ëÍG1ºq7š¿I´iº4[º”b0q07v.Gå£Ò‘iÇpOÞÓäg¨0œ‹JyZV5çsmDâp§—W�åŽP¬©pqøüM5vLúôºŽ£þ‘΢9�{8Sº´õ4çŒ|«5å­ðRæ Î%)ƒ¡Ý}~žÛ{�µ%6vÖÚ³R(ê< åD;�Ý�^.¢át+î];QëÓK¸.R.ûnÐ<@D^²0œ&ž^7È$Z Ô–êY[œO÷@„£sC(ÊV±Uké?xŒòGö(Î,†»®Bd’XE­Ò¡¤Œ™ÂЭÙDsþÓZ³CÎE­‚Ê|-yù\’8zÁË+G{©(²±v•3k…¢Ã¢Ça1ÐÖàá�éå"îoCªÉn÷0) Çb§pëjhr~Œ"›uÅž9ç¿Ie™"²™oŠÕ%6šì¸ÍÙ%óöì!üÜóDkÓÇETûFP \ÃöîÇ”eÙ‰ËIaØÆÔMÇÐ¥yõråi®³4j¨)ÑS]”Ï…�0'.xåXoV'ÚG7îFý‹oÙµ½5=\ÄXB‡ovMÉB÷p¶0ÜHsþÓä[�)w3Òµ ÖjY�ŸÏÕa‰#|Y/kÊ.â®;Cz\ÏÑà8Ñ‹�IJ4÷P’CŒÞ†.m ;ݧÄfe…J…N3q™[½)£t÷ùøÖË×Y[j¥¹Þ�+K„¢ÎãÁX¾ŠH× ¤õ»”'Ó鸲Ì=”eè qÁw€‰x?m#eºw-Ÿ0¼IzÜï�F u%ª‹ò¹4æÄÅì­ñ&ÛœÄʪ<|œU·(ýWQ…ƳÎ=œ) ]Úzvç}œB›%cÆÅr¢V'„bE^WG ×>)ËœY5ÆœV=N«�Ã<”&;š‡ÞhCZ» 9ËÜÙÂС­¡)ïã[WÎ1œ‹âõMlfÝ,¡øÍ›BqO�GlfñìÙÃÔóßFªÙª¸‹¨ö�¢¸ŠýÉßPú´,×LJ8?ö¦0,Ö½cÙ…a¦¢SCm‰�µE‰Ò‡»²³Æ›´±™èÏ¿ÅÔ®í-Ê.qFc>ÜšÈ=\éÇýTÓ,ǰžÝž�Q¸‚Ë\éŒFU…:*óóèur¨ÓË+DzO(Ö”;9Ú1DãZ+Vƒ²Ç ޾Ø�ô®ßSú´,·s KíÊ�±´™I“Bq<åbŸ�g^飦ÔÊž'¶ îÌ¢ËËÃT¾*Q±a§¢±èOÀ±s'jƒAéÓ²dú'†8;ÖÆDìÆŠ C™ôÚ¤2_4jX[¤gM~>—#ëήo²ÍI¼¬ŠáÃ'Xõ�²Œ†º®¢šœ ¶ºNéÓ²df C�¶žæ¼�“o³äÄRòBQ«au¾–ò¼|z‡£ºàË*¡è´°™uîçá�ʺˆCûÚˆUoÈ ÷p¦0tëjØíþ8Eå…a’yϨ+ÕDÂzS(†¦$.öùøê¯ú¨¯°Ñ²Þ�UŸ™ƒÌÙÒÂäw¿—订U¦¬Œ*èEÝç»Uút,‰þ‰!ÎyÛ—n CÃÛWÎ1\áN*Ë�FëJôTpy(Ê‘NoÖÅè¦fÔ?–ÉÆ-˜ÊEŒÄ`òH±MÍíÎZJÖÔÓ”ÿq ­Bε * t¬ÊOÅ#ý¼z¬—ò,е.Žv ±s­ «I™{a$0A¤ë<Ò»>®ôéX’<ɨtxÚ1lÊûE[ÚÝ6ÒÆAœ‹Ù¨eSukËn Å_ôQ_ncÏzæ Іü|Œ%¥DºN!5ìP&†Ó‰º‡™êŽ„9=ÖFPJ,%­¤0Ì2Ôj¨.Ò±¦°€Ëƒwù2¾°ls/]Ãà‘S¬~H™ªCÝ}¨'D*ë•>‹bÖR²¶�Ýù§@ÃEñ¦PÌ£çfŽb¦ E§Õ€Õ¬ãp÷8oH]í½»1°ÿ ±µ‘MË×-d%‘äIÆbÇñÆŽãЬK[a˜dþ3¬BîIR(V—It÷ùø·Ÿ÷R·Êʃ›\˜tizVoƒkOóMq󊻈ª õõ+ØŸÈ<÷plrˆÓcðGûpkwPmP2Ç03—˜ïÄ›· è•8Ü™ÙB1º¹õ/þ�PãVÌÖ•}ŠÆ |p±�™çJr�é0¾Ø9òRЮ+—Q«`u¾ŽŠ¼3»FÈ6ñâÕ =ÁêWÖEºtÕDiMƒÒ§aÞÌ,¾›¯oàÏÇp[„0L*”»u”7yèsp¸+á(–XY[æÄ ÏŒÊ.»«)‘‹øÈ ç"8”È=Ì ÷p¶0¬¡ÅóQòmʸ¯‹!3îü3H Åû6—â›�ù‹½¼|jŒ!_˜e®Ä³ì¸÷4£=wbÒŠ}§*èCsý2ŽíÛ”>üÛrλ�NÿÑéŸýá!öõ¿ÀkýßC/f­ñ÷ÉÓìJ q˜á)ˆób•[ËûZòùàý%Äc¯íåüÕ1¢±øô{&Ã'/ +êm‘65?}”‰‰ÈÊ}g‡öݸ;#ÜØb0ú:#_E§‰òpéÇØSúˆ‡+D™[Ë{š<<õ`):-¼v¢�³—G GbÓï‘bqŽv *êm©©pqþª_hå&ÜHp‚Èù³H �Jþ¼�äI†¤Vº#_A¥çþ¢�ò@Ùod”8„uRI/õe™ÎQtr±ÏÇ7_¹*«†B»‹QC¡ÛÈê<v‹òâÀPXˆ¡¸˜h×i¤ú•lúöVÛ¶¡1¦_‡ƒÞñótN¢S뛺Î9ßF'{qëY›†9†ª4í¤’ Š]ZÞ³;Ÿ!¿Ä�ó³»FŒ‡"Ü a·ø©*M¯î q‡‡xQÇO`yhej�]샀—Xš»‡3Ã"c�z>ŠEŸYV6QäÔòäNÞq­çý¼v¢oÚQŒJ1†}“t\óRWáR:ÔY¸m,&Ç/yxÃʸˆÃm‡ˆU­G6§÷õc’Q)ázô5¢RŒsWưµ¸íéswÙŒ˜�:Ž]çá�©}Øn=„TÙ�6îa¿ôk±.¤™ó`×Ñ\ø.¬z§Ò!.óO˜É÷D§U³½¶‹I‡Z­ÂmÕñ•—úxùä(㓱¥Á2áÙ³ýùCO]Lªq?šÞn\�+»!æ^ŒM ð«Þ¯!„^eîi _»‹Uú'(Ó=�ŠôpanKŒ�Trup’þ±0.»£.q2Þ8}ƒÉðÊåÕÎiS rû‘”æ"Æâ0Þ¶?­ÜÃ2Ý;±©ªQM_¬*ÖÙy¨ä)!3€þÑ).Mâ²i1Ýܸ‰Æ8x~�À æÕ·Úr'çzüø§R÷à M>wiCz´ª(Ö¾»¦žé A¥bµe�®úݬ‡° ^Ì™1;ÚÌ:V»9{yŒMëŠY–¸|ýfÁíÕšk]XMÊÞÌ EE òˆt·#­Û’’ïз·aÛº5mÜñð0í£­x#½8µ›È×ìIߥdÁmY]hbua¢u(ãúÈ$Ýýa® …Ø{¬—ª2;U¥®´(Ýwæ/*gèÈ)*L�+=|ù:jÿ(‘ê J.�èÊà•Žà:•‘ˆÂÿñ#¤ê�Ëî>¨&h{/àz\ùÜñ©aN�À¹Fžv'kE¹š¬Àlа¶ÔÊÚR+àÁŠr¤+ÀÞã=¬*´§E�·è¦Ô/—ÐÎ-˜ÍË»—aü`+ñ4pg¶ëZe­åmî�qvì &¥qvä=¦hl‚ÅcÔ«©*6QUœx(›K¾àõ››YªË”еå.Nv�°}­»qyM¤x(ÄTûI¢O|TÑc„D^ï¨tŒ1é8Å–5¼Åõa.úŽâ�°+ÿJ‡—2æßj/Ãò¯Šç$Λ Z6¬ñP]êàÒu?_ùÕuÖ–Y¹¿Á‰Í¼òƒÌPT„>/�H÷¤u›—õ³õímضlVÔ=ô†‡h9ÌXä*ÝÖ¥á®dÁòá0ëxË�5vÚÎÒ¢­ìÌ#ž_ÊðÑSTÜ¿¼Œ†/ ö�yH9÷p¦0,3×°+ïc˜4 §%ÏPF‰gj•òn®`y°´<´ÁÍÎuvvøyãx/EùVjÊ]Š E�ÈY¯áX÷8­_^—¯¿õ¦{hU®R´0Œ� Ð´†·ÎØ|â1—°N¿�*}ò¯—›œ»{˜ ZÖ¯ñpß–RBøêK}üôÈ�ÐÊçP¹ïkA¦mYsU4W;pìP¦¥ßèä¯_‘×û¿‡JÎg�ñ“iSÇpÉdÖ3’"8Ì:Þ¶ÝÃÇÞZ‚Q'óÊÑÞ[j¼­$ÑM-ÄNf"]¶ÏŒË0Þ¶�è†&EÜCiºŽá—1ê§x¬üãì,|Û´8¨´oÆ N¯Ýå‚åÁbÐòÈfŸx¼ ·UÍkÇû8Ý=”BclÝ*'ç®ø ,c.b<"|ö4ÑõÊäÆå#±C\Œ|�ÆË[K>DsáÛgíL.·¬Ç¢K¯2_ËMÌÚ‹#)«n:Š_ûõuªŠ-ìYïÂmY™›¾±¤�Ç�¦û ±er¹‡[ИWvr�æÌèa|Ñ+¸µ;XgxÙûd%¸;N‹Ž·o÷Ð\ë õ¼oV�·•ì!»ò‰ç—0rô–er‡®  "öà»Wì8 Q|wT:Œ7~Š} �æ«(W“³X ZÝ⦹ÞÁþs>^;ÞGI¾…uå®é .+AžÓ„Ñ áØ¥qjXžëq í(±Õµ+îÆåcñŒHGpëÖðpñ‡qè3¿\ÍbIû^Ì©&)×–9¹tÃÏ7ÝGe±…ûê�xì©×Ïy{Zˆ¾ðSBÕ–ìF¨&h®uàü�•Ë=žæ¬ï¾›KÉk…0Ì Qã-ÈÁ¾³~E„¢´©õ«?`bÇf,KÌEL¸‡û¹‡)®c:ÿŒv]n] ~ Gß,/Vƒ†·mõÐRç`ÿ9?oœè£8oe…âºUNÚ»GÙQeöÄÌ&)4ÅTûI¤·ÿîŠÄo ÃQéNÝ(ümÜ&÷Š}º²€N*Ù�A¯¡~µ›êRÝ×ý|ëÕëT[ØSï"ÏžºAf(+Ãàvî>Klݦ%}–þÌAl›7¯ˆ{8æÜØ!|ÒU<Ú¬3þ††‚;â0ëxGcÞqûÏûyídeù+#ãîBâžbFŽ·cÙ³´FÃWQ�yàÉ”Ÿ³Y}\uëx LB n�ͤå±íö48Ùw~e…b¾Ó„Q¯áØ¥ .ÑEn;œpmΔŸ³YÂP»†–ü‘oÉ]Çp.ó裸í ñ&zÝ¡øJåEöÔ¹(r¥f�¹îk!ü“Ÿª^¿hQOä~â÷Rz~†&†9çK,%{´;XgÈ%a˜#ƒ …¸¬:žhÌc$èä@ÇÊ-=K›[P¿ò&¶m\´‹˜Ü¹ÛØ”R÷p–0Ԭ㾼�à±®LK3Aæc3ix|››=uvvyãÔuŠÝfjÊ�õ©»nו;9sy”íklØL‹û ir’©s§‘Þöᔞ£™ÂЮ®d—çCÛ„0œËê æV†þ\¡øük©ŠÆ²2ôN'áK爭ݸ¸xÏ´aݼ ­Å’’ó181ÌÙ±CbWqi¶P­ÿUjÛ˜ ²—<›–w6æ1p²†PLU鎸»�x^#ÇÏ`Ù³¸FÃWQ�ô#Ý÷Δœ“™ÂЩ^Çî¼�P(„¡`‘ØÍZÝê¢i��ÖN?¯Ÿ¼A±'uB1ßiB¯ÕpüÊ8Ô/®(ûðÁ£ÄÊÖ¦Ì=œÎ1ŒÆ¢©`§û·)±‹¥ä;‘³›TæKR(&7³<ÿZ« ÍìipQì\¾Ó纑ŸüŒPÕzP/ls¹*4ŽæÊyœ)pû'FèðÂ/]¹) ß*„¡`ÙȳkyrgcA'­þ”Öx“6µ ~íG„¶oļÀ¨ñ8µ_¿kÙÝÃDñÝ„0thÖÑ”÷QЬb)Y°<Ø­ÛÁA[G€×NÞ $EB±f•“³WFپƊu�¹ˆ±©0S§N}ûï,û9˜) ­êr=¿M©Ý#Ö„îÁüÄ?“†9BñÛ{¯SVhfO½›’epMeeh�´WÎ!U-¬¶šîlÖ�—Í=”�ëÁ.øâŽ¡`pÛ´<ÑèÁ;‘H´O…PŒ{Š�]ù ?Ãê–…u0îB=ÜO´å‰e;æ™ÂТªb‡ûÔX] }>æ…ݤá7¶ºh®µs 3!‹\&jÊ]˜�Ë#ó]&t½Ž_çþºˆCmG‰•¯C^Æ¥Þ¹Žá×oSa÷ˆ16O柃˜¥»˜Ê\¡ø�×ú(+4ÓÒà¤Ô¹´\à››OcR—³Õñ!V9…0\,óˆâéö¶èujÊ]TÛ¹Òà»ûúY•g¢y‘BÑݲé¿Bª¬¿§‹¨šœ@sé®�/Î=”eè ŽÒåk#¿*CAÚá0ky|»›Ýõœ÷-‹P”6µ ~ãBÛ7ÜsiM–aü@+R}ã¢ÝÃ7…á ¬ê5lu|˜2‡KLZ‚´ÀaÖð¶mnšë�8ïg{?.ëÊ�XŒ‹»ækV99{Ù˶5÷vcSSLœ:†ô¶Å»‡s…áû‡¨pºÑ‰1¶$„ƒ¸LÜN(–zŒÜ·ÞM±kþ§Ù¼z5Z» ÍÕbkîú^ݹƒX×7,Ø=L ÃNÿA‚±Ë¸5[…0¤5.³†·o÷p_½3QGq ]#âù%ĆOœ¡b÷Ý]Ä‘¾aèïEjz|Á1'û¸&…á&LJ)w8Q¨5µ@pWì&5oÛæºé(úh=½x¡Xè6ÓÕëãä•qöÔÞÝE>|œxiբܸÁogD:„I]Êû‡Xíp W~™q™™+¿óÆ�„PlpQŠj i÷üÜÙÅwmš5l¶ÿ6«œn! ‰í¦P¼¯ÁAkÇ8ûO'rç+“.â‰+쩽}…�¡¶cÄK*çíƉâ��ž†›¤Ìîa[OçóˆB.½V=K(~wß%{”ÜE(ºZš ¿ô2±Õu·ºˆáI´—ïíÊ2ôOxéðÂP�•¸¬‰]Ͼzm] «ñݲÕ¾Ÿ2¹u¦Û¸ˆÞû‘ïéΆueBŠe.A–`1jxt‹ƒ=õVöŸ_˜P\w3qk¥å1‰j?ŽôÖ§îÃLahV—²ÞöAÊ b 4¥ˆM*+DR(®)qpù†ŸïÝŠ÷¯wRäºu�™++1XLD¯u&Dâ tgb­¯C{—ÜÃ� çFá� a¸lˆ‡¤´ÅiÕòض„£x #8¯®ñüRd›“¡Sç¨Ø5»ƒÑØ /êþ¦š»ãwÞN–‰e.A–b6$„âî:+;ƒì?uƒ<§‰Ú Ö;ìz.r›éêñqúZˆÝë̳~7|øñ âÏ¿óv°Âá!…3XÀi q9Ðׂ͊|û�~JóŒÜ¿ÞEÑœ:Š®æfÂ/¿J¬¢vÚET…'Ñu·ãüèGnûù£!gÆ1&%„á:Ã'P³À’öA†â´hy|»‹æZÛ´£x·bÀÑÍ{Pí‘©­ë1êß\ ö؇T¿ã¶îá-ÂÐñ!Jí.±Ì%È lF oÝì¤¥ÎÆþóã´ž¾»P\·ÊÉén/[V›1ÝNr$ÂÄñcDßúÁÛ~GRŽFaTQo{«…Â1\aÄéV�VMu™ƒÕÅ6®öùöÍ:ŠlpRàH 2óš5èÍmD¯u[] €æÜaÌuµèŽYŸç�òÒ>z˜Ñ¨†Á›Ž¢ƒ¶N?oœ¾)çÔx‹”·Ú>yŽU;Œ‚CcpýÒηÍú̹ÂpãÍ¥d! ¹HÒQli°q°#@kû ò· Åb�™®/§¯N°k]"Ñ{ô8ñâ dWþ¬Ïœ% 5EÔÙÞK¥£ýÒëw �ˆ £ÕÌŠÏí½A±ÇÈ#›\ä;ô¸›v}õ5&+jPE¦Ðu�Ä5Ã=ô‡½œ9ÄH¤ —f³†)DV‹5æLÃiÑðØ67͵Ntúx£½ÿ¡ÛÔ‚Ôö bÛëÑh4x÷·"ÕmŸvg·ë*OC»[,s €E¯æ‘MNšjlè§õL?yvã,¡XSîäÔ%[×XÐÅ#ø�#úȦ?ãv°ÂYÄ2u,Ñ‹9M˜+ÿýµ~JÜFÚXNÜháô©K„'#l_· �Ó‰?ìçÌhÑ.œêͬ3~RC�à8,jÛæ¦¥ÞI[ÇœbÀEåÄ-vnœìĽºéÚebïyë-}\·9?D©]l>n‡Å¨á­›´ÔÚhí ÐÚÞOž#!‹=ºz|´_ R>ÒA¼° Ù•?K4Elp¼�r{!:! Ó±‹9͘+Ÿ­ɲ‹Ø„ 0ñË©2.�m#f9‚K³™µ! ‚ùb7©ù�­.Zêí ¡xª·CϨmÒ\öSVùViN1>ŒYSÎÇo³Êéåj‚y`6ªyëf'{êl¹8A[{?N›�ɰī§G!æ¡À^@uìØ´cXïx/«E"]#Í:=MI E�ZřˣӯÇd7n¸hYÿûbW²@°H¬F oÝ’p¿ùòu¢ñ›K$*½1žÐ;‹?L�Ù%v% ‹ÀdÐpÿz;»j­|óÕD¥xâj5ƒqœ¾ÛÊÞO‘µ@¤k¤)â™8ÍÑêT·ìWk§ˆR:´œC%\ô¬ÃlPc6ι ÊPaÙH©MˆC�`©´j·Œ1%†:Ê�B¦3óˆ"qe™˜’h¿8ÂÙKcx:T¨PƸ̶º(W"ÏÒ}�°<¦t¨AF–âêðã�0ó1Ìd”èˆ|�ýý/ˆx•S ÈX"Q™c ø¢o¾(ƒÁ§Wýoôÿxtñ_ H)B»§¡)‰‹}>F'ØZmã]»Êð]žâÂ~?žÇK{©Ÿ2_ U›9ã=ÎÕÉǬ® @{Õ›� ¹F$çPg€c}ä»Í¼£>Ÿî×Ljo6ãï±®º½ñãŒJÇx寳äªØâiƦw)º@�D¢2Ç/8ÜåÃe5ðΦ"öŸC£Š“?|™2‹…¸écxcí¼zãÛxô«ØèÙƒËèYú— – ±I%MH ÃþÑ ¶VÚxrgÆ›»—[}X7»P©ÀºÁI÷¾škWÑXØÄ¤´�3£Ç¹2ùïX„PîH8ç@G�S—|ä¹L´l.ÅjÒ1´w€õ�.Ê6Û¸¬ Ò×îÇTTD�¶�v;£Ò1^î�v ›ó÷àÐ;•>� -‰H2Gº‚ëöâ°ÙÙPŒÃ¢gl|’ñI‰O¾­ŒñëjF^ø1S5›ðh¶ãRoÄoçõþïàЕ±5ï>œF1‡¥ p…BLã¡(û| z'Ù¼ÚÆ»w­Â {så¨k‚˜ ƲD›"C©‰ñ3Z†º&(¬µ`Òêi,lb}x+g¼'BQ#„bjy™H(ã`W�Ó—ºMìÙR2ÝC62&ê�P²¡€U­\=è#<8…¡ÐˆcB(²�Qé8{o| —®ŠMžf\Fá( á¨ÌÁ®Ä×Ãj˜†IÎ^õÑ\ç@­Va++fØ•�æb;±š-¨Uúi¡8?ÁkƒÿŽS[ÁF÷<&á(*‰XbVˆ`(JwŸ�aï$ «m¼·© ƒþÖ”Ðî>,›gOD–õº÷�QPc™Î 5 ì,jb"²�3co ÅBíýèUb"äÁÉ8»‚œ»ê§ÀebÏæâia8ýžÓ^Ê�¨5‰�¤Ó©(Úæd¤Ý‡á-EÓïÓ`ºé(&„âkÏâÑW±ÁÓ‚ÛàTúPE˜ˆÄ9ÔäÌe?›�� E³„!ÀX0L0$±~µ Hìg°6ïaâÅ[»Ô‰•2µJOžfnõVÆâ'Ø7øvm9Ý÷‘oBQ æ/…�¸,$…á�o’úUVÞ³» £îö{…†.L Ioº‡IŒef&Nûê§°Ö:ëw½ž]E»oáìØ .O=+„¢ §�q°3@W_�B—‰–M· C€Èh˜¨?Êê­¶Y¯×4Z8á#24…¾`v�ѹBñ�þoáÔV±ÑÝ‚ÇìTúЂÁŠs´;ÈÙË~Ü#»7ß¶3À…k^v×'J¶%)X]Äe—m÷¤u›g½®PÜŸŠžû)0‹U±•dþQ-–×–B0¡»Ïϰo’š2+Oî*Ãl¸û&òK7so‡e£“îýcÔXo»ÃÜj0°«¸‰ÀÔ6Î�çJäß±ª×�¯mBq±ˆ:7iÍp0Æ¡?Ý7ÆŽá„a’à)EÛìh´³�F£bÕv'ýí>ò)ºíßΊû†Bqƒ«™<‹_‚ìdl<Αîq:¯ùpÛï. ¼�0“Q6­žý¦R�»¹ï‹?AªÞ0í"Îd®PlüwìÚ Ö»÷PdŽâJ –˜SÌLaX»ÊÆ»v–b1Þ»¸ÚÐ… ¢8V™oû{ã*3ãí>†/„(¨1ßñsìF=M%M¦¶rv섊‚¬c(çP—�K×°å 2!:¦ê}ù·ý}õ+}G¼·ug2W(î~çX <»É3Û•>5Á²à�ˆs°#@g_€<‡‘Ýî. “töziª›í&qU–âuºoë"Îd®Plz›¶œ ®(²Š9,•�˜".]÷3ä�¤f••'v–a3ο.yw›˦»_üÖ�N.ðÞU &± ì.iÂ?¹•ó¾\ ¡(Èl†1uú¹xcœB—‰=‹1ÏcÒžòR´Í‰á.¾J­¢´ÑÅà?ž‡ïÝÊ2)ÝšmŒÅ޳è¸4ëhp¶�o³Ýóï‚tdl"Qª³7! [6ÎOøÆÃ„BQ¶TÝùú·7ï!ðó;»ˆ3¹E(?‹m¬‚ ®û)²‰9,ˆÄefZú&©/wð®�, †Ã'ˆNÝÙ=Lb\efü´�¡‹! ÖÞ[$8LšL ¡xvì¤p€éÁP@âPg�î‰Ãû ¢c¢£aÖÞÁ=LRµÝBß‘‘0ú¼ùµµÔªf ÅÖÑgpøkhpí¦Ð"EAf0ŒqðB�®EÃ$W½ìªuÞÖ=Lâ©,Ågw£¹t–ØÚMóúܹBñàè¿cóURïh¦Èîíá–á .3Ãú ïÜ™‡Õ¸¸¼ÍK­~l›�óê^cÙèäâ¾±y Ä$“�æÒ]Œ†¶ÒéKÏóA-ÊÜ(†,À_âHW�Ký7…á¦ÌÆ…ß§¼ns »G°F£¦x›�‘vž‡ ôs…bÛð7pŒÖPçj¦Ðf“˜ -Æ9Ò¤«×GžÓ´(a7ÝÃÉ([«¬w}ŸJŽ–=ùSbUëïé"Îd®P<<öv%µ¶fŠínÔb�-™yß]Õ"Aÿ¶&"\èõ1˜J8†»ò°/$†»CLMÉØÊ-óz¿©ÜLèŒ�¡îÕ ‰³žfó.F'7Ó鎢 ½�eðI¹äÒ� Å3l)Á¸È®oº‡ózõ;ýÇDGÂèæé"Îd®P<4ú vo ë=ÂQ¤#ãqwéê¹) 7•,J&éêñ±«Î�Fsï¹0oM)» ÍåsĪ7.ø»æ Å#¾ç°×PçØM±Í-Ú/�yßeãÂ=™E áBOBÖ­rðÞÝù˜— “\:à›·{˜dº.â"b�ÉÈnS#¡-tŽ{S(jZЫ�+pF‚Ù úcê p©éÂ0Ið´—‚-ôúù °D]D£‹pg2S(ŽJ‡iz·¶†zw³ŠÅ�s¸#ÈÅëÉZ¡%÷Üàu/|ãüãSlY3¿‡0• ,»[˜xéEbkÖ³XëïöŽâjì»)qˆ¥çÅ –˜È´0ôOÑPaç=»ó—äÎdôrˆH8Ž­b~îac……ñv#—BäU-^$ª€|³‘._¿) ·•aÒÏ?'é^Nùðl¶c6/l€ét* ·Øñ¶ûp?¸xq&Z•y–PÜ7ø5!)gl<Æ�ÎÝ}Áe†þ‰þÐ;Ö.ì!L­ë®&^þ9Òš†E»ˆ3Ѩ ¡¨Ų̀tŒ£ÞçèòWRçÜC‰Ý¹Ü§6+™·@ÌU}˜†Þ`˜ •Þ¿;ã29†3½"ŠãY {˜Ä´ÚÂø×&ɯ2-KLjÙŒZ÷0:¹�ޱ\‰~ «º*7…b®‚32ãÀ9?Ý׃)†pÓ=œbí;óõ÷kwÚi=é'2F¿Dq&·Šnm ëÝ{È·¡(XFÇãìðqqµBC×5/�kæ&É_»Šàš+çV–‰é~êÚíŒJÇ8<ö,vßêÝÍ‹:Šweþë69¶IÅ?áâ aø¾–|LºÔåav·ú°lXXîá\¬œt¿1F~U鲯¦RAžÙL‹¹…ÑÐVÎ{�O Åm :•3eçE�½Œ�ÇØÞOw_ê„a’àiù[ì˜Í‹s&ôz…[Œ�ñãy`aîÈ|¸E(} �®– y-xŒB( ‡w"N[‡Ÿ )r gâŸHä6.Ð=L¢V�mW {E¬²~Y\Ä™¼)Eí�<‹ÝWE½SÅ;!rçà „¹ÐçÃ?as•�ßÜ“�A›Ú :cWCLãä¯^ÚD`¬°0qÆÇèåIÜ÷/¿‹8Í¡¸÷Æ×)0Գѳ »AtfÜHâ`g�s=AŠQD~±&"ø‚S4.q\¨U`ÞÙÌÔk¿"¶ºnÙ]Ä™ÜÒ&sð[8µkØœß‚Ë Eâ›Âp"Âæ5všjòÑëVnCüèÕ¡@Œ‚Õ‹Ë=œ‹©ÂÂè£W'ñ¬N­Hp›Lì)ÛÃèäv:ÆBѦ®¡@ÛŒV%&2Bû;tõ)Ë·®˜0�üQ¦¦Ø¼D÷0ÉÚF;m_îCòFЦÈEœÉ\¡øÊ�g(26°9f­p ‚“m aXè2qÿ"‹È/–®Û×9Ñ-Á=LRTWÁ•ÃV4×:KÍ)f®P|­ÿYÜÚ5lÍoÁžãBqÞW�*˪MzƒS\èõœ³µÚASmÁ][¥ŠK­~l�‰G§e@¥JÔE¼¸o ÏêåÍE¼“‰–Ò=ø¦¶Ñ1vœîÈ3سL(ªåì©&’h=ï§³wœ²+lY9a8Ãiù›lX–è&1Õäm´Xq&³„bô¿êý:Ŧ¶äï¨B1W™˜Šqà|€³=Kë.´‚¡c�IïÏ_ú‡‘˜ M»v3µ÷× q…´ÇÜ~ê¯ö?K¾¾†-ù»±èr³ViÎ-1'…áx(Ì–*'M5óªöž Æ®M&ÜÃÊåq“W[™h÷1zeOeê]Ä™8�fšJöŒlçüèq.…ŸÉG1K†À²1â�0�S–gœõºo<Êþó~.^ŸHí+/ ¤`”pÿ$•o_Þ¥uMv|©/¥¹ˆwb–PŒáç½_§ÌÔÀFO&íòÞGʘ”öE¨*ž]¾,–8ФýJ�’¼å)"¿Xºz|ìX&÷0IAM%×Z.âêº=ž¹Ý�^ºþ E†¶ä·`Òfö¶às1ß7ª2|óX`Šî>?ÁP„mëì¬VN&¹Øêöɹlîa’d.b÷>ïŠ Ä$6½‰�Å-„¤­œ=A÷ä×±«kg ÅëÑ)Ö¾µje'YÁÒ™ŠÄøé‘jËÌÓÑŠÒz.@Wï8« ­<¸µ ƒÂ0Ið”Ï;6ËòÆ`4ªÉÛä`¼Ý‡k]Ä™$…¢GÞÁhø(¿ìù*«,ëÙàÙ…Q,=g’ç…¶AÊòMÓqb*Æ¡N?íWÇ)ò˜yp«r Š2êŸä{–'…#‰V †ÆfØÿ ±ŠÚsgÅ0S(JÇùUï×)±Ô°ÑÓŒI“Žâüë fØêÚT$Ƙ’£!¢RœÉ©(»j�l­ÊG�]¼}}“„|1 —)÷p.¦JëÍ\Ä)<«�KÿÀEbÖši,la“´�óÞã\šø:6u-ùºf¦â#ôEÊ*ý{P‰VŽƒ,à ‡ò…q[5Bm>Î÷NP–oå¡mÊ CH¸‡S7&Ùøxj:'T7Ú9ôµ^E\Ä™hU–›åq¶1>ÌÏ{¿ŒEg§Ü¶ž2ó:¬WZÜï çÅc#Ü‹`Ðk …cêòqòÒ8%yîÛRš²’P ¡«×ËöuNôÚå¿Æ j+é=bRÄEœÉ,¡>ÎÏ{¿‚Yc§ÂZÇ*KV�µ*;ÇØ=Ò{¿|#€"L8c2"š’ˆÅe4xpC[«,iu£ì~÷¬¹‡sQ©À¼ÞI÷þ1<«K”>\ Z[ò[¨wo¥Ó{‚Kã_#&G˜Š2}…bÝ[”Q0O^:>µ¡I.ôMÐ}=DE±�·(/ “O§Æ=Lb±¨p¯·<ãÇ}ßòä^-­ÊF±î¬ê z¥87ögÆöaÕØ0iíèÔF¶xÁªs*ª`¼vfŒ®ë《kC|ñg“Óéé ÆCQF½“üfËòº‡IôZÐoß m{sg’Šu%½‘ïrÞw€ó¾˜4Ì+z�‘ îqèSs>”`þŠINï%f«Y‡<Â�o’`(J,.c3«ùƒwT°}­-­Ä¡¯oŠ O¼&µ9C¦5V¦ÆãŒõL)}ÈÓ4fª ˜5V@•Œ7~Šaé€Ò¡ æÁkí^Ú¯ŽOçcÆQ¡ÖªÑëµi#cÁ(S}“T7¦v¨ºÉAx`ÉUú�§±iÖR¢ý Ô*jdB±¾È…æ !3„Ã|ëò#Ç‚(W¡Ö¨ÐhÕi#!ÑsyÛZ†¸‡IòëÖ€ÞˆæZ—Ò‡;�E]J©î�¨ItTšŒùñFp‹³JÂbúȫۣU«0jåé‡ ·MLJ,Ű‚%kæËÅ}^¬œ)s“¨T‰ÍÝ­^¥yš˜åØè¯Pzu"¯F–c Iû¹ùQ‚J‡(¸íׯ9Þ@¬&«‹ll¯)à�-¥¬-s(Þ4�vîõ6¬¶ÔŽ}›Y�«ÁN°Ý§ô!Ï©ـ[³µ*!&̪<Î�àØÐ+LÆÆ•Op®ô‡h= Ž ³QKE‘�-ëò¹os) •©I—X ã¡(#¾IvÖ¦ö!̨íÖ&t§[Óʤ²iªÉ×íFM¢Æ¤Y�G—ï(GÉd,{æ°ù/1+Pf>Œ¦èºæe*¥¹ÞE÷� Æ"<º-»9ýÊ<úû½…÷¯L"¹i�•‘3>Æz'q¯RfÃÊL4*÷}€p,ÄÈäuÆ¢}x' H#t‡¿†C]G¾®¹µc,] J´�÷Ó}cœÕÅ6Ö–9Ñ¥Ð5X ±`”©ÞßZ¶"ß·f§�ãÏô DÑÙS_�x¾jï'÷1Á5Ju$N˜Ñ©#ü¢ç딚ëip5aÓ‹Í,éB cÿ9?]}AŠóÌÔ–»Ùù?_ºz}l]kO©{˜¤°¡ŠëÇZÑô\ VQ£ô¡O“§ÙI$î%ï H÷$ôŒ†�ð‹ž¯Qd¬c£§%ãÇØÊܤ�z‡„0ì¼æcj*JS½“-k9†7F&inpR‘¯ÜÆŒ»qq¿Û'ªÜɺˆÝ­>?¨¼@œ‰Ac¦Ôº–RÖÂÍz¤“Rˆöá#\ 'v=çëZБ&ƒ,Ãwò/”á DÛyÝ7&¨(²ñðöUi+ “Úý¸ÖÛ±ÙWfruÚÔØëm‰Í-Êç"ΤLÿv®F¿‹Fe@ƒ�"Ý#‰^Ïá#¼|ýëäëÙàÚ�Ó(Êã(E $±ï|€ ½AEKB-„‰©(#ÞïoYµ"ßgÔ�fÛnT‡ß V¾Nñ\Ä™ë%E�•Jýf?õè~}=Ñ&s½'sû©Ï¿ÌMš8ˆc�):{¼„&£ì¬uѸÖ6ëzyxK^Z.+øoL�RpßÊ^,¦*#güx{§p­JOá<«ÖÌÎâI�œ>B÷Ô×phÒL(f9Ã~‰}ç¼\ QQdã‘ †±q)á>ºrâªíœúÆu¤@m¹ˆ*4Tê~kÖk:•ýM¡=ÂÞþ¯QhØH½k.Sz=@f3¾q‰ÖÎúÝ…2A&éêñ±¥*µ¹‡sÉoXËÀñ64½"1MP¡¢R?{Œ%û©{´�ŒÞì§îÖÕ°ÁÝBž9³VÅæ_æ&®l c�):®y‰Fbl]ç`ça˜$]Å!ÀÅ}>¬+è&™v÷{ÙñT±Ò§a^˜o Åú©´�¦‡PÌvÿp8 ±ïŒ�«C% “Û}¸¬Øl+;Ѻ 6‚g|¸šÓËE¼³„¢t„×¾B�~#u®]xÌB(¦ŠÑ Dk‡�KÉ"ò tZ SQ½“¼w·gE¿×¢ÍÖÝp¬5­âÝÐÎi“ùÆà×ñèjipµ�oÉ ³cÞQ)qØ7Ig�Iг©*! u™3ž¦ „ ŒD)ܣ̅a®²2xƇ¯o gYz»ˆ3±-4—>ˆj'gF++³T!ú¢ì?ççZ† C€Ø„ÄdOˆ†�®¬{˜dM£�ϤŸ‹x/ÞŠ;•ŽòÆàWÈÓm¤Áµ �EÅåb$ ±¿ÃÇ• a¨tùÅr¡ÇÇÖ5vŒ 1 ké?qÓE\µVéS1oæöSß?ôuܺ\»Ò^(¦ß.Ž› û&鼿EŠÉl\c§±Ú†!sî»·paŸ[ÃÊ»‡Ó¨UØÖ;éÞïcû‹”> Æa4ÓRú #;9ç}S(h[ЪÒ{�¥+>‰Ö³^® gÖRòí´ûpÖ[q8”™t] Žz+Á3~\Í™WêB§rÌŠC G±Áӄ˘9”鯠_¢­ÓÏ•ã- B“Q½!Þ³{erçb6Ìp3H &¹�PôhëiðìJۥ紈þI:®y‰I2«쨶bÌ`a ÷08¥ YY!c®¶2xÖ‡¯ogYfºy3÷[Bñ¼÷0Ýá¯ãÔ4�§Ý•r¡˜&i¸KfÀ'±ÿœ�ž¤c¸c:Mf CH¸‡SW'Xÿ1eÜÃ$UMN>s�XPBcK»[뼘+_ëÿ2…†�lð4a7¡8_ü;|\éÏlÇp&]}>6W:q“¬_Kÿñç"Îd®PÜ7ø yúÖ»vá6§—Ù±€»Xj×צ…aL¦~µƒ]ÕVL…ÏÎ2ѽߋµÞ¡üFµ ëz'Ý­~¶ 3b’<‹™=–o¤sìèŠE…Óp—L¿W¢õœ—ž¤c˜áÂ0I°Ý‡³Á†Ã¡¬(sÙ5Øë¬ÏøpîÎ<q&3…â°t�Wn|‰BÃ&ê�M¸ÌB(Þ‰l†�pFC¼g—2îa³4[vÉÌtg2W(¾>øu<ºÜ»ÈK¡¨øcnRÆã2 vv¬µaV®µé²ˆàï�PÐT¨t(Xªoæ"ö‡qg¶WV ù–o¤Ëw$¥BQ�i ÉoÒ;&q°ÃKßð$•ÅÙ# áfîa¸‡IÖ4:9õ­>¤ „6C]Ä™èTJt¿Až¶‰é ¯ &„b­Cä(ÎdÀ'qà¼�kƒÙ% “\èõ³¥ÊŽQ¯ü}£`ã:ú�·¢éí&¶ªZép–Œfz×sµß7øu<úê]»ÈWX(*Ö‹y¦0¬«pÐXmÅ’Ùzå¶\ÜïÅÚàD¥Iq¡VaÛ�ØÑ¼ýý™—‹x;T*(´™)°&„b§?5BQΰ:ˆ}c‰IëúHˆÊbo/Ëa˜$xÆ�³ÞŽ]a÷0‰Û¥N¸ˆg}¸š2ÛEœ‰~ŽP|cèËè7ÑàÎíò8}c‡º|ô d§0…%Æ&xw“²îa³4ÛšádkVÄ$Z•å¦PÜÆˆt˜ý7…bƒK9GqÅïªÃ¾IÎ_MÃMU¶UY1exŽá�† ô‡)h*P:”Y˜ªm �ñèŸÂ^œ=ËEI¡˜o}€Áàºf Å&´ª¥Ö,óCR*��ËQ_ð1è�du‘�‡·•eìæ“» IL^gCš¸‡I*w:9õ�^¤õάpg2W(¾6ðe ›Xïn‘C›YúÆ$wù¹60Ny†‘_,z|lª²¥…{˜¤`c ýÇ î»D¼¬Jép–­Ê6«UÂQ¬§ÞÕ´âŽâ e/í‹ÇBtöøˆÇe6W;Ù^eÁ�]÷Î[èÞïÅ’NîáMTjÖ†Dw•­ïËq&jÛ-Úd ¸ƒ þ£t‡¿¶d¡Oã:72pe(¡Nÿ´0|hkv Ã$Á3~\õVliâ&ñ8ÕØklŒŸõáÌ"q&s…â«ý_"_·™M»°ë³W(ö�E9Ô '„!ÀdX¢t‚w+œ{8³Ô[w£?µŸ©,ˆIæÖ*Ý3GqƒgnÓÊÅù×A\äÜ88¢«Ç‡,Ël®r°µÊšõ 8Æ×¡`WzäÎÅ¼ÎÆÐÙìsg¢VA‰ÝJ‘íAƒÛéô^¡˜n\Žr ÃÇPŽC€X(FèÊ8›ÓÌ=LRÕäää7z±np¢µfï ïM¡¸‹é¯\ÿ…úÍ4xváÌ"Gñú˜Dëy/}77xe»0Lr±×Ç–ÊôÈ=œKÁ¦ZN´¡¹~™Xé¥ÃIs…âë ¡¸Þ³ OŠ…bÊî\ aèE–aã;ª¬è³t)ùv\ÜïÇZ—~îa’¤‹x±Õ϶÷eÏ�üv$E…¶G˜Þ̲p¡˜n»˜¯ E8ÔágÀ—;Â0IðŒw­ ³==Å—Û¥ÆYgcü¬箕í:¡z•s–PÜ;ð ´[©smÇcÉÜûËõ1‰¶/=C™_+t¡L†%®�óDcz¹‡I,zÐmÛ §[³Z &™+ßHÜ®wî¢Àš¡8ÿ»ë¥­Ã÷¦c˜E%¡B"÷pœw¦©{˜Ä¨S£Û¾ùTkÎÄ$s…â�á¯ãÛD�{…Öåcóߤr›×f C€MklÏAÇp&ã#QÆzÂ<™ÞîasMÂE …±dÎþr VA™ÝN‰-)¨RÈAì s༟~ïU%6Tç¡QºèºBÄ'c„.�³ñãeJ‡2/j[úÚulhÌé-hSAR(æË»–ñúðWÈÛÂzwz Å”}güôgGw¡¥ÒÝçcc¥#­ÝÃ$Å›jé9zuÿUâÅ«•gŹU(~™<_B(æ/±¨ý¢:©Ì†µŠÆ'›+-äðxš¦{¿s½•‚툂J£ÂZç {¿Ÿ­ïI¯r<+Å›Bñ- Œï¼ãÒ³j±;µÉõ‘­�>nŒ&„á#Uù9+ “ÏúÉk°b±§ÿÄ`±iqÕ&z4çš‹8Ým„b�o+óv`7(÷`:ä—ØwÖGÏp(ëŠÈ/–ɰÄ�á Þ¾#½S8’hµ* �MÈ'÷ÎA�˜äM¡˜(¸½ðËäé6±Þ³÷"k•.è‘V–áÆÈ�=^t5Ûֺغƌ63îÕ)g|$Š·gŠ‚'3«´…¥ÖÎà�{sÒEœÉ­KÏo:вlE«ZqÖ?æõ³ ǰºÔÁ#Û…0„¤{dKšî\¾µÍN~­Û'snß,“BÑ#ï¸Yç+6³%ÇŠÆ1Œòú×'©,ÉÎ"ò‹åòõDÝCK•)Þ\Ï•C¹ë"Îdn?õ×¾B¡a#›òw-ø³æ}Xô2ý#\éÐT禾̌)‹Zâ-—ö�a®Ë÷0IÒE¼|ÀÇæ'Ó³,ÏJ2ÓQ¼läÒøAú¤_"Éá”~¯$ÅùÅñâ&=Õ¥NÖW a8“à9?õVŒiºsùN˜íòëu�¹ë"ÎÄ òPª{;ay”áH+¿ìý*¾ðXÊ¿7�³ï¼Ÿ}½ý¬)µóÈZ! §™ŠÄèç±í™‘‘D­Vakj&x"·]Ä™¼)·3,µñòõ¯0<饔’yƼG†V«fM±‰ß{k1ÛÖq8—‰ÑDî¡¥Ö¦t(‹ÂRcg¬7Lp0¢t(iCB(:¸¿ä7ØžÿVtêÔ^ôRlfo[Åš»‡3ˆ‡cLvY×äT:”E±n�ƒ‰KãÄ&cJ‡’VTÊôïdµáƒDã2Á©Ô~_TƒNËÃÛËX[æâp—ú¼l®Ì,÷0IÁ¦:ÔášþkJ‡’V$\ûÇX£ÿ¢q™‰ðü¯ù�SËLº[}Xì¨3Ì=L¢Òª°Ô9¸tÀ§t(i‰Q�úÊõ*µšÒ|‹†·!xÆ�§Òˆ!Crçb´h(¬·2~Ö@, ÄfbPåaTåOq;K�JMIžUÃÛ0‰Ñ;4ÎŽuN¥CYj5ŽÝ»Ñ�Þ€*à…xºU¯U�ʉIUB<6ÿ1&FÉèxy”Ñk“Lx£Œ]�ļήtHKÂ²ÎÆÐÅc½)~ŒÜ! oO<'Ô$4*)Ê’X×â`²;H4eäÕ!b!á&ÎE•âRRq1ÈîÈÉî!´5VSf>„¸7­O¸ˆ×¯¢ýǨ|ÃJ‡”vÄUócB .�p0FçËctþjK}溇IÔz5Z½šãßíÇw=µùv‚[‰ËéÛëY)dF~Ý�,ÇÑ™2{|é-Z« ø^êG D ‹±¹ÄR=âbŒÝ޳Ý# �Na1föC¥Â^½ãþ£ö¡èQ:¢ôc¦jæ%¤á@”ÐH„ÉQúI™ðp÷ý¨2x‰PëÖë�Ñþ£Ö>”GqCvô+ÎÄÜ5‹x4Ž÷�a¢c‰åX{Iæ&>vLÐõêS2ª›Ñ‘Tˆñ5‹��xštCJbq™SG¸>2*(Í[\9”t`òêU†þsbãã‰'K@ð*VF“á� Ê“d ).Ë2ñˆŒµÎ‘Ñâ@ëL”¹ OÄé|y” ¯¥~g¡à&+TF'�üF_`êzhú5Gaæ–`*¬³ÐðXV÷›ÏäñPTé°Ò�ÔŽ�T/ag“a‰ƒg¸>ü¦ r[3·Ë…iõj ž|]þ›M*äPPé°ÒŽ…˜èB .’ÀÀá`"‡HŸ§ÇóP†¢ôé °Xô3JˆÈ±#—&é=P:¬œ@KÌÓLöN¢q¾9Yiõjœ¥™ënxÖXØüþBì… '42&â\â)^#ìMÆBX-:Œ5*UB ”çeîC€±¤„âßüMLhGû•)í�ð&â"»2 Èhmzò-AcËÜ'¯™èŠL¨Ô µiq”™ÙýñRVmÍìÍ7‚ÌöÞ�Æ¢¥x“�â:+z‹:cw0ÏÄìÐ±í·Š1˜5ÄÆ%Ä3Á\Rí¢ —>Ie±�õ.Ô²ŠúUÌ&5ùŽÌMãH¢±X(|ÿûѺ\0‚¨¨0“…Üs„@\$ã#TÈ{1*möÜt´‡Ž¼·•3>*׊!–˜§‘#q¦.Y³ËAý;<¸+2ß�O¢Õ«ÙþábdYFò‹ñ5¡—W–«ý~jWYxÇÎ* Mh4ÙqRi4”ýÞï�F‡¦ç‚Òá¤bó  ÕbÛàD�eµ!U*Èÿ�4& ¦Z;—ø•I�ƒÏûñT›1»t¨Õjê~#éšF˜�:ЬL^žP:”´"ÕiâìM"Ñ—ú4Õ:x|G�Ò!-+*µ× ½|NéPÒ •XbN-“þ(£—BXêJ‡’’¢×Zkgôò$!á"®bîJ�Ä uYÛìT:””RÝâ$Ô 6%ê!&IõHuŽc&qù†�úr+6sö3qlÙ„:8†z¨OéPÒ±I%Å\:àǺΖuîá\Ôz5æZ;Ým>¥Cäã~\kL˜œÙ;qíZœk-LtˆM`Iâ©¶øÄS)ÎÕþqvÕf§É‘D¥VcÙÑ„¶½MéPÒ‡¸ôÙ­pRÀT@bèBsCv¬$Ö:;#—¦˜ðŠ—©Fx ÷p¢#ûÝÃ$µ÷9™è �ˆ–`+�Z¬1ÐÝ磮܊Ü›+ï†gÛÔþÔÃ7”%ãq�t·ú°ä€{˜D­Wc®±qEôhN=bK+•&¬žìŸ¸Ì-ö5fÆÏ‹\_` e‹1‘âô hªÉ�ê�Ó¶]èÚ(JZ°�G¤ÜP9ËÄT@b¨ss]n ¬$ÖzÃÝ“Lú2»nº£Êqw#‰3Þ :GÜÃ$ëö8™è.âJ D¸Ô秦̊3ƒ‹b/”ü›PùFP�ˆºˆ AÄÐ}À‹e��1óë±-µ^�e��K"1¥äz¡ìñζrÎüÜ™¸n-– 3ãÂEL¹~ËñM*Q)NO¿Ÿæ,Ï=œ‹V«A»¥­p”ç+â<™ H u„07ä–{˜ÄÒà`èBˆ�ÈELê oÓ¸ähœ‰ÎU-N¥CQ„µ»LtrÞELùCRŽÏx—®û©*Í-÷0IÞ¶M¨GsÞE\ÈCXŽ—ùs©Í‡y�-çÜÃ$*½ËZ— —#U䲃8ÞÀZjÂS�{€§H‡¥Ü$v4§YÎ݇°h,ÎÕÁ ÷­w*Š"˜�Z4[v‰Í @Äy—ìœÀš#;—ï„¥ÁÁPç!Ÿpˇ,ÉŒw¨Ê±ÜùT·¸ïð#ç°‹¸�>±‚…q麟ªBNKv—�ºù;6¡ÈiQµ€Û‹ˆó û€K• uŽº‡IÔ5æ;—ú”%KÉÍÉq¢Ó�¹ÄD^qnº‡Iò u˜ÊÌ;s×ELu–…jmƲ‰¨çÚ� ÷ç¨{˜ÄlÔ¢Þ´3§]ĸXb^>ÂãƒãXÖç¶{˜ÄÚà`¨#Ĥ_¸ˆËNêCY’ ž°¦)7s{çRÕìdâ| g]ÄÜ”o©çÒ ?«‹Í9™{8ÏöÍ qt@éPA% e/—ø0UYsÞ=L’pE.b*�sp‡åxgs‘‘Â2ƒÒ¡¤…%:Ì¥&Æ»rÓE\Èäµrq ;*Źr#ÈýõÂä°Y´¨74欋¸�Í�B Þ…ð¸Dÿ¹ ¬ N¥CI+¬ ;'˜ Šºˆ‚Å#K2ãçýT6‹‰k&«[œŒŸ�梋˜{.Õ\¾ ²ÈˆÛ.ÜÃ$î›Q�ô£ö)ÊŠ³�bñB Þ…Ëm~Ìk­hLÂ=œ‰Ú ÁTeãªpK`¢3€±ÈH�pgQT¢ÃXb$”ƒ.bªsU9æÒG¥8—ûì©w)JZa·êˆ7lG{:÷ê".¤!ƒˆw <.1pn‹po‹mƒƒþóã„1¥CÉrÈß@èböºˆò–¿C¶>„Åâ2—oøi&Ç’°Ûô¨ê¶eõŽæ…T Èy��ŠÑwr\¸‡Ë„mƒ“ë§‚„C¢.¢ˆËŒŸõQ¶ÝŽ&çï6K§r·‹`{v»ˆ©$[®öÈw(s‹ÜÃ¥âÙµ ÍõËÙí"Γœ¿e_=À´Ê$ÜÃeBcÑbª0sM¸ˆ`¢{�CGYµIéP²‚ÒŠ›;š³ÔET«…ð](±x"÷ð¾z§Ò¡död.b–îhV‹V{óC ǹ~*ˆU¸‡ËŠu£‹¾"ÂEÌmnº‡Å;œèÅóײ±z·‹ñ³~ä,,‹¤NqŽ`ö�1¸:$ÏadU¾È=\.Ü;·£ííFô*ʲ£R‰%æyqå°Ã*á.+‰\D3=GEw•\fâÒ8Z»ŽUÕ"÷p9)^­GïÔº8®t(ËNjÞ”‹Ë\îó±»Þ®t(Y…Ãa$^¿]{ö¹ˆbó<�ÂqzNˆº‡©Â¶ÑEÏÉq"S¢‡ì|ɪ¹1.<ã£`›£xþZVÔÀê'Á3¾ìsS|8©v(WškAÕ7ÿG}óQéó$˜Íè믟 czèQâ$®� ´ê7ï�Kc‹üûék‡7cYji]!�@ îA,Bòû1+ÊŠ ¢@ �`¼�@ ÌBD�@ Á,²^ ^½z•Ó§OsñâÅÛþÞëõrúôiNŸ>½¨^¸Ï<ó Ï?ÿü=ߋŸìg?ËáÇïú>ŸÏ7OòŸ«W¯‡•>•AZrôèQŽ?~Ï÷ɲÌK/½Äµk×–å{/]ºÄ+¯¼’’cš˜˜à¥—^bxx8%Ÿ/È|¢Ñ(^¯—h4ªX äÔ©S÷|_GGûöíS$Æ×_� .(òÝ™NæÕDX ?úÑ�xýõ×1�<ûì³�³;<<÷Üs¼üòËüÇüz½~AŸßÝÝ�Åòf]ÅãÇ�ó¥/}‰¿ÿû¿ÇãñL¿�Çioo§¹¹ù®Ÿ×ÑÑÁßýÝßÝòºÅbá©§žâïx‡Ò§T Xÿöoÿƾ}ûðx<üßÿûQÍÙúü“Ÿü„ï~÷»|ã߸eŒÞ‹Ÿüä' ¶mÛÀ�7hkkãmo{Û¬±�Çù¾ÀÓO?MEEÅ]?óïþîïhoo@¥Ráv»YµjO<ñuuu@B˜þøÇ?æ‘GYösæõzù¾À_üÅ_�ŸŸ¿ìŸ/È\:::øÞ÷¾G{{;’$¡R©ÈÏÏg÷îݼ÷½ïÅn·¯X,?øÁ())aóæÍw}ßo¼ÁÉ“'¹ï¾ÔÔcïÞ½Üÿý·Œ—gžy†‡~˜uëÖ­Øyɲ^ Øl6b±mmm<ôÐCÓ¯‡ÃaZ[[),,dpppY¾kjjŠÁÁAâsöªët:¾ýíoc0̯Pô_ÿõ_³yóf$Ib``€o|ã|õ«_¥¦¦F\肌"�FéííåìÙ³lذaÖïýë_#IÒ²¹ä===<ûì³´´´ÌˆjµšO}êSÔÖÖÞó3&''ÑétüÖoý�pö_zé%þìÏþŒ¿ýÛ¿¥®®Ž;v�——Úº}ÁLöíÛÇç?ÿyV¯^ÍúOÿ‰òòrb±çÏŸçç?ÿ9&“‰~ðƒJ‡y ÷ß?õõõ)ûüÑÑQž}öYjkkoˆýèG)))Qúd$9! [¶lá•W^™%ÛÚÚhjjâ…^˜~=‹qèÐ!ªªª(**š~= qòäIêêêp»Ý·|ÏÀÀ]]];vlúI®±±­VËéÓ§Y³f Å Ø"¯Õj)++ãCúG�¥««k–@”e™#GŽL[èuuulÛ¶m–KsæÌ´Zí´ó‘äøñã8�Nªªª€ÄrüÀÀ;wîäðáÃ\¼x§ÓÉîÝ»g¹¡I®^½Ê±cǘ˜˜Àét²iÓ&V¯^=ë=§N�âܹsH’Duu5»víB£E^s ‹ÅBEE¯¾úê,�xáÂz{{y衇ػwoJcP©T<úè£ Šyæû÷ìÙÃïÿþïóë_ÿšºº:ªªª¦ÇÎíF’$ŠŠŠnqM“LMM100€Ñh$??ÿŽc#Ù5£°°ðŽŸ%Èn†‡‡ù?ÿçÿPWWÇÿøÿcÖjW]]�?þ8W®\¹åœ¤¨¨è®î|,ãÆ�˜L¦Y>ŒŒŒP\\|×¶`0Èèè(˜Í³;úÔÕÕÝ2ÿÌä^×w4edd€‚‚‚Í!<ðÀm_—$‰ëׯ£Ñh(--½ë¸ …B SXX¸àŽL&'"À#�<ŸüÉŸ0000-ú^}õUZZZnqõ¢Ñ(ŸûÜçøÔ§>5K Ž��ñ¹Ï}Ž¿üË¿¼­@¼víà¿ø:�`Ú~ÿÜç>Çïÿþï/H &˜%Ô¢Ñ(ÿãüΞ=KMM ñxœþð‡lÞ¼™Ï~ö³hµ‰ÿ¼ßþö·±Ûí· Ð¯|å+lÙ²ez’;pà/¾ø";w½�’’._¾Ì÷¾÷=>ÿùÏSPP0ý·Ï<ó /¼ðÅÅÅ”••qòäI¾õ­oñ£ýh:¶¿ÿû¿çøñãÔÔÔ`0øÙÏ~FUUý×=o'U�=<üðÃ|á _à“ŸüäôMöÕW_¥¡¡aÖ8ˆD"¼÷½ï哟ü$�=öØôëýýý<ýôÓüùŸÿ9;wî¼å;öîÝËÿþßÿ€O|âÓ¯ó›ßÄápðä“OòôÓOóøã�/8þ’’œNçôdöÝï~—ÿøÇ|ï{ß.ÆG>ò>ñ‰OpèСé%ê¼¼<þôOÿtÖƒÝÔÔ_þò—yã�7�¤Dw!‹ÅÂûoÿmz©÷œ?ù“?¡££HL þç~˃˜ ûùÅ/~A$áŸøÄm…šÑhœu�ïîîæÿïÿMOO�0{ì1>ò‘�L ¬_ÿú×ü¿ÿ÷ÿøìg?Ë¿øEÆÆÆ¸ï¾ûøô§?Í÷¿ÿ}~ðƒ Iz½ž?øƒ?¸e™8�óoÿöo¼ôÒKÄãqôz=úЇxç;ß9ýž/}éKœð>ð�(}9¬9#kkk)--eïÞ½<õÔS ræÌžzê)Nž<¹,ß±sçN$IâsŸûÜ-¹C M$Þ¿?ÝÝÝŒŒŒ°oß>vîÜ9kRüáH{{û¬ÉòÀ�|îsŸã…^à½ï}ï‚�abb•JÅW¿úU4 ###|êSŸâ…^˜žp÷íÛÇ /¼À>ð>øÁN?yÍìWüÝï~—Ó§OóÿðÓc__ŸùÌgøþ÷¿Ï‡>ô¡e9ç‚Ì¡©©‰û·£µµ•Gy„H$¾}ûøÈG>2=1-•Ý»w‰Døâ¿ÈßþíßN;!N§sQ›Ðfâóùðûý·,‘ÏåùçŸç½ï}/ø‡H àóŸÿ<ÿú¯ÿÊÿûÿoz¬|îsŸãìÙ³<ýôÓÓ-;::nypúÖ·¾ÅSO=Åÿñ3::Ê?þã?ò…/|�üÇLÉ#AúröìYÌf3•••÷|¯Ïç›62>ÿùÏ“ŸŸÏk¯½Æ7¿ùM4 ùÈGf½ÿßøÿå¿ü*++9pà_ýêWO´¤ý—ùŒF#_ùÊWøâ¿È¶mÛf¥n=z”††¾ô¥/a4ùþ÷¿Ï׿þuŠŠŠnû7“gžy†§žzŠÿþßÿ;CCCüã?þ#_üâgåá—––ò7ó7”••‹Åxýõ×yæ™g())á-oy uuuÓ©ÿí¿ý·éùæv«^�ȇüêW¿ÊÛÞö6Þ÷¾÷�FùÚ×¾Æç>÷¹Yó$Ƥ$IüÓ?ýv»�þð‡|ûÛßfóæÍóJUÉt²~s•JŃ>Èk¯½†,˼öÚkÝÕöV’cÇŽñÒK/ñÒK/ÑÚÚŠZ­¦¦¦õŒ¾K‡bÆ ³ass3555¼þúë‹þîßù�ß™~ÂÌËËcýúõÓO¡�xê,--�%�igT–e~õ«_Ý’\VVÆ}÷Ý·l‚\�YèõzöìÙ믾 $®_I’hiiY¶ï0�8�N qíQTT4kÜÌ—H$Bww7/^äÀ�üõ_ÿ5ñxüžÍvîÜÉ{Þóòó󩪪â}ï{½½½ŒŽŽ‰eõãÇ�óÛ¿ýÛ<ú裸ÝnÜn7ÍÍͬ_¿~ÖgíÙ³‡Ç�ÇúuëxòÉ'éêêšv>¹ƒ×ë�µŠs7öîÝK0ä3Ÿù ÕÕÕ8Þõ®wqß}÷ñóŸÿüÃâƒü Û¶mÃívóŽw¼ƒââb:;;ùã?þc***(,,ä©§ž" ÝvGðg>óŠŠŠp:�üÞïý«V­âg?ûÙ=ã|衇xì±Çðx<ÔÕÕñŽw¼ƒsçÎM»…ÉØêêê°Ùl8�NÞõ®w±}ûvŽ9$î+I1èv»§Ç|ro.?ùÉO(//瓟ü$yyyó™Ï|³ÙÌOúÓ[Þÿ§ú§TVVâñxøÈG>‚ÑhäôéÜh8Ÿ3"Àƒ>ÈóÏ?ÏÙ³gÙ»w/=ô�bùÁ`�ööv>ûÙÏÎúÝÐÐÁ`P‘s.Pž‡zh:ÕcïÞ½455Ý’¯´R�Y9[�f–@æ¿þ×ÿ:ý»’’þàþ`Ö2Ô혛Œ_XX$–‹óòò8þ<À=…&@CC쟓KñcccŠ�7�2¨Tª[6?Þ‰žž nIEضm¯¿þ:³–qç^gùùùØíöY×XRœ&t’TWWc³ÙfŹeËÞxã�{Æ9÷{“&ÃØØØôµ y饗¸|ù2�@HT*°Z­ >‡²,ÓÓÓÃã�?>kþ2›Í444ÜR«¼¼|Ö÷èt:<Ït>d¶“S1??ŸM›6ñå/™ÁÁA~øáýýrv%”$iÚŸMMMTWW³wï^>ð� Ë2ñxü¶ÎˆZ­¾ãÓÓLnw³¹]òïí„àÝ™X,@ee%›6mš×ç rƒºº:JKKùÁ~À©S§¦ó|” ³³“ÿù?ÿçôÏv»�çž{núçââbþùŸÿHL óu!ç&±'s�“ãbbbà–±Ûa2™fýœŸÉ¼EAî�ŸŸÇz¾sñù|·-wãp8ðûý³âÜëL«ÕÞr½'¯½¹óÆí¾Çjµ�eù®÷û¹c%ù�Éïã�þè�°X,´´´LÏ'¯¿þú¢ÒR&''‰D"ÓçaîqtvvÎzmæRúÌó0_¡žéä”@„D¢ü?ÿó?³qãÆ;Ö3ºÞ<½IDAT hµÚ[ÜÌ»;‘D÷“k×®åOþäO{<ŸžT*EEE³–~“\»vmÖF«Õz‹k�Foyœ/¥¥¥\¾|ùŽƒßåra2™0™L Ú5*È ~øaž}öÙé¶Û‘œ æ ¡åtŸo»¤”D­V/Ê¥¸ÉÉixxxQÖ¹ÉæÍ›9{ö,çÏŸ¿gɘüü|._¾|ËëÉ• å,Ït;¡æõzñxbr¾È²ÌÞ½{éîîžuchllääÉ“œ={vúµÓ§OsæÌ™Yy‰eee\¸pa– üþ÷¿¿h⡇¢§§‡Ÿÿüç³^OÚÿ�†‡~˜½{÷Ί Ât¹:Y2“‡~˜÷¼ç=|üã¿ã¢V«q»Ý·”íHV ¸IQ—têÒ�­[·¢R©øå/©t(‚ âÑGÅf³ñ¥/}é¶J£££;v H,ûú|¾[ºœ¼ñÆ8�Îyç2·‹/Κï"‘díÚµKþl¿ß�V«�µÔ=::zK`R<ÎgÌWUUÑÖÖ6+Ïqtt”öööe‰9›È9Q§ÓQ]]}Ï÷ýæoþ&ÿðÿÀýÑQVVFgg'7nœ.7q'ªªªX³fÍô®+µZÍßüÍß,¸CË¿üË¿LÿÍØØÑh”†††Y»ÏÞ÷¾÷qòäIþò/ÿ’­[·�Ç9yò$555¼ûÝïž~ßÛßþv^zé%>ýéO³~ýúéºk‹}Š|ä‘G8þ<_ùÊWxã�7(++Ãëõrþüy¾ÿýïðᘞžþüÏÿœ 6�ŸŸ�ßï§««‹;vðGôG)ùï+H\.׬’wbÏž=üô§?¥¸¸˜ŠŠ Μ93¯–z˜L&¾öµ¯M—ŒyûÛß>¯´‹• ¤¤„'Ÿ|’ýèGLLLÐØØˆJ¥¢££ƒuëÖÝ3ÇQ�›8þø�ÿ˜¿ýÛ¿å¿ü—ÿ£�>:½³·££ƒ×^{�w¿ûÝlß¾�|�Ÿýìgüã?þ#úЇÈËËcïÞ½´··óŸÿó^Ô¦­;át:ù«¿ú+~ë·~ £ÑÈ /¼Àøø8ïÿû—üÙ6là¹çžã_þå_xë[ßÊØØßùÎwnIÏÈÏÏ'//�ï|ç;ôöö #ãvåè~ë·~‹?ÿó?ç/ÿò/yâ‰'ˆD"|÷»ßÅ`0Ìš79 yä¶nÝz×÷466’——7�+‰òÿõ¿þGŽ!Ow`¨««£¼¼|ú}ï|ç;g‰?�FÃ?ýÓ?ÑÞÞÎÈȲ,£ÓéÐh4|êSŸºçÒ@UUŸúÔ§f½f6›YµjÕ- ÇF£‘ø‡àõ×_§«« µZÍþÏÿ™ûï¿V.¡Çãá_ÿõ_yùå—å‘Gá­o}+mmm³,õÆÆÆÛ.y=ôÐCÓ¥8 á°þáþ!<ðÇ�gbb‚ªªªYeuŒF#ó7Ñ#G8sæ “““TTTÌ뿇 »(,,¼gi·ÛMuuõ,Gñ©§žbjjŠ_|‘p8ÌŽ;øã?þcþïÿý¿³rƒJKKg‰?›ÍÆ_ýÕ_ñË_þ’£G��FyôÑGÑëõTWWÏ«Yqqñ-yY·‹yÍš5Ó?kµÚ[ö!1ª««gå[ýÎïüüò—¿äµ×^Ãd2QYY9½q%ëÜ(“ÉDuuµ¨#š£lÚ´‰ý×åÇ?þ1{÷îett»ÝNii)¿û»¿;�Ò£×ëùŸÿóò­o}‹çž{ŽP(DYYŸùÌg¸ÿþû§?Ïn·S]]}‹`¼]qwµZ}Ëø)++cË–-ñÜsÏ122Byy9ù—9«ˆ|AAÁ¬y39&æn´2›ÍTWWO�纺:þàþ€üà´µµQXXÈ{Þó�ÀtS HÌ»ñÁÏ~ö3Nœ8ÁÔÔ;wîÄív³zõêYfH]]ý×ÍóÏ?Ï?ÿó?OoNû³?û³é eÉsp;ÊËËsf)Z%/çÎ �@ AÆ“s9ˆ�@ ‚»#¢@ �`B �@ f!¢@ �`B �@ f!¢@ �`B �@ f!¢@ �`B �@ fñÿBt3fKÅYë%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00/ "2+Ͻç~ïù�ßù“a� ë˜»=�@°�£@Ð#1 =‚£@Ð#1 =‚£@Ð#1 =‚£@Ð#1 =‚µÛ|I]Ñ)” U�BU¥$iT%IÑ©Öu$YCÕ dÕÀ0(š€Ù 6³Ã6‹3N‡—ÄÇaÅe7ãq˜ x­ÜV>—“©ÛW-x€I„Ãužj]#Y¨“,($ó [Y™bMÁÐ ½¯Ï�o®”y÷ZŽˆ×ÁÁ‰0N»pÌô†kÉwVrÌ »xóhïs@ð܈1WQøí§ʒΑ©!ßóùöíuTMgn-ÏjªÄ·�‡96áëö�:Æž£aÀÕÅ"ï_Ï35`z$ Î û€bUæÚ|—ÝÄ_ŒñÙ»=¤¶³§Å˜)ÊüÃ')LX86ÁíÜÛ1£{ À…�ó^;äì~·‡ÔVö¬?[(òÁõ<³ûBLÄŸSg/R­©\�KárÂ�ÏÆöl0úžcµ®ñë‹ire�S³{>ƒâyÁ0`a­ÀÒf�ïž shƒì)1®¤jüý…$#>Ž·KSö¹R�ÏæSÌ:ùÎéÈž:Þ3büänž wŠœœ` àêöpmDQu®Í§Ð •Ÿ¾Ç¿GÌÖ¾£ª¼s9ÍzVæÌì î/i!hKEæ×süø\ŒÉÁþ÷µ‹U•_|˜Àç¶sd2º§LÁÎHå%®Ì¥xãp�Ó}îmí[1neëüÍÇI¦†Lõ÷$vG¥¦rñ·Fܼ}<Ü·çÈ})ÆÅ-‰_’äèôñ°HXlï#/ßMàw™ø³—û²z]߉ñ³…ÝÌñÂ�A‚"¤MðtÃàÚ| YQøó7†pÚû+µ¯ÄxáNžKóeÎŽ G�à™ÜºŸ%_�øó7ã}lÞ7b<'Ïg eÎzn+± vÎÜZ��L‰Ÿ¿®}!Æw?ÏroCâ¥Ãq6!DÁÎXX/²šÌóoòö~$VÏ‹ñ½kîmÔ9w$.êÑæ~¢ÄâZŽ¿üöwo ²§Ÿînd¹³VãÜa!DAsŒú˜òÿ!AIÒº=œ¯¥gŸð‹sE®ß¯n QT¦ì‚É!?£1?ÿõ½MÊ=,Èž|ʯ,¹x¯ÈËG†pg� Lû‰…=üâÃMêªÞíá<•žã¦Ä·òœ;Ç)„(h!÷…ð¸üÝèzï ²§Ä˜Ì×ùõ')ð-hǦ�¿¹”éöPž gÄX’4þæÃGg"„Ed� M˜Lpj6ÆZZæü�B·‡ó=!FU3øë7� {º=ÁÇj1söpœOçŠÌ­W»=œ‡ô„ß¹œÆa·35èöPÏ N»…òëOÓdŠJ·‡ô€/ÍYMËœ˜èöPÏ��ã!þöã-êJ÷:]ãZºÆG·ó¼xpP$ ºÂÄ ŸÛÉo.¥»=”&ëüý…'¦£Âs*è*Ǧ£$ *WŠ]G×Äø›Ë)CnC"9XÐ],fgføàzžLQîÚ8º"ÆkË%¶r*ÇÃ]»p�à«xœ6öï ñËóI4½;¹c¾¢òÞÕ§÷ˆ}¢ §˜ˆû°Y­|p#Û•ßï¸u!ÅÔh¿gï72ô'öǸ¾\a-SïøowTŒWKH²Á”¨æ&èQìV3‡'#üãÅ$šÖYsµcb,K*ÜÈrb´oKé ž†#œ¼“ïèïvLŒ¿»œfß`Ÿ[˜§‚ÞçØôŸÍ—Hw0:§#bœÛ¨�,¨ìán‚þÀi³03â· h»5ÝàÝ«9OD0 ûTÐGLÄ}Huƒ»k•Žü^ÛÅxi¾ˆÓac Ôÿ�IÏ&ž ó߯fQ:àÌi««u� · š‡û‚þ$ìwðØùô^ûsÛ*ƯçðˆîÁ‚¾æÐx„‹÷Šm/fÕ61ª ·W+L�ÛzA»q;­ŒDÝœoóQGÛÄøá�<ãÃ~Q\°'˜ qc¥B©ª¶í7Ú"Æ\YanCbjHeö›…}1o[Ú"Æ®ç˜ö‹âÂ=Åôp€[+UŠmZ[®–|Ya1QÝ„{»ÍÂØ — wómùû-ãÅ{EöÅ}XEo Ádj(ÀÍå Õzë=«-UL]ѹ±Rf2îëØÍ:‰Ón!qñùbëKt´TŒŸÍ• ¹pÚEMÁÞer(ÈÅ{EÔ÷ìh™ ./™vúÞÅï±ð8¸½ÞÚ˜Õ–‰q~³‚Ãn& 2øÏcƒ~®,”Zú7[&Æ+ eÆbƒ*x>ˆ‡]dËjKó["Ʋ¤²–ª1ñvíæ�Äd216àãÚRë9-ãµå2#1‹ÈWùŠBYÒðºš{A™ Ãhj×ùŸþq…í¸&ªn¬&ʬ&KÔ�ÃûÌ»E’5–7 ¬%˼V�z�9 :vÔõL× 6²uî'kÜ^­P“uFb>&ã¾[do%xù —£Í95›cYÒøßÞYåû/M|ãg Ã`y«ÄÂzžxÈÁÙY?ã1×®ÛÂUë7î—ùän¿ÇÎìX¨í¢¬Ôî®äHjœ™ñsbÒ‹ß½ûDêõL�OçJ,'$&‡üL ÚÞÕy5Yf~-�ßcá¥Ù3C.Ì»üͺ¢s{µÂ…»¬ ³c¡¶‹²¦hÜ[ɱ™©p|ÂÇ©iaßî‹f' 2—çŠÜY«0ó±,ˆí^”÷Öóø¬:ß>Õ\ý¦Äxg­Ì…»ÎüÚÏe‹5®/fy-|ëx˜X°õbÑtƒkKe>¼™c(êav4ÔrSIÓ Öó,o•xé@€füج­K®¬ðþõë™:‡'# 6¹ ø:ŠU™‹¬ƒïœ3m½X î¬Ux÷ó,!¿“CûÂ8Z¼·4 XÞ,2·žçÄ”�s¸v¸š7BYÒøøVž»ëŒ‡xv´Y¦Xc~%ÿÿîHS¿Õ”5KY1³$øÌuo-ÇZ²ÄwOEš^¶¡&ëüþó,Kɧ÷lÑ>¬RSøìn’ˆßÊ÷NGñ5¹h„å¤Äo/eû�žˆ´l•\Þ,ro-Ï[ÇBœ˜ôµ½i­¢|t;ǵ¥2'gZv V—5®Ì¥°[ ~øB´%+á7±•«ó›KilVÇg¢O]%uÃà� ÷ù_~2Ž­ FSbü«Þdräé&ˆ¢é|v'‰Óvn·£³Þ¶»kÞù,ÃÁ}aÆb»‹™Mäª|>ŸæÍc!NMu6+¥®èüæRšd^áÅCqœ»XYtÃàê\ YQù—¯Äz:[£h%Uã.¤�û˜yÆ |§äËu.ÝIpzÚÏ«‡ƒí‚­éï~žåîz•³‡âOõ—||}�œ‰4eq4µ®§K2ï“&g]Ö8c“±¨�?#Þq!õðo¿5ÄÂzŽù�æ;­¦Ê\_Hó?¼>Øq!8lf~úrŒã^þxcƒ²Ô\F¹ªé\¼•Àã€ÿñÛC"À¾'ÿá_ “ÊU¸±”¡9—!¤ro'ø“³¼v¤³B°˜Mü‹SÞ:âÂÍMrå'ù^;ÉœÜÔßoXŒ¹²‚Ãj~b™–�ó7796îá;§"¿Q_%äµño¿=L"Sf~½qA®&ËÌ­æøË·‡ w÷ØáåCÞ<âÂÍ-*µÆ*YkºÁÅÛ †Ã6~r.Öv§Ð×áqZøË·‡�e™K™†¿ŸÊK\]Hñ³×™Šw7êë踗?9;À¥; ò� Òãr°Uh.§a1& þÇVEM3¸x'Á‘q¯võF=Àë´ðoÆYKYMî¼pP"WåîJ–¿x3Þ‘½ÈN86áåµÃA.ÞÚ¢®ì¬x®a|v/É`ÀÊ÷Ït÷åø‡ÍÌÏ^¤"Õ¹·šßñ÷ å:WæRü«Wb Gº& 0wñ£¢|z'A¥ö¥ÕpÛIš³bšc�ãQ1^[J3²ñæÑP·ïÑ#<ä�•ùÒ7¿­ª5…ÏçÓü›×‰ôˆpzÆÇÑ Wï¥vdæÝ[Íc³üèÅh·‡þv«™?c�õt‰­ì7‡�ɪΥ»I~ôb´-žßÝ03ìæ�£!.ßM>,½áóØÉ4Y¤ªa1&rò#+ãJ¢„$ÉüàLoMúB^?8å³¹$Šö좳ºapù^Š×�»nš>‹7Ž„°Û`~-ÿµŸKå%ÖÓe~rn`×g‡íÀí°ð/_Žq}1Mµþõ¦÷çs)Žîó°¸õÇ<­àÔ”�‘°�›_˜Þ6‹›ÕL¾Ü¸ c±ªáun;jŠÆ�•?}9†µ‡‹QÍŽ¸™rsç~YX/öZ83Ó»å&M&øÉ¹–¶Š”ªOwhºÁõ…4z6ÚÚN ;8»?ðð!~kÉ2š®ñæñÞ²¸çûg¢dK5Ry �ÃB¾Úx/ŽÆÅXVp9¶Åx{9Ë©io™tOã­ã!¹ …§xÀ*5•¥Í"ß;éö0¿�Ó›GCÏ|ˆï­æ�9�õ~jÛKüÔe•Í̓檢éÜ^ÉòÃ"=T`³šøÞ©07—2è†�Ûa£PnÜ£Ú�몎ªëØm ™l±Æ«‡‚ݾ;Âi3óÖÑwVž\çÖr¼¸ßߒжNprʇaè$r�>Ä5Ec5Qä['š Çê4f³‰ïžsw%ûÄ>xq£ÀÌ�›x¨7· �3=ä&â·±’(átÚÈ7Ññ!1æ+*^÷ö*¸°–çÜÁ@O›§�stÜ‹TWÈ•jÿMª«$sgö÷®yú8&¼z8øÄÞqq½ÀÑ gïš§�3sáuYØÌ|Y¶BQu–·J¼r¨¿:_¿q$ÈÂz—ÝB¶Üf3µXQð8¬Të*™b�“]8 ß f³‰s,m~Yzq³ÈÉ)N[õ“<0âAÓõ‡/M3XInÇÎö¯ °¸ùåyðj²Ìä ‹�·÷·?_e(ì â³!É…r›WÆj]Çjµ°ž*shÌÓTü]·92î%•—P4Ã0ØL•9>Ñ¥&M&81ée-U`#Sa4âìHìl«™Ž»©ËÚÃ(£�t‰SSý7''§¼äJ5$¹Í+£$ëØ-ÖÓeŽõá ÛÏã1é ©|�€×Ö3‡û�rtÜËFº²ýRÉ”9>ÙŸsb2Á‘qëé2媂¬êìè}ÔÓØ?â¡P®#ÕÛ¼2JuÃlBQôž=‹Û ³#n²‰TAbv¤?'Àç²p[É–êd u&û÷Zf†Ü¤ ‰¼ÄôÐîó]»…Íbb,êDQi8·!1VêuYc_¬·"!e"æ"U¨‘-J}qðµ×w±–*õÛpôÙ¾÷«ŒD”* ÙB•É~Ÿ“Av«©aSµ±•±¦¢¨c=–Ô(^—«ÙD±¢õwæÑˆ“|©Îè@ÏÉv}#;¹²ÌH´­.€Ñ¨“¹ÍbT4PT�hò~—ŸÛÚóÊßDÄgCÝ#sòZQ5Ÿ«?Î{ŸEÄgGQuvÓÿ�†Ä¨i:R]í;—óÓp:,„½ý=éA¯Í0öÄœ¸ìüîþó?ŽÍjÂf3Qnðà¿¡§Q3 dÕÀåèß½ÉÌæíJÐý΃E÷ž˜£çë°î§ÕBUnLŒ Í ®™Ðt�ºÜšN­ÝB7 êŠ�¦7îñê5u»PrµÖø¹V/!«:ŪÊ^�bYÒƒJUoè{;®�se¾È?]É`3œÝìùhú§!Õ5þ�^§øET}Äoãß}g¤/VÓ5þö£-êŠ� ˜‰{øW¯Çº=¬†YجòRȪŽÉ‡Æ¼üø¥�n«)Þ»–åÒ\M70™ ¾{2©™�EEíxe<7ÏÕj:\Y,¢´ Ad§ùàFî¡2E…Oïwñ»Çû×rÔ•í90€…D•D¾¹ú+Ýäƒë9du{1 ¸·^!_iüмÛ(šÁç‹¥‡‰Æ†aâü��—}Ù±_? L4YŒ¼«¨O±4½1s¢Wпÿ&£%t;~�ý¿aðð�î' ÃxòZØùuìXŒ§§ý£"Ì&ÇÜ;.ËßK¼q4ôHÒ­ßeåìlÿWÃvæÆóÚ ‡ŒôH�˜F8w0€õ+ Æœ=Wöd'Ø­fŽzVW0™ ÎLï<¨¡º©ÿû?­#)g¦¼œë“<Ƨ¡¨ÿù�5UçþÓ}}•ö8s›U~ýIšƒ£.~ðBî³Ê5�¿þ`‹LIá?6Y¸W˜ß”øûóI~|v€ÙÑ�— ihisÚ-½$µ?ͺ‡m†º¼} u¥¿¯¥TQñ»m4—ÜSx�jêö�ºÐûÞG0 Voc¾á†Äh³€ÇiãþV­‘¯õÙ:~��hÀÉJª¿¯e)Y#q³’”º=”]Q¬ªÈŠN$èâ~ŸÏÉrª†n [\ ‰Ñå°`·™É–j}¼¢,oI„ýNÂ~‹[ýûë†ÁjRb(êÅl6‘êãe9)1pñ»XÜìß9XÚÚΗõ8‹ðjHŒ‡U5ˆ…\Ü]«4òÕžâÖj…¡ˆ‡xÄÃÜFµ/=wˉ^· §ÍB<ìáÖjÿÎÉ�û#‚.¶òu*}Ä�.*Hu M35œEÓØÊè´ k#Q/×–ÊÝ¾î¦ØÌÖÑtz¸ìó›»ëÅÞ-®-—Šn'�ƼÜX.÷eDQYÒØÊÕ ¹±˜M …Ý}ûb¹~¿D<âÁn77œ“Ù˜mfY#r‘¯¨l5Ùࣛ|r¯ÈXìËÚ=£¾¾<ô/I*K[UF¿£ßmÇf³0·Ñ/–KóEF¼ãl÷ úøt®Øw/E5¸¶X&tãj"·´¡o¸�ꚎÉdbr(ÀÇ·óݾþ†È—–ãñ/Å8õR¨h¬¥ûËipáN�}ƒ¾GÃNùðfnµóÔ�«‹%¦†¾<ë ùœ8mn¯ö—õuy¾H$àÄb15Õ¯!1=6jõí¢Aãqëé:™æ:îtƒw¯å˜òcýJ-“ fFƒ¼{­â|YáæJå‘`(âFÕ¶»÷ ßÊ3vãv>êì˜ ñþ�|ßDÕd�Oî˜ R­«„|m£ßc¥\Ý£ÅlâÐxˆß\J?–Õƒ,'$6r2“ÃOFÛŒx‘ƒëËýñ&þÝ•,ÓÃ�§¶æ>2៮dúâü4]”¹¶\fvß“ Ñ€ŸËÞPlg7yïZ–ᨿÇNµ¦j"W¶!1:¬f¬fóöd#^, ço÷ö «}Ñøè3Zr›Lpd*ʻײ›¨ÝI®/—É•U¦†Ÿfö;‰ݼûy¶ÛCýZ4ÝàWÓ =3¯ôðd˜ËóÅž~_NHÌmHÌŽm¿Tj²BÀÓx8_ûLŸÇ†ô•¦�'g¸<_ä~:ÿãÅ4± ›XèÙ…Ž;“Ãþî�Iô=êÈ–~ÿy–“3˜¾ÆUwx"ÌR²ÆÍû½»Ò¿ûy³ÉòÈþýqœv+G§"üÝ“=»ÒWj¿º˜âÄLôa᪤pw@ŒA¯…ÊWb¯v 'fø‡ORäšhƒÕn>¸™#[V98ñÍý'f†˜Ì~{¹ñκí¦Z׸Ň M„ñ{¾¾ˆ–ÕbæôlŒÿ~5ËF¶÷öôW—JÜ[—89ûͱ´Ã‘€‹_žï½—¤¢üÍG ö ú~ù¢¯Ô5B †ÂAbŒ+�š A³£!þŸ÷·¾Èrî .Ϲ±\á…ƒƒ;.ÆýüŸïmöÄ yþN�ów œ=o¨Ö�ÅbâÅCqî®Wùç+™®O~¥¦ñ_ÞÛÄçq°,ØÐwc!‡&"ü×?l²Ù+äÍûe~s)Í‹ãxœ;XM&85#SÔøû É®GLɪÎ/>L jfŽM=ÚF°X–‰ú›+ÿÙ°‚vJÏè=7=`z8ÀÿõÞ&«] öÕtƒß}–áóÅ2¯~Âe¾ìV3çŽq?-óË É‡Yè�&Y�ù«w7‰=™h®wäHÔñé(ýQ‚{ëÝ 0Œí#Œw¯çxùÈAoã«ÅlâÅÃTjðß>Ø¢ZïŽV¨¨ü—÷6±Zlœš�=±w/VebÁæª6”Ïø€ÿõ—÷ùÎ cÏ43Ry‰«s)^Øïç•CÁŽ•jÏ—~y!…ÕjåøTô‘ñfÐtƒ›Kòå?}9Æ`°s�¯,–xÿzŽ#“F¢žÜ›:ŸÍ¥80ìâíãáŽåpVjÿßÅÕºÁ©ÙÎ]Vä3 ¸·–c-YæÇ/E;Zþîz…w.g˜ 29ôtoöµÅ³CvNO7ž°Þ”ÿê÷›L�„ˆøŸ]ź&k|>ŸB×5~p&Êp3Ð5ÝàÂ�çŠ 21ÔÚ^‹ëé 7—2÷òúÑ`[+¤‹2ï\ÎP• NíhÈœû&MçúBšRUæ{§#LÅÛ÷ |¶XäÃyÆã>fGC-})§ò×ÒL :ùö‰p[[¦«*ÿt%C2¯prf€ ïÙÏòÇ××ùÁ™£MTÝoJŒï^ÍP”-Ì~eãú,ÖSenßÏ1uðê¡`KË髚Áõå¼SÀïvpx"ü°Åy«‘�Û+9R¹*/Î83ãk©(³%…�oçYØ”80dß ¿mE*/qs)CÐkåµÃAöµ°5€aÀ­Õ2ß*`µš92Åׄ3c'¨šÎÜZžÕd™SÓ>^Üïo©(K’Ê…;n¬T˜ò3=øZG ¦üîâ2ÿñÏ&š²<šãÝõ*ço—8{xpGŸ×tƒ•­‹›‚+Ç'½õ4Ý t+'sã~™›+e‚^3£ABÞÎÔ~)UeÖ $sUŒz86ámê-Û®ñ{®/—ÙÊÉLù™òïØË¸ Ã`-Uaa=�Ónâø„�Ccž¦»gK 7î—¹¾\Æå°2=|ÄÝßNª5•…�é2SCnŽOx™ˆ5×ÉJÓ ·$®-•YIIìô15ôôh§ÇIj,®gùwßnê:šc¥®òŸ»Æ÷^œhè‚ Ã ‘“ØH—Id%"~ƒ.ƒvÂ>~·§íËÔU3�d�lI![RXI×¹Ÿ”°˜ÍŒD=Œ x[jÆ5BMVYKUØH—©ÉûœìpñÛ{m¸lVÓW>¯S’T²%…d^f9U#™“‰� G½ÄÃî§FµÀtQb#Uf3S%à¶2w1ôÅœ Ã0È—e2…%é‹9©«(ŠŽÉ¼-\“iÛÛìuÙð:møÜv¢Þ6™¢Í"+éb�\©NU’)IÛs"«:v«ùáv >· �ÓFÈç$p6m™\¼½Å+}ÌŽ4çpkZŒ¿º˜Äbu2o­³¶ûӛͦ¾m˜ùUTM$K¤_Ñt³‰¯ ÃëUßµ§ýq ÃàwŸÞçúÁhÃå6Ðôˆ¦‡Ü¤sí‰GµXö†�=!DØ>çÛ BZ.D€l©NÀmoZˆ° 1N ºI¥¾HŸÚM2'±xw«¦Åè´› ùìdŠý•!/´ƒT¾ÂT|wGD»Z¯gâ.RÙþ«¹"´’º¬Q©k ‡ww¼¶+1îõ�hÓ¾Q è¶rU¦bnÌæÝíEwõíxÐŽÙ ùrogb íd#]áÈøÎ{j<‹]»•�ºÙÌönF¹@ÐNêŠF¡\g*Þb<8îe#Õ?ÕÈ‚V²™®0=ìjIÌ®Å8°c7›È—»Ÿ¼*tš�l…Ãc»Oqƒˆàø¤‡ÕDÿUåvC¥¦P­Ê-1Q¡Eb<6åc=]EÕz³‚—@Ðî'J›ô¶,¾¸%bô:­Œ 8ÙL‹½£àù`;­Ìñ‰ÖÅf·,Hïô´�•D©+7F è4[Y‰ˆÏJÄߺl•–‰q*j*âÌQ°÷YM9=ÙÚŒ¥–‰Ñd‚g|,mä;}_‚ŽR¬Ê%™ƒûZãE}@KsINMûIæjHõÞîW!솅õámªê7Ñr1úÝVf†\,‰ Á£®h¬$ËœÝßx�â�Жš¯ ²¼^«£`O±°–çШ¿§=ÑÚ"Æ ×Æþa7‹bï(Ø#ÔåíUñ•ÃÁ¶ýFÛª%½~4ÈòFYé�qA³Ì­å89åÃïj_�¶‰Ñï¶rdÜËÜjïô9š¡ZSÙHW9w°={Å´µŽàGC¬g+”ª"*GпÜ^ÎðÒ�@[›ë@›Åè´›yíP�›ËÙ¶^„@Ð.Ò‰¢Tçìlë‹u?NÛ+ìžžö¡i*‰œ¨"'è/ n-eùîÉ(–ô³l»Íf3ß:áærV<ôK[E|.3ûGZ“<üMt¤öüô�‹¡ �{«ùŽ\”@°[j²ÆÜjžïŸ‰vì7;Öâ{g"Üß*‰+A_p}!Í‹û}-ÍWü&:&F¯ÓÊÛ'B\_H#¬UA/³‘® +*/ vôw;Ú"éä¤�ÃÄüºˆÌô&uEãÖr†ž�v¼wfÇû•ýéÙ–¶ò…¹*èA®Í§8:îed—}3š¡ãbô{¬|çD˜Ïæ’hº°W½Ãòf]ÓxóX¨+¿ß•NžGÇ} …ìÜZÎt墂Ç)WæVóüøå�®µvïZ[ݾ%S¨’-å]FÓ .Ï%yëDˆˆÏÞµqtMŒ›™Ÿ¾<ÈÕù4eIéÚ n.¦‰mœhC)�FèjÃù¡°ƒ·Ž¹t7‰¦‰ý£ ó,m)I2rv ÛCé®NMùÙµóù|²ÛCö½)F€ö81áåü­-Q Y°+7‹¬%Jüü­a¼m,µ¸[zVŒ°]™ü਋ B�‚&YÞ*±¼‘ççoÇñõ°¡ÇÅð­ãaf†\¸±) " ba½ÀòfŽŸ¿=„ßÝž’ü­Ädý‘wþNžÏʼ|$ŽÓÞû7VÐ]æÖ ldJüü�xÛzc´š¾#ÀÅ»y>™+ñòá8ngoDMz�[Kòe‰¿x+ŽÇÑB„>#À•ÅïßÈñâÁABÞÎgc zÝ0¸:ŸBWU~öz§½çwa�ÐwbXNHüò|Š£SF¢­í«.èOUçÒÝA·™?;ÃÚ�ß�Ò—bHæêüâã$ãq?3ýÖ$è,ÕšÂ'wqó­án§iúVŒ¥ªÊ/>ÜÂã²stª{åÝ#™“¸:Ÿâíã¡®'ï–¾#€ªê¼s5ÃzRæÌÁAÜÎþÙ° vÇüj�•d‘Ÿ¼<ÀhÔÙíáìš¾ã.ÏùèFžûˆ…\ÝŽ �(šÎÕ¹$fC积Æðî‘ðž#ÀZZâ—Ò ‡ÝcîÅh`Á®Èk\�Oq`ÄÍ·O„1ï¡­Éž#@]Ñyçr†�œÌ©ýøÝÝ«ö%h†a0¿Qdy3Ï�^`f¸w’‚[Åžã®,–xÿZŽÙ± Cíot)hÕšÂå¹§‰?9ëé`ïݰgÅ�)Éüê“4šaâøt�ˆÚé+ Ã`q£Èâz�W�xaÿÞ>ÂÚÓb„í2 W—м-ÏDÜÇÌXPì%û€bEæÚB·~ôÂ!ßÞ‘îy1> PUøí§i �#SÂþþw…ïEMgn%ÇzºÌ·O†9:Þßg‡�ð܈ñ·Wʼw-‹ßãààDwïe V%î­æØ?ìæ­ã!ÜŽ½¹7|Ï�TÍàÂÝ<—î•‹ûØ?Àj鯠â½DºPãöR·ÓÌ÷N…‰…žÏ€çRŒ(J¸–eqSbr8ÀÔ°_„Ôu�l©Î½ÕuYåíãAŽz»=¤®ò\‹ñ™¢ÂG·s,oÖ˜¢l;ŪÌÂjžl¥Îk‡·k™ÍÂ2bü ‰‚̇׳¬ee¦â~Æã~l=ZI¬Iå%–6 ”%…W8>é/½¯ Äør%…K E®ß¯0v15ÄëÚû®õv`›Ù*‹kTCçì~''}XÅKî „¿†²¤rq®Èç‹e">£ƒ>C.Lâœò©ÖTV’%ÖR%¢^;çù™Šï½¶V"ĸÍàöJ…«‹E²•±˜�ñ˜WÔáy M7ØÊVYM–(•e�{85í'ê÷i'16H¦¨pu¡ÄÍ•§•¡ˆ—‘ˆ×sz^©©¼ÄVºÌfVb0hçôŒŸÙa7–>,}ÑM„›Ä0`9)qkµÂ½µ*—�Á°›Á  ¿gogŠ(šN:'‘(TØJKDƒ6ŽŽy™ñìÙ îN ÄØt]g9Ygn­Â|¢Š¡›ˆ� ÝD®¾÷È*2ÉB•TN¢Pª3q0;êfvÄÛó•ºû!Æ6�)É,mIÌmJldê¸Â>A¿‹°ÏÑóÙ#ª¦“+×ÉëäK52Å>·…‰˜›™a7ûœ}Y}­×bl3†±}~¹ž®±’ª±–©£*~�¯ËŽßãÀï±ávÚpØ:»Âè†Aµ¦RªÈª2•ªBQªS­«ÄF£NFŒE]}Wƒ´bì5Y'‘¯“.Ê$r ‰|�|UCS5<®maºììv+«»ÕŒÝnÁf5c5›±˜MÛå&L`û"¦VÓ t}{*eU dEGV5dUGQ4êŠNMQ‘j 嚊¬hø]6">+±��Á ƒ�€�°×Þ“ý ÷:BŒ=„¬ê**…ŠJ®¬R©«Tk:’¬S­©ÔTYÑQ5Í“õ/ºs™Í`5›ÁN›“ 63.‡�ÝŒÛiÆí°âs[ylø=6üb¯×S1 =‚Ø=‚£@Ð#1 =‚£@Ð#1 =‚£@Ð#1 =‚£@Ð#1 =Âÿ¼úª!3C%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00ŃD­Än…½|0£¯3dú¥ÈK4UýÜléeÊ›Û÷SÌ>Lƒþ7N[üâÄÏ­ˆlŸù•<�%H¤k•‹Ž¶ Ýq"­¾ŸýÚ'këLÍ©ªÑ(š"€^w¶ô2Ù|™‰ùORëÄ#>.Ÿ�Ós0húeŠ4µD¦Äµñ$÷ÖþöÂAýÝ1X¯·6ûê†ËCªjÔ¥† ­Ì–^f%™gr.A®Pû¾½‡‚Œœ‹c…¶ö}Eäû ¥*7n¯òÕ�4¶ >�›·:Ûè9Ž…òƒªõ¯ah»fK/c;ó3Ì,¤¨Ø6n7œë�rqÀÂïÕ^‘­p˜ZÌpm´‹ê:€Ò¹ ŸN=›-ý^úŽíÞlée67À-¯aÛÏ6À�ïkë™”Ȧ™¥ׯ“¤¿Û~8âtwŒÖ:èX°š)21—$•)ßU5ÎÆéllñ;Ë«¨Ëª·ÙÒËüp\[ØË‡Ú'£T‘�¿I°œØØîg ;F,Z÷‰SsIÖ‹µ�ìë 1|&FTëC;ªîèE³¥þîÁ:˜-½ÌÓµu&g“¤óµ2á±ýAFÎÆèØg¦L(bJv½Â§W›Íðy8yÔâè�ú.o©ª±ûê&€i¶ôS66ÀÝZLQÒ8Ùc66„6™¤TynCx—…¯�.àëÅ 3‹©Í§^#A ê©×�`<€u¶ô2àædppøÜ¼ßoñNo·»qþE^ÕÝy>K²–+�c´wãö‹ªÃgcPUcÛ  f™-½Lv½Ìä\‚Çßm€‹E|\ŠÓ{Hà¤9$2%FÇÌ>ª-⇃>ºãì·šã3®ªÆÎ2@Í8[z™Ú¸$ùBíõö 2r6ŽnÎ×+ͯP²¹>�Úlüëóº9ÙeÑ}(‚«QK/¡ªÆÎØÕJ¤KŒŽ7ïléeÇaîa†™Å•ª�ÛçND¹Øoá÷é,�acCøèx’õ¢� G†é;jáߥ á&©ª±½v%€öÚlé¥ïE¹ÊíÅ‹+B´NÀüã£cOy²V»“oß` 'N´uï­‰¨ª±=v4€lÛææ|ŽO'÷æléeV³E&ç’$ÓàüŒœµèl×LJêK=o7IU�­Û±šœgt,ùÜl)È@OlOΖ^æ…à†bD[ë{ß“4¿RÙáËÛÏm÷¸8q¸>7„›¤ªÆ›ÛöJeË|:‘bf©Ö 5àãôq‹Ãquø)UÛáîÒ³ p^�‹_kœ4³”ct,Af½Öï°Q6„›ôâªFLm}^bÛH³¥­Ó81íaªÈÕo’,'jÑ}a?gzbX]D_ÕƒDŽé¹$ù窗†,ömñ�Ìf´-¤ÙÒöJ¤ LÌ&6ϵ?Ú`d(Æ~KÇ>ÈÎȬWù|:õlCx‹‡“]�½!Ü$U5^Í–èa¢ÀÕñÔæl©-âg°[³¥íà8°ô4ËÔ\’ÒsÇ> Y„ì²Mª¶Ã7Ïmw»\?¡ï¨…×£ åVJn-¨ªñSÞ(€4[Ú=åªÍ·K«Ì.§±�ڸߜlãW'£*mÊ–Ü}�çêX‚Õ\­TTÛ§UçZm;U5^ìµH³%s²ëe¦æ’¬¤òXa/#gãôj5=4i0‰t™�Ç̯Ô6S†[} �Ó±6„›¤ªÆ�½rÍ,åød<ÉÚó‡J�i¶´Ë%óLÍ%É}·îÄáV.Å´N~V¾X峩$ã³ÙÚ†pŸ‡SG-Ž©r±«6Ûú<Ìà8{»­Ï+Ðÿú?sDC- öĉ7Ð1 ÍÆvf¤¹s•JÕ¦ÿX˜¿~·Ãô°¤Îݸ½Ên¦š²ño#ÊæËLÌ'xò][Ÿÿ1rxÏ•ä^ûÓ÷ÁÐ…�anWí„ØÁž¸é¡Hê9e ;®ð1,ÜêãüéƒDC{wsþku«.ÒØô7,õBS 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒxí*WmÓc–ïxS+¼ÿè�´­ÌšŠ4�rEÃõ¨PqLa×y_õ?º\à80ú—%Nµ8z ‚Ëezø{S)�¦øÅ(Ý+wpáÀÔ2Vï¿rÿÁƒ¦‡'ujãïua%Ãz©Â@wœpÐgzX{žû»ßËÿ¾þˆwOîã|_>ÏÞ¸¸ºÇy¥ØM¤Ë|<–`~e€p«�Áãq:¬ é×°g8Õ ™¯>'>ûg¼Õ2.·›@WÅG�°‹EÂCCÄ.\À›®ÔÛ¶¹9ŸãÓ‰$ë%.Ž sê¨E‹Ïczx{V¡TåÖB’û�³„>¢ï¾‹õÞ{¸<º°È÷J6×§S|}7�ã€Ïëæd—E÷¡¨ª­fŠLÎ%Hfj“ɃV #çÚéŒûMmǼvTm‡oîeøl2I©âàv¹8~(BßQ ¯GÏ5l§õÇ�q¾øOâkKxÂaƒƒøøÑÿ­ærd§§)./àmk#öᇄúúL¿ ©CªjÔ§ûO²LÏ%)–«ô séŒE¸ 'ùo@2ëU>ŸN16› Ðâád—Ö‡¶Ce=OîÆgì_º‰Û©ÝÕ„Þ~›`o/.÷ËC¾ôä Ù‰ *é4�ãlj_¾LKG‡é—%uHU�úS­:Ü]^åÛå5lÛÁçqñîÛQÎ÷µáõ6Ï$K´áa¢ÀÇãI$j·Žm?Ýqb‘æ½uÜ)Ží�¾ù¬©ëø«Ep¹tvÀíõ÷Óq 䦧±K%p¹ˆ a]¼ˆ§µÕôËÜÓþñÿ‘ßýîwÄb1ÓCÙ¤ªF}ÊÊÜšOñ ‘ -ìåÃÁ}�!ÓCÛÛ@&2|r3E®P»uìÚæô±þ­C¼Šìì]ü%ZHàko'28ˆwß¾7þžN¹Lvf†Âì,Žãàöû±.\ üÎ;¸Ýº°˜àõz‰F£üþ÷¿çþáðzëçNCU�úôtm�ÉÙ$é| €cûƒŒœ�ѱ¯Åôжd[ TvøòvŠ·ÓTm�ÇʼnÃû8ÑنǭOð‹SIÊ7®Ññä.ž`�ÐéÓºº¶ígT32““”VVðÅbÄFFhíé1ýò÷¯×KµZ›¤ òïÿþï ›Ö÷zDvb‚j®ö{ ööÒ~å Þ¶6ÓoÇžñ|møÛ¿ý[>úè#º»»Mï{f–rŒŽ%È¬×Æ{8¢¿;FÐ_?wm{M¹bsû~йü-n.œ¶x§7ÜpU�   ó�óŒŽ%y²V }_��žÑÖÆ¾uܪôä8ÑÉÏ–jAà?r„pÿ®¬Ï8¶ManŽìÌ N¹ n7Ñsç°.^|­u&y3/ €––þþïÿžý×%�šæ&U5êSv½Ìä\‚Ç©ÚSŒ±ˆ�‘³1z6ÎïŽ<·n2ÉzñÙ¸¾£þ=¶.·´ˆ÷««´eàkk#<8ˆ/ßõ±Ø…¹™ÖÀqð„ÃXï¿OdhüwÎOІC‡ñ/ÿò/üÝßý]]ÍhXÕh ø8­ª†q+É<s ò…ÚSŒ½‡‚\9×N[¨þïRw%€6üô¸®&¿à•Òkn|ÂþG·qáàõõÇå"ÐÓC¸¯—¯¾úp——ÉNNR]¯ÝÒ‡úúˆ ã­£rP3xÕp¹\üö·¿å£�>âèÑ£¦‡¾IU�úT(W¹½˜bq%ƒã@(àáB¿ÅPw}>Åh$€6Ü}�çã±$k¹ÚLê€ÕÊ`OŒÖ@}]˜ßTæÖá±Oh-×z<ù$<8ˆ'T¿%‹ŸjëÓvþ<î:z\¸‘½Nm…BüÓ?ýÿüÏÿL P?O¢íåªF=[Ë™˜K’L×&ù¬®œ�ÑÙ^_“|£`Û_?·ÎårÑ}(ÂÉ. _ƒîø]_YÁ¹ñŸÄ×j-q<‘‘�Z^Ð>§^U××ÉMOS¸ó5X|@d`ÀôÐ8qâ÷îÝ3= #z{{ùè£�ø›¿ùÓCùž½TÕh$9¦æ’¬këC}�!†‡bD[ëc2i<€6d×+üqzõÙ8Ÿ‡“ vìC%Ÿ'ÿÅ5ö?˜Âå8¸|>Â}}zzv6X~ò„Ìä$•µZTÿ±c´ SPýІf¯j4¢ªípwéY[¯Çů뤭OÝІG©"“`y£­OØÏ@wŒX´~Ê?äT«¤¿ù±Û_ÐR-ÖÖyŽ#têTs<Öì8––ÈNN>;ö¡¿ŸØåËjëóš©÷"ÍXÕhëÅ 3‹©Íc"A š=ö¡îhÃÌRŽkã ÒùúÞ—¹w‡à_®)¬µcƒƒM¹pï”ËäîÜ!ïØ6î@€¶ßü†è¯~¥c^Û<„ðoÿöotmcgŒÝÐ U�fôt­ÀälâY[Ÿ?ÃçÚ9` ­OÝ@¹êpãÖsàÜ.N©� p…ÄSª_ŒÒžœÀ >}ÿ‘#¦ß¶WÍfÉNLP|¾­Ïð0­'N˜ZChôǰ_W#V5š�ãÀÒÓ,SsIJÏû0ÌïÿûºÛˆºUµªF’t¾¶ ~8âtwŒÖ:«jì%åŠÍ·Ë«Ì.§±‡€ÏÍoN¶ñ«“Ñ]™ä7DmXx¼ÎèX’Çkµ[Çx4À`OœhhwnÓ“ãD'>#X®ítu½ö1 ÍÆq ³³jëó­ÏvªçªÆ^–]/35—d%•jm}†‡bœ8´³k¼ @P»uœZÌpm·¸€÷OWiË=ÀgYµö9utž‹iv©DîömÖ¿{:Í a]¸ ¶>/ÐHÍHwJ&_á“Ϫ�/§Ž›©jÈ3OV×™œK�Éמb<¾?ÀȹvÚ£;ócÃІB©Ê�Û«|u'�mƒÏãæ­Î6zŽDqoÓ¯´¶FáËúlŸS¯*««d&&('ø¤}dDm}žÓÇ1ìÓU ù1Çq˜{¾­� Î�Ø™¶> @™£c)fÕnÃAýÝ1Xo~ëhW+dþ|ƒöooàµ+¸ÜnÝÝ„O�Â¥n¯¤¸¼LvjŠj¾ö{ õõa]º„o ‡ë5 ¯×˾}ûøÝï~WwÒ™`¢ª!?¯T®rgi•Ùi‚-nþÛi‹_œˆnÛü»áhÃüJž�Ç$ҵΎ¶ Ýq"­¯w똹5ExüZK�Ó>§^ý¨­�×Kô׿Æ:~Oy=É]v£ª!¯o5[br.±ÙÖç`›�‘sít¶oý)Ʀ x¶îúT’bù¹ pG-|?s®}aeû‹ÿG<ýø®}Îà -û÷›~Y ¯žÛúHýIdJ\Orïa­)îvT5dëV’y&fä‹ÏŽ}ø«wâì{ÍIþóš*€6ä‹U>¿µºÙ ±Åëæí.‹îC?¾uÜlŸ³<…‹gís‚==ZçÙfå§OÉLLl¶õ tu»r¿B^^`»ª²}ª¶Ã܃4wî¯R±m¼¿|+Â{§,ZÞ ËESІGÉ"WÇ,=ÝØ×Bwœx4ðÓísNŸÆÝ¢Ð³ÑÖgb»T[x÷÷c ãU™S~`+U Ù9…R…[ [oëÓÔ´az1Ë'7“›çÚŸö®q|áÆžhŸS¯ÔÖG^ÇëT5d÷<]+05—`-W›Lvu9ã@Û«íܵ p_̬rk|�¿Zü¿xÂaƒƒø蘄fSÍdÈLNRú®­�5†y"ÚΟ¯í­°mÓC’:vÐòó߇sâPíœ!{OLŸë›ËÇF¸ü‹Ú^¿×¹¥Ù3´!¨=þëòzq5QŸ­FçÒº›¼‹Ê´õæMÖät#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆ¡#@""b„HDDŒP‰ˆˆ 1B$""F(€DDĈ½@Žczò<Û6=Ù‚7¹¤îÙª¤Ó¬þ×QÍdLeOsÊe2äggMEÐÄl‚»ËkØšP•Høt|ùµ¿Îå8{ë7gÛ6Ù¯¿&õÇ?b àrìé!ÜׇËç3=¼½ÃqXŸŸ'wëv©.á¡!b/âim5=:©s©l™Ññ$wä|ôwÇ8Ógg7å ¦ç“ø€ÈÀ€é¡I³m››ó9>�L²^´qáâèÁ0}G-ü>�éá5�‰ÓsIòÅ }�!. Yìk}ý Òž  ù»wI\½JeuÿÁƒ„ñ„^íVR~šS­’ÿö[rwî€mãòz‰þú×´�?�Ûë5=bÃÃx£QÓC“&•H—¸:ždîQí3úèŽ³ß šZC*”«Ü^L±¸’Áq ðp¡ßb¨;ÂVs]ôÕL†Ô矓Àêë#xì[~Ç÷ˆòê*Ù‰ ʉP»£´FFvvššìwä¹:–`5W+°Zì‰ÓÐ]÷«p‡¹‡fSTª6nœ;åb¿…ß·=P+€^¢øð!É«W),×/ôµµ:s†–XÌôÐê–](�›™a}aO(„uá‘¡!…·ìºªíðͽ ŸM&)UÜ.ÇE8ÙeáóîÙ](?k%™gb.I¾P{¸£÷P�‘³q¬ðöV‚@¯ 73CâÚ5ªé4þ#G à ê–~ƒã8fgÉÎÌà”Ëàv=wëâEÜ~¿éáÉ—]¯ðÇéUÆfkûþ>'�Z=°õ2R3É®—™œKð8U+_Æ">.Åé=´3×:Ð+rJ%R_~IúÆ œj<Bo½Eë[oáòìí'mŠ�‘�˜ š«íööÁgY¦‡&ò=SE®~“`9Q`_ØÏ`wŒXôÍÒ›A¹bsû~й>7ï÷[¼ÓÆíÞ¹;EÐkª¤Ó¤>ý”ìÔž`�ÐéÓººLm×U32““”VVðÅbÄ/_&ØÛkzh"/5³”ãÚx‚t¾ ÀáxˆþîAÿÞZrXzšej.I©\{/ú�…¹<£Õ¿ókÐ*ÌÏótt”ò“'ø::ˆ àÝ·ÏôÐvœS.“�™¡0;‹ã8¸¬÷ß'üÎ;;:[ÙNåªÃ�[)nÜNSµ'24„¥ö9ÒÀÒ¹ ŸN¥˜ZÈô{é;fÑÕ6=´±^¬0³˜âþãÚë�=|0h1p,²ëcQm»P uã鯾ªm´ôù½ý6ÁÞ^\MrGPzò„ìÄ•ïÄ;Fld„–ŽÓCÙó� ŒŽ=}®­O€�žxÓ´õ©Vî.?kŸãó¸x÷í(çûÚðz"P´�J‰©ÑÑÍÎΞp˜ðà þnëSÍåÈNOSÜx}ß>¬K—õõ™šÈ¶s˜ZÌpmÇç#úî»jŸ#{B¡dsãvŠ¯î¤±íZ[Ÿ·Ž´Ñs$Š»�žÛ^˹9›$•©µÏ9`µpål|Kís¶“h‡8¶Mæë¯7Ûú¸\. rìƒÚçˆÔ$2%FÇRÌ>ªûÖŽ}8`Õ÷šg¡Tåöý +p ððþ6µÏÙN  VÍçYýüóÍcÜ--„Nž$ØÓSw�Ê©T­}N2 @ËÁƒ´�ŒàWûÙãæWò|<– ‘®•°:Ú‚ tlj¼Aè�d;ó3Ì,¤¨Ø6n7œë�rqÀÂ_‡�@»¤øè‰«W).-àmk#28ˆ/7=´·Ï ‡±Þ_ísDžcÛ_ßËp}*I±ìàr¹è>áäQ ŸÇüŽÖ>'A¾P ÉÞCA®œk§-T¿%sÐ.ËÍÌ�¼vmói2ÿ‘#„ûû�<ÆìØ6…¹9²·náT*jŸ#ò òÅ*ŸßZÝ<ö¡Åëæí.‹îCQ#óµl¾ÌÄ|‚'ߵωG|\>§ç`ý· Sà”˵Ƕ¿ü²vá7ÐÖGísD¶æQ²ÈÕñKOkm}ÚÂ- tÇw­­ÏFûœÙ‡ipÀßâæÂi‹_œ0„oBdP%“!õ‡?ÕL†ÌÄ¥Ç�ðÅãµö9==¦ß‘†t÷Ažÿü&A:ÿܱ½qZw¨­�ã8,®d™^LQ.Wq¹`¨;ÂÅkWÚçl'P(,.’}ÖS­½�Èàà¶¶õÙhŸ³~ïn¿ë¢¿ø…ÖyD¶¨\uøË�4ŸÏ¤(Wjm}ºGy»³ ï6®=Y[gj.I:WkŸs|€á¡ûÛ³d®ªm}®]ÃÎç·­­�ÚçˆìžL¾Â&Ÿµõ ´x9u|ëm}r…2·æSÇkYÄ>ø@ísDvÑOµõ9},†¿åç×jî?É2=—¤øÜ1 —ÎX„›èHqP�ËÏÏ“ºz•ÒÓ§@­­OøÌ¼/hëóSís¬÷ÞÛ󇿉˜R(U¹q{•?ÝISµÁçqóVçO·õYÍ™˜M�ÊÔîžÆZø«¡8‡ë¤}ÎvR5€Í¶>ׯã‹?nëã8––ÈNNbkÚp?±K—ð„›³¥¼H£IeÊ\Opïáw-®>zžµõY/U™YHn“ºùp0f䘄ݢj •\ŽÔgŸ‘jO²µž8Aay™Êê*þÎNâ##¯Tª‘Ýw÷ažkãI’™Ú±¬Vö…Z¸÷`�ªíàõ¸x÷d”ó}¾&XçyPúa[O$BìÒ%§O›žˆü ÛvøÓÝ4ÿ5�¢X~v >ÙâòóÇ$ìPËݺEêúuZO�ÂúÍoê¾Ë¶ˆ|_®Xáúä*�R%.Åèêh¾už—Q‰ˆˆæ[¸ŠˆÈž¤#@""b„HDDŒP‰ˆˆ 1B$""F(€DDÄ�ˆˆñÿš`À|àSÐ…%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00·� G#àµtÛñ¹mí~d  ÈP´­%WÖYÍê¬æj,fê¤ :Ù¢Žf³áqÛð84\;N§ ‡Ý†Ã®âÐT4» EQpØ×-ª¢`³)˜æš8tÃÂÝ0©ëuân˜Ôê&ÕšA¹®S,X¦EЯóiôEœÄ‚ñ�ƒ Gk÷+z©�l!u]°˜©±˜¬2›¨²œ®a³+¼üžµ?��ˎݶµÖ€aZ”ª…R�B¥N¡\'_®c˜‚�°“=.cN¢.´/….i>R€MDXHUy´Táár™L¾N8à$èu ¸û�8µÎ^úÕu“t¡F*_%W¬’-Ôˆúìì÷°»ßMÔ…"õØ4¤7IM·x¸PæÞb™Ù• —�XÈK<ä&p¢vyo5-A¶X#‘.³š«P®ŒõºØ3èa|À‹Ó.ýx›A pÔ�5ÑÝ™/1—¨Òp�zˆ‡=¸:|†Û,ÕºÉJ¦ÌjºÌj¾ÊpÌÅ¡Q/ã}^Zw6í@ °fU®M˜Z*ó»è‹yé‹zжØ~ëtÓb9Uf9U"™«2ÞïæØ.?#qw»›Ö5H~ÅŠÉíÙ×Qì 0ÜãC“K¯o �Eæ@pt§�Ã#~¹ÝñH>‡•\�/&sàiw³: )À/y°XâÌ­ †¥0Öd°ÇÛõÌNÁ‚…ÕS‹9œvxçp˜ñ~)D�d>Yå“›iJÁž!¢Þv7i[³š­pw6�Ó¡ð¶œ_^.ejüûµ4¥ŠÉîa)¼-DXL•x8—ÁïUùàxŒ¾ÐËi#¾t,V >»™åáJ™½;ÂìèñËÈŽ6!Ì% ܟͰ{ÐÃ;‡Â/�×ô¥ i .ÞÏra²ÀHÜÏøppËã/%ÏF7,Ìgyœ(òúþ§vQÕ—cT|)8Ÿªñ›‹ ÜNûF£x]òV'RªêLL§Ñuƒ�Š1ÙþÛ>ÛZ€º)øóD†›ÓEŒDêñµ»I’u°’.sk*Åø€‹¿9ÝÖñ¦ÛV€3+e~}1I4äfÿHTîåuºaqg&I¶PåÇ'ãŒÆ]ínRKØv4MÁg·3Ü™-qt½™eïŽ0£½þv7GÒf– Ü›ËðÁñ0‡G¶Ç7îzš¦à÷×’L'jœÜÛ‹Ï-sšlg e�Ë÷VØÕçâÃãÑ®_’vµó“;·ŒŠ�c{â/í¹¼— ô¸ñp•ºaðoÆ»:‘T× p>UãßÎ.3Öb|(ØîæHÚÀƒù,³+yþþÍÞ®Ý3ìJNΗøíåÇw÷K/çËÌJ¦Ì�I~|"Æž¡î ìî:^¼ŸçÂdŽûz ù¶�7L²qòå:—î®ptÌË;‡"ínNCt�…€?\M1•¨òÚþ^\N&ùšJÍà‹»+Œ÷;ùþñX»›³nºB€BÀ¯.­’ÈœÜ×+ƒ¨%ÏD7-.O¬Ûøèd¼+N¹t¼MKð‹ó re‹“ûûºÞí,i-¦%¸|oŸ~þFïWéû;•Ž aX||~•šÇ÷ÆeŠɺ°„àÊä n ~þF{GDulËLKðñ¹u^‘â“4€ª(œØ×KÍRøøü*–Õ±sLg Pøå *:ßG‘â“4ˆ¢(¼²»—šŸO`YV»›ôL:R€¿¾´J®$xu_¯ŸdÃ(ÊšéR¬ ~u)E'['Àß_I±’58±¯W.;%›FU^ÝÛËjÎàßo¤ÚÝœ§Û×îü5&sL'ªœÜß+½�’¦aSNìïåÑR•/îåÚÝœoÐ1œœ/qñ~NîóIZ‚fS9µ¿�/î癜/¶»9_Ñ=})Uå÷WRœÜ߇Û)#\$­Áí°qbo/¿½’f>Ukws€`¡lðßήpt¼‡ WÆvJZKÈçàØxŒ�ϯP¨˜ínN{hY‚�/$ ÉS ’-£7ìa¤'À¿ž[Ælóa[ø»«I*»äy>ÉÖ²{8„M±óÇé¶¶£m¼>�gv¥Æñ=ñ¶¾ÉËËÑÝ=<\¬p{¶}N™¶0™×ùôf–W¥ÇSÒF4›Ê‰½q>¹–&U¨·¥ [ÞûMSð‹ó+ì ËJ’¶ã÷8ó‹ ‰¶Øƒ[.ÀÏneÐ4;#ñí‘VNÒýŒõû±©vÎÜÊlù½·T€3+e&—8:.í>Igql¼‡Û³EfÕ-½ï– °fXüúb’#»b2cµ¤ãph6Žìêá7—Ôõ­[Šn™>½™!rËZ ’Ž%vö»8s{ë¶&¶D€ é÷çKì‰nÙƒI$áÀhŒ»�K[ªÖrš–àWW98&K„I:Í®r`4Êo/%·ä$}Ëqñ^·¦Ñõ¶üa$’f0ó¢iv.ÞÏ·ü^-`±brþ~�ýcÝ•,U"94áÂdŽbÕhé}Z*ÀOo¥�ûñºä†»¤»ð¸4†{}|~+ÛÒû´L€ËÙ:S‹Uv Ê@kIw²{(Äý¥2Ë™Ö9dZ&À?\M±w4,/’®ÅnSÙ3æ“­‹�i‰:¦—Ë”*&Ã=2ÜLÒÝŒôúÉ�–EÈ´D€gneÙ½#ܹù%’¡(kg?mÑ,Øt>X,QÕý¹í Ù Ä|Ôt‹©åJÓ¯ÝtþùN†=rö“l#ƇC|Ö‚µ¦ pj¹BÝPè‹t_¥R‰äE D½T«0½ÒÜY°©¼0™e—Ìï"Ù¦ì 4=±oÓ¸š«“ÌëôǤí'Ùž Æ},gë$š¸/Ø4ž»›c¤/(ë9H¶-ª¢°³7ÀÅû…æ]³)VL¦–ÊŒöË}?Éöf¤?À½Å¥ZsbD›"ÀÛ³úb4™áL²ÍÑì*Q7·¦JM¹^SsmªÈHo ­/F"Ù*vô¸>Ýœe覸¢£ò9Ûý^$’-!ìwa …Ç«›OÛ´¯Mî•¶Ÿäåb¸ÏÏÕ©ÍØÝ”ë†ÅÔR™á_»ß‡D²¥ Ǽ<\¨ ››K[±)>\, ¸ä‘#ÉK‡C³ 8y¸°9g̦”sg®$s½H^Zúb^&—7u� °¦[—†Ç­áumè•o B@¹¶öMJ�ºnaY†%Ðì*6›ŠËaÃçvàwk½ýdš‚B¥NéIÿ2-LS€6UÅ¡©xv¼n ¿GCÙDÿŠ…<<\ªÐi<lC½áár™=C�Z)Vt“%Rù ÙB� ÏNħñÙqùm8ìk/¡n*u“L±Æô’N¾d 8ˆÜ ļmOô+„ ‘­�È”IåªÔt“¨ßA4 óÙ°Ûm¸4 ݰÐ͵�faµLº¨cš‚XÈM,ä¦?âi{‰îºa­}“\™Õ\—ÃFįóÛ‰zmhv »M¡Z_T²¥*V dŠ:^·�ˆßE_ÄK4èjësäKuS%Òù*¹b��ÏNįñi85NMÁ åšI*_åÑ¢N±b 8‰Ü Ƽ¸��É"róp!ÃÛC ·¹aÖuA¦ ¬OíBæWKÌ®ä©Ö îðqt4ÄPÔ…f_ߨS7,æ“5-•9w{ ¯Sc¤ÏÏ@Ì·¥¹gªºÉôBŽùÕ"!ŸÆ�aß; t¬û¹²Á\¢Êä|‰‰©}QcýAÞõ_£¤rUf–s$³Uvö{81îcGO ¯k}f…°”©1“¨pg6EM·Žûíl©gÜ´�¯0,‹C;|¼º3Ì`ԉݶ¾ÎQÓ-æV«8¡§�H#L¯Tøãõ4ÍÎ�Ñè í÷;Ói†"*¯ï5t�†ø_Î,Ñ >7óÙôRžóYÞ?æÈhëOIצò|~;ËÞá0#}͹§nX\¸Š°L~|2ÖÐ2s£”k&¼–f!]ç•==ø=͹g*_åúƒUöyxçpxKJ„?^­òëËIÂ>Æ¢MP„€‡óYfy¾<ʾ¡Ö‡AZ–àâý<îå84eà99�–Re’ÙÿóÛ½ ]¿aþŸ¿œå{džpjßœ ,!¸þ`Ý0øÙëqBÞ­õö¥ :ŸKàu;8²+¶)¯V¡\çÒÝìðòÞá0j“g£ïâÖL‘On¤9¼3ºéXÛéå<�æ³|tª‡�}[[¼nXüîrŠÅt�“úpobÛÊ0-®ÞO Ù?9Ç·N[µY¬dë||.AOÈÃþ‘ÈS«‡ZÝä̵yþ�Ÿ�4t݆†ÂlQdžú”ø ÓââÄ 'üóûý[.>€ˆ_ã?~0€]±¸4¹²ærÞéB� ˼4ÌûG#[.>€Ã£>þéÝ>î̤˜[ÙøÉë{�3<^Éó?Ørñ8ì*wº‡£;}œ»½H±¢oè:uÝäÂÄ2½A;ÿë»ý[.>€Þ�ƒÿíÃ*µ×®b}kÞr:l¨6…|©±\1 0‘¯ôsYdZ‚‹“+ô‡íüìt¼é¶K#h6…¿+NÔgãÒ½•§^Òw‘-Ö¸<¹Âß�êáÀŽöžqì 9øçïõ3µ˜Ý�ï=Î�É—ùç÷û zÚ»÷øú¾ ï sáÎ¥ ^ê¦ÅËìpó£±¶f\wi*ÿôN›Åõ«OE¿<ùzC×lH€É¬þ /�pí~‚¸ßÎ_mïËùê�…�Nõp+Üx˜\÷ïJU�KwWøèdŒ±6ÌÏ"äÓø§wû¸?Ÿa9½þ€ß™¥<+éÿË;}-qm„ã>Þ<ââÄ25Ý\×o,!¸<¹ÂÎ>ï·û°Û~þF“;3©oü›Ïë ™k,"¦!.ekøÝ_Ï€æ3ØTÁG§:C|OPøéé8º¡óhñ»3›–àʽï3>ÐYñ­aŸÆ?¾ÕËÍGIJÕï^Â¥óU.dù§w;G|Oxu<À�ï3g�g11“&äµñÁ±Æƒ>Z‰MUø‡7{É*�÷…Ñl‚G Ùþ¿¥T‰T®ÂG';kp‚SSùùqîΦ)–×F¿ÛAªÐÂ0_¬ãqÙ1-ÁÍ©�ìYwäD;xìüà•(·%yž³7™«’ÎWøá«�5Ê~›Wvù‰øí<œþŒ>9›fÿ�§-—õ¢(ð“Óq¦–òÏuÊè¦Åíé?=݃SëÜxÓXÀÁ»‡ÂÜœZ3u¼n;¹V9aŠ»Ý†Ý¦òp!Ë`ÄÑ1¶Ò‹Ø7ä%äµ1µøt+KnO'ùþñè–ì�m–¼ez9ÿLGF¦P%™«ðN‡ØJ/Âï¶ñæ�w¦SÏü÷{sö z[ÀÑLŽíôcW�Å/ƒï×ös×˺{]¾¤ãuÛ¨é&3KùŽ[—¿ˆ¼åÑbÝøfê€Ç+E">{ÇÙ}Ï#à±sjw€óOWk�œËð½#[³ÉÞ NŒÐ “Õì7³–ªKÉïéü�Öfô¼åþã –øÜvråõÏ‚ëþZÙŠ�Û©1½”çÀ°¿»s—žß&ìÓØÙçffåëYP˜ZÌñÖ�P»›×'vHd*ßpȤ 5juƒýÃÝ“ KQàÍÁ§lÁG YŽ�ûquðÒóÛôGœô5¯q; -C×?–Mœ;³+^Û×}5ߨbf1ÿ•-¸œ.ã÷ØеÿM#85•c»üÌ.}=˜L/æxc¨£ÏL>‹Ã>ªuƒì—N2ݰXJ–89Þ}eÞÜbz9‡Ëa'[\ÀÁºX*›Ôu“Þ�£-‘.›%Ðúì¬f×Ò‰/& ïP¯çwqtÔÇBª„ݰHf+]5û=AQàðˆ�…äš+!Yb´Ï�»Ã¶OÖÃp� U A¹¶þ,ië`Y7)WuŽŒvo죣>SÅ/;m•½CÝaû}›°O#äÕXÍVYL–ë÷t´·ðEó³˜,­�/L»ºÚá£RÑ)×[ ÀRÕ¤PÒÙÕžÏ籫ßC"S!™«Òuv�ÃâYìp“ÌUHå+ìèÞoòÚq;T2Å*Ùb�‘x÷>Ëø€‡RU§Ò@íÀ†¼ ¯½+—Oxì85•åT‘±ÞîýУq7©|…Õ\µáC �ÆhÜÍÜJ�þðúO±w"½!uSP¨´`¢R7ì2‡Å³Œ:É—ë F;�éEôEäKuv¥«<ÒÏb(æ$[ª3ÔÓÝßDQ ?ì¤Tn� =�ö&Cj=�rÍ ØÚ,ÍFUÜN‘&¤Æh7¿˰ˆnƒþ hè œÂY·U"þîA^÷š×íè^ûï .Ͷ-:mÄoǰ¬m1˜Dýj+h!¶E§Už:PÜ­ØTðv±Mþ‡]Åtµá n§Š¢¬_'ë ]í5üê�ptß6æsžEYwjÇNDzÄWya»§]E(-˜ j÷ëïˇîþ kF;34›n‹äyæ3¨JC½kÝ’RÐ�Í•ãí õõ;©:ÓRž 0ïVEA7»ÿYê†E#*i@€ µmð±…P0¶Á‡^{‹ê6…X3 jz÷?Kݰ t¯õoCX‚|Ç,:•šaQÕ-,k;|lA¶Ðýß$_1°©Ê¶è_¹’A#™>×-@SÒ…�¥•ë$2E—f#ÛàÉåN¤Z7I7yß©¤ :ªªn‹þ•ÌëЀ¸nÚ…¥tc)×:‘•L¯ÛN"×ÝÏRªšXb-Wk·Ï櫹:n§�ålw€D¶Ž­�Ý”u ÐåT™OU7\ ´0-Ár¦F,àfv¥ÚîælŠÙD…xÈ�ÏmgiƒÅ!;…é•*}as‰�—zîªu‹\ÙÀÙÀvݺÿ§Û¡â´Û6\ ´˜OÖxmìè/3Ýå{z¥J4¬ 9˜^îÞÁÄ´ É*£ƒº!ºÚ4˜ITú¸¨/¸~ºì¼&æJí~Î 31Wd0nÑÍcX‚åLw.yLKðp±ÌØPš‘�"w7Ñ6ñh©B$  ,3·31Û½Ïrg¶„ßåÀël� èÖT>wæŠ §|ï Spo¾Ä®¡µ™o´_pkfãuÚÉÃ¥2A¿‚Ï-è�Ö0Lѵ+“›3F‡Öfðñá2·ºT€ÕºÅ\¢‚×£5R·núÝ* >·Æäãî›oωmxÜkƒÇîá wæJÔôîÛ¼x?Ï®¡¯—�»†L¾¸ŸßÄÛC¶dð8Ye¤-2¢'l Áôr÷™WåéïqÒ.àuµÂtÚ©&»Bœ�Èv•3F8?™ãÐø×�ÖëôÇàÊÃîê¸ ©*ù²ÎÈÀ×á<{G«L-WÈtÙ–Äù»YvïüulüÁ�uÎÞͶ»i ¡›‚Kò/àrÖ*ön=vL¡36¼‚ªÀ�¹îY*\}”ÇíÄ#ß4ðí®pé~¾¡Dªíæ�×3×ùëPÍ{†-ÎÜζ»yë&•×¹·PæÀØ7—Σ:…ŠÎ£¥õ£i7_Læè�¨„ý&•ª ÔÀ±ªu 0àµcSj¨¶*'ÕøÓ�4Õ’Ï´‹RÕäì�,¯îÚSô Fº™ÙÀ•·žÓê¦ÎÎÁ§gºCãU’fºÄ»û»«)ï2qhß\J) œ:PãwWRè¬ñ¸•d‹:—ä8¶omÀÈ•T‚ d \ÿ è¶S®®Í±�Î`\á߯¥Öûó¶ñÛ+IÆ!xö,wdo…éå2Snw<©½þÚáê3‹•ØlðêÁ¿½œêx»öÚT�r­ÎžÑg;ŽúzL"!‹3·:{`~u)ÉÁ�às¯½óTÞl¨0κèsÛ(Ö¾‘N(±˜©rk¦s—¢—îçIëÛûüåŒfƒ7�UùÕÅÕ†’él%–üâÂ*ûF "�ç‹k(n�˜üúÒúë"n5«¹:gn¥yãxå…U�^;\åÞ|�û �»ýóDÃÒÙ¿óëÁ;—W* ×Ð ?‡êÀk?±Ùà­c>¹‘f>ÙyÁ3+ÎMfxç•ÊwžcŒG,öŒ˜üë_V¨wà‰�ß_I¡ÚêØõÝû–'THªüe"Ûîf?E©jòÿŸ]áä� ÷ÅËK‡]ðæ±¿½²Ú‘aƒ“ó%nLxë¯!T4[ci5`Äç Zýzz ú-ÞgÙåy~{e•÷OTé�<í/He¡'ØØÇRD§óeƒ_^šç{'žý"SYg¯»ØÝïáý£‘-Ër¬‚?\K1—,óÎñ*Aÿæg¯»S&¦íüèÕ{·®†Äj®ÎÇçD‚&§V:Úò,êºÂÙë°ìüôt�-,]}õQ�Ïog8y ¾îeç‹H¤TÎ^wqtÌÏÛ‡¶®TU·øÍ¥$ÉB�·_©àŽYó»sNþñ­H”Ü�þ¯_Íò³ïUž{äP7àÂMÙ‚Ê_‰¶¼ŠîƒÅ2¸–"†“ËØíÍéW³6Î]wÒvñáñ~wë:¯nÎÞÍrc*Ï+ûtv5wö½óÐÅÝ•×÷9¹'ÐÒΛÊëüîj’rMçÍãÞæ}“jÎÝðR«©üèÕhËËËÝ™-òÉÍ4ý‚W÷?ß¡'„ÊÇtòŸ~:ÒÐõàÿ÷Ù2§Ž”q:_¼_Hh\žÐˆú¼u Ôô5›¨pv"K¡¢sâ`�¾hk–‹¦ ·¹x0§rdÌÇk{‚x]ÍË_©›‚ëS.LæˆGÖ>ò_öͤPR¹xÛM¥¦ðæþG¼Mb¶¨ó—»9,–8¼ËbÏh�Vé|vQãê¤FÄÉ[Bô…››ÖþáR™³Yê†É©ƒ5bá÷¯jÕÉÕ 7ÿøv_C÷iX€ç&2hÞý±ïÞŸ±,x4ï`bJÃë²qtÔÇþa® &ø­ÔL&—¸1]¤¦Øe06Xg+2ó•« wz˜Y²ØÙçáȨ�Ñ^÷†;ØJ¶Î­™"sEbA…C{*/Üãk&Ë)�Ûœ+‚£c>îðm8ë¹i .•¹9]d!Ue÷°`ÿÎÚS.­À4áþœ‹Éi•°OãȘ�½ƒÞ —j+VLnϹ5SD‹ƒã5vôëúÆËI7F%Èé}¡†îÙ°gnÌ­òÊþõo�  ;3‹NW-¢~�±>7}a'¿FØg*¿¥i­å It3ufV*d :ƒq•±¡*ýQ³e£ë‹¨é ÓófíÊÃ=.FãnbA�ˆO{¦�U©[¤ :É|�¹Õ*³‰* #‚]Ã5üžö8H2y•G�]Ì- š�Ѹ‹¡˜‹¨_#âמêÈB@®l�)è¬äÖ¾ÉbªF$hct ÎÈ@½!om³°,x¼â`zAc%e;�»é ;ˆú5B^;ê·ú—a~Ý¿Ò5fV*äËC½*;«ôF ʸv×ÃñÑxÃ+½†h˜‚ÿû7³üìý�y´L’YKI�|Q%W„BÅBQ@ûÒió$ÿ¨ß£ðBÈoÑ×£ Z•¸ZSXIÛXIjÊ ¹’ \µph vUÁ‚Z]àÔ•€O ôÅŒ¦ÚEÍ SPXNj¤³vòe…|ÑİMÁ¦(èæZ iŸ[%àUúLâƒÞ¨µ%³Ýz1L…Õ´ÊrZ#—WÉ— X±PTpØ,!0L@È«â÷BÈoÒÓ‰†¬ ­¦ðß?qò¿ÿx{ƒÙãö*Øm >—F]·ph�ïËØlÐ5ŸaLŒ/ÿJ³ÓQB{.§`¤ß`¤ÿ›ö�n€i®eï¤Îù"Â~AØ_¾þ¦B€n(XØì¢-³[£Øm‚þ“þž§û—n®eß¶ÛDSûW­æ$àv5,>Ø€v ¸Iå-ú£ÍÛµÙش˽SÐì 5ÑÛ.¥{�ïâëþÕüçIfììؘ“qCãÀÎ>/3 í�‘H:�™%Áø·Û6$ÀÁˆ“ÅUËÚ&S–D²A,¡²’ôE¶pTØs’/vwIa‰d³‹NFbߎڰ)ºgÈÃãå.ð”H$-d>¡n*Tqà ðò`ÞÑý5Ý$’� „Âä¬Åxè´« „�äK­�Å“H:•|ÑÍ`Ôµ©ÊÑ›ZCñ1µ 1’—“™E…ƒ;¼›ºÆ¦8ÞïáÁ¬‰°¶IÑu‰d�aãác‹]ým Ã®2Öïf5'—¡’—‹tÎÅXŸç«ðÉ�²i7æñ�~î>ÚÑÉz¹;-xe—Ó×Ù´GânŠE…z]î J^tÝA.¯6åŒkS6òŽîò1µ°±ódI·1³`çhf?h’�ø¹ùÈÄ’ÎÉ6Ç6nL ŽŒúšr½¦Ðç¶±»ßÃrªµù_$’v³’t³»ÏÓPöëÑ´X²×ö¸2a ddŒd»".ß59µ7дK6M€ñ�“ ×I&·u)ü$’­$“wö:é 4ÏáØÔhê7ö¹6‰Œ•lKn<€×÷›zͦ p´×�iªd ›‹�H:�bÉ�¡Û‰7×ÏÑôóDïse9 J¶ ¸xGá½Ã¡¦_»éï÷ ¢’ÉK[P²=Èæ¼`Ùím~Ÿnɉڷ…¸4!ä,(éz„P¸4ï·äú-àh¯‡ÍN"-mAIw³šöáÔšoû=¡e9%><å/7,,K†¨Iº!l\¸eðÁ±hËîÑ2ö†œŒõy˜ž—G•$ÝÉ좛�}^z¬ù×-ͪô½#!®Ý3ÑuyRBÒ]膃+“ïj�í÷„– Ðë´sz_€ë÷ä2TÒ]\Ÿtrz_¨i1ŸÏ£åyOí �Î*¤s͉—HZM:ë#™…“ãÍ9rô"Z.@UUùñÉŸ_µ0¥CFÒᘦÆÙkÿáTì©’f­`K2ëöGœìôrç�tÈH:›ÛSNö ûš^q÷ylYjëw‡™Y2)äRTÒ™ä‹kE‡Þn±ãå¯Ù2:ì*ÿáTŸ^10M¹•t¦©ñÙe‹¿=ßt¦³FØÒâÃ=nö ¸:é”aj’ÎA(\Ÿtqp$Àh|kͤ-¯®òÞ‘0™¼Ârªõ&‰d=,&ü¤²ðÖ�Жß{˨ª ?9ÕÃÙëÕšÌ!#i/•ª‡s7 ~özÛx=¿M[ê‹E><áó+*–�µ%$íÁ25þø|p»¢±«ÏÉÝÍM¬»Y:J€ß?ÃçpqéŽÑyÍ“t–eçüMŸÖv�ç³èÈþã“1Sãæ=¹G(Ù8–°qé¶»jçoOÄP:°+u¤~r:N©äàú¯¬¸$i!l\½ãÁ0müìtUíȮޙ„µ=Ÿ¿ÞC¹¨quÂ#—£’u#„�Kw<Ôëvþáõø–œlß(ŠB´»/²,~u)EݪðÚá*Šbµ»I’FXv.ÜraGã'§;[|Ð~}i•šUãÔ¡ Šb¶»I’d-Ÿ‹“°ÇÅ�:Ôæû6]!À'üáZ’ål™w^Õ±Ûôv7GÒA†ƒO/ÛÙññ7Ç;ÏÛù<ºJ€—ïç¹ô0Ã^·p8jínޤ¨ÖÜüþ<œÞâÕÛçû.ºN€÷çËüþZ’O |žJ»›#i#¹‚�O¾°øÑ‰»;(Âe½t¥–Ò5þõü §*ô÷”ÚÝÉ#Px¼äçÊ„É?¼§‹Ò6›® @¡bòñ¹¢a“£{ªÒ9ó’` 7ï¹Hålüýëq|îöŸjØ(]-@ÓüáZšål™w_5phÒ.ÜÎÔë.>½¢2óòÁ‘HÇo3|]/À'Üž-ò§[iÞ;® É%év$‘òñç�p`Çö8À½m�*ÔùåùUz¢G÷ÔPU£ÝM’4˲qó�‹DZåg¯ÅÛ–@©l+ÂÚ’ôÌí  ¼{BÁç)·»I’MP(y8sE°o0À;‡B]¿äü6ÛN€O˜ITùÍ¥»w¨ì« JMWaY6îN»yøØâïNõ0ܳ=sÈn[è¦àÏwÖfÃ7Ž)„r6ìrEg®XŒõxù›ãQö툿­ø„¥t�__L Ãñ½u4é)íH SãÆ=É´ÂßžêÙ²aíä¥ €e .ÞËsñ~ŽcûTÆePw§ „ÊÜ’‡+w-^ÛäänÇžßk6/�ŸPªœ¹™enµÄé#*±P”—êtB!•õpþ–ÅHÜû‡"-¯ÉÞi¼t|ÂJ¶Æ¯g¨›u^;Ÿ´·’|ÑÍ…Û N»ÆÇ¢ôínR[xiø„ùd•Ïn¥QlG÷(„ür¿•”Ên®ÜS¨Wí¼{8ÌXïöôn®——^€O˜Z®pævÍnr|¿IÐWmw“¶B![tq宂0ì¼w$ÌèK.¼'H~‹ùd•sYrõÇÆUúb2È{£¡’̸¹²ïõðÚÞ±Àö k&R€ßA©fpk¦È�©~¯ààN…H¨"“C} !TR3P(¨ÝåçȨï¥ój6Š`<^­rõQ�é•2{†UƆLüžÚË»�! %'sË*÷æ£q¯ìò3Ô!…Oº)À  ›‚‡ %&æË,eJìÝ¡2¿·¶ígFKØ(Ì-«<˜µй80âc¼ßƒÝ¶½¥·)ÀMR7,.”y°TanµÂ@vô ¢A‡Öý6£@¡^ÓHåìYc.Yc1S%ôGTÂA�Ïcáv¨êÖosÀ4íTªÅ’B* I‹bQ¡/âb¤ÇÉ`ÌEÄ)—–-D p‹É— ù:É\�¥¬A*W£ªxݱ � <.p:ÍB³[ØT E¨ë´/…¥bZ*†¥bè uC¥RU(UùŠB*c’/)øÜvzNúÂ=A'ñ †ßÓ½ Žº)À¡\3Éur“\Y§X1)וšA¥&(×M,K`aa K ÙAU,¡€PQ»ªàrØp;<.;nMÅçQ z4‚^;A�]ntR€I‘.,‰¤�HJ$mD P"i#R€I‘”HÚˆ DÒF¤%’6"(‘´)@‰¤�üæŠÈ”!c¯1%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00·ÍǾ÷Ûç{®F’$ AüB+÷!�‰€ ‚‰€ ‚‰€ ‚‰€ ‚‰€ ‚‰€ ‚‰€ ‚‰€ ‚é垀 (�$Á†å”VÛ1t<�àh“WÇŠO0AèÆáóVN_´QcsQZcgÛáJ¯�„n”UÙ‘$Mû¿íNï— B\n‰2«£ýß- ŒñîòÄ=˜ tÊã‘ør_¥5ÌF-É ¡ Ž aÌp‹×¿CLn@’`ÃþrÎ]m"Ô¨åÿ&'k1ôø÷ˆKDA¸�ÍE•œ¾ÔˆQ¯aþ½‰½ ˆ€ Â/ìú¾Š#çëÑë4̽'�Ä(ïï¹®P—ˆ¶3g¨Û³�ÛMxj*Q÷Ý'÷”•Ù{ª†‚­h5ðȯãêÓï ˜€I5;v઩Àj³:b!C†È=5A%ŠÎÕ±ûx- ÌOÚÀ0ŸgÀ\"J8�íÿö47c¯ôþ A!¸�(¶±¥¨€©cb¸yˆ¹O~oÀL‚>.éÂ|ÿ?�ø~¼ÒÀ¦ƒLº-ŠÑ=(Ãw'`�0gQ÷ÞKHRU[·ânl”{Z‚‚—7²~_’wß2€q7Eöéï×ä¶m’ÄÕO?¥ùâEBÓÓI|ôQ¹g$(ÐÕj;ÙyWq¸$ƤE0uLlŸ¿F@}‚µÓhˆ›5 mHM?þHý‘#rÏHP˜òZ;kòKq¸$nM6óàè¾jÀ½ÅBì´iTmߎ£ªJî) Qcs’“_†ÝáaDRý*�Æ÷ß{#0sFá·ÞŠätR¾q#’Û-÷”™Y›Üäì.¥¡ÙMr|(³ÇÆ¡Õú/0€˜©SÑGEá,-¥:?_îé2j´»ÉÙ}…Ú£MÌ�^ïß|À´F#q? Z-Ö‚‹‹åž’ÐGœ¾÷ìŽÝé!'¿”*«‹¸æOHÄèçpA dà@"Ç� rÓ&QºW9‡ÃÁ+¯¼ÂÝwß�7Ep—[âóïÊ(«q®gþ„DBŒý󧈺ûnLÉɸm6*¾ýVîé½àñxxÿý÷3f ¯¿þ:¿úÕ¯ÐtS�hëéºXÑLx¨–Ç&$Ú+ó{°N¸êë¹üá‡xìvb§M#bôh¹§$xA’$V­ZÅòåË)((Àívc±X8qâƒîâ8X_PÆéK�„µ,œœDL/ÛNz+h>ÁôÄLŸ@Õ¶m¢t¯[¶laùòå9rwk%øþûïï2\ðËž®þYÀÂ329Éå¢ü«¯ð¸\rOIèÆÔ©SÙ²e III„‡‡c0X¸pa—Çìi;é­€éë �ÑHüìÙ\Y¹ë�„JXZšÜÓn@’$žyæt:YYY477Ùi¸ŠÎÕ‘²o{º|”Ÿ`mj÷í£&/mXƒŸ|]x¸ÜS®³téRòóóÙ¾};fs×=Z'Šml,li;™–Ó§m'½t÷`EŽGhr2žÆFÊss垎p�7ß|“o¾ù†ÜÜÜnÃuMOר¾íéòEP �†Ø™3ÑšL4Ÿ?�õða¹g$´úôÓOyûí·ÉÍÍ%::ºË±{ºÆß<€q‘rO¿]pŒ–Ò}ìŒToÛ†£¢Bî)½mÛ¶ñÒK/±yóf†ÚåØËÕvÖ}WŽÛÓÒÓ5ad´—¯Ò?‚>`æ›n"â¶Û�ÜnÊׯ¥{²`ÁÖ®]ËÍ7ßÜåØŠ:Ÿå—âtIÜšî·ž._ˆ€µŠ™2Ct4ÎÊJjóòäžNP:{ö,¿ùÍoøøã�ߺv´356'kv—vèéŠñ[O—/DÀZi:¬º¯+,¤ñÜ9¹§T®\¹Â<Àk¯½ÆŒÖKöÎtìéJ‰ñ{O—/”9+™˜‰º÷^*¾þ·Í&÷”‚B]]3fÌà¹çžã‰'žèrìõ=]�ŽOð{O—/”;3™DŽ+J÷ý¨©©‰Y³f1aÂ^zé¥.ÇÚ�>Ë/ë÷ž._({vrÐhˆ{è!´!!-¥û¢"¹g°Ün7 .dÈ�!¼õÖ[]Žu¹%>ßSFi�½¥§ëÞþëéò…òg(�ÅB\ëªûêíÛq”•É=¥€Ó¶ª®®Ž¬¬¬.ï¡<‰/ö–s±²™ˆP]KOWˆ:Vù‰€u"즛¿ýv$·›Š�‘Dé¾O½úê«=z”¯¾ú £ÑØé¸–�Wp¾´‘P“–ÇîHdxÿ·�ô–Xbï¿Ct4ŽÊJªví’{:ã?ÿùŸ}ö›6m"¼›õŸ›‹*9}±¡¥§k‚<=]¾ëBÇÒ}ýÁƒ4œ9#÷”T/''‡üãlݺ•øøø.Ç*¥§ËA°+W®ôh¼)1‘èÖÒ}en..Qºïµ�;w²dÉ6nÜHJJJ—c¿;YËþêÐjá7¿Nðù9]r ª€�={–ÌÌLJJJztÜ€±c IIÁÓÔDå¦MrŸ†*=z” ðùçŸ3º›½PŠÎXÉ?QÓÒÓugê3\dKKKcéÒ¥Ì�;»Ýîý� ñ=„64”¦âbê’ûTTåܹsLŸ>�wß}— &t9öD±�-GZöJ™zG,7Uw�^P àOúC† aéÒ¥=:NAl[é~ÇìåårŸŠ*TTT0cÆ þö·¿ñh7O¹9s¹ñÚž®arOßgA0�FÊ+ÈÍÍåÿû_�Ž5§§·lõÖºê^”î»fµZ™:u*�?þ8‹/îrlqy#_”+²§ËA»eÀÑ£G™2e yyyݶEt$9�\þøcœUUX23‰yðA¹OE‘3gÎ$--�÷Þ{¯Ë±—«í¬É»ŠÓ%‘™Áƒ~xN—\‚î¬Ím·ÝÆk¯½Æ¼yóhìÁVÚƒ�¸Ù³ÑètX‹Šh<{VîSQ�ÇÃÂ… 1›Í¼ýöÛ]޽¾§ëötù"hðÌ3Ï�™™ÉÿøÇgŠ�¿fÕ½(Ý_ë…^ ²²’5kÖ Óé:×±§+=)T±=]¾ê€¼÷Þ{�••Õ£ãŒKXjª(Ý_gÙ²eìÚµ‹/¾ø“©ó/†­MnÖäuèé— Øž._Þõ�ÙlæË/¿ä•W^áp7½‰�1mXMÅÅX”ûTd·|ùrV¯^ÍæÍ›‰ŒŒìt\£ÝMNÞUê]$µötétöÑÕ*è�žžÎ[o½Åüùó±Z­^§ 'þ¡‡¨Ú¹{¯ºß°aË–-#77—ÄÄÄNǵ÷tÕ;‰``ž zº|¸gÖC�=ö“'Oæé§ŸîÑq¡Ã‡ci+ÝoØ€Ôƒ‡Âм¼<ž~úi6mÚDzzz§ãÔÚÓå‹À>»ú÷¿ÿ͹sçxç�wzt\Ô”)ââpUUQµc‡Ü§Ñ¯Ž?ÎüùóY½z5™™™�ŽSsO—/DÀ:0™L¬[·Ž¿ÿýïìÝ»×ëã´z=q³f¡Ñé¨?|˜†”ûTúÅ… ˜6mo¿ý6<ð@§ãÔÞÓå °ë$''óßÿþ— PYYéõq¦øx"'N ò›o¾t_YYÉôéÓÛ×vv¥­§ËdÐ0ÿõõtùBìf͚Ŝ9sX´h�Çëã"ﺋÐáÃñ45Q±qcËÿºPcc#?ü0�=öÏ?ÿ|—c;ötýv|"‰Ñêëéò…X'^ýu¬V+o¼ñF�Ž‹�1�ÙLsI µÈ}}Îétòè£�2jÔ(–-[ÖåØ=¿èé ‘{úýN¬z½žììlþõ¯±mÛ6ï�3›‰m-Ý×ìÞ�£´TîSé3’$±xñbL&ï¾ûn—c‹ÎXÙ =]¾ëÂàÁƒùôÓOY´hW¯^õú¸°ÔT"ÆŒi)ÝoÜ0¥û_|‘ââbrrrÐë;¯+©¨ž._ˆ€uã¾ûîcñâÅ,X° ýÜÞˆ¾ÿ~ qq8«ª¨Ü¾]îÓðÙ?ÿùO¶nÝÊW_}EHHç—zg.7’[ØRš|{t@ôtùBÌ ýë_1�ÝÞst¤Õë‰{øa4z=¶#GhTñ†9«W¯æý÷ß'77—¨¨¨NÇ](kjïéºçÖ(Ʀ�{ê²ó‚V«eÕªU|òÉ'|óÍ7^gŠ‹#ºµt_ñõ׸z° K)6mÚÄÒ¥KÙ¼y3C† étÜåj;_ì-Ãíiééºç–H¹§®"`^Š��'''‡'žx‚ââb¯�³ÜygKé¾¹Yu¥ûÓ§OóÔSO±aÃ222:×±§käÐÀëéòEÐv4÷Öo¼ÁºuëÈÏÏïrGÚŽÜ��\^±wCQ“&9nœÜ§áI’8}út—ß56'«w^¥¡ÙMzR(�ü:> ÛNzK¼=´téR ÄË/¿Üþ³ÚÚÚ.�Ñ……סtoïAERN�¦ËpÕ7º‚¢§ËâÝè!�FÃG}Ć øüóÏ9yò$sæÌéö¸ÐÔT,™™àñ´<¦Öá�ûT|Òhw³fwiPôtùB\"öÒ÷ßÏ”)S:t(ÕÕÕœ8q‚°°°.�‘Ün®|ò Žòr"F�&vÚ4¹O£WìNÙ»®PZÛÒÓõÿ&%|ÛIo‰w¥vìØAVVƒ�¢¢"JJJÈÎÎîö8�NG|ké¾þÈl§NÉ}*=ætK¬ÝSJi­3hzº|!Þ™^ˆ‰‰áÔ©Sí«í%Ib»—_&bc‰ž<€ªÍ›UUºw{$¾Ü[Ê¥J{PõtùB¬n¿ýv¾ýö[Þ|óM† ´tõz»ÒÃrÇ„¦¥©ªtÿsOWskOWbÐôtùB¬—4 Ï?ÿ<{öìaæÌ™TTT°e˯��k[uñ"uû÷Ë}:Ýúö`?\ÓÓåÝWÁNÌGIIIlܸ‘>ø€cÇŽy}œ.,ŒØ™3¨Þ½ûåËrŸJ§v­æûb[ÐötùBTeV¹};õ…… éÉ'Ñš”õÇ›¼šïNµôt͹;1hÛNzK|‚É,fÒ$Œ 8ëê·aΡ³V¾;U‡F��áê0™it:âgÍjYuÿý÷4(¤t¬¤ž­‡[zº¦ÝKÆ`³ÜSR%00ÄÆuß}T* tÿãå†kzºnòž._ˆ€)Ä€ÌLÂFŒÀÓÜLù† ²•î/”5±¾µ§k‚èéò™˜‚ÄNŸŽÎlÆ~é5ýþúW*›[{º s¸…ñ¢§Ëg"` ¢ #nÖ,jwï¦ùÊ•~{íŠ:9ß•µ÷t=˜#÷ÛDÀ&4%Ë]w�$Q¹~=žž<¬½—®N׌;E¸úŠ˜EOœØ^º¯öó†9¢§Ë¿Ä;©@�ŽøGAc0Pô(¶“'ýò:�v7Ù¢§Ë¯DÀÊELké¾jËœuu}úûíNŸí¾Ju�<§K.âU°ˆ1c0gdôùªûŽ=]Q¢§Ë¯Ä»ªp±Ó¦¡‹ˆÀ~éµûöùüû~ÑÓ5Qôtù“˜ÂiCBˆo-Ý×äçc¿t©×¿ëF=]ÂDO—?‰€©@ÈС ;$‰òM›z]º=]ýOL%¢&NĘ˜ˆ«¶–ª­[{|üŽ#Uí=]sï=]ýEL%4Z-ñ³g£1±?Þ£Ò}þñjœ±¢Õ£wÇ386øžÓ%01DEÝaÕ½³› Oá—=]©‰aÝ#ô0•±Œ�ù¦›�ìönK÷ÇEO—ìDÀT(vútt öË—©Ù»÷†c~¼ÜÀ×í=]Q¢§K&"`*¤ iYu¯ÑP»gÏ/J÷Åe�?÷tÝÉØôH¹§´DÀT*tÈ,7(Ý_©lfÝÞòŸ{ºn�òñ•_ˆ]¥TÌãñPºjö«WqEÆa�Ê>M 6�ž‘)á̼3Nî)=0•sÖÔpiùòöbG­1’â»fóÈø�hÄÂxÙ‰KD“$8{µ·F×þ³N+úZ.…«TÝ”$. •FLf¶&§/5r伕J«³ýç‰Q&F§FpË�pŒ†ÎK‚öÊJ$‡½Å‚><\îÓ®#&I‚’òFŽœ·ñãåÌB”—O�´·nN*>½”)è¶ÿ~æÍ›‡½ui‘F£¡¹¹½^Ï”)S¼z˜yoUÕ;8V\MÁB«…ቡŒJ‰ =)´Ç{¶̘˜(Ó;*t%è6vìX^}õUž{î9œÎ–K2“ÉÄ¢E‹øàƒúüõ\n‰³W9rÎzMÁ":ÂÀmÉŒJ5c6õþ?ƒ£µÀ2hP?¿“‚7‚&`v»�-[¶°jÕ*6oÞŒÅb¡ªªŠAƒ±lÙ2/^ܧ¯×V°8ù“ GkÁ¨×0b�™QÉfR|o|”\. Ñ`JH�å}ºð;tè+W®$;;›ôôtüq>úè#-ZÄ©S§x÷Ýw™8]|ÿ¥\°ššÖ®]ËÊ•+¹pá¿ýíoÉÉÉáŽ;î¸áø¬¬,Ÿ^ÏÚàâäO �·bmlY¨Ñ@J|£‡[HO C«õïŠ[G[QL±T°ë﫦N�ÊË/¿ÌôéÓÑëûþÔ\.gK›~Q°ˆ ×sË3·§Z°„õß[jo-pEÀK•k»¯Z³f #FŒàñÇgÅŠDDøg߉Ò;ÇJlœ(±Ñìh[¨aDR£SÃû¤`ÑS®†\uuh Lq¢±R©T°’’Ö¬YÇ~ˆÑhdîܹìß¿ßç{¨Î4;Üœ¾ÔÈásVÊjí?o+XÜ<ÔŒIƧ‘´/�8Ñü¥\ŠXmm-6l`ÕªU>|˜9sæ�••Å=÷Üã—×k+X+ià‡K ¸Ü-‹ƒ–Œ!f2S#ˆ�RÆŽ¸öÖ‡Q¬àP4ÅìF÷UK–,aÚ´i þyPA}£‹% ¹`¥¶ÁÕþó¶‚ň¤0t~.Xôø}jý ÷_Ц˜€µÝWåää�––æ÷û*·[âÌÕFŽ×s¾´©½�1"TÇ­ÉfF³éåz@9´8DÀ”MÖ€ýôÓOdgg³bÅ ôz=óæÍcß¾} 6Ìo¯Yiur¼ÄÊ÷çm49®m`”«`ÑSŽª*<ÍÍèÌft‹ÜÓºÐï»Ñ}ÕG}ä·û*hi`‡ƒ¢¢"Æ�×íØ¶Gˆ(p(^¿ìƒ>`íÚµüîw¿ã�wÞÁâÇËšú&7'Šm¾PO]ÃÏëŘ•Á­ÉátÊ*Xðç?ÿ™‚‚‚nǶ8D‹ŠâõKÀž}öYž}öY¿ýþNw\ Õ229œÑ©ˆ4+¦žsC»víb¢ÖHnwË zÄ 5Pö_]7ª¬Ž•Ôw¹ã’Z¾ƒÍËËãÅ_ìvœ½¬ ÜnŒ±±hMʹÄnLuëéŽKjàp88xð W…GÛ zqÿ¥ ª X¯v\R‰ýû÷“‘‘áÕ½isÇ%R‚â):`¶f§/ö~Ç%µðöþ :ìÁ!>ÁTAqëË—Ô"//�^x¡Ûqžæf\µµhôzŒb½*(&`UõN–Ø8Zl£¾É \ßÀØó—ÔÀápPXXÈøñã»Û¾À71M¾�HÖ€uÖÀØW;.©Á�HOO'22²Û±v±ƒ¯êÈò×Û;.©E^^“&Mòj¬]l :ý°¶—ŠÎZ)¯ûec_︤yyy,Y²Ä«±¢‚¨>~ Ø5‹+ xZ¾ î——ÔÀét²ÿ~¯¾ÿrÖÔàijB†Á‹ËIAü0%츤`Ĉâþ+€õYÀ”¶ã’ôäþ«YL•|þ‹¯°Ú9QbãÈyå츤yyyüáðj¬C´¨¨’×k´»Ù|¸Šf»‹Ô�á˜ôšî¸42¹eéRˆ1ø =ár¹Ø¿?999ÝŽ•<åå˜D‹Šªx°õûÊ(©héþ©ÜNë BMZF%‡3jX8q±ºÛ[……… >Ü«û/GY’Ë…!:mˆz×\#¯fmþy·% 0‡jy`t¬"w\Rƒ]»v‰û¯ àõuœ%ôç,š úU<ƒÍ"\½”——çõ_‡xŠ¥jy°ÙãÈFr¼‰I#cHM •{îªår¹(((ðjý!tXA/¾`V¯/ÃL:ùµxÈ[_8xð ©©©ÄÄÄt;Öc·ã¬®�S|¼ÜSzH”údЫû¯„4:uuj "`²èÕý—¸®ÁƒóÖ[o¡éæ±/íK¤DQÕDÀúÁ Aƒ0™LhµZ–,YÂ-·ÜÒí1m»øŠfu÷`ýÀd2a2™HKK㥗^êv¼ÇáÀYUZ-F0UŸ`ý$%%…uëÖu{i­ßIƸ84zñÿ@5ÿõúÉ·ß~K”—Ë�b‹€€!>Áú‰·á‚9_0«ž˜5·m *ˆª'¦0.› w}=“ ct´ÜÓ|$¦0í98°eCAÕDÀF<,°ˆ€)LSi) (DÀ”D’D‰>Àˆ€)ˆ½²Éá@o± —{:BS»XApDÀ¤}‹l±þ0`ˆ€)ˆ£µÀ"¾`"` !¹\8**@£Á” ž(DÀÂ^Z OË z£Qîé}DL!Ú,E�# ˆ€)€»¾žºÃ‡0ŠG0™yìv®fgã®­ þèQ¹§$ô!0™5œ=‹³¦¦ýßîúz\6›ÜÓúˆ˜Ì ÑÑhL¦ök t­;P ê'¶ �YÈÀ�XÆŒ¡éÌ$­–ÈqãÄ>D#I’$÷$!P‰KDAð#0Að#0Að#0Að#0Að#0Að#0Að#0Að#0Að£ÿôÝ*?HÒ%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00|l©ëV�çêé_�ç<ç9GPUUECCCC#oèJm€†††Fµ¡ «†††FžÑ„UCCC#Ïhª¡¡¡‘g4aÕÐÐÐÈ3š°jhhhäMX5444òŒ&¬yFV �——ÍŒËnÂe7b1ÞÙÏÊ ±¤D4!Mdˆ$2D"õ. íõ&:êm´×š5¡­2²²ÊÐTš¡É$Ã3fÂÜNn»§ÝŒÛnÂi3¡× ·%•ÉMˆÄ’"‘¤H(’U¡©ÆBG½™%�vj]šÐ~MXYV˜Lqz·¯ÓŒ^Wx�+©L–`4M šb:”F`Iƒ•žV� Ö²²µT,ZaU…Á©4}ÃqÎŒ§pÙM4xm4øl8¬•ó–d…éPŠÉ`0E�ÇÈêv=­6ìæòy!h\L<%sj,Îñ¡ÓQ‰ÆZ+õ;u+Æ Z…Ä’S¡$“¡$ñ¸ÈÒ«Út5X©Æ.:a %$÷Ç92Ãj6ÒTc§¹ÖŽÅTùžž¢ªL‡RLÌÄñStÔYY¿Ô¹¨'x¹¡ªÐïOñö¹CÓš}VkÔy­çãð•LZÌ26“d"#�‘Y×é`]—Ï"‹Ë.a=7‘âõÓa¦B­õvÚ\8lÕû��•Ʀ ùcdå,×.sqM—³*^ •HZT8t.Ê[çbM:Úë]4×Ú1è+Ç3Í•XRbÄax*A³ÏÌæKm¥6«(Tµ°Ê²Ê±¡¯ŸŠ¡ ²¤ÙCs�½*<ƒ\ÇEÆÃLS¬îp°i¹kÑy¥"”�xãL”cƒqš¼V:[<¸í¦R›UTdEe|&AÿD=*[V¸XÝæ,Êæ[©¨JaU•Ã1^;Án5²¤ÙM�ÇZj³JNZÌ20eÄci«�½\6-["I‰=}aÎŒ&éhrÒÙäÆª­˜§87!•–¸~•‡µ�tU¸ÙUUªªpt(Æ+}!l&=^l”®W.ŒMÇ91¢­ÖÄ­ëk+>»b…UUá๯‹ÐÑìbi‹[KL^ ÓáÇú4{Œ|hc ‹½ñT–_½=ƒ?œeMW µZAÈŠÊ™‘0Ãþ;ÖxÙÐí,µIó¦"…5yúõDE`ÝÒÚŠJè/wdEåôH˜QŒ[®ñ±¦ÓQj“Ê’C1v ÒÑàbY›gÑeš\„¢ ÄÃè"„H}"‚ e@–$qö£Õ`D5˜�w ª»ÕáæýÖXRäȹÌz¸{s-5ÎÊË¢¨8a=x.Êîca–·zèlrUUÀ»œˆ&D�™¦Î¥çÎkë´*Gï�ÌÈ<}`†`B暥µ¸YêÔûÑüè&1L£›Cgµ¢÷ù°ÔÖ`ôzÑ™LF#:óì²’É Š"Š("‚ˆÁ R0ˆ’É@C+RCrS'ª·U…�ñ(çFÃìXëaýW©‡›#¬ïNèP\f}O�æ¥UU93fh2ÊÝ›ëXÚ´8’»/Çàd’§_Ÿ¡¡ÆÆÊ®šEé¥ ±0†�>ŒýÇÐél]]Ø:;°´·£³ÌoÃXN&I“"90€ª3 -YMvI/1ÁÂÛ§§¨qè¹kSå¼à+BXGgÒ<±wšæz;+Ú¼Z,µ¨LGR>=Ã5ݶ¯ò.ºU‚ªÂ®£AŽ%X¿¬Ž÷âË8ÑM�a>ºÝÌö•+q®Y�¹©© ÏJ�Ž=zŒäÉ“(Í�¤{·rZê´å5`6êÙÒÛÄ›g¢¼Ý-µ9Wå­³QÞ8cÛê¦Å•ø/‰X^ø Þ-›q¬^]jkò†kýz¼ëz¹yæ5Ý5N4%—Ì–’kFRøéîI:›ÜÚFU•a5éÙÚÛÈ+Çœ›H•ÚœËrf<Ák'Âlím\t ÍžÇÞцûÚ�¥6%ïøvìÀUëfsò?}ÅO&«”ÄŽ¢ «¢¨<¾w ‡ÃÄ’f-¥ª±Y�\»¢�§L3Δڜ‹ð3<{ ÀÆå ØYÍYý™Ã˜Â“ÔÝvk©M) wßEmhˆÎ¤ŸÇ÷N¢(Å×¢ ësgÈH°¶»®èƒÕ(§™Þî}uŠx:[jsÎMÉ<úÚ$k–Öâ­ò#¹DˆG0ÜEãÇîE0VoŽ®Îb¡ñž_cÙð^ä¤È o‡ŠoC1vx ÆðT† +êµU‹€æ;­uNžxm E)yV²¢òø«~:\4.‚>¦7wâÞ´ cMM©M)8ææf«V²%yœ³þGcE}~Ñ„u2œá¥#!Ö÷4`Ð/žÝ×ÅNO»EбóP°Ô¦ðâÛA�žemžR›Rtôcý#Ów`!øvìÀ4ÞÏuõ2;…ð‡Š–*ŠÂ¥E…Ÿ½2ÉÚê]‚h\šk–Õsj<ÅÉ‘DÉlèŽsv2Å5ËëKýuUÅôæNênÿ‚añÄ”u&57݈çØ+¬î®áñצH‹ÅÉ(аþò�ê}6šj´´ªÅˆÑ cCO¿|+@4Yüxk(!ñÂÁ —×/ª\ÕwÑ�Âh1a]²¤Ô¦Go/z1Ik6@�ÇÊ/gåTðYvt0ÆDDdegõÇu4.�Çafi‹‹'÷OS̳~ª ϘaI‹{Ñö§2÷íÇwÃõ¥6£4Þm[1Û˪®&B"}Ã…�·TXC ‰�‡BlX^¯µ¦Ö`I‹‡¬ ûO†‹öÌ}'Ȳ@wKuTßÊ�½šÅ¶ti©M)ŽÕ«ÑEƒ"3¬_VÇóC_9TXŸ{#°¨=� X·¬Žý§£b…?r8•8p:Ê5Ëo]_Sÿ1\ëÖ–ÚŒ’"èt8W÷bì?†Ûn¢»ÅÅ3oNô™ÖÃQÂ)™ní€Æû°š ,mõðÌ�‚>GUá™7§YÞê]T%/@Î"ŒœÁQ¡U«ò‰sÍôý} ªt·¸‰Æ•‚† "¬ÉŒÌ®Ã!Ö-­Ó:ªj\Ä’&i‘‚Ö8x6J& MÕÕÝ ô#g175¡·k›ÆFŸ£Ó�Î?„ ¬YZËηƒ$3…É(ˆ°¾t(@K½�C h\Œ ÀÚ¥5ì:.ÈÄNd²ìé sMwÝ¢ &p,[¼±Õb[ºÃÄ 0{2°©Öή£…ÉÈ»°úÃ"ý“i–µz ùiT8.»‰æZ¯ö…ó~ïÝÇ´ÕÛq,òœi�k{{©Í(líèýCçÿ¼¼ÃÇéÑTAä]X_xk†emÞE™/¨‘+:|M0ÉßFÖT(ÃÉáËÚ*«Øv¾âtY cmm©M)Ì--႘À¨×±¼ÃˇòïÏ«ú��“UÚo\Kcî :–¶xØy(E2^8dE§öb×ü˜ššKmFY!èõêë‚Sçÿ®£ÁE<¥rz<¿§ó6ûT^9¡§Ã·¨ãZ¹ÑÕèd:&22�^ð½FgÒã2õÚ‹]ˆ1ÕVfÿ±BbòùÐEß‹« ,ïð²çH8¯Wò&¬'Fâ¨Ô{­Eý¢4*A'°¬ÕÞc ÷Zw ÑÓæÑ2Q},ˆÉ§ ë1×\(¬�> §ÆòçµæEXUö ÓÓ±¸ãZó£­ÎA0)3¼¯up2I8)ÓR«u¤ÐÇB5a½£Ï‡>~ñK|y»—=GCyóZó"¬§Æôzê<š·ª‘;‚N`y‹›W�‡ç}�½Ç£,kõha¨wɤÑY,¥¶¢ìÐY,�¹ø^ïµ":Îä)ÖšaÝ2B×"=‹­‘ZêLEE¦æ‘ú2™‰‹ZSÊ÷#‰èLZùÑ™L�½tJW³;o†,¬£3)bi™F­}µÆÐ ]õ.^?�ûi¬ý'"t6ºÑiîêyTIDg^\­gæ‚`6#H—Ö¦Z;Ñ”ÂøÌÂ7R,¬¯ŸŠ²¤Ù­-Á4Lg³‹³ãIâ9´-ާ³œ�H.꣫—BPU´_Ê‹t:¸LsAA€Ž&¯ŸYøQë k<%34•¦µNÛ0ÐX8FƒŽ¦ZGs(Žqt0Fk� £ÖîçTƒU’JmFÙ¡ˆ"/"i¯w00‘"‘YXYÁÍÆcC1šjm‹>[#´Õ»xûìÜ…õísqÚ´ jD0™fEDãQD½‚°Î¾Ü­ZØ&Ö‚ñí�8Ú¤ÖÈ#^—�^`h*uÕk&SèÐáqh±Ä‹0˜P2ÅkžW)¨™Ì=V€¶‡rx¹_Šy ëèL Uð8µI­‘_Zj�™C»â#ý1ÚµØê¥Pì.²‘üìpWÙHÅvegÐç² +,hkÞÂz|$A³–Þ¢QZêœO!Ë—ÏÖ–e•sþMµÚ¼²Ë‡Ê_ †jA ‘�W?8ÑTkçÄHrÞÏ™—°ª*œMÒ¬Mj�`1éqÛLôO^~bŸó'q;ÌXLúR›[–(.™™Âvi¨DÄ@Õ}uam­wpb$1ï“XóÖÑ™½‡uq×»Ô(MµvŽ�\~¡o8As­–;}9TOâÔÔÂoTeˆSS(žº«^ç°ÑéuŒ®ë¿óÖÓ£)j4oU£p4ÖØO]ÒcP…�© >m^Å×€‰ §æ' Õˆ ¢(*ªÓ3§ë›jlœž˜_8`^Âzn2A£VÅJ£€XMz,=�‹7Æ"v³^ \ �µ¡•ôðp©-)ÒCC(Í�s¾¾ÞgåÜÄü6°rÖX2K<¥àÖR\4 L­ÇÆ9ÿÅW¿?I�WóV¯†ÔÐAr`°Ôf” ‰Á!䆎9_ïqXˆ%²Är8 ø.9 빉$�^«vZN£àÔ{lœ¿x)vΟ¢^«¤vU䎒'O¢Ê…éDZI(™ é�²mso®(Pç³20™{8 gašÎàÓÂEÀç6ˆKˆÙ÷Îvg$…`T«­˜®Šêp£xjIõ÷—Ú”’“8u ¥©̹iW­ËÊÐTîáC®�I³i•§d_ÐbåÍý{LOžÿ³×WKÇ’e44µ–Ú´‚¡¼Nc� ] ³¿c� 5n“Ö%`ŽH]½D�ölY©M))Ñ£Ç�º7æü9¯ÓÌÁ“áœ?—“°ÆR2IÑÒ¬JÀÃßù¯ï}»}ö¤Q&�B’DîþØ|óÛÿ„Þ�ó;²"ð8,ŒÒç…u4�ÂíÐVLs%Û¹’ôۻɆÃ<žR›SD¿)B¾iîa€wqÙM¤%…x:‹Ã2÷ß±œBc�µ.­*y©Ø°ùö�²ïD�·ú“ü×ÿù}žzìGüûÏXjÓ †×eaø}K±Ñi¯vŒzî˜Ìd—¯'¸o©-)Á½û�z·€n~Y$5 c�Ü ÚääæL…%v­*y9 ÷ÞÿøæŸügO^ð³ÁþÓüð{ßf¨ÿ v‡“ßs?wÝóéó?ýÕ—ØóÒ³üÁÿÿ?.øÜÿüÆfÛŽqÝŽðþ×aÙŠÕ8\n~úÿ'“N±åú[øìþzý{“T3üü‘àµ]Ï“I§hníà×>õy®Ýºãü5;Ÿ{’gŸü1ÑH˜Ž%Ëøä_`Eï5W§ÛaæÈ¹÷&õdDdeWå «� ‹¢Aô‘ºx!�IDÍJ�•@–ŒÆÙ*L&3‚Áˆâð�uÕ :½¨nŠ»tsó‹ÄU›H<ñ0ò ×£w.®Ú âÌ éÑQ²›>2ï{8,&ü¡4=-s?�’“°úCj¼‹ë¦œ9ðÚË$qV®^þïN?ÌçîÝÎÒž^>üÑûì?Íþ΃œ9q”ÿôõopúäQ~ñ³^$¬O=ö#jjÎ ëóÏüœ�Ï=I6+q÷Ç  ð�oýáPàü½2™4_¸ÿCœ>q„û?÷%šZÚì?ÍsO=z^Xÿú/ÿ„þûÿÉ'ü-6nÙÎ�½»xà#ÛøÁÏ_âš�Û®8F«I�"ÏÖþUUU1WPþª £›ÆèB˜BÀXS‹ÙçÅÔZƒÁÛ�ÞnGg2!�èŒF½E’PE9�FE¤p)$=vœìÑJ,†ZߌÔÐ�ÒØ�RÓxy¡5[‘{Öxyõ¿öÑR%EeæÅ�ˆ«·¢æ¾tÛMLEâ9}&'a�ŽJtµjk©8~ä-îûðµ$qÆFùê}‹;ßç�~û/þ_êšùçÇva2Ízv M­üïÿñ§Üÿù/ÑØÜ–Ó3ƒ3S<ýÊIlöÙbæ&“™ÇòƒóÂúÓù?~k�>÷æ%=г§úøÞ_ÿÿëáG¹ý#Ÿà�ßø]¾úÛŸâoþòÿãû�¾xU<#3Ñ ŠJEdÉ8ú¡“û�¡KD1··c_Ö‰ùæm˜jkçt½Ñ6Ûù_PK{û?WD‘Ìø8ÉÁA’o>O6Fî\AvÉj”ú‹74¥5בxêû¤††°vÌ=—³’Iœ<‰‰‘Ýžû¦Õûq9Lœ-P( “UH¥³ØÌÚÆU©¨«oâSŸým¢Ñ0¯¿úÿò½o³ùº›Y»a G¾Îçû«çEàãŸ~ˆ¿þË?áØ¡7rÖí·Üy^Tz×näþæ[d2iÌf »_|†MÛnºì²þÍý{0™Ì4µ´Ówä­ó¿´§—ýã_ÏɇÕÄTXDQÁa-ßM:ýèYŒ§¢›Ƕ|9®Ûo¹Hó…ÎdÂÚÙ‰µ³“š›fËáÅŽ#¶ïdtd—®EZv ¼3Tƒqã-L?ÿmý‚¾r¼þù ˆ"3;_"}ýGç2¹v‹‘T*‹(©˜ŒsËF™ó, Ç%6£v0 „Ô56ŸV€ßüÊæ?|â&þü¿Äc/¼M:�"ÒÐÔrÁçjëÑëõLŒ�äüL··æ‚?MfTUEÌd0›-„C� Bdt¸Y‘ùý¯|梟¹<Þó}%lVÁ„„ª*Ø-e汪*ú¡“˜ŽíCoÐáÛ²ûò�#9KÃàvã½áz¼7\OflŒÈ[I>ù0ÒòõdW^‹j¶"·/';ÐGॗ©ýÐm¥þæ ÊÌ/Ÿ#Û¼¥!7GâRØm ‘zÏÜæßœÿõ#‰,V‹æ­–=«Öñãù;EÁb±ât¹ ¦/¸&œA–eêš0MHèT©ª*±hî…‘›[;˜žš¸ìÏ&“™g_=}Á†W.Ø,¦)PʨT¥~ø4惻0:løn½ ë’%¥6 sK õ--Há0¡½ûf7®z6 ­ÙFfÛ�Äžùg¬ímØ{zJmjAˆ:DrršÌ]¿ž·{ZMF"É윅uÎ>r8™Åj¬îåC¥‘•$ÞØ·›Ö¶.tï,wV­Ýȯ~ñ(Êû:Q>÷‹Ÿ"«Öl ±¹•X4‚ÿ}ì�×^&�ÊýèÞº�[9ðÚËŒ]útÏõ7ÝA2çWO=:ïqÚ,¢É,¡„Œ-‡\ÂB¡‹…±¾ô3¬GöÐpçí´|î³e#ªïÇèñP×�´ýæC¸¤0Ö_ü#ºÉ2Ûïaú¹_!ƒ¥61ïd&&ìÞCêÆ��>sÅbš�ƒseÎOŽ&$Íc-1£Cýü¯o~€pp†·^…‘á~¾õÝ9ÍïþþŸó›÷ÝÆïýƽ|ä2xößûë¿à“þm�Ýl½áVjëùÚïãÓ¿þ¦'ÇùÅÏÿ‡3÷þeüÆïòôã�ð¹{·ó_ùš[;ê?M2ç÷þóeÍúÍ|ú׿̟|õ!úŽ¼Åº [I%ôy‹p(Àÿß�\õ6³�HR¬æ «ªb<¶ãñ7ðlÙ‚{Ë'fÛ)—9—‹ú{~�ÔÐÓ¿zÙáEêÝÆøO~Jëç>[5)XR(„ÿç�‘ÙvªëêŬsÁf1N̽æ‚þÏþìÏþl.ê�c·šqiy¬%a|tƒÑH4" a4š¸vÛ�üùÿÞù¢M-í\·ãC~k¿zúçLONð¹ßúOüîïÿùy¯Ö`4²ýæ;9úö^~þˆ¢Èùÿ@<eýµ×ÑÙ½€‘¡s¬è]Çò•kÏß?™ˆ�„¸ýîO`01šLÜý±H&ì|îI^Ûõ+‰·ÞqÏùûì¸õ.š[;ØÿÊN^|öqÎ�>ŽÓåæc÷ÿZÚ»®:v�NàÜH�žvoI¾!ÇòòcؤM÷} ÛÒn„ Ûp0z<¸®¹b¤£o’mì"õÖë8W­*zL8ßÈñ8cÿöc2ko@îZ™÷û'ÒY’)‘­s E ª:·æ?zÙO[ƒ›:­‹F xñÍnݸð͈\ÑM b~íÜ׬ÃwÃõTÃnzd„Éÿ²Õ‰‘,Í÷߇ÞáXø�K@6fü'?%Ó½iõÖ‚ÿÿÓégO"èt´´vðùßþê… �ÃÞAN±0æÏÓXÁ¹œóa÷îÝüéŸþ)Éd’\ð³º;?ŒøÃ%{ê Ùž d®» !E:}ˆØO†ÞjÁ¹º[W¦úú…£ªd&'Iõ÷=Ö‡"+d—¬Fºç·P­¥¯¡¨*†¤oΪt(ŠŠ^‹³V=.·—¿ÿѳÎïù3Œ� Ò½|k6lá¾Ï~‘Õ뮽䵪¢fÕ¤(X^ýÞë¯ÇÜØXð1—O?ý4?ü0/¼ð™L†oûÛ]#èõ4|ì^Æþå‡(µÍ(5�¨vÒúH×lGï&3tÃÁCbs{;–¦FŒ^/¦š ^ïeKªÙ,R0xþ¿Ôø™‘T›¹©“ìÖ»PêZ®6Œ¢2«}sÏJ™»°ê- ‘'RÉ™tŠ¿üÛG¸ý#Ÿ¼jå+�ÙÉ�oL_Æêqâ¾vaÅ�+�Gy„ï~÷»:tI’X»v-ÿñ?þÇK^oôx¨»ãv¦_úwR}è½*ü‚€ÜÔ�ÜÔ�‰(iÿ0ñ™iôý£Ñ Dó»�F‚ù�š°éôl A§ÕSƒìô¡4¯DÙðá²ðL/‡¢¨äRœmÎÂj2 de­ÎµF>°ÚìüÍ?=9çëe²yέÔüOPÿ[_(õ×Qî¾ûn`ff€OúÓçkH\ ûŠ$ΜE:òÒ†›.y�jw!w¯æ¢l$9‹�•ÄÙ¬Õl™çy6õ+%²¬`È!0gßÖjÒ“Íæ�È¥¡‘GYEó(¬ªŠùÀóÔÞ|Ó¢Ù¬òx<ØívŒF#­­­ôööòÕ¯~õªŸ«¹åfLg#„¦çð”÷¡7 š­(NŠÓƒj²T¤¨Âl‹yî¶ÏYX-F™ÎÊjh䓬¢"åÑc5œ>„ɨñzu©‡V4¾ó�ïð�ï|‡×^{�»îº‹;ï¼Ë^*z»Ïö°x¾ÔC(¢$cÍ¡‰åœCV‹QÒ—�Djþ/wÝäz£sÓÜÚkT*ßýîw "ªÎ5k0ö+õ0‹†ªª¤ÒY<9ôû›³°š :¬f= -ΪQdâ)‘z·‘z—‘Djþ%ìŒ}8×®)õp ÊÃ?\8Q}çê^ôƒ'@Y¡Áx*‹ÍlÀ˜CyµœJ²×»MDb©Ç©±ÈˆÄ%êÜ&êÜ&B±y¾Øå,º¡S8V­*õp ÆÃ?Ìûoÿ�—^z©`¢ `p»1ÖÕ¡ë/õ�‹B4)ÒàÍ­ökNÂZç6kªQTR™,ØÍV‚ �žÇ&ª~|sC§³ÔC*ÅÕwqõ®Â8trá7ª¢q‘zOngùsÖ&Ÿæ±j—HB¤Öý^l«Þc"Ï= ÷aïê,õp ÂÃ?Ì·¾õ­¢‰*€uÉtƒ¥zQˆ¥24xæ_……µ¥ÆB0–Ò6°4ŠF0š¦­î½c—íuf‚±Ü…ÕàÂÒÙYêáä�wEµ�1ÕKap¹ŒFtá™REU!IÓR[ÀP€ÃªÇbÔ-hgVC#±4muï5ôk­1‰¥rº‡�NB"†¹¡¡ÔÃÉ+±XŒGy„Ý»wUTßÅÚÑ�Î?Tꯡ ÄR"‹»yî©V�£°4×XÄŠßûFcñ¡¨*áX†fß{˰æ Á˜˜Sm`ÝäæÖÖât#,"N§“={öÐÑÑQ’çÛ:Ú1L�”úk((ÁHš¶ÚÜ«Ÿå,¬� V‚áÜ< �ùŒ¤ñ¹M˜ ïMS³Q‡×a"”C8@žÁR_ý'­Š�©®¡ÊC�hšöbkwƒ•ɰgÕ(ÄÂ�çä傪Ât(Å’Æ"«ÓfÀaÑžÇά†F.L‡Rt7[/úûî&3áĜgE Ä<óÌ3œ<™ÿ¥Ç{ŒÁÁÁ¢�G0ÐÙì‰hÑŸ] B±4.ûlš_®ä,¬ÝMV&ƒÉR�[£ŠI‹Y2™,Í—HÌnö™ˆ§å¹ç³FCÖo~ó›twwŸÿoÓ¦M|éK_bxxøü5_ùÊWxòÉ'óþìx€—_~¹ ã»Ÿ!(ɳ ÍT0Ewƒu^ŸÍ]Š�ž;¿8`E‡·ÔcרRÆg’,i¶]r¿I§Ó±¬ÑŠ?˜ ³ñʽ慬„ªÈo¿ ™ššâ?øCCC|ûÛßæñÇçøñãÔÖÖòw÷wtww—ì;-F§!=÷ÕC%áÆÙ¼|~­½ç%¬­µdE!–”pÚ´î‚ùg"�àæ5—/ļ¢ÝÎ+}Ñ« +’ˆÎ˜[r÷|1™L|êSŸ:ÿç�7rË-·ðì³ÏòùÏž5kÖàr½gïøø8&“ ŸÏÇÞ½{‰D"lܸ‘ÆK´áN$ìß¿Ÿh4J[[6l¸¨ `*•b÷îÝ ¶lÙ‚³§Ìt&‚T}‡†¢ E�Mï›óV€•­VÆgô´{JýhTi1K4)Òu…eXwƒ�§_Ÿ!-ÊX®Ô‹(+"˜Š#¬¤··€±±1¶oßΗ¿üe¾þõ¯³R[ZZÎwN•$‰t:Í£�>ÊÝwß}þ>?ûÙÏøâ¿ˆ$I´µµ122Âm·ÝÆO�`U›mÞŸŸWŒ`E«ƒ‰@¬ÔãרBFgô4ÙÑë.Ÿwª× ,m¶1>såe¨ ‰¦ùy åùçg›ï]IÜ}ôQ~çw~¿ß�ßïç¶Ûnãk_ûÚùŸ9r„|�ûî»�@ ÀñãÇ üñÿñ÷ùþ÷¿ÏO<Áðð0CCCX,¾ñ�o|Œ:“ ![}Â:H°²Í1ïÏÏÛcm­µ ‚± >gi&®Fu2ê�óÑÍWßlZÛeç—o†XÒ|…p€œü§yN$“I¾þõ¯£ª*ýýý<ùä“lܸñïóƒÜpà |ö³ŸÀh4ò›¿ù›ÜsÏ=ÄãqßûÞ÷¨­­å»ßý.¦wY¥L(bq–ª‡ƒG}4§Ï®âM;Ä9د×ϽS>Q3TCibØ…@Ê*LR|lë”,H mf=õVF¦ã¥þ>4ª)«àŸI²&a]Ýå`b&‰”½Ìé£ Š$¬…`åÊ•pVq× V«ÕŠÕzå¹ÿA‘»ÔÉ(ƒÁ€×{ñQq£ÑȦM›.yßK]o±X®˜��TIBI§Pí¹¯2Ê�É`•eM UÈC(fëoïõrr(TÒ/G£2žŠãu.hÁ’+�õ6¼v#So¤f�>¤`°Ôì:¤`Áå­ŠâgFÂìXíÉÛPò–#µ²Õ�^PµªW9¡¨*gÆÂܼzá}nZãåìHø¢X«ê­#59Uê¡VâÔЧ¶Ôf,˜‰@� ÐÓšoò(¬‚Û×x95Ò24æÌÀX”§‘æyTiÿ ­µV|.#ƒžRÚ�ÆÆP«´ s©H ‘m(M[˜|¡ª*g†ƒÜ¸&¿•úòšÕßÓbÃaÖ14Y]GÜ4 ƒ”U8;á–õù›Ô·¯¯áìHñ}y­ªÉ‚êò�™˜(éxEá¯þê¯H$ª#ƒ&=4„ÜTÙÂ:à�á´X–‡ «÷“÷ãRÚàãôHIÖ¼�+sb Àê6;u®üÕš¨uéi·qzøÂ˜ªÜÐAj¨tEEᡇâ©§ž"‰8%G QTP�•[“YÊ*œ sûúüAÏ»°6xÌ,m²qfXÛÈÒ¸<Ñ„ÈT$Éö<ÄV?È�½^&¦“Ä’ï È6v�ì(ÉXßÕþþ~ž}öYŽ…�C/R(Í�¥6cAœ²²ÙF�;ÿ rÀÿ–µ^ƧãZ_,�K¢ªpôì 7­öa1å ÚÌz¶¯ñpøìÌùx¿Ò܉� ‡‹:ÖjU€è±>²+KmƼ Ç2L“ܸ¶0-{ "¬6³ž[®ñÍNl¥ò—=ù¥"ŠÕ,°¶«p'vÖ/qa1 ïuÕé‘;Vë;^´qV«¨J¡ÙH¹©³Ô¦Ì UU9zn†Û®)Ì‹ $¬«;œxlzÎ�E öiTÉt–³£aî¾¶°i:‚w_[ÃéÑ0©LiÉjbG�eœÕ*ªñcÇ�—ô‚®2+Ú��àvèYµ€BÖW£ ßÌ]›j87%’¨Ü"ùCUáÐéi¶õ¸ð: _óÆebër'‡ÏN£ª Ô5#£#=2RÐçV³¨ªŠBôè1¤®ÞR›2/Âñ ýãQîÚPØ{A…Õm3ò¡õ^Þ>=…¬…=gGØM°¥ÇS´gn]áÅlPϯœ¤•›îÝW°çU³¨$úúP_C©MÉYQyûô4wlðá²¶«DÁ}ùÕNZ¼&ŽTgïq�¹ŽeðG¸wK]QO@ |ts=çÆ"„ã"Ù¥kgdüþ¼?KUU¾ò•¯T­¨¢ª„ö¿Nfõu¥¶d^럡­Ö̪öÂÿ»%HrÇÆáÔU¿iT'bVáà©)>¼¡§­8ý§Þ�ËfàŽ�>žšBR@\¹‰Pž½VUUùò—¿L___uŠ*�8uŠ¬Þ„R�‡F§ã„cîØ°°Îs¥(Âj1éùÄöŽ� \�[¨QýÌÆU§XÕfcEkéÄfU›ƒž+‡NO“]ºŽÔèXÞNb½_TùË_V¥¨ª²L`Ï+ˆko(µ)9Mˆô øØuõ˜�ÅÙp+Ú¶^ƒÛÄ-×xyóäYíTÖ¢áäpƒNᦵ¥?¡së:‚ pÚŸ@ÜpÓÏýŠ…¶X ¢ 9ðY›¹eI©MÉ IVxóäZï£ÑS¼NEÍ—XÛédi£•ƒ§¦ªâXŸÆ•�Š31ãÞ­ m.:�ÀÇ·Õ12cÄÓ…¨79t(çû ‹GT³Ñ(á7ß^jSrBUTžœby«•ÕíÅírPôÙ~û†¬f�ÃggŠýh�"Œ¦9>äS;qXKÓAôR8¬î¿¡ž¾s¦Wí ´ç䊢¼ñÆ<øàƒ‹FT¦_x‘ìŠ�(NO©Mɉ£ý3XÍp[ VKEVA€{·Ö‘L‰œÕT#ñ”Ä›'¦¸w[ 8‡½Pê=f>²¹Ž}c2É%ë˜|êé9‡þê¯þо¾>î¸ãŽE!ª±Ã‡IBˆ«·–Ú”œ83&‘Îðñ­–J²>3tÜ¿½�a„A¿Vb°šHe²¼~ÜÏ-×xél(ß6=ÝMVn\íáeºH¥eBûö_õ3ìÞ½›H$ÂîÝ»¹ñÆ«:¤%ÎÌص›ÌŽ{AW>«Ž«1è�16㾚0KÓÝ d�/§ÍÀƒ77qn$Ìè%ÚihTIfÿq?›–:YÛYþ�;×w»ØÒãa—o3á7ߺjYÁo|ãLMÍv"E‘üà|ík_+õ0 ‚*IøŸx’ÌÆ[PÜÅIQÊc3 ÎŽ†¸ÿÆœ% Aå¥KëB˜ gøñn?«»ëhª±-ü†%A”döõùéí°±cUé3ra÷±Ó}g¸vê­Ÿû,†KtZ …Bttt‹Åèîîæºë®ã/þâ/hmm-µùùGU™xü ’XÈ\wW©­™3�ÇÎÍðÀÍ�y­ñ;J¾U[ï1sÿŽFŽ�›flZ;@P‰¤E™½Gý¬h±Vœ¨ܸڋoU7}Þ^Æü“KnfýÑý�‡?üÃ?äСCüð‡?¬NQf^x‘t"Cfë¥6eÎŒMÇé;7ÃýÛK/ªP뻢?Þã§»ÅCGcù/#5fIe²³žj›•›×VÎ’ñRì;&±o/=ŠŸ–@÷¾öѯ¾ú*[¶lÁh,|ñ˜R|å"§Î‘ºý0–߯ã¥ôÇ8;â3; R´z>”�°b"?Þ=Ig£‹%-î…ßP£ D"oœ˜dÛ ×.«Ž¯ý§"ˆ{vÒmIÒô©O^ ®ÕNèµ½D%uççP-•–;;ft:ÊgnlÂë(Ÿ—^Y +@,%óè+X-fÖ-­E¨‚žåÕÈt$ÅÁÓܾÑGoŠZ““£ &~µ“nyŠæÏÜ�ÁYý+¨ÀΗˆž }ë}¨¶ò¯ªÂ±s3D>½½¡àÕªr¥ì„ #)<öÚ’,°¾§ƒ¾ä¡`�÷14ãÔP�Ol«§­®|SªÂàTš¾g÷ЛCfû=(uÍ¥6éªÈŠÊÉÁÓá$¿®�Foù‡+*BXaÖsxî­c‘ +êpÙª{Z(ªÊé¡ �$Ù\KG}uÆSçÊàdŠc¿Ú˪À1Üë×á»þz„ J¿Jœ²©®`]UóMÅ뻈±ëpˆîV]Í®JXÁT$áx†Ãgf¨w¸»‚&t¡Ifd^Ø;LÃÙ·hÊLQ{Û-Ø{zÊz)-NO3³ó%ÄhœôæÛQÚJmÒUQU87¡,Â-×x+âˆôû©8aÅ$ž~c†”¨²vi-.»æ½æ YQ95bt:Æmë|¬î¨¬ ],Ž Æ8¼÷›£G°ê|×mñjUY ¬è÷Ü»�ôè(bïV²+6VDËêhBäÈÙlfwoª)«üÔ¹R‘Âú.o÷GÙs$Lk£“å­ôúò™Ô•Èd0Iß@€–3wl¨Áf®üMšBOÉüêPihˆ ÉSX2q<›7áXµ �µ4aUQH yë ™É)¤Þ-d—­C5”¿8ee…3£aFýqn\çåš2ß º-¬0{ à¥C§2¬ìôÒZ_]ÉêÅ ž’8> �ÉrûK+ãÔM¹pn"Éóƒ4Êzƒý˜ÛÚñ¬]�µ»»(Y¢ßO´¯�DßqT§‡L÷ZäîÕSîod*ÎÉ¡ �õVn½Æ‹ÃRþ©_W¢â…õ]Fž{†¬"°¢ÍG­§üó¥&#Êœ 11“dëJ›–¹Ñé4¯>Ȋʧ£ì?¡Ýg GžÂ6|aÆ�±¥Gg–ŽÌ��y d£QÒCC$‡H ¡êôd»zÉv¯FuVNæÆt$Å©Á&=|hc -¾òßñŸ U#¬0ð>>cÏÑ“žeí^|.M`?ˆ(Éœ›-2¾¶ÓÁõ«<Ú²?O$2Yö�pt8NG½ƒ¥õV,3£èýCüC�¢óù0y½˜jk0y½èívt&‚É„ÎhDÐëQ$ %“AI§Q% )""‚dƒPU”¦² ÈM%¦0ÛºçÔpI’Ù±Úê*;]UÂú.Š¢pl(Á+ÇBX-&º[ÜÔywªÌV¢�04§·ÝÎu«¼¸Ê¨U5Kfyµ/ÄÉÑ$m Nºš]XÍ3è¢A„h]$€>BȤÄ d¥Ùÿ F0šQMf0‘dW ªË‹êò¡Ú]¥⼘ ¥87&#JlïõÒÛn/ÛÓS ¡*…õ]dEåÄHœ}'£HYènuÓ\kG¿È–»‘x†³cfB)Ö-q²i™ §­²cX•B4™å�ÓQÆhôZélvãqTÇrw®ÈŠÊØLœ�±(lëq±ªÍQÕa§ªÖ÷3àOòúé(ã� ­uvÚ]U�¦%eF§ãŒøcÈªÌÆn7ë»�˜�ÕçTIá`”·ÏF1èô´68i©s`,Ã"ù"šöG�JÐ\cak�«¬û å“E#¬ïIJˆqø\“YGS­ƒ–ûì2­Â‘•©P Ád EW“•õKtÔÛÊ)½rQ£ª08™äà¹C“i꽚êœÔ{­U±’Jf²ŒÏ$˜Ä%…kºœ¬ët”]Y¿B³è„õ]T†¦’Nrf<‰Ãj¤Ág£Þc­(OVÌ*L‡’L“L†’4x,ô¶ÛXÑæÐNK•9Ɍ̩±}à ¦Â"M^+µ>;õkEy²Ñ„Èd(Åd(N")ÓÓjeU»“Ž:Ë¢}¡/Za}?Š¢28•âÌXŠsþYE ÞcÁç²âsY°•QN]VVÅ2"if"IbÉ,m5f–5ÛXÖbÇ¡mFU$ñt–3£INM$›Éà¶ñ¹mÔ¸Ìx�沪IœLg DÓ„¢)¦B)ô�% 6zZltÖ›«r3*W4a½�˜HÿDšá™4£Ó)T�@�Ó‚ËnÂe3á´™Š"¶RV!–‰&$¢É ±DšH}`ii©êp!„B©P†aUAª.†a°{÷n©<ïWÍ,X°€’jB!厾Á‘OJNN†���ªÃ ÕÐ7ß|ƒçÏŸ«:Œ*çÊ•+ ƒ¿¿?|||`nnNÉ4!ÄÈÈ:t@çÎ�qèÐ!U‡C!ä+DßâÈ'Éårðx©|zzzÈÌÌTu„B¾B”PBH%¢ªB*—Ë…\.Wu„B¾B”PB!„B!eÀWuä딑‘�Û·oC*•¢C‡ÐÑÑ©ôœœœÐ²eKüþû諭%–••…���bË›6m �bË`gg±X¬êÐ !„B©q(¡&ånûöí˜1c<==Áãñ0iÒ$\¸pÎÎÎåvܸq¦¦¦ݦW¯^°··Wõí(•àà`téÒÍš5SZþ矢víÚª��bžºíÓ§Oa``333U‡]bQQQàñx°µµ-—{ebb‚Zµj©ú²ÊäñãÇ055…‰‰‰ªC!„Bª J¨I¹zðà¦M›†[·nÁÅÅðüùóbóXËårdeeÁÐÐð£ÇÊË˃T*…žž^±uiiiŸ�eÙ²eŸ\Ÿ›› ™LöÁãŽ\.Gvv6 ÊtŸÞ¾}‹¼¼¼>033õk×>¹~~> 8Î× //FFF=Æ›7o>úÅ>''ùùùŸ|`A*Ç¡C‡ P(Я_?vÙÚµk1räȽÿNž<‰àà`€©©):wî ++«r‹ïÊ•+ ÅãÇ�ѨQ#lÛ¶í£Û6mÚ�:uÂáÇËý>9rÝ»w‡@ (õ¾2™ ĵk×Àår1`À´k×°qãFhiiaÅŠ_Ÿ\.GãÆ�Ñ»woìÙ³§Dû¤§§cÓ¦M˜?¾R¿ûÓ§OCCCžžžåvÿ<ˆÞ½{t 7©T  8;wî,·óB!Õõ¡&åjÓ¦M9r$›L€½½=ûeP&“aÚ´i°°°@‹-àêêŠG�±Û.\¸«W¯ÆÐ¡CáââSSSÌ™3‡]ß±cG˜™™!##fffàp8àp8¸pá`æÌ™ì2‡ƒÙ³g+Å7þ|¬Y³ÿûßÿàêê SSSÌ�;—]ïãヿþú‹}ýúõkˆD"öµT*ÅäÉ“aaa�fÍšÁÍÍ�MVÀÛÛ[éËrLL ÔÕÕÙ×b±ß}÷š6mŠ^½z¡^½z(ñý-,,ÄÈ‘#aii‰ `þüùJë†Á´iÓФItìØ‘½ÞÞÞì6kÖ¬�••:wî ;;;=z”]WPP€nݺ¡yóæl ÿ¦M›*ÿ�DXÄðáј˜È.[³f 222J´ÿ‰' KKK„……ÁÍÍ üñG¹Å7uêTìØ±={öüì¶'OžÄòåË+ä>�?¾L]är9ºuë†_~ù­ZµB“&M0iÒ$¼|ù²\ããñx8uê/^\â}ôõõñ믿âîÝ»JËçÏŸ‰DR®ñ�5꓃v œ:u .,×óB!ÕµP“rŠ |t½¿¿?>|ˆ—/_BSS§N�BçÎ�ñâÅ èêê6lØ€½{÷bçÎ� ƒ»»;¦M›SSS6qæp8HJJ*Ö‚úã�?âÇøùùA¡P‹aÆ Ø·ovíÚŶªM›6­DeŒË—/ÇãÇ� ;v �:u‹/ ­­ýÙý�=ŠäädDDD(j©þïܨ™™™X²d ûº]»vhÛ¶-`éÒ¥ˆŒŒDll,´´´päÈìÛ·�ÝöôéÓ¸qãBBBÀçó1bÄ´mÛC‡PT:~ðàA<~üúúúˆŠŠB›6mТE ˜™™áСCÈÌÌDxx8€¢–êׯ_Ñ{"<<NNN_tŒš®yóæXµj6nÜøÁõ‰.\@FFÚµkW¬{€»»;FŽ :t(Ú¶m OOOØÚÚ"44fffìû_,ãáÇøæ›o€}¯+ \¹rÆÆÆðññùhKæ½xñ Š’Ê÷P½/** ·o߆ºº:|}}•Æ](,,ÄÍ›7‘˜˜4oÞœ]Ž””dddàÖ­[ì,wwwö3…a\»v qqq¨_¿>š6mÊîÿ믿"11<€P( >\©E˜ËåâíÛ·8sæ ø|>ºvíªt………¸qã’’’àèè¨ÔeãùóçìÃ555¨©©»?zzz8wîºuë¡P.—‹o¿ý§OŸFëÖ­=ä{ýúµRë´B¡Àµk×gggxxx(�ãþýûhÒ¤ òóóqþüyH¥RtêÔ zzz Û7oðöí[ܼy“½nhkkãÙ³gHNNˆD¢bñ¿‰{÷îACC�:uRšg]¡PàêÕ«HHH€‹‹ 5j¤´ï›7opíÚ5ÂÃã\»B!�Z¨I¹ÊÏÏÿè.øë¯¿0{ölhjjºuë†ÚµkãÌ™3ì6½zõbË-���abb‚ØØØr‹±wïÞhÓ¦ ÀÕÕÆÆÆ%>þ_ý…9sæ°„õèѦ¦¦8þ|‰öwwwÇË—/1oÞ<ܼyjjjpuuUÚ†ÏçÃÆÆ†ýy¿$}Ïž=X¸p!ûeõýÄQ·n]ðùEÏÊêׯ¯Ô‚þûï¿Ã×ס¡¡¸~ý:âããáàà€›7o5j„ÈÈHÌŸ?ÿý7„B¡RµAYàÉ“'åöû«‰ € ..®Øºøøx¸ººb÷îÝGÛ¶mñ믿~ôX�7F«V­pìØ1ÀôéÓqåÊv}bb"|}}Ù×[¶lAß¾}Ñ·o_<}ú³fÍBß¾}Kû½{÷°sçNìܹ&LÀöíÛ•Ö3 ƒñãÇÃÇÇaaa¸~ý:\]]‘•• h\GGGìܹ/^¼À Aƒ”ZywìØ�?þør¹{öìaÏõæÍE­Ú¶m‹üÑÑÑ?~<&MšÄî¿ÿ~L˜0�M¦›Ö,22�;wƵk×°téRtíÚ•]÷èÑ#8::b÷îÝxþü9  Ô çÎ6¦qãÆa÷îÝJÇÀÂ… Ñ¥K\¿~K—.E÷îÝÙõ=zôÀéÓ§Ù×gΜAçÎ�ÙÏÙììl´nÝëׯÇË—/1jÔ(̘1£Øûçüùóhܸ1Ž?ŽcÇŽ!%%@ÑgÂ»Š…]»v±±¾ëVsûömvÙØ±c•àE-üÆ C·nÝðôéS\ºt 6D^^€¢�[´h��7âåË—1b„RÕQDD5j„àà`DGGcÊ”)ðóó+ñû‹BQ5j¡&åªvíÚˆŒŒüèúŒŒŒbývkÕªõÉòU55µ¶4——Òÿcñ¿”ésêׯ�'Ož`×®]X±b=z„1cÆ`åÊ•lhmmm¶Eù¿RSS?9 Ówß}üòË/033Ö-[”¾§§§ãáÇl‹!ØØØ°}j���ŠÝ»wcÙ²e ¸q㾨Lwúôéøé§Ÿ0nÜ8¸¹¹}Áoªæâóù?~<–/_Ž­[·*­›1c|}}±~ýzE¥ÏÎÎÎèÔ©lll>x<{{ûRUãðáÃàp8˜;w.j×®�‡¢I“&ŸÝwÈ�!2d€¢òðÿúóÏ?qõêU<~ü˜}P”‘‘Á>HjРÙþâ½{÷FëÖ­±hÑ"p¹\¬]»yyyøë¯¿ð믿«Y¼x1êÕ«Ç&� ,@ƒ gggDGGr 5 ¨õüùóÐÔÔDZZLLL�””333¸¸¸ ((úúúŠ`///ÌŸ?Æ ðaÃßÿý�ÿìÙ3\¼xšššHII�©©)RRR`bb‚öíÛ#!!¯^½‚­­-NŸ>ÍïÝõ4lØ�}ˆ2þ|8::b̘1J×µhÑ"\»v­ØçÇúõ둞žŽ}ûöá÷ß/Ö}äÈ‘luÃèÑ£‹Å¾yóf#44”­ÈÈÈ`šÎ�;M›6e«+æÍ›Œ3vvv¸xñ"\\\°zõjö˜R©´ÄïÍÒ°sï„ëOŰ2âÃÒ€¡€óå%„RãQBMÊU¯^½ðÓO?aâĉ엫ÂÂB0 ‘H„ àîÝ»lI¤D"App0fΜYªóhjj²- åI$)%ÇïJßyÿ»’E±XŒ��¶_¡H$Rz8ðßý�¢�¡fÏž�Ù³g³%¢}ûö…»»ûgã³±±Ahh(Ûªýß/ž™™™hРÔÕÕƒ‹/* çææ''§Oöƒ477Çœ9s0gÎ$$$ÀÁÁýúõ+sKµ½½=fÍš…ü£F�*VŽJ>O¡P`Ú´ippp€ŸŸ[�ׯ_ÇñãÇÙ×666hÔ¨®_¿®”x½¯°°�MKÂÖÖ–}࣫« www<~ü¸D õçœ?C† Q*~°5555ddd`Ó¦M D^^òòò���]¢k¸páÜÜÜ”ºQˆD" „……)%Ô+W®¬�ÑÕ/\¸€áÇ+�ñþïïÂ… hÛ¶íã³³³C¿~ý°gÏxxx cÇŽðòòBûöíË=Nxv6à >]ŽÀh ´¸°6äÁÒˆ 5J® !„” %Ô¤\�5 ÇŽC»ví0qâD`Ĉ5j–,Y‚^½zA[[666øå—_àîîÎö.)///,\¸cÆŒA~~>lllÊ¥ŸnëÖ­±yófØØØ 33'OžT*ÿ\ºt)ú÷ï XYY! -Z´`û7¶jÕ ¿üò ¬­­‘‘‘�Ó§O+õ5�1c Ñ­[7Ô©Sׯ_‡H$RêóúöíÛb£èvèИ4iæÌ™555ˆD"üüóÏJÛEDD ==°³³C\\ø|>{ü~øíÚµ—ËE›6m�››‹'N`ãÆ�˜2e †A×®]accƒk×®AKKë‹G…¶³³ÃìÙ³±víZ(ŠrIÄj===Lš4 kÖ¬Qš“œa˜�Žöþ1wïÞU*«-mˆX,V*‘þ …â“ý±�?Ž… ÂßßS§N…P(„P(Ã0ì6Ÿ»þ† *½çÚ¶mË~^¸¸¸àîÝ»J÷}‡ÃaÏøða,]º«W¯ÆôéÓÁår¡©©©_iq¹\¥ý{ôè�?þøvvvhÕª•R¢Îápàææ¦ô@®mÛ¶Åú!êáCiß?ïûÔlïŽíîî®Ôµ¥mÛ¶ì:SSSö~¾zõ AAAصk×�±fÍäääà»ï¾P”h½?¢õ¥K—Šíó®?3P4ˆVHHH±‡`ÈÌÌ,õ5yyyaÆ ˜>àp8ðññAHH&OžüÁøbbb`mm ggg8;;c„ ÐÒÒBLL êÖ­[î÷ò°4äÁÒ�†ÞdË›&ÃÅP)„¬ y°6âCO“’kB!ŸF 5)wïF—1bÄ×»ºº~t´â•úM™2¥Ø2¬Zµê“qtèСزÍÛú~¿N�@Pl”òÿ–£»¹¹}t*)55µOî/Я_?¥9…ßgkk‹~øá“×õßýßàgâĉX·n�RkÜöíÛÙ¨ÀÚÚú£sꪩ©¡ÿþèß¿?*BíÚµ1wî\øûûC.—£U«Vrž¯•¶¶6&Nœ¨ÔºüÓO?ÁËË =zô€��<ˆµk×*õŸ>vìBCC555œ>}šM^ „!C† ..oÞ¼�‡‡G±–Áëׯ£C‡pqqÁþýû±råÊbÉf—.]°xñbŒ?‰S¦L)6àÞ‡Œ=·o߆‹‹ zôè�¼¼<\ºt gÏž…££#ºté‚~øÑÑÑHOOGvvöç¯3f z÷î�^½z!55=zô€��–,Y‚®]»¢eË–ðññAZZ‚‚‚pëÖ-ví��xxx sçÎ�Éd¸}û68P¢„ºK—.X²d ž?Ž´´4äææ–ªœ¾$455ѦMìÝ»k×®UZ·|ùrtéÒ­[·†··7RRRðøñcܼy³Ä-Ïï>³¿ýö[ôèÑÉÉÉJsqÊäÉ“q÷î]¸ºº¢{÷îÈÉÉÁÕ«WqùòeØÚÚbÕªUèܹ3Ú´i///¼yóOŸ>Åõë×Ááp°}ûvœ„»»»RâÏ0 ®_¿ŽØØXXZZ¢eË–JýzïÞ½‹çÏŸÃÐÐÞÞÞÅJÖcbbð÷ßC$¡cÇŽì´]QQQàñxJ-··o߆»»;c`` ÂÂÂØ)¡Ÿ¯tü[·n¡Q£FJ÷àõë×HJJúheÇíÛ·ccctèÐAéÞß¿NNNŸìÓýþÔ[ÖÖÖhÑ¢E±)Î"##¡®®þÁ÷PXX¡¯¯ooo¥{Ï0 nß¾�—/_ÂÄÄ^^^Jñ¥¦¦âÆ�ÈËËC½zõвeKT„²ü{–™§@\š ±irHe ,ÿ) 7Ñåá *å !„|E(¡&ŸD uõsåÊÜ¿R©uëÖE·nÝ”æô­LŸzÿ$%%aÕªUøî»ï>X9ðµªnS³gφB¡`çw'¤ºúÒ¿½· ĦÉŸ.Ã[1K¬Œø0Óã¡ö„B¾2TòM>‰ÇãA*•›J…T]^^^ðòòRu�J¥ÅZèÞgff†ùóçcåÊ•�Ë奊B*›¶: ¬¸h`%@~!ƒ¸t"⥸Y ý¢²p >øTN!5 %Ôä“LLLðòåË�–xò1ïÊ;?¥V­ZX°`V¬X¹\___U‡MþcÍš5ª��*GCÈ�ƒ¹æJħËýF†ûQ˜èpamć¥!j|ª '„�¯)‘OjÙ²%.\¸ ê0H5táÂ…õ…466ÆÂ… qáœ>}ZÕaW¸wU„�Ê#—ËK5òyiØ™òÑÞY„MÕacÌGB†ÇàÊ1^$IQ ¡Þu„òµ¢„š|R—.]ƒ³gϪ:R�œ={111ìTGŸchhˆ… âÚµk8qKïP¦¦¦ˆŒŒTu„Ô(ÉÉÉå2ýßçxؘðñM}!z5Ó€ƒ¹i9 œ,ÀÅP1Âã¥ÈSrM!_ÞâÅ‹«:Ruñù|¸»»c×®]ˆŒŒ„žžtuu?Ù7–ÔLR©/^¼Àž={??¿R}�UWWG³fͰgϼ}ûNNNª¾¤ ÁårqôèQ´hÑ¢Ø(Ø„�ŠqìØ1ÔªU �5ª´sr9€ŽVF|Ô·@KÄAJ¶!1¼J‘A,„|DjTN!Õ�òMJD,ãÌ™3¸wïT©¢,,,мystéҥؔ;%•““ƒ+VÀÃÃ}ûöUõ%•;†a°{÷n!¤º¡„šRå¼}û«V­‚³³3¨êp*ijgÏpéÒ%ÄÆÆ")) …BÕ!òÕ100€»»;zõêUe’éÿÊÈU >ýŸ¹®å ¬ ù°2âÁD‡æº&„�ê€jBH•”›› 888`È�!ª‡B*\Î{s]çþ3×µµ1¦º4×5!„TU”PBª¬üü|øûû£N�::t(8Ô\C©!ò ĥɗ.GfžÆŽK£bBj<¹HÌ”#.M†„ 9t5¸°2äÁʈ-%ׄR(¡&_äÈ‘#ˆ��Ç”)ST ©B"""€ À¢܎+‘HðÓO?ASS&L ¤šBþ¡`€7YEeáñr¨«q`eȇµºôYI!…jòEf̘�Ñ£GÃÑÑQÕ¡�*æòå˸wï,XP®Ç•J¥X¿~=&Mš�Fç!ʲ²²päÈ###CÕá222‚­­-úôéKKKU‡S©R²åˆK/j½ær9¨ýÏ\׆4×5!„”+J¨É2d¶oßN}¦I1………=z4víÚUîÇ–Édذa`Ê”)àóùª¾\REdeeaÑ¢Eððð€——ÌÍÍ©’¡KKKCHH>Œ Ô¸¤ú�ôws]§Ê!W0°ü§åÚX—* '„�/Cß2È‘Ëå”L“ …�Édrl>Ÿ�©S§‚Çãá矆T*Uõå’*âÈ‘#ðððÀСCaiiIÉt gdd„: sçÎ8tè�ªÃQC-.ÖVC·ÆêðtA$à 0Z‚£÷òqÿE!3åPPó !„” }Ó „TK<“'O†H$ºuë ‘HT©‚ƒƒÑ¡CU‡Aª˜Ö­[ãÕ«Wª£JÐÑàÂÙZ€NîêðuW‡®Oã¤8|/w" ›&ƒL¡ê( !¤ú „šRmq¹\L˜0ºººøñÇQXX¨ê�ˆŠeeeÁÔÔTÕa�*FOO™™™ª£ÊÑràh!€·«Ý=Ôa¢ËCT² Gïçãf¸¯Rd�ȨéšB>…jB>bïÞ½ Su&00óçÏÇüùóqþüyU‡Sf\.ãÆ�ƒ‘‘Ö¬Y±X¬ê�ˆ ) ¨ŽÃår!—ËUF•&Rã ®)žÎ"|×DVF|Ä¥Épüa®†‰•,ƒXBÉ5!„ü%Ô¤Rè½ñå �œU4W|ºÂçºÖ¡¹® !5Í5C*U�:uP§NÄÅÅáöíÛh×®�Òúû÷ïÃÄÄ………8tèþ÷¿ÿÁÜÜpèÐ!äææâíÛ·øë¯¿ØÆ;wî cccE}(÷îÝ‹7oÞ nݺ0`€Ò´JG�E·n݃C‡±­Ñ–––¸}û6¢¢¢Øm5j¥ãââ°oß>äççÃÓÓmÚ´QZäÈ|ûí·ˆŽŽÆáÇ!“É0räHXXX`Á‚X·n¾ûî;À�`ee…yóæÁÑÑwïÞ…¹¹9rssqäÈ…B 6 µjÕ*ñ=ÎÌÌÄž={�šš {{{ôïߟ-�}òä ‚‚‚ðèÑ#˜™™açÎ�€nݺÁÀÀû÷ïGNN¤R)»ºwï}}}U¿}>‹Ãá`ذaؽ{7V®\ ???hii©:,ò•’Édˆ��g_[XX|U³H¥R$$$|ôú>·¾$`hhX¡GIùárs}ÌõyhZHÍ–#6MŽ«abð¸Xÿ3×µ%ׄ�šƒjR¥ìÙ³111�ÉdèÚµ+Μ9ƒ½{÷"44ñññHIIÃ0xýú5›(¿kM�‹‹C»víгgO¸¸¸àÔ©S8tèNž<ÉžcöìÙxóæ ~ûí7ôéÓG©|:==111ŠJ³{õ꥔Pß½{=zôÀ¤I“`nnމ'¢G�X²d »ÍÌ™3‘ššŠß~û ½{÷fcKMMÅÓ§OѵkWv[}}}4oÞW¯^…££#vî܉¤¤$Èd2téÒ'OžÄ¡C‡ðèѣݿ˜˜´oßýúõƒ““Ž9‚cÇŽáðáÀììlÄÄÄ 77™™™ìµ¾»±±±HIIa�õNuA{È�!Ø»w/V®\‰¹sçB[[[Õ!‘*êØ±cÈÉÉhkk£eË–%Ô,55Çܹs>„«««ª/IIXX•–‰D"ôë×ï³û&%%±×wëÖ-¬ ‹ÖBÈW�!ä 0 LûíÚµ‹iÓ¦M±å“&MbzöìÉ( †a&77—áñxLll,»Mff&€)(((¶ÿàÁƒ™~ø�}­P(WWWæáÇì2;;;¦]»vL^^Þ'c3f ³råJ¥eÍ›7g~ùåöuRR#‰˜èèhv™�� ãééÉäçç+íûôéSF$;Ï Aƒ˜E‹1 Ã0cÇŽeú÷ï¯t­‡INNf†a²³³�½OŸ>ÌŠ+”®ßÑÑ‘yüø±ÒvÆ cüýý?xŒÄÄD†Ãá”é÷ú_ `nܸQ.Ç*‹0³gÏf²³³U©\¥ýLrpp`þ÷¿ÿ1 .dȘ˜˜0¿ýö[©Ïkbb„††ªúò‹Y½z5ckkË 6Œý™=zcccös£V­Zìÿ $$ÆÆÆ¨[·®Ò±âââ`ee…¬¬,„„„ÀÉÉ &&&JÛ4mÚ;vì(ŸD"AJJ ,--Ùeéééàñxåò·�åË—#44vvv€1cÆ`Á‚Œ(ª6JJJ‚��ÍŸŸ¨Ž®.Ö\¸X �+f—&ÓX)n=+„…VF|˜ëóÀ£ÊpBÈW€>ÊHµÃå½m™Œ§§©©‰)S¦`ÇŽìÏýû÷•ʬ@MM­Ôçåp8 …Å’ûÜÜÜbÉó‡GKKKèéé)•_2 ƒ   4lذ\î�††f̘¡tý<@ÇŽËåþ–ÅòåËÁ0 -Z¤Ôß²²ôêÕ ­[·Æ²eË�‘‘Qéç'Õ‹¥¥%²³³Ù÷ÿ™3g`ggôéÓ¾¾¾ÈÎÎ.ѱ|8BBB=�ª[·.Ö¬Yƒ^½z¡sçÎl‰:Pônûöíhß¾=,Xܺu«Dñ=yòÍ›7WZ¶páB¬_¿¾\îå©S§Ð¶m[6™€Ñ£GãØ±cP(ŶÏÍÍ…··7Ž;V.ç'Uƒ–ˆƒú–ø4¡«‡:Œuxxž(Å‘ûùø;¢¯Rd�Êi|\BHõE 5©v´µµ¡§§‡ðððbëúôéƒ={öÀÔÔ666°±±�¦¦f¹�öüí·ßbãÆ�ìëË—/#%%¥Dýÿx<†ŽÅ‹³SemÛ¶ B¡íÛ·/—øúöí‹={öÀÌÌLéúÿ›ðŠ¡¡!ÔÕÕQ.1 …BŒ7�;wƲeËð÷ß—ËqKãÛo¿Eûöí±lÙ2¤§§WúùIõ�ššŠ¥K—ÂÇÇééé0`:„ãÇ�³­Ä³gÏ.ÑñÞ=Ⱥ~ý:»ì�?þÀèÑ£ÙW³gÏÆºuë°yófܹsjjj8uêZ´h�ÔÔT 4ˆ !44úúúðóóc�WPP€W¯^!((·nݸqãð믿*ÅñôéS,Y²„ýy|„ŠS¬E½nݺÈÎÎ.öp+''¾¾¾èÓ§¦M›V!ñØ7éŽcòq>¤7ÂÅx%AX¬ÑodHÎ’#;_©Œ»Š¤®ÆA=3>¼\Šæº¶0à!6M†cÞ›ëZJ¿BHõB%ߤRùûûcëÖ­ÈÍÍEnn.lmm¡§§‡àààƒÃáà‡~@§N�жm[ÄÇÇcþüùèÚµ+æÎ�‹×¯_ÃÁÁ-Z´@ZZx<Î�;Ç~�ýèÝ»7œ��ajjЍ¨(=z´Äƒ^-[¶ ƒ ‚��LLL�‘‘�'N”zd\'''¶… Ö­[‡ž={báÂ…3f {ý)))PWWÇ©S§”¶ÿ>Ÿ�… ¢}ûöhÓ¦ âââ°|ùrtèÐá‹î]Û¶mQ§N°%àe©(«®]»‚Ïç³åßïF…'dРA‰D …ðööÆ_ý¸rå êÖ­‹–-[²ÛŽ?=zôÀÖ­[KtìY³faýúõh×®¤R)öï߯4È`~~>;H—H$‚D"Avv6´´´pùòe888(µ"�;ýû÷ÇæÍ›•bz÷÷íîî®Ô-E•8N±J—w¯ßÿ<ÊÊÊ‚��ÌÌÌ0iÒ¤ ‹çùÓ˜ý}?äKHH((dð&[�¼Â–2`êB.4Ô8Ðr þÞÕÕ8ÐPãBST²ÏSòqj|êÔâ£N->dr 1S†¸t9‚^I ¯É…•aQi¸¦�î5!¤j£„šTªw_ß÷®!,^¼¸Xâ333¥eS§NÅàÁƒñìÙ3Ô«W�í_Ìçóñûï¿#33ááá°´´DíÚµ•ö½q㌌Œ>ëÊ•+•ú:€��®^½ŠW¯^!++ ÎÎÎÅ’á¿ÿþ»XÆwÔÕÕqôèQÄÆÆ"33NNNJû¯X±Bé~@xx8;m˜¶¶6^½zUì¸ï’C555üùçŸÈÈÈ@DD¬­­aeeUlûµk×~2‰÷óóÃðáÃ…zõê}ôzJËÊÊ Ë—/ÇöíÛ±páBL™2…½¶Êàëë �‡åË—cÞ¼y¥šŽŒ|½öìÙÃö¡~_AA455•–iii!??¿ÄÇîÛ·/-Z„—/_"$$­ZµRzßÍž=cÆŒÁ¤I“põêUtïÞìùÿ;í›¶¶6 >z>>Ÿ_,‰mР~øá‡J¿¯6668wîœÒ²/^@OOO©_ù˜1càçç‡M›6áÒ¥Kðöö®°˜4„EÉq‘�>-“ò% òÄE‰öÛ)Ù HäKÈ3l‚Í&ÚB.4…ÊË„JK‚Ϭ�ø°6âC¡’³åˆM•!,®Z",ßÍu­^= +Åb1Μ9ƒ»wï!1±ò»:‘ê�Ï磞½=† úÁïp¤ê¡„šT*}}ýOÎgüßÁ{ÀÚÚúƒÛ¡uëÖ=O«V­>¸îÝ—ÕÏ144üèº÷ û¯÷øùkkë^ׇÎùþv§Dƒõ|ôúßݻϩU«V…$œB¡ãÇ�Çõë×±téR 2䓱–7oooðx<¬X±sçÎ-ö°†�wš4i‚ & 55•}huáÂ4k֬ضjjjLtù|>¦N�ŠM›6!** Ó§OWZîÜ9üøã�àr¹X²d ÜÜÜ”Î?uêT¤¥¥±³.\@Ó¦MËåú´´´�žžŽÂÂB…BÈårDDD|ðšP(üd"ÿ¡õݺuüyó�:uê¶oߎž={*µPûùùaúôéhÙ²%z÷î�‡ªôï’Ï´Õ¹ÐV ûñí Ø–üBÞü“t½f “3Pr %ä%ÙJ-Ýh ¹PrÀ¥¼›Ååþ;×5Ã)9rÄ¥Éqå‰ÖFEs]Tѹ®ß¼yƒ•«üadf…vÝÂÔÊ|þ×3?=©xr¹ Á÷±tÙrL›:NNNª‰|%Ô„•h×®ììì°ać‡cèС•Vîéé >Ÿ�+V`Þ¼y•ÚJNª'''Œ7^^^˜0aâââ°}ûvœ?¾Ø¶žžžðóóðaÃ�••…)S¦°ëFŒWWWhhho!??GŽA»ví�™™‰ÐÐP|óÍ7¨S§\\\0räHxyyáûï¿Gll,vìØ�‹/–ËõÕ«WÖÖÖèׯ¼¼¼pþüù�Žîíéé‰Y³faÈ�!ÈÉÉ)VšýnýàÁƒÙõ¶¶¶X¸p!<==1bÄDGGãæÍ›ÅMkÔ¨ yóæ˜8q" „Ë—/—K7�Šô.1þ…E-Ý…Eååïíô·E‰w^¡ù… ÔøÿI´E\¥×êjˆÔj^ÖÍáµty¨õÏ\×iÿÌu}ëY! kC>¬Œx0Ö©s]‹Åb¬\åç¦mÐ䛊«´ _7�çÆ­ ­oˆõ6`ÑÂ…%j¬!ªÃ[¼xñbUAª¯#GŽ W¯^ªƒTQŸ{èêê¢M›6xôèNœ8� ”¸?ú—ª]»6tuu±yóf¸ººBWW÷ËJT®´ŸIpwwÿèûÎÇÇŽŽŽxúô)ôõõ±iÓ&¥Q«ß騱#;å“«««ÒôZ�÷îÝC·nÝ”úC+ \¸põêÕCvv6²²²�1cÆ k×®¨U«|}}aoo�ððp`Ó¦MJ2666hܸ1Û…CKK ŽŽŽì``ºººhРÁ+[8zö쉬¬,H$øùù¡}ûö°³³ƒ©©©Ò¶¾¾¾(((@RRÜÜÜŠÝ___äçç#99îîîìúÖ­[£Y³fxõêêÕ«‡M›6)�_`aa777¶´½eË–PSSƒ±±q¹¨âß+§¨¯°–ˆ =M.ŒuŠZ^­�ø°«Å‡£….Öj°«Å‡©>zš\¨ 8�Ê�ì|ÞdÉñ*E†ðx)B^Ið2E†Ø493åH{«@Vž¹b’Sãq¿îÖn !¦z<8˜ `ªÇCn!ƒˆx)žÄJ‘S ŸWTz_Â!CÊ݉'�/eоk_Uß*òÐ30‚BÁ øá´lÑBÕá�Oà0å57©‘† ‚íÛ·—zP-òõ“Ëå6lvïÞ]¢í¯]»†Tz ø½{÷°k×.Ì™3§X{Rý 8{÷îUuJ"""àíí�§OŸ*=¸¹ÿ>fΜ©4ò½\.‡““þüóO´ /Påª*¾7Jƒa€üÂZ»ß/5ÿg0µwËyÜ÷ûusþé×ýo‹·º°¨Õûk’+f›&C|zÑhí–ÿÌumVÉs]OŸ1žß†¥mÉç«'äSÞfgâÀÖ5øå½fHÕC%ß䋘šš"22ÎÎΪ…T1111ÅZ¹>å]ËØ† �¡C‡VʃšæÍ›ƒÇãaõêÕ˜5kÖ'ûÇRaaa˜0a¢¢¢°mÛ¶bUÎÎÎÈÍÍÅàÁƒáââ‚ÜÜ\\¼x½{÷¦dšÃáš"4EŸ.o–Èþ--/*+g�™'GBñ»\Â( öOï¢~ÝÿöõðªGâ­%âÀÉR'K $ âÓeˆL”âÎóB˜éñ`eȃ…!¯Â¯'5%¦V6ª¾ä+¢¥­‹ì¬,U‡A>ƒjòE:vìˆ]»vaÑ¢EÅF£%5Wnn.¶nÝÊÎÃ[RÖÖÖX±bþøã,Z´“'O®”Á‰š4i.—‹5kÖ`æÌ™,é%¤´ìíí±sçNÔªUëƒsÁkjjâÑ£G¸{÷.^¾| }}}Lœ8‘FŸ'_D�Ï�Ÿ]�Oo—WXÔ²�/ù·ÅûM¶‚Ù<_RTÀø®·¦è?£š« ¨VÕ¦µ*šëZ€zfHd âÓåˆI•áÁK Œµ¹°6âÃÒ�W!#°Ëår€Œ”+— ¹\®ê0ÈgPBM¾ˆ——áçç‡îÝ»³ó3WõÁdHùS(HNNFXXNž<‰¦M›ÂËË«ÔljD˜0a®^½Š%K–`èС•ÒZçáá�‡µk×búôé°··WÅm$_ˆûÏ—�ÿN?§ jjjŸ•ŸÇã¡uëÖ�±€”¹\Nÿ.ý‡&› ü¾HåÿÎÏ�WX”dç0x“%g“ð¼B†mݱsvÿ;…Ø»9¼Õø•Ÿxÿw®ë„Œ¢²ðÀWhraeă•!ÿ½©Ô!¤ô(¡&_„Ãáàÿûš6mŠK—.áÒ¥KHJJ‚B¡Puh¤’q¹\˜™™ÁÚÚ'N„££ãÏÓÓvvv@DD† Rá%ànnn˜0a~úé'L�:õ‹¯�T>===$''—xzòçÑÝ¿qãÒYL�· <þÇÛwoÛ×FMÑУY…ŽfΘj= bM@-Ô„�*M$aÒ¤I¸|ù2~øá 6Liꡊàää„©S§býúõ˜0a\\\T}H õêÕ ‹-PÔ%ÅÜÜœJ}k(…B�ÄÄD\¹r���Xºt©ªCªÑx\@KÄ…–èÓۉ߽üŸŸÔl¹Òk‰Œùgóâóu³I¸%ùÓçp€Zz<ÔÒã¡I]5¤æÈŸ.ÇÍðB ¬Œø°2¬:s]Ǽ|ÿ…3ððîM¨«kÀ·{oLò[]=}@XH öÿ¹o’âáàäŠQ“fAÏÀ�ÝËÏ+¡¡¡‰ÿ��¢êK)5ÿ…3`mk‡�#¾g—½xö‹g~�¿N]ÿhrüŽ©¹%ºõ„·9Ù˜>z~X»ù£ûÞ»…cûwbÌT?hë||ZÍû·®ÃÀиBjRõQBM©:tè€zõêaýúõˆˆˆÀàÁƒ+´ÜÑÑÓ§OÇO?ý„qãÆÁÍÍMÕ·€”€žž–.]Š#GŽÀßߪ‰¨���ÜÝݱtéR*ù®&DÿôÅÖÿÄ6 ìTaï'Ú¹E¬å*PPÈü3/õûeåEóT«ÿ§Üü}Æ:Eɳ»-�•§@lš ¢$(”2°4,šC¼–.Oes]Ï3Ýû Ư{N ?/;·n@bükèêé#*2ËçNÆä9‹QË܇÷lÇäá½±ëÄ5vÿì¬LÈe2Õÿ…\Üãàîß•ê—΢ž£Óg“iÐÕ7@ãß #=õ³ÛŽ�6c§ÍUõ%“j‚jBHµQ»vm¬\¹Û¶mÃâÅ‹1yòä -···Ç¬Y³ðã�?bÔ¨QðððPõ- % §§G¥½„|Ÿ%œB¬PÊ(ÍÙ�WÈ ý­\iY�„�¦èŸQËÿÛ¯[Ä�­ N–jKˆM“#ôµ9ùEɵ•aåÎu­P(ý­=}Àáp ©¥�ïg,`××upÂ_§®³#�Ïúa5Z:š"=õ �Köo¥\&Ã�]¿áþß× R×Àwýÿ‡mþ`4/÷-þüõg„<º‡Zf–àýsñ“ý–Àи’âpìÀ.D†…BM(BïÁ#дU;¥sܸt—ÎCjr6iŽ!£'A[GgŽîƒH]^�º³Û&'ÆãÀέ˜2w¾ñê„¥³'!#=†Æ€›WÎaäÄYìö‰ñ±8þÏù…"uô2 MZ¶)ѵ¿IJÀæ—±¯5µt0{É¥mÒÓR°ó×õˆ ‚o¼:‚GP”P²²²päÈSk Q)###ØÚÚ¢OŸ>°´´¬�s¨««còäɸté~øá >ÍšU\©•��fÏž�µk×B¡P I“&v.B!åG((êo­§ùéíòÄÊÓ‡å2ÈÎ/T­hÀ58œçç6ÕçB\È (F‚üHÆ:\XðÀ+ôz¸\.ºõ€IC{cÜôyðý¶7ÔÔ”Ïùþ´]™iàóyÐÑÓ/Ññ†ÁôÑ ¡¥�‰³@Fz*üÎÀô…«ð�gÑ4˜³ÇÿN.XðŽíÛ‰KgŽác'C¤^4OÛÏ+À½iKŒ›1¯^DbƘAØqôê:�G²aÕBü}徟¹–Ö6¸|ö8®ž?…oû†��=ü&GûŽ]Ù®:Çì‡Sôÿ:ºzhÔ¬n_»ˆn½!#=ÑÏŸ¡Å7íÙkøyù|4nñ ÆÏ\€èçÏ0mTì>y ¶u>{ýêšhÜâ@Jröþ±Y)¡ÎËÍÅðžÞhÙ¶ÆÏ˜�gOBüð.|ºõªÐß;©ú(¡®æ²²²°hÑ"xxxÀÏÏ�ú •JKKCHH–/_^ázy{{£nݺì(àƒŸ_1i¶¶¶˜3gV¯^ ¹\^á}¸ !„Tž’´vKe ² ÈÊ+J¶så ø\Ôx R²åHΔÃ{ø† �uÑšM8}dvlþ «aØ÷Ó0pøxp?0UàÏË`àÈ ÔJtìÀ{·ðêås¿Äoê¼å8¼ûw|ãÙ …÷þ¾ ÿMB[G#&ÎÀ›Ö¡k¯�lÉõêÍ;Ùãéé¡�+îÞ¸ŒºNx“”€=¿oƱëA°°ª °wúwŒ’ =`fa…›—Ï¡�O( œ:´Ûžc·ñô톗ϡ[ïA¸}í"Z´ñ‚šðߎùk·ìþ÷üz°¯ïŒ;7.—(¡ÖÑÕC·ÞƒÑ/ža֟?yºzúð[¶àÖ¸9n]¿Tá¿sRõQB]Í9r4¢-©ŒŒŒÐ¡CXXX ,¨Ðé‹lmm±råJüöÛoøá‡0eʘ˜˜Tȹj×®�¹sçÂßßr¹­Zµª°ë"„RùòÄÿôËþgÞí¼ÂG%ÏMŠ£)âü3 úZdå‰Yrp¼ 9».#—ËE÷>ƒÐ½Ï ܸ|kÍDvf&ÌZ¤´Ý¿üˆÔ7IXüã¦ûåó¤¾IF·o\ÙeR©&¦æì¹œ\qýâitë=×/ž��]=¥þË!�îáÏÍ?!7÷-¬lê ?/â‚À«¨HÔ2·`“é6n*vüú3ÚùtÁ½›W`[Ïæ–Öìúö»bãêÅ�ɤ¸uõ"<}»)íôàvmYÏž_\PÀžÿK½z gwªR#ÅQB]Ícî\4�T-õë×G¯^½°cÇ,X°àËø êêê˜2e .^¼ˆE‹aäÈ‘V–mee…ùóçcåÊ•�ËåhÓ¦dý²!„¨–Dư‰rþ?‰rÞ?‰ò»×ï-Óý“0kraaÀýg9jü¢ÄQ*g™ óD)t4¸P0@}+NÿzèU± õûÚv脜¬ Þ³Þ[þûƵ¸}í"~ÙuL©üs ŒŒaïäŒ�Ç®|t›ö»âÌÑ8~`7ŒMLñÓ¶}캤„XÌ=>;{Àr¿Éìz]}d¦§B"),VªþNËvÞX½Ïßàø�Ýè3Xy< #SØÖsÀ£»#ðÞ-,\½‘]—÷³Ç Á‡/ v�º€%³';eQNCSñ±1_ø[#_#ª ®æ²²²`jjªê0)æ›o¾ÁóçÏ+í|>>>˜3göìÙÃÎ9[ÌÍÍ1þ|>|W¯^­´ë#„òqyâ¢Ò똞ÆIñ ªמŠq&¨ïäãøƒÜŽ,Äó$)2óð8°ÐçÁÍFoWu úFß5Õ€OCZ9áf£†zfXð §É…Ÿ¹�—âä£ä(PÏŒ�Œ9ê˜ðánS²²ê/‚ñƒ¾Å‹ˆ0@~^®_<'×FŠú@¯[:oßÀæ¿N@SK«TÇÿƳ#R’“ph÷ï첄¸×HINd_ïûs Öüº :ÿM*µ6¿IJ„P¤Só¢1TÂBñàÎ v½cƒ†¨]Ç«ÍD¡¸¨Õøåó\<}T)Ž¡c§à·€Õˆ ÌöÝ~ŸgÇîØ¸z ¸BK[çßó'ÆC¤®Só¢Ê¸'AñèÎÍbûkëêB¤®�ga!ÀÆò9­ÛwÄ�KgØûüð.ž†–ÿ/šT;ÔB]Í) ðxUcnDBÞ' +,©ý˜w%à[·nÅâÅ‹1eÊ—ûyÌÌÌ”Zª½½½+õ:IÙˆÅbœ9s÷îÝCBB‚ªÃ!• 2J$¯<[—ËBÁ/’¤x'…‰.\DˆK—#R=ikk£°°PÕaT9_[ërY$e%Ò àf£ ådr×à !àq�'V ±�Œu>üo�ǃ\&¯Zk …BÎ6‚‘ª‹êÆÜ܇†··7^¿~�¤¤¤¶°¶jÕ çÏŸ/óyZ·nýEû—Õðáᥥ…¨¨(àéÓ§JÛp8_þ }ûöhß¾}¥__yHOOÿäúò¸?U•��V­Z…_ýK–,ÁäÉ“addTnÇ×ÑÑÁ‚ °jÕ*Èd2 8PÕ—LPô°èkªº ¥Çáp¾Ú‡…S“Z—ËâM¶¡1RHd \k `mTü+±DÆàZ˜ºšd¼UÀÞ\€ÚÆÿêljjŠ¤Ø—°¬ã¨êË#_‰Ì´èêê©: òôÈ£†qwwǹsç —ËqäÈ4kÖŒ]———[[[¥Ÿ‚‚çæ“J¥ðððÀýû÷áêê �@ÄÇÇÞ¾}[l±XÌî¿aÃÌž=pppÀŽ; ©©‰ž={=zT,I�5k¶lÙX¿~=æÌ™sss8::bÇŽÐÐÐ`Ëk_¾|‰3gÎà—_~a¿<«««£qãÆJÇ FÆ !ФI$&þ;¿âñãÇѶm[XYYÁÐÐßÿ=är9 33³Øõ½[÷îþµhÑ·nÝ‚³³3š5k†äääÿ~Ñ«W/XYYÁÌÌ ßÿ={srrкukܼy 4€@ @óæÍñæÍvÿgÏžá›o¾A“&M`ccÃÆŒóçÏÃÞÞ«W¯Æo¿ýÆ®2d»?�ÇÃýû÷áââ�@€-Z %%EÅïÚò¥¡¡�3f yóæX°`‚‚‚ÊõøÚÚÚ˜7oÂÃñ{÷nU_.!ä+Uó.�Òr¸òDŒû/$°7㣋‡ú“é ƒK�Å0Ñá¡ 0ÒáÂÉòÓæ:vìˆk§  ?OÕ—I¾�þF£F|%Ô5ŒB¡@“&MpãÆ 9r:t`×ijjâÕ«WxõêÂÃË•G3 ƒ��¬_¿W¯^E~~>LLL°nÝ:E‰Ä»ýÊ•geeáܹsxñâLLLpëÖ-$''ãìÙ³ˆ��…X,f“ówÒÒÒ���­´TT qçÎ$''ãôéÓˆ��Ç£G�àììüÉG‡ƒ­[·âêÕ«ÈË˃žžÖ¯_Ï®ÏÈÈÀÆ�‡W¯^áæÍ›Ø³g@__Ÿ½¾àààb×§P(ðèÑ#lÙ²7oÞD^^´µµ±aÆýnär9|}}ѪU+ÄÆÆ"66¹¹¹X±b{üà÷ßÇßÿ�ÜÜ\hhh €=Æÿþ÷?Œ7>ıcÇ ««‹W¯^ÁÝݾ¾¾xþü9Fމ1cư×ò~ÒÇ0 ~ÿýwܼy¹¹¹ …ظqã½çöïß�¼¼ª÷å¢sçΘ9s&þüóOìÙ³GéáÈ—ÒÒÒ¼yóðâÅ üùçŸ5®eŒòe$2Yy $dÈñ"IŠ� nGâb¨ÇäcÏßy¸ô¸!1R$dÊ!•3Ð×äÂÞL€VB|×T}[j K#u´o BÓºB4°ÀÆ„]ÞWQª]Z™¹ \{*Æ­gbؘðÑÍC6&||èNä%Óµ�ù�È€4±ûü\Ó^^^hèê‚ÝK|÷2R“Á”C73R³0 ÒÞ$âöÙƒxþ4„Æe©¨ä»†)((ÀèÑ£±cÇp8œR8¦P(ðË/¿ÀÐÐн{wœ={¶Äû·nÝ055…��´µµ¡­­�œœœRíoffoooèèè@[[ÙÙÙxûö-444>¹?Ã0ؼy3tttݺuÃõë×Ùõ#FŒ€T*Ń---„„„àÿû_‰â“Édزe ´´´]»vÅíÛ·K´ï�7ðöí[ôìÙ¯_¿P4§åœ9s°lÙ2EU[·neû¦wéÒ<`�…-Z6lˆ¨¨(äææ²ñ”ä÷»uëV…Böø_Ú‚›››‹3f sçÎðõõ…ššÚ¯<Õ­[·ÂJÀ5440oÞ<øûûã�?þÀÈ‘#¿êrúšÊÏÏÎÎÎóFŽ©êËT²ÿ~p¹\'à PßåÊ“�¯Àã×R¤æÈál-@['¸Ÿ¸}9 \}"F}Kdr #WoWJòñÍápð¿ÿýM›6ÅÅ‹—pæÁ ¼IN.—±[HÍ¢o`€FîîXºt)ôôôTù J¨k Î�;cäÈ‘X¾|y™ö?)‰DUæ +++DGGƒa˜O&.ŸŠóæÍøý÷ßáíí wwwØÛÛC*•~Ñý)iËgrr2Äb1–,Y¢´Ü××·Äñ<~~~˜1cŽ;†Ö­[—8™.ÉñËbÔ¨QèÚµ+:„iÓ¦¡gÏžh×®]¹Ï ]Vššš˜9s&Μ9ƒ… b̘1pw/Ÿò*‘H???¬]»Û¶mÃèÑ£)©®&Ö­[( hiiaÖ¬Y˜8qb±íNœ8�ŒŒŒrM¨===áêꊽ{÷âöíÛ¥N¨Åb1~þùg\¼x|>½zõ¸qÿŽÊ;kÖ,>|@Ñ‹=zôÀÌ™3Ùiàïï�µk×(ª>š;w.ÆŽ  ¨{%ÔG}—«†· <Ž•"9K'KZ:?;gtfž×ÂÄp³U—DÄKÐÑM|^é~ŽŽŽpt¤~Ô„Ô”P×@B¡×®]ƒ��]‰[O+ƒššZ±–êÌÌÌïߺukˆÅbœ:u Ý»wg—K$’µŠÆÆÆbÁ‚xýú5´µµOŸ>EVVV¥\ýúõ¡P(ð믿–zôð÷¹¸¸àôéÓ°±±ÁâÅ‹‹­‰Dl}e155ŤI“ðêÕ+8pgΜAŸ>}мyó*“`véÒì(àýúõ+—¤_$aöìÙX·n¶lÙ‚±cÇÒˆ�UÜ•+WðóÏ?#((VVVxþü9þúë/(Šb¿»ˆˆˆr?¿³³3àÞ½{xþüy©÷Ÿ9s&ôôô°mÛ6dggcذalbž––†Q£FaþüùÆÜ¹sñ÷ßãܹsàp88{ö,¶lÙ‚Ç�ÃÂÂÏž=Ãþýû?û°²¦ Öåª-OÌàI¬ r8ZЬ®ü|”§æÈq3¢Më !ä?+„—³êjôû"„|%Ô5TÆ UB1NNNÈÏÏǺuëЦMìÙ³ÑÑÑl óçhjjbãÆ�:t(V¬X'''„††âÏ?ÿÄ£G�>»¿P(„D"Á�7àää„'N`×®]JÉyyxöìvîÜɾ‰DèׯÜÝÝѦMôìÙK–,�±±1®_¿333tìØ±DÇ>wî-Z„¦M›B(âÍ›7Åæÿæ›o0jÔ( 8µjÕBll,ÚµkW®×ø1¶¶¶ðóóCxx8öïß�S§N¡ÿþpuu­”óNݺu±råJüúë¯X¶l&MšÄvoøB¡3gÎÄO?ý„M›6a„ ”TWaQQQ°¶¶†••ÀÞÞK—.e×ïÛ·/^d_wîÜ}úôa_>|FFFHMMÅü‡ƒ3f(�YqíÚ5üüóÏ(((€¥¥%€¢V­9sæ”(Æ'Ož`õêÕHHH€��~øá6Þ€€¥÷×”)Spþüù¶t»»»ãðáèS§®^½ ///DEEÁÆÆ†�ÂÑѱØÃ9555>|Û¶m�ÇÃìÙ³ÙÏ…B�C‡áèÑ£HIIAݺu±lÙ2˜šš²÷ÏØØ���¸pጌŒ°dÉÔ¯_Ÿ=~HHÖ®]‹ÄÄDÔ«W?üðÃg¤(oÔº\}åK„ÅJ›&ƒ½Ý«CPÂßER¦w" ÑÒAM—‹ÑÊA=Múœ&„|%Ô5ˆ¥¥e±òassstéҥض|>Æ Ÿÿï[„ÇãaذaJe�uëÖUú’ø©ýÝÜÜØ–ÑvíÚ±ý·û÷ï}}}hiiáÈ‘#ذa®^½Š)S¦ S§NlÉ´››ۂݾ}{vÿ°ýK kkklÞ¼‡‚££#Ž;�ÇÆôþô9öööì(ÚµjÕÂÁƒ±iÓ&0 ƒààÁƒxñâE±ëSSSðaÔ¾´ ‚b×ìàà T2îææ†ØØX¥~Û:::èׯ€¢/š[·nÅ?ü±XŒæÍ›³¿³wç|¿Õô¿%e:tÀÁƒ±}ûvE-Q‰÷î݃¾¾>€¢QHçÏŸ�… ‚Çã¡uëÖh×®„Ba±ãׯ_¿BJ³�œœ°téR<|ø»w®.ú÷ï�ºuë–û¹JKKK‹-_°`ÆŽ 77·/>®ššf̘�õë×# “&Mª2eïDY÷îݱlÙ2øúúbÞ¼yhÓ¦�Òú¦M›ÂÌÌ °uëV*%Ô���8~ü8ºvíŠ+VàâÅ‹èÝ»7’’’ ®®Ž°°0 4.\€©©)ºwïŽnݺ•øÁYPPºvíŠõë×£iÓ¦8{ö,Ú·o�'Ož@]]½ØÃšèèhØÚÚ~ôxZZZðòòÂÍ›7áåå…ž={bÕªUèÒ¥ æÍ›‡V­ZÛçÀ��ÉdX¹r%Μ9ƒ^½z!)) jjj Ĺsç0~üxXYYaݺuèׯnܸxøð!öîÝ‹%K–à÷ßÇŸþ ooo<þxðàzôè�€€xxxàĉðôôÄãÇ�•þý) j]þúˆ¥ žÆIýF†º¦Eƒ� %ÿ=Å¥Ëñ ªmœ„ÐVçâBHÜlÔ`ªGŸÏ„�bHµ6`ÀU‡@ªˆ«W¯2]ºt)¶ÜÌÌŒ TIL%yÊåræÚµkÌĉ™Ÿ~ú‰‰��WI¬ÉLš4‰Ù»w/#“ÉÊå˜R©”ùñÇ™ü‘‘J¥ª¾Ä¡,Ÿ“éééÌœ9s}}}¦qãÆÌõë×?¸Ý¬Y³˜9sæ(-óóóc†®´LWW— e†a~ýõW¦ÿþìº�72“&M*vìU«V;Ã0LÏž=™õë×+-ëÒ¥ sêÔ©bÛ>þœ±´´dbccÙeÆ c–/_®´Ý„ ”bHMMefΜÉèêê2Íš5cþþûovÝŒ3˜1cư¯ £¡¡Á„‡‡;jj*súôi†Ãá0ùùù Ã0Ì´iÓ˜Ù³g+mgkkËœ9s†a†éÚµ+³yóf¥õ>>>ÌùóçKý{|ß?ícŽÝÏc.„0·ž‰™àW…ÌóD Ÿ.c2såL¡TñEÇ'•«Pª`‚_2ïä1�^2’Òÿþ^¾‘2Gîå1¹rF&g˜óÁùLhL¡ª/�RÍP- !_ „††bÇŽ¸~ý:Ο?�¡C‡¢E‹å6ÈVEàr¹h×®~úé'ØÛÛcùòåØºu+ÒÒÒTìíí±råJÄÅÅaÙ²eÈÈÈøâcòù|L�:<?ÿüs©½#•ÃÀÀþþþˆ‹‹CÏž=áëë‹gÏž•x]]]¥×ÚÚÚ�H$€fÍšáöíÛˆ‰‰A^^Ž?^ª*ˆgÏžaÇŽhß¾=û‹‚‚¥í’““ѽ{wlÚ´‰-ÿ˜ääd³¯�ŒŒ°víZÄÅÅ¡K—.ðööÆË—/?x}GéúÄb1.\ˆV­Záûï¿Ç�;wÀ0ŒR|ÿí‹]»vm$%%±×÷Ûo¿)]_bbb±ë+­çOÖÈy—¿6R9ƒ'±Rœ|T‰ŒA—Fêð¨£Q)Z¥ 2QŠÇ1tpAO“‹ÛÏÄÐÑàµvÕ™‰‚R=PÉ7!_ {{{\½zÇŽÃßÿ <ÞÞÞª­DºtéOOOœ>}š-µýî»ïJ=Ryyz7ÂóéÓ§±`ÁŒ3æ‹KÀy<&OžŒM›6aݺu˜>}z•šNŒüKSSsçÎÅ©S§ðàÁƒr¹×ÎÎ666˜:u*òòòðí·ßbĈÜ–ùÀæfff¸�¥¥%‚ƒƒ!‹QPPÀ¶Oœ8‹/ÆãÇ�r¹çÏŸg÷{öìÚ·o�I“&¡U«Vˆ‰‰ALLL±jˆÌÌLܾ}›�#þÝ�£F�ÂÂ… ‘’’¸zõ*¢¢¢Ð¸qã]_BBjÕª.—‹üüübS¾»§111`?þø#¸\.Ú·oÏ^ߢE‹ðôéS€L&Sº>R³(À³)N>ÊGVžÞ Eha/,s2üJ‚ש2x»Š )ä 2±hj­6õ…ŸœŸšB>†êj®V­Zì—Bª’—/_ÂÄĤÌûëèè`ذaX¾|9’’’0}út\¼x2™Le×doo�+V 66+V¬øâp.—‹qãÆÁÈÈkÖ¬QéCò¯w-¬®®®àp8˜:u*víÚ‡bÛêëë³þ½¿ÌÀÀ@i™••; –——®]»333p8ÀÝݧOŸVÚ§wïÞ¨]»6LLLàì쌰°0Àwß}‡•+WbèС°²²‚££#._¾ÌþmøùùA&“aõêÕJeÓÑÑъʹÿýw4iÒ‹/Æ Aƒð×_±ç]²d Ñ Ap¹\Ìž=ûöíc[§?tÍVVVl•ÅÂ… qñâE£cÇŽhÖ¬Ú´i£ô€ÍÂÂC‡…¶¶6N�:…3gΰû÷éÓ‹/ÆÀ�amm '''\»v�×0 x‘$ɇùHÉ–ÃÓY„VŽB託í«+àAT!R²åðv-š+.]Žðx)Ú5•xDpBù/ó¡z2RmlܸðññQu(„(Ù°a,--Ñ«W¯r9^\\öïß�øøxôîÝ­[·VÙœ¸ ÃàÔ©S8þ<Æ�÷ÅÓ~1 ƒ?þøñññðóóû¢yÈIqÄÞ½{UkèСèÞ½»Ò߯Ï?ÿŒÓ§OãÊ•+ª¯ÂMŸ>B¡«V­ªÔóVµ÷ù0†¢Sdx+�®: mÔ` õeí? ܉,D�”A;'!ø<Òß*pý©í�E_||BHÍFŸ Õœ··7N�:…¼¼êÔ©ƒaÆ¡sçΪ­RìÛ·|>¿Ò Tµ÷ùW\𠡝¥Pãsа¶µÊih™œÁõðB¨ 8hé ‡Hd .„ŠáhÎG=3�ª/�ò „ú+qùòe\ºt ñññô䟨Œ……š7oŽ.]ºTJÙ2Ã0¸uë> KKKôïßÿ³ÓUT'OžÄ… Ê¥|ïÞ½ Ãܹs¡­­]é×óµ2d¶oß�€¾<×Tr¹Æ ÃîÝ»U yOb†¡¯‹Ûkh£sýòI¤�¢ÄùZ˜úZ\4©+Eœ] ÃH› w[šY�R>(¡&„T{2™ W¯^ÅñãÇáììŒ>}ú(Í©[Yž={†_~ùmÛ¶E¯^½Àå–½”ðàÁƒ Äüùó¡££Sé×ò5™1cF�].S^‘ê))) ëÖ­Ã�?þ¨êP€ä¬¢DZ&\k«Áʰüi(�0¸&†¹>O)q¾Y†Z;ÒôX„�òÃ[¼xñbUA!_‚ËåÂÎÎ^^^HNNÆo¿ý†ôôtÔ©S‡Y¹2¡uëÖ¸xñ"nܸWW×2·Ô7hÐ999Ø»w/š6mJ•}�ÜÜ\£yóæª…¨ÈÝ»w!“ÉÊmê3R6©9rÜ�”àuª ¬hRW]�òíÜWÈàò1lMøhXûßd:4F‚Ì<mœD4=!¤\QBMùjðù|Ô¯_íÛ·ÇóçϱmÛ6ˆÅbÔ©S§ÒÊ}…B!Zµj…ŒŒ üþûïì´Geáää„‚‚ìÞ½Mš4�ººzeÞίF�:upäÈ( g¢ÊËËÃæÍ›Ñ¿©:œ)=W�ûÏ •,ƒ£…Íê ¡§Yþƒ�å(p屎8Yþû™•,CT² ^.4=!¤üQÉw C}­IEáóù°··gçÆ­ ÒÒÒpäÈ„„„ k×®ðññ©Ô~´áááØ¼y3Úµk‡ž={–¹üÝtJ ,€¡¡a¥Åÿ5yóæ üýýaccƒŽ;ÂÎÎŽúTå¤R)"##±sçN¸¸¸àÿûŸªCªq²ò}-AF®ÎVj°3åWXëpfž×ÂÄp³UC>»<)SŽ»Ï áÓP-�èM)”P× ïF:t(èË$)W2™ ·nݾ}û0eÊ899©:$VBB<ˆèèhôêÕ mÚ´ù¢þÍ¥‘���M›6A¡P`âĉÐÓÓ+ÓqΟ?�óçÏcþüù*éþ5‹Å8sæ îÝ»‡„„U‡C*‡Ã�¥¥%¼½½Ñ¡CU‡S£ää+ð8VŠ”l9œ,°7 "?rSsä¸Qˆ¦u…Jý±3ó¸úDŒ¶N"éP2M©”P×Ïž=æM›àïïMMMU‡C¾bOŸ>ÅÆ�1yòä*•T@TTöïß�ììlôíÛMš4©”ó2 ƒcÇŽáÊ•+?~<œ��ËtœK—.áôéÓ˜7o^…NIF!e‘+fð$V‚Ä 9ê[ `o.¿‚óؤL9îD¢¥ƒfï�ž_ÈàBh<ê¨ÁÚˆÿg „�O£>Ô5ľ}ûвeKÔ¯__Õ¡�¯œ‰‰ ììì°qãF¸»»W©ª ЦM˜ššâðáøqãjÕªUá-¾õëׇ­­-~ýõW ~ýúàpJWûhgg¡PˆmÛ¶ÁÍÍ�¦Ô"„T ù… ‚^IôJs}>Z9 aªÇ«ðÁ¿âÒå¸÷¢mœ„JsWKå ®<£ž©uM©�R±(¡®!:„ï¾û޾€“Jall ‘H„Ó§O£M›6ª§˜ZµjÁÓÓêêêøë¯¿ èëëWø}iÕªÎ�;‡[·n•ip[[[hjjbË–-”TBTJ,a#Å×ÔÒ塵£æú<ð*aíè‚¢%ðtÁPûßdša€á…0Ðâ¡¡ Í5M©xTò]C 2þù'x¼ò�ë‘��),,ÄèÑ£±k×.U‡òIr¹ׯ_ÇÑ£Gáèèˆ>}úÀÔÔ´BÏÉ0 Ž=Šk×®áûï¿/SiüíÛ·±wï^øùùU™Aà!5C¡”Ax¼QÉ2ØÕâ£�•BAå�ž™(ED¼ž."è¨+×”ß{^±”A['JYD!eB#4Ôr¹œ’iR©„B!d2™ªÃø,�///üüóϨ]»6/^Œßÿ™™™vN‡ƒ^½zaܸqØ´iŽ=ZêQ÷[µj…!C†`ÕªUxýúµªo#!¤�È<~-Á©ÀÈä@Wu4ª£V©ÉtXœ‘‰2x7T/–L‡ÅJ‘•§@kGJ¦ !•‡jB ¦¦†îÝ»cݺuÐÒÒœ9s°ÿ~äååUØ9���±bÅ „‡‡cÕªUÈÎÎ.ÕþÍ›7Çðáñzõj¼zõJÕ·�ò•’É„ÅIqòQò% :¹«£I]5¨«UnÖüJ‚ש2x»Š )T>wLŠ Qo¤hÛ@>µB*%Ô„òMMMôïß«W¯Fnn.f̘�“'OB"‘TÈùôôô0oÞ<ØÛÛcþüù/ÕþMš4ÁÈ‘#±fͼ|ùRÕ·�ò‘+€ˆx)N<*@N¾ŠÐ¼ž°X2[Ñ¢ ‘’-‡·«¨X"ÿ&[ŽÀW´o ªô$ŸBhP²âÈ‘#èÕ«—ªÃ(wÉÉɸ|ù2+ô<×®]ƒL&ƒ¡¡ág·MHHÀ±cÇŠÐÐP¸ºº–z4çÿºrå   *ô:Ë[u~ß©««£Q£Fhܸ1îܹƒ={ö@$¡víÚå>‡5‡Ã�““¬­­±yófH$8::–ø}cnnKKKÀÞÞ¾DïSBù¼H’âïˆBp8´°¢žYåö“~‡a€;‘…È+dàé,‚€¯Cv¾×à ÑÚA¨48!„Tj¡&Å<þÇGzz:»ìäɓسgO©Ž“ŸŸ�#FàÖ­[eŠ#""¡¡¡ŸÜfÆ èÑ£âãã+ôžàæÍ›%Ú6==ׯ_Ç… 0lذö#öóóÃðáÕ~öîÝûÉë,ë}$_ÆÔÔ“&MÂÌ™3ñðáCÌš5 wïÞ-uŸç’xWþôéS¬^½999%Þ×ÍÍ &LÀO?ý„gÏž©ú¶Bª!†¢’e8ù0‰™r´wá›úBèj¨æë¢\ÜC*gо�|žr2-–0¸þTŒF¶jJÓfBHe¢„š“œœŒ]»vaÍš5ì²ÐÐP|ˆÍ›7—)ŽcÇŽáĉŸÜföìÙ¸ÿ>,--U}ÛX®®®Ø±c~ùå—�nsôèQ£]»vìOݺuU:ù[[[øùùaÔ¨Q8wîæÏŸ�Ç�—ûyÞ•€ÛÙÙaÞ¼y¥JŽ]\\0yòd¬_¿¾Ô¥ã„�š‹ð*E†S�ˆM“¡u}Ú5A_Su_erמŠ!àqÐÖIÞB‘)€ëábÔ©%€­ _µ7�R£Ñ'ù æÍ›ã¯¿þÂôéÓQ«V­nsóæMÜ»wuêÔA×®]‹Í§{ðàA,_¾cÇŽEAAÔÕÕµ\_¹r]»vŹsç///´lÙ@QÉô‹/p÷î]ìܹ`mm�öíÛ#''ÇŽcÏ#дiSöu^^®]»OOO>|èÚµk±„õúõë¸ÿ>êÕ«‡.]º@(²ë†Á… ooïŽ�~ãÆ „„„@]]=zô€±±q©î±��:tèðÁu ….\@hh(|||>xþ+W®àîÝ»°°°`K�{öìÉÎKŠ«W¯BGGß~û-ŒŒŒØ}% Nž<‰§OŸÂÆÆ�:u‚‰‰Iù¿‘¾BNNNXºt)>|ˆÝ»wCWWýû÷/×"\.}úô�ƒƒбcGtïÞ½D%àNNN˜:u*Ö¯_� &ÀÅÅEÕ·ŒR…ŦÉðøµBÍë©ÁDWõ-½ƒkabèkqѤ®ÿýäcÜ~&†ž.ÖU‡K©á¨…š|‡ÃÁ�!C°zõê®=z4¦M›…B�ãÇ�ÃÃÃC©D<777nÜ€¯¯/š6mгgϲë222ðý÷ߣoß¾8{ö,ÒÓÓÑ¡C\¿~@Q©÷Î�;ñâÅ ¼zõ ׯ_Çõë×(((`—�:u ãÇ�WŠ--- Æ ƒ··7""" ²Û 6 ³fÍÃ08|ø0š4i¢4MÒÀ�1gÎbÕªUøûï¿•Îáããƒõë×C,ãÁƒhذ!RRRÊåÞ3 ƒþýûcÞ¼y(,,ÄŠ+pçÎ¥mfΜ‰U«VÁÊÊ û÷ïÇòåËqýúuV¬X�(*á÷ððÀ‹/Øý{ôè�ÇÃÆÆÑÑÑèСC…Nõ5jÒ¤ V¯^�Ö­[cÆ øù矑��P®çpuuÅŠ+ZªpGGGLŸ>›6mBHHˆªo!¤ JÈ�ãlPÂã¥ð¨£oWQ•H¦ $ .=ÃD—‡¦H¦ ð¥rдž°ÔÇ'„�rÇ�aÀ€%ÞöÆ�Œ››“’’Â1 ÌÒ¥K™É“'3 Ã0—/_fÌÌ̘·oß²û 6Œ™0aûzß¾}LÏž=†a˜mÛ¶1}ûöe×ÅÅÅ1\.—yðà»lܸqìñß;v,³dÉ’OÆúòåKFGGGiYLL #˜””vÙ¬Y³˜þýû3 Ã0çÎ�c,--™¼¼~ü˜111a233Ùe7ndFŒÁ0 Ã( F$1�=*ñ{¢¬ À¬ZµŠ¹|ù2“žž^áçS‰Dœ>}š7n³eË&55µ\�/—Ë™ýû÷3'Nd"""J¼_TT3nܸJù]Bª‡Ä s.8Ÿ9˜ÏħËTŽ’\±‚9ñ0Ÿy+ùè6ñæt`>#‘)T.!„0 Ã0TòM>H¡PÀØØ£G�ÆÊ•+•ú(ß¾}žžžÐÒÒb—uïÞK–,a_[ngg‡Ù³gcíÚµP(Js„�š%%[ŽÐ×RJ¸ÖÀÚ¨j}Ì)Pàê1ê[ à`þá2î¸4"¤èØPM�E©ªÖ§)©rfΜ‰úõëcÔ¨Qì2>Ÿ_lN^‰D>¿èíôöí[\ºt 3fÌ@LL ÀÒÒgΜAß¾}?xž%§ÜFRÎÉÉaÔÏůP(>yÞììl4nÜÓ¦Mî]» ««‹qãÆ•Û=g …â£ë9¦OŸŽï¾ûÍš5Cxx8¶mÛÆ®WSSƒ¹¹9†ª´Ÿžžûÿ£F�ÂСCqçÎ\¸pÍ›7Ç–-[лwïr»Žwš5k†fÍšA¡Pàùóç B@@d2ÜÜÜФIÔ¯_Ÿ½ÿÕ™ºº:úô郎;âèÑ£˜1c|}}Ñ©S§bc ”…««+–/_Ž_~ùÏž=Ãøñã•ü|ˆ­­-æÌ™ƒÕ«WC.—£yóæª¾M„�J”öV�ǯ%È3p±ÀÆ„�ª–Šfæ)p-L 7[5ÔùÈciox%�§‹•<6!„|JõÿK*”��Æ�‡]»v¡{÷;bíÚµHHH€…… vî܉.]ºNœ8�fÍšáý)ÎÕÕÕqðàÁ�&Ôbff†—/_–)n…B�ääd˜ššB.—c×®]èܹ3À××HJJ‚™™Y±õÍ›7ÇØ±c‘�� ]]]dee!**Š=vpp0ÔÔÔ0aÂEž={sss¥455Áãñ�’’RªQÈ›5k†I“&!'':::ÈÌÌ,v¶lÙ‚ÈÈH¤¦¦;¶¯¯/æÌ™###8;;är9är9€¢>è¯^½‚““Ú¶m‹¶mÛ¢°°W®\©�„ú.— GGG8::bàÀ�HJJ£G�pôèQÄÆÆ¢aÆpww‡»»{¹´êª’ŽŽ† †.]ºàСCìOOÏ/~p```€ùóçãСC˜?>&Nœ{{ûOîS»vmÌ�;þþþ�ËåhÕª•ªo!¤‚eæ)#AVžÎÖj°«ÅG §¶¯T©9rÜŒ(DÓºBX~¸w®X�›áb´pªtäqBùJ¨ÉgM›6 7nd_{xx`Á‚hÚ´)¼½½ñôéS˜˜˜`îܹŠÊ½¿ûî;¥c|ûí·X¼x1rssK|Þ!C† E‹èÑ£ôôô “ɰ{÷îíËãñлwoX[[#22:::˜1c€¢„uÖ¬YhÒ¤ :tè€'OžÀÒÒ³gÏtíÚ-[¶„››Úµk‡§OŸÂÀÀ€=vãÆ�¡P(Ø‘±ccc?8·P(Ä€ЩS'4jÔ¦¦¦Jƒ¼Íœ9úúúìëV­ZaùòåøöÛo±{÷n¸»»£M›6‡¡¡¡Ò±���áíí ;;;€††¾ýö[øøøÀÚÚ[¶lA‡жm[hhh 00ëÖ­ƒ··7âââ0tèPèëëÃÅÅééé¸yó&Ž?^iï) è�I·nÝЭ[7äää $$�=Ÿþ 4jÔ�7þè(óÕ�±±1¾ÿþ{ÄÅÅaÿþý8sæ z÷î�Ö­[—hÄî�áñxèß¿?±~ýztêÔ ]»výä1­¬¬0þ|¬\¹r¹mÚ´Qõí!„T€ì|¿–"5Gg+Ú8‰À­‚‰4$eÊq'²-„0Óÿp2](ep-¬®µÕ`®¯úAÓ!ä¿8LyÕÔ’*màÀ�Ø»wo‰¶-,,DzzºR‹kJJ ø|¾Rb™””„ÈÈH*MÍ##£b%®¯_¿†™™x<âããQ»vmv]vv6¤R©ÒÔN@Qëï»Ñ¹ÝÜܔʖ�¢¾Ì‰‰‰°¶¶V:Oýúõ‘““ƒ‡‚Çã)M«õλé¹ÞoÉ}_pp0rrrдiSˆÅb¶åT,ãÑ£Gàóùhܸ1 —ˋŧP(ðàÁˆÅb4nܘÝ?!!R©Ti[ ¥©«‚‚‚ðöíÛbç�‰‰ÁðáñlÙ2Èd2@tt4Æ��W¯^±¿·¼¼<œ(+Àå'b˜èráf£VÊ3BHå „º†(KbS]½~ý‹Åª¥BìܹçÎ�ÃþýûÙeáááðôôDTTT•*—.�÷ÝË—/„   dffÂÝÝpqqQš;¼: Æþýû¡¡¡�þýûÃÁÁዎ'—ËqðàAܽ{·D%àoÞ¼ÁÊ•+ѵkWx{{«úvB¾@^!ƒ'±ħËáh!€£9ü*>`WtŠ !¯$hï,úd ÷­g…€ÖŽÕó³žR3PB]CÔ¤„:!!žžžå:jxUòöí[ <111prrBbb" Ö­[÷Á–xU*ï÷]ZZ‚‚‚ðèÑ#¼|ùŽŽŽhܸ1ÜÝÝ‹UTu ÃàÖ­[8|ø0,--Ñ¿XYY}Ñ1CBB°uëVtéÒ]ºtùdk~jj*V¬X___øúúªúvBJ©@ ,VŠ×i2Ø›ñáh!€¿j'Ò™(ED¼ž."è¨<™~%AÚ[¼œEàVá–vB¡„º†¨I uMñöí[¤§§C[[»X몢"ßwb±AAAFpp0ÌÍÍáîîŽÆ�qbZ™d2®^½ŠãÇ�ÃÙÙ}úôù`Ÿü’JOOÇÆ�¡©©‰ñãDzb!==Ë—/‡——ºvíªê[A)�B)ƒ§qR¼|#C]S>œ, ª~" aqRD¿‘ÁËEÍOŒÔý"I†g RttU‹‡„�š�êbðàÁعs'x<ЃT¹\ŽaÆ•x ¹/=Wdd$†aàáá8::V‹÷½X,ƹsçpþüy´hÑ={ö„ŽŽN™ïÇ�pïÞ=Lž<ù“sŒgdd`ÅŠhÓ¦ ¾ýö[UßBÈGHd "â¥x‘,ƒ�1ÎVˆÔªO²üJ‚ÄL9<�EPÿD܉™rÜ{^Ÿ†êÐUŸë#„Ô\¼ÅïÏmD¾ZW¯^…»»{™¿ RZ¯^½Â³gÏàããSáçâr¹066FÆ áëë dddàòåËØ»w/âââØAï�ªoÍñù|Ô¯_íÛ·ÇóçϱmÛ6ˆÅbÔ©S§Ô1s¹\¸¸¸ÀÔÔ¿üò 8ÎGûU«««£Y³fسgÞ¾} '''Uß BÈ{¤ráñ2܉,„¦�ƒÖŽ"Ô6®úý¤ßa<Œ*Dú[¼\D}¢5=3W�¿# Ѷ�z4=!¤š êâ�?þŸÏÇСCU ©rss±téRøøø C‡*�%++‹�’+""uêÔa[¯¿¤´º¢¥¥¥áÈ‘# A×®]áããS¦‡iii€ŽŽÆ�MMÍn—““ƒ+VÀÃãTóÅB*†L<ÿ§¿±¹.ÖjծŖa€;‘…(�2hç$üäC€¼BC ÐØîãóQBHUD u ‘••…E‹ÁÃÃ^^^077—Fù åH¡P 99aaa8yò$š6mŠ!C†T©i®$ žFPP~ûí7tïÞ�;wþà6¹¹¹ð÷÷‡ƒƒ† ¢êË&¤ÆP0ÀËdÂâ$0Ðâ¢amµj[ö,“3¸^u-Ïeu«€IDAT„øÔsU\ CWƒ‹ÆvUës—BJ‚jB�’’ÂjöêÕ+899±­×Uiì�Ç�cÿþýàóùèß¿©û<¿+×ÕÕÅøñã¡¡¡Ql›üü|øûû£N�::th•ª2 äkÃ0À«žÄJ £Î…«� µªg"  žv-L }-.šÔâsŸwŸB"cÐÆIôÙm !¤*¢„šBþ#??Ÿ�’+$$VVVpwwG“&M`nn®êðÀ0 îÝ»‡C‡ÁÄÄýúõƒ­­m‰÷—Ë娷o>|ˆÉ“'ÃÎήØ6b±þþþ°´´ÄÈ‘#)©&¤¼N•áñk)ÔÕ8hh#€±Nõî;\ ap5L s}Üm?ßÚü$VŠ„ :¸ªƒ_}Ÿ!Bj8J¨ !äd2ž={†G�!((<�ÔÌÁÁA¥cÈår\¿~G�…££#úôéSSÓïˆmÛ¶á»ï¾ƒ¯¯o±õb±k×®E­Zµ0zôhJª )'qér<~-Ÿ4¬­S½ê�HEƒŠ]y"F�ZESz}NtŠ O^KÐÑMý“#BHUG 5!„”Âëׯ„   ¼yóîîîpssƒ»»;D"‘Jb’H$8þ<Ξ=‹Æ�£W¯^Ð××/Ѿ©©©€¾¾>Æ�W¬¼°°ëÖ­ƒ¾¾>ÆŽKƒò3å�‘(J¤Í ª" 9 \}"F}KÌ?ŸL'gÉq'²\DÕrÀ5By%Ô¥ ‹qæÌÜ»w ª‡�*…ÏçÃÞÞC‡…•••ªÃ©ì”\‘‘‘¨[·.ÛïÚÈȨÒãÉËËéS§põêUxzz¢[·n�&ë}r¹{öìA`` ¦L™‚:uê(­—H$øé§Ÿ ©©‰ &PRMH)½É’#ôµƒ†µ°2â«:¤r“™§Àµ01ÜlÕPÇäóו�¯Àå'b|ã(„‰î×ñ@�R³QB]BoÞ¼�¿¿?lllбcGØÙÙ•iNXB¾V2™ ·nݾ}û0eÊ”R–UÝâñãÇì”\ððð€»»{±µ¢effâÈ‘#xôè:wî __ß�ZþðáCüñÇèÑ£:v쨴N*•býúõ˜4ix<ú"LÈç¤æÈñøµù… \¬¨mÂÿªÞJÍ‘ãfD!šÖ-ÙÜÑB àV[ 6%H¾ !¤: „ºÄb1æÎ� ooï�N5C)òôéSlܸ“'O®qIõ; Ãàùóçì”\………ì fõëׯ´‡qÉÉÉ8tèž={†ž={¢]»vŸM„SSS±aÃbìØ±J%à2™ 6lL™2|>}!&äC2r�‘ »@뢖ۯm‚¤Ì¢²í–B˜é>™–É�K� `eT²>Ö„R]PB]GŽA||<¦L™¢êP©"""€ ÀÂÂBÕá¨\rr2;¨ÙëׯáêêŠF�ÁÝÝZZZ~þW¯^áÀ�HIIAŸ>}мyóO0&“ɰgÏcÊ”)J#ˆËårlܸR©S§N¥JBÞ“•§Àãפ¿UÀÙZ v¦|p¿²D(TíAT!ÚÔ–hdr†n„‹¡®ÆA³zBU‡O!åŠê˜1cF� GGGU‡BHµqùòeÜ»w ,Pu(UJnn.‚ƒƒ„Ç�£víÚhÔ¨7n\ªºË"<<û÷ï‡L&CÿþýáêêúÉíß•€÷ìÙ>>>ìr…B�M›6!//Ó§O/Q99!_³œž¼–âM¶N–Ø› ðµ5�"CÈ+ Ú;‹ ¯Y²‹|%Á[±íˆ¾º–zB¡„º† ‚íÛ·SK !¥PXXˆÑ£Gc×®]ª¥Ê’J¥ˆˆˆÀÇ ¡PˆÆ�£Q£F°··¯°iª>|ˆƒB÷ÿìÝwT×ÛÀñ/¤H•&R;ö‚½ÇÄÞ{oQcbb7Ñ$j4EcŠKÔ¨±%±$*F±7T@T¤w) Ë2ïüœ7Ô k¹Ÿs<Ç�zg`—}æÞû<•+3pà@<<<ž¸mRR«V­¢J•*Œ?### 8¨^»v-ééé¼ÿþûˆ^'áÍ“­�¹W@\šŠšŽÅ®u_ãô7㔄Ç*iWÛ3£ÒÓá±Jî$Ò±®!z:"šáõ#êR}ú<±ä×ùóçÙ´i}úô¡cÇŽ@qP½aÃbcc™={¶ª…ךB)ö¿À²º½.ÞUõÐ×}ýÅ«w ˆKWÑ®–!F¥ Œ“³TÞȧ}mCÌK94\áU$êRA� <ñÞ) …‚«W¯ÌÕ«W±µµ¥Aƒ4hÐggç29G^^Äßß???zöìùØ„i‰‰‰¬^½[[[Æ�‡‘‘’$ñóÏ?ÍìÙ³Õ2ƒ Âë _)q#VIdB!n¶ºø8éa¨÷úÒp12Ÿôì"ÚÖ2,õÇyEø_WЬFé2€ ‚ ¼ÊD@] ¯[P°sçNòóóhÞ¼9Õ«Wìv*•ŠÍ›7Ó­[7ìíí5Ýì2óË/¿PXX@«V­*¼FpY‹ŒŒäîÝ»´oß^ÓM)áu{ï¼ ŠŠŠ¸yó&—/_æòå˨T*9©YÍš5_¸”UVVûöíãìÙ³téÒ…®]»–èuV*•lÛ¶�ëׯ3cÆ 9¨ßºu+7oÞdöìÙ’½\Ê›²P"ü�’[ñ…T³Ö¥V5½7fè²$Á™›ùä)%Úx [Ê!íùJ‰#×øTÕÃÝN”Öáõ'êRxÖ `æÌ™r'õY²d ß~ûm©öŸ7oqqq8991hÐ ¼¼¼ÊìzV¬XAnn.Û·oçÃ?d̘1�Ý.$$„:uêðå—_2sæÌ2½§ÙÙÙlݺ•I“&=ó¾?üð.\�_ׯ_Ÿ‘#GbffVªý—.]JAA[·nåã�?fèСezm/jÏž=:tHm™……_}õÕc·ÿùçŸÙ³gÐtÓKuù‹‹‹““šÝ¿ŸzõêQ¿~}4hðB=ÅÉÉÉìÞ½›ÐÐPzöìI»víJëçÎ�cóæÍôíÛ—:°}ûvBCC™3g¦¦¦š¾=‚ð\ UÅ ¸"(q´Ô¡v5}Œ ߌ@@U§Â´ò2D§”#¶UEðwˆÛÊÚÔuÙÿAx3ˆ€ºž5(prrBWW—ˆˆ ˆŒŒ¤Y³f$''—jF�E½zõ8}ú4«V­â§Ÿ~¢wïÞez]=zô gÏžO ¨._¾Líڵ˼,έ[·èÓ§!!!ϼïÀ�±²²¢_¿~dgg³cÇ"""¸téÒ3eEîÔ©Çéê¹sçªöÃÀÀ€fÍš=v{P �deeÉó®oܸ�««+¾¾¾øúúR¥J•ç:æýû÷Ù¹s'±±±ôíÛ—–-[ª½Ïùæ›oppp`ܸq²k×.._¾Ì¼yóJý ëߎ;†¿¿?±±±ˆ?So&]]]jÔ¨Áˆ#prrª�sªŠàV¼’±JìÌu¨SMÓRf³~]ª$NÞÈÇHO‹æž¥.s%AáùhkC O‘õ_„7‡‹SNêׯÏÚµk™6mÚcׇ……ñûï¿ЫW/¼½½ÕÖ×­[—:СCêׯÏèÑ£éÞ½;lÛ¶Mm~ctt4‘‘‘r�Ø¿þú‹¦M›râÄ BBBððð`РAh—²(æÁƒIMM•_ÛÚÚRµjUµmrssÙ½{7111˜››3tèP¬¬¬äõW¯^娱cäææÒ¢E ¹÷*//�]»vMFF?ÿü³¼ÏðáÃå/ê<`ûöí%öÄÝÝ�6mÚЭ[7,,,—ïãõë×Ù¿?ÚÚÚôéÓOOÏR]û£Þ¾wÞyGmùþýûiÖ¬666\»v�ýû÷cdd$/«_¿¾\×÷Úµk8púöí«6¬þÀ�´k׎K—.qòäIªT©ÂèÑ£Õ²8;88È×÷8gΜÁßßttJÎO æÀ�jíóõõ¥V­Zܽ{—_ý•¼¼wî_|ñ…üúóÏ?§uëÖœ={{{{–.]Ê{ï½Wê¶ÇÅÅCLL óçÏçúõëjëïÝ»GíÚµ9rä...$%%ѧOyý÷ßÏÔ©SÑ××ÇÆÆ†±cDz~ýz x^ö£cÈÿ�‰‰‘{¡N�:EÓ¦M),,ÄÑÑ‘yóæ±dÉ’'¶7??ŸÂÂByžçæÍ›éÑ£¦¦¦Ò¡C~ûí·R]»……&L **J^Ïĉåž¶£G�Ò§OjÕª…žžS¦L!22’ÌÌL6nÜÈ;#™™úúú´k׎ýû÷ËÇûøã�3f ?ýôæææ|÷ÝwÏôóùñÇéÛ·/¦¦¦ÄÇÇóù矫­ÿ믿èׯµk×FGG‡)S¦%·ïرc´jÕ (ÜgΜÉÊ•+åý¿ýö[-ZDõêÕ±µµeÍš5ìÚµ«Ôí^úúúÔ¯_ŸqãÆñý÷ß3a´µµùé§Ÿ˜ùänÞ¼ €žž£G�¦oß¾,]º”ãÇ�Ó§OZ¶lÉ’%KHKK+u»#""¸xá<ЛZ5ªˆ`ú ¦««C›æ^LÛ�Õ«¾!66¶ÌÏ!I•XÈþ‹¹5«Ñ­Cvÿú ï½ÿQ™Sî&rýžc-ZÖ4ÄÚìÍ ¢ÉÉ—ø;D�›­.µœôžißi*Bï)é\×è�(!&‚ðo" .'EEE,Z´ˆ6mÚеkWyù�;wÈÌÌTBÛ²eKòòòˆŒŒÄÇçñCÚ>|øL ~,,,äÿ?ÊüCíÚµ_øÚNŸ>ÍÎ�;Õ–ýsر¶¶6[¶laß¾}äåå‘””D^^^©Ž�žžNxx8+V¬à믿–—çåå/gä¾xñ"¹¹¹3jÔ(ú÷ïÏÍ.**’ƒi€víÚ‘””Ľ{÷J•Ñ{êÔ©øøø°xñbÌÌÌØ´i“ÚƒGGG¹g®  €;wîÈAHDDÚÚÚr0 СCâãã‰��•³!?zýèxÙÙÙjm˜0a?þøc‰¶Ý¸q£Ä|êùþgûòóóåaùPÜÛÍgŸ}¦Ö³���Mrr2ööö|òÉ'Œ7ÚµkGçÎ�éÓ§Ïsg�^¾|9 …‚ÔÔTrssÉÍÍ%55•ììl''‡ÜÜ\,--144ÄÜÜSSSµ€ÜÄÄD^ÿ( ܃(áÉlllèÒ¥ ]ºt!77W.ɵmÛ6iР¾¾¾%¦z<¢¥¥E«V­hÖ¬Ç�géÒ¥ÔªU‹~ýúaooÏâÅ‹ùù矙7oÓ§OGWWWþýh “Ü�‰¡o×îš¾EÂK¦eoŽþZ&Ǻ—RÈõ»JôuµhR]ÛÊovY§¬¼"އ(𪪇§Ã³ÓiÙEœ½•O[Ã7*i› Â?‰€ºyzzÒ©S'µ¤L†††¢P(äÞÖ‚‚”Je‰Ò4�ܽ{—ÈÈH6l™ýg�ðÉÍÍ%??ÿ¹“ý›��>|âúGó�ׯ_��� L˜0AmmmíÇ&244D[[›U«Vaii©¶îŸIiøØÌㆆ†(•J”J%zzÅ_  EEEO¼¿ÿfiiÉ€ظq#õë×ÇÕÕwwwyýäÉ“iÚ´).\ 77—!C†Ð¤Iùü�† ? @sssŸéüO£­­MAA’$=1Û”)ShÑ¢gΜ!77—Q£Fáëë ÷ÀkiiñÝwß•è ¶µµŠç§?~œ„„Ž?Î7ß|ÃöíÛùã�?ž«Í•+W¦råÊòñK#--�¼¼<233ÕîÔÔTîÝ»GZZ …B^_PP€µµµp[XXüg@þ¸¹ço¢J•*Ñ¢E Z´h�J¥"""‚Ë—/³bÅ ´´´ä¤fžžž%î™®®.�:uÂÏÏ�¿þú‹ùóçÓ¬Y3z÷îÍØ±c9}ú4Ÿþ9  {÷î|úé§Ì�;÷©¿ ‰I)T±®¬éÛ"¼dÌ+“ž‘õBÇx�¦âZLÚÚàë¦/ê#é9EœUPÏU·*Ïö•0'_" LAÓêX™¾¹½û‚ " .g .”‡vCñPð:uêðÃ?ÈáºuëðòòR ÚIHH`ذa : 8ð ÆÃÃÜÜ\¶mÛVb¿[·nÉÿÿñÇ©S§ŽÜ;úHåÊ•ŸkNZ¯^½øâ‹/hÓ¦�\–çäÉ“rb«cÇŽñÇ`ccCQQ'Nœ(q GGGîß¿Ovv¶Z½Z###ºwïÎ/¿ü—_~)/OMM-UT£F \\\øé§Ÿä’\?üð�5’ïß#æææO¼þ™3gÒ¹sgš4iÂĉÕÖ}õÕW|ÿý÷ôëׯÄ~^^^T­Z•�7ÊCç¿ÿþ{š5köLå“ÔªU ]]]~ûí7z÷î�J¥" @m›/¿ü’uëÖÉCÒÿÉ‚öíÛ³}ûv>ûì3µûû(iݱcÇhÓ¦ vvv <˜jժѷoßnû³xô0ÅÑѱTÛK’DJJ ¹¹¹äää¨Ü—.]bçÎ�ÄÅÅQ¿~}¹$×?Ò«W/:vìÈï¿ÿÎ|@ÇŽyë­·psscÕªU899Ñ­[7>ûì3æÌ™óÄÚö*• �ÒÖèÞÚÚZ¨TEϵoBFq ]Xu�õ©j%i€ä,�áù4ö0ÀéïÉ£äeÞNzâ~ ‚ðÆu9sww§cÇŽj½{;wîä�wÞá÷ßG[[›¤¤$öíÛ§¶ß°aÃ022âáÇ >œ¥K—ÊëfΜÉÈ‘#ùî»ïP(Œ5ªDÒ¨£G�²oß> ¹wï,Ѷ±cÇòÎ;ïpéÒ%âãã9uê”Ükþ4Ÿ}ö£G�ÆÃÃÆ�…››Mš4‘ç ¿óÎ;´nÝš»wïÒ¹sçǨQ£Ý»w§nݺ4oÞœððpöíÛGµjÕøé§Ÿ0`µjÕ¢Q£Fܸqƒ–-[ªØO¢¥¥ÅîÝ»éÕ«¿þú+*•ŠÌÌÌÇ&%7n}ûöåôéÓ$&&$—«V­�5âĉüôÓOjûµmÛ–‰'òý÷ßP¥J¼½½yÿý÷111aÏž=ôîÝ›;v T*yøða©“¢=²}ûvŽ9¢¶ìöíÛ°nÝ:F�Íwß}Gzz:õêÕ+Ѿñãdzzõj¹}µjÕbæÌ™óóÏ?Ó¿êÖ­Kƒ  ¥S§N|öÙgqðàA&OžŒ¯¯/úúúœ:uŠåË—?Sû+š––Ö%þ7¥RIFFYYYäçç«äQQQj=à …‚”” 155-pbccƒ¡¡¡Z@þÏ©¯"'''œœœèÕ«\½z•Ó§O³aÃÜÝÝå¬á�6˜˜˜0tèPºtéÂÞ½{™9s&o½õ ,`ûöíøûûÓ®];>ûì3æÎ�[â!— ”¥¤L×î*Q(%êTÓÃÙF|åy$>]Å™›ù4÷4xæžú" Ãó±·Ðyæ!â‚ ¯#Q‡ºžµ–nll,¶¶¶ò�ãGsFÿ9dY’$BBB�$‰:uê¨ ß�‹‹£  SSÓ'&ñ‰ŽŽ&99™úõ룥¥EZZšÜÚªU+Þ{ï=š6mʃ¨[·îëH'%%qãÆ j×®ýØsÅÇÇcnnþØ@;55•°°0ÜÜÜJ̵¼sç Ô¯_âââÛÛxëÖ-RSSñôô,1ÄûÞ½{DGGS³fMìììäåÉÉÉ!!!\¾|™«W¯baaAƒ hР�ÚH›ÈeòÍÃß¶m 6äêÕ«Ìž=»D}áÁƒ³}íûš¾Dá%4x—¥ú…EÐÊëÙ2� ‚ ¼®D@] ¯ZPЪU+f̘¡VÊJ(½ôôtΞ=Ë„ ¸råŠZÏg^^öööDFFʽrtèÐ�ŋӭ[7�¶=;;›jÕªqûömùIzz:íÚµcùòår­òŠòª½wÊÃÇQ($''£P(Ôòôôt>|¨�gggcnnŽ¡¡!–––«äfffòúGyiF–”I’¸}û6W¯^åâÅ‹( êÕ«GÆ ñññAOO�ÈÈHvîÜIff&:tàøñ㘘˜ÇìÙ³Õ¦£ˆ€ú¿ýyô4É)éÔòvÇ·ž×·Ý¾û0 ë{SãÚ·IKÏâxÀEúöl¯éK{ªÿ ¨3rŠŽ) =§ˆÚÕôq³Õ%œþ%:©�à;´­eˆ…ñ³O­¸~·€øtê!ff‚ ãŸ^CvvvòÜfáÙäååÑ¢E øý÷ßK #622âË/¿¤eË–ØÙÙ¡R©ÈÏÏgúô馡xÈí²eËhÑ¢vvv¢T*™5kV…ÓB1SSSLMMŸiHú?îììl9 ÏÌÌ$66–ŒŒ µ€\¡P`mm�¡¡!fffT®\Y- ¯T©ÖÖÖjù£4/JKK‹5jP£F  @bb"—.]âÀ�|ûí·ÔªU ___¦M›FLL ;wîD__tttøüóÏ™={6®®®šþQ=“#ŸeÍÚ]¤gdáYÝ™YÓ‡S³†‹¼ÞÿÄy‚.SÉÈ�>ï´Ç³zñCƒ¸ød~ö#kWÍS›+þÃO{pqv kÇæÿyîø„b$røØYÚ´ò}b@��“Ëðñ ?ª7ß5û‰Ç‹¹Çûs¿~éê'ÉÌ-"äž’¤L>NzøyŠ@ú1nÆ) �UÒ¡Ž!fFÏ G'r'IE—z†"˜AøP¿†vïÞ­é&¼²ŒŒŒ¸qãÆS·3f cÆŒ!??}}ý'fÛÖ”ñãÇ3~üx E™d*Þ£éOJÜõ8)))äååñðáCµ€;11‘¼¼Œ_‹@q/ÿ§+6°ÿׯJuþ1Ãß #3û©Û™WâÚ™�8U}ñ„ˆ/£lE×ï*‰ÏPáå¨G³"Ð{‚ÐûJ¢ éX×cƒgÿ›•�¡"8¦€u 1Ð{¹þæ ‚ hš¨KAGGG­ “ /}ícMÓÅÙšEö׊ò¬YÈU*iiidgg“——Gjjª�ß½{W­‡üQ@®¯¯ÿÄ€ûß¹‘‘–––´jÕŠV­ZQXXHxx8/^$88]]]ÌÍÍIKKC¥RñÉ'ŸðÑGiú6–ÊñÀKtj×”ÞoWpðòtåÝ äõ³gޤZÕÿÏûð0;‡MÛöS¿î,´´´x§{k’ê+×"ÐÓÕUëiŽŽyÀ‡ÈÊʦf ú÷îXê‡wAWˆ¹'¿ÖÖÖÂÌS}ÀÍÛwÙýÛ1Œ��hP·¦¦oé3ÉÉ—½WÀýT5ôhä¡�žŽòžäê�âÒUt¬cˆ‘þ³ß§Œœ"Nß,žsý<=Û‚ ¯;P—‚��7oÞ¤V­ZšnŠ ¼2bbbÔ’É /lllži(z~~>YYYdff¢P(Ôò[·n•è!OKK£R¥J«ÜÍš5“vccc9¨þg)·—™_óú¬\µ•U?ì`üÈÞ©?\ûg0 PT$Q©Òÿ?àêÝ£Ó>\ÁK¦pð¯S¼Ó½µ¼þ؉ ¼?ïkõ팃½ _|³… —Ãøòó÷JÕ¾ä”tbîÔûœ`ÌðwðúG@}<à"ý†Ä´‰‘$‰Yó¿Ñô--ƒJ•¹U@Lr!Õíty»¡úº"�~ ¸™Ozvë>×½Ê+�8¦ ¡›þs%0Axˆ€º:wîÌ–-[X¸p¡ZÍdA/;;›µk×>¶dšðê200xæ <''G®t P(䀼°°�‚‚9³yff&¯JŽÌv­ñÛŽ•Ìš¿Š%Ëbò¸~Ìœ:óÊ%3´'§¤³eÇAŽíÿA^ÖºeS‰º‹»kUbŧÿŸ�¿­_C‚Oo—{¤ë×õ¤sÏ©¥¨ûöl/χ¾u¿Äú™s¿æóES™0º7~-êÓgȇš¾­ÿ©I÷–äH×é\×S#ý?àkL’гqç)%Ú×6D÷9zð U'ÂÔp%ÇAžF|B–Bûöíål´o¿ý6µjÕÂÎÎmm1ôI)**"!!�ÐÐPöïßOãÆ�ißþÕLr$”�œœˆ��çÁƒ$$$ÈÿŒŒŒäyÙyyy@q‚³W%¨îض Á§·ó÷É ,^þ¿î=ÊÕÓÛ©dôÿ=Ñyyùôú!½7RNJ §§K�®­8t$ˆ½;q÷~<­š×—×ëèh³ÿÏ@vî9BRJ:Je!iéYH’ôÂ9Š®‡Þæ­.-åe¯Êß² £M ÎÇÁÁÌ7+/ u5—áþe¥*‚Sá Úú<_1I‚SáùX›jã]ULwAxP—‚––ǧqãÆøûûãïïO||y##=-š{H¢ªc•Û=ÌÎåòÕpª»;áèPr}Jjúúz˜™ª÷Ü*\ÇÍÅ{;ë'ÿe2x—lß¾ý‰ë•ªbÒoq/=<¬¼©¤ÿúÖ9ù‡(p³Õ¥–ÓóÏwNÎRžOûZ†˜¿óêA^" AxÍ>>ôèуºuë–Š/\¸ÀÖ­[ñññaÅŠäççóÉ'ŸP½zu,--9þ< .D_ÿñ‰“´µµQ©ŠÔæ ‚JUôÜ[u´uq³òÂÙ¢:÷2"¹pÿ$F6xXû`ú Öñé*ÎÜ̧¹§öÏLKÀé›ù˜iSÇùù™ ‚ ¼éD@ý‚öîÝ‹¯¯¯ZRAxSY[[Ó¡CY½z5óçÏÇÑÑQÓÍzi¼Hé)MHJJ’³t›˜˜àççÇСC15-9511‘Í›7“––ÆÔ©Sñôô$22’o¾ù†·Þz }}}öïßÏÇL¥JO®ln^™„¤tí­4vÝÂË'!)óÊ/6ZG[WËšT³¨ÎýôH.Þ?‰¹‘5V>˜škúKå~ªŠ ‘ùøy`cöb#<®DPP(ѲVÅ<˜Ax]‰¤d/hêÔ©Ì™3G ‚ð/ÇŽãܹsÌŸ?_ÓM©PÏRzêQOóÓJOU´üü|yHw\\œœ¥»Zµj�Ý^©T²ÿ~Ž=J�=èÚµ+:::œ={–Ÿþ™‰'RPPÀ–-[X°`Á^ë† Ðå!#ú·Òô­^"?ÿz‚B*3fì¸2;f‘¤â^FÑ©˜Zâa탙aÙå(kÑI…ß) m-C,^0 ÷Í8%·ã éT×}]‘Ç@áEˆêô¨gIu­ZµbË–-šnF¹x–ÒSÕ«WæÒSšðhH÷¥K—ðöö¦{÷îÔ«Wï©óœ¯_¿Î¦M›pvvféÒ¥XZ×XÞ·o'OždÞ¼ydff²víZfÏž]ª}úôaá I´o僃�%ÚÚâ ÿ›¨¨H".!�¿O…pùz ‹Z¦Ç×ÖÒÁÅ¢ÕÌ=¸ŸÅåØ Ì Íñ°ö¡²¡¥¦/_ÍÍ8%á±J:Ô1ÄÌèÅ‚éØT7î+éTÏHÓ‚ e@Ô/¨¨¨H$Ö„Ç000 °°ðŤ!ÏRzª^½z/\zJ’““å,Ý•*UÂÏÏ�Áƒÿç0ó´´4¶nÝJLL #Gޤnݺ@qoõºuëHLLdÉ’%¤¤¤°fÍÞ{ï=œ��KÕ&sss/^ÂÞ½{Y¶úwÒÒ34}› ²´0§~ƒú,^ü)æææårm-mœ-ªãdîNlf4WœÆD¿2Ö>˜i~êAè}%щ…t¬k„±Á‹À©‹8w;Ÿvµ _øX‚ B1P ‚ðFÓt驊–ŸŸÏùóç $66–æÍ›3sæÌR¼*•Š#GŽðÇЩS'&Ož,÷ºgeeñÕW_aeeÅ‚ HNNæË/¿d„ xzz>SÍÍÍ3f Œ£éÛ%¼A´µ´©fî�Se7b3ïwc}S<¬}°0²ÖH›®Þ) .]EÇ:†é¿Xœ£�¸¡ Y ,MDÒ?A„²"jA^{/[é)M' €K—.áååEçÎ�iРA©GØÜºu‹�7þ¯y±Úðíû÷ï³råJüüüèÓ§))),[¶ŒÁƒS¿~}M_º <--mœÌÝ©ZÙ•Yw¹w#}c<¬|°¬dS!m�€‹‘ù¤gѱ΋Ïs.(”8¦ V5=-Ũ:A„²$êWHNNÉÉÉ@qi™'% */ÙÙÙ¤¤¤<÷ùÿ¹¿ŽŽŽZÝÚ{øð!‰‰‰xxxTè5þ[||<VžHx~/{é)MHII!00�€€ŒŒŒJ=¤ûŸ²³³ùå—_ aذa4iÒDm}pp0?þø#ǧyóæ<|ø�eË–Ñ­[7Z¶l©é[ ÏMKK›ª•]q4s!.ë.¡ 1Ð5ÂÃÚ«JUÊí¼’gnæ“§”h_Û]� ¦‹$¸‘�ƒ¥5ì_Þ<‚ ¯*PW0¥RÉöíÛ ÁÝÝ�#F<µ„Ì?�9s†Ï?ÿœ¼¼}*ìܯ‚W­ôTEËÏÏçÂ… rïÞ=š7oÎŒ3puu}¦ãH’ĉ'صk-[¶dåÊ•%>>|˜ðÁàáá�B¡`ùòå4iÒ„.]ºhúVB™ÐÒÒ±² •�‰ÏºGXÂ%ôu ©n僕qÙfèWÁ©pm} )‹rìgoåc¨§E}WQkZ¡<ˆ²Y/hðàÁlß¾½TÛJ’D÷îÝÉÍÍeÀ€9r„û÷ïsêÔ©RÕ·o߯××÷™êÄÄDìììX°`::: 6ÄÚºtÉP111QË2\PP@rr²Z�ì ȉ„¼¼¼øòË/Õê;wîpûöm\\\¨Q£F©¯/!!SSÓÿ<ÿ“( 033£mÛ¶jëóóóÉÌ̤J•*„„„ðàÁ7n,—êy$))‰àà`ÌÍÍiܸq‰óLž<Ÿ'¶#,,ŒдiÓÇΡ½}û6QQQ8;;cdd€³³3Zÿûö“˜˜ÈµkמxþË—/�ƒƒ 4�—ÇÆÆ2qâDŽ=J³fÍ3f *•JÞ&=====LLL #66///µá÷‘‘‘DGGãî»{‰ó_ºt‰„„;¿õ¿Ö—•×±ôTEKIIáÔ©S¢¯¯�ŸŸ+W®|îlÈyyyìÞ½›³gÏ2pà@üüüäßëGrssYµj:::|òÉ'RTTÄš5k055eÔ¨Qš¾-‚P®´ÐÂÞ¬vfN$<ŒåfÒ5nk…RÝÚ‡ç:fA¡Ä‰P&Ú4ò0 ,òoG%r7EEçº"˜A(O" ®@`РAÅÃȆ ÆÆ�™5kׯ_gÚ´iÔ¬Y“ÄÄD²³³ %88ø©ó�Ù°aQQQlذA^¶qãFÎ�;ÇæÍ›»�••ÙÙÙòë÷ߟßÿ???.^¼HãÆ�ùé§ŸJ•œiýúõÄÆÆ²víZµeW®\Qkӓܸqƒ÷ß(®ï­T* •×_ºt‰¹sçâììLzz:éééܺu‹k×®ao_Ü;ðý÷ß³lÙ2:wî̽{÷xøð!þþþ¥.e4nÜ8Ž;F«V­X°`ñññjë-ZÄ_ýEçÎ�™4i’<üÈ‘#èëëóí·ß²bÅ :wîLLL yyy=zT�гgO233iÖ¬ׯ_'11‘Ó§O£¯¯Ïž={hÒ¤‰LCñ\õÞûeË–áààÀéÓ§¹}û6ÎÎδjÕŠ÷ßI’˜öüqqq’¶¶¶”��ýØõÏcРAÒÌ™3¥/¾øBÚºu«äïï/…„„Hiii/tÜ7ÑÍ›7¥uëÖIcÇŽ•¾øâ éܹsRAAÁ 7..Núì³Ï¤9sæH·oß~âvÒ¤I“Ô>Ÿ$©ø÷nÁ‚’B¡Ðô-�KÈŠ•‚î–‚î–²bÿsûlE‘ôÇÅ\)äÞ‹¿—IÏVI{ÎæHI™…𾂠oÑC]�tuuÕ†ï©Íq´±±¡C‡òkooo93ö177gøðá¬]»– põêUŠŠŠhÚ´©Úv5jÔ@KK OOO¦M›Æ¸qã€âC½{÷–8éëë3pà@þüóOÆŽûŸç·´´dÈ�!¬[·Ž¹sçréÒ%tuuiذa™ÝC{{{Z·nýØûsàÀªT©Â?ü ¯OOO/1W{òäɸ¸¸¨%«:|ø0  råÊòõ?.™Õ£8mmm222äåÀÆÆ†ï¾ûN^–‘‘Á•+WäŸíðáÃñõõ¥OŸ>´iÓ†víÚÉÛJ’T"aÚãtëÖ�¡C‡–X~øðaú÷ï/÷†Ñ¿þüóO „��ƒÆ××—Þ½{Ó¦Mµaõvvv 4ˆ 6f¢<– BEurww'""BmYDDÄSKC•¶Fì#ï½÷Í›7ç£�>bÆ L˜0¡Ä6·nÝzì^¥R)“�RPPðLç÷óócÖ¬YO<YÒÑÑAú_^½ÂÂB,,,ä`ÀÅÅgggµ}5jôØ9Ô¹¹¹OMgeeŰaÃh×®]»veïÞ½,Y²DíþYZZ–8ÿ?_oÞ¼™[·nqøða¾þúkÆŽË‘#GðññÁËË‹;vüç5ÛÙÙ=v¹R©,Ô T*å×[·n•Ïÿå—_2vìXŽ=Š——ZZZlÛ¶�›7o>v½P1”J¥<¤ûÎ�;4mÚ”)S¦üóºzõ*›7o¦zõê,[¶ì‰º$IìÚµ‹sçα`Áµ\���øûû³hѢDŽ7YGª˜8’œÇí”0"SBqÿ_`­…é9EœUPÏU·*eóUL©’8ªÀÓA�jÖâë� BEŸ¸¨_¿~Œ5йsçbnnNAA6l`Ê”)ÏtCCC ………%2ø:::Ò¾}{¶mÛÆ¡C‡X¶lY©�Û¼ys¾þúk–,Y"÷�?þ(‘áÚÐÐ�¼¼� 0ýÌjÔ¨A�5˜6mýû÷gïÞ½øøøÐ¿æÎ�Ëþýûyûí·�âà*,,Œzõê•êç·mÛ6æÌ™ƒ¶¶6’$qðàA 'œ***R;Ÿ>}Ø·oóæÍ“×{zzâééÉôéÓéÝ»7¿ýö›¨+ÀíÛ· àÂ… xxxжm[>øàƒ2M–’’–-[xðàãÇ�jr¾üü|~üñG233Y¼x±Ú{êòåËìܹ“… –H (Âÿ³1qÀÆÄ�äœx"ÿXW©äEhŒ �= q²*›¿�’§Âó±1ÓÁ«ªHÜ(‚P‘D@]�:uêD�=hÖ¬½zõâØ±cT­Zõ™³âV­Zooo @�:upvvfäÈ‘òúY³fÑ´iS† òL=GÆ cïÞ½´oßžöíÛsþüy ˜6mšÚvÎÎÎT¯^��R«V-\]]>|¸¼þÃ?¤E‹ >ü±É¥\]]qsscРAøøøàææÆ°aÃ^øþ¶oßžwÞy‡Æ�3lØ0LMMùí·ßXºt)Mš4‘·›?¾Z�\Û¶m>|8ãÆ�cݺu¼óÎ;Ô¯_ŸcÇŽ© �•$‰¼¼üİ””¶oߎ$IôèÑ£D†âÄÄDÎ�;Ç;ï¼#/KJJ"((ˆÞ½{ËËÎ�;‡¡¡¡ZÀyùòeΞ= ט®Y³¦¼î—_~)1OÙÓÓSžgž™™É¾}ûÈÍÍ¥o߾ܼy¸{÷.“&M¢oß¾èèè�››ËåË—ùã�?ˆ��—ïÓ¥K—8{ö,ZZZtìØOOOù\YYYøûûsûöm9ÿwýäøøx>Lff&-Z´ Q£Fj×”ø}xD¥RqôèQÂÃÃñöö¦cÇŽj£2339vì·nÝÂÉɉN�:©Õäþ¯õÏêyëP¿Î”J%—.]" €èèhš6mŠŸŸßS§~¼ˆððp6nÜH•*U9r$666OÝþîÝ»|ùå—òªºsçË—/gÚ´ix{{kúV Â+å~ªŠ ‘ùøy ­›JdJù…y¸[yã`æüÜòCï+¹ŸRHÇ:FèŠiÓ‚ NÔ/èe ~üñGöíÛÇÑ£G5rþï¾ûŽƒò×_iúV”©Ï?ÿœ¼¼<µyÓ·nÝ¢Y³f$%%•éðõ×ÅËøþДÈÈH9wînnn´nÝš† –[]íÌÌL¶oßNxx8Ç/UrÀË—/³~ýzÆŒ£ö ŠëÌ/^¼˜1cÆ<ñ�Ž ��THð�ÚÖ2ÄÂøÿh§å&™F^AîÖÞ8š9£¥Uú¢Ñ1I…ß- s]#ŒôEy,AMC¾_#6làÓO?ÅÆÆ†½{÷Vøù×­[Ç矎���FÎ_Þz÷îM�=ˆ��ÅÅÅ…¸¸8Ξ=Ë®]»D0-ÌG}„«««Úº´´4–.]ÊÀ�E0-Ïèfœ’ðX%êbf¤,[V²¡q¥6¤ç¥üoŽuîV^T­ìúŸ�uR¦ŠËw èPÛPÓ‚ $z¨_ÐËÔ'I©©©X[[kìüiiij‰º^7\»v�œœLMM©_¿þ‡Ï /×û£¢(•J._¾L`` ‘‘‘4nܘ֭[S½zõr?wTT›6mÂÐÐ�Q£F©eå~•Jņ ˆ‰‰áƒ>(ìggg³xñbüüüxë­·4v_áUz_Itb!íkblðßAoF^ñPðì‚Lܬ¼¨ZÙ íÇÖY¹E QÐÜÓ;sñ@WA“Dõ ÒÖÖ.ólÕÏKKKKcÁô£ó¿ÎÁ4צþ÷PXáñ^–÷EE‰ŠŠ" €sçÎáêꊟŸï½÷^¹ éþ§ÜÜ\vîÜÉ¥K—}º˜Ö ¥$Ipæf>yJ‰6Þèê”ÍÜæ,E‘©a$=LÆP«:­jÔDGKôN ‚ ¼ D@ý‚222X¸p!¾¾¾´oßñåSx#‘��@hh(û÷ï—ë�?o)˜—Mtt4���œ9süüühܸ1úú[÷5??Ÿ}ûö@ß¾}iß¾ý3Ýã'N°k×.¦M›†——×c·Ù¸q# Ìš5«B†¬ Âë@U§Â´ò2D§Œ¿ \Š* #/K‹H2ò’qµô¤š¹:Ú¢§ZA“D@]222Ø»w/W¯^%--MÓÍ�ÐÖÖÆÞÞžjժѱcGµú߯ªŒŒ NŸ>M`` øùùѪU+�å*¸xñ"[·nÅËË‹!C†`ffVê}%Ibûöí\¹r…?ü°DýóGvïÞ͵kט?>†††¹NAxÕª$NÞÈÇHO‹æž”õsĈJ¢ éTÇ=]-²ó3‰L½AZn.5p¶¨.kA µ Â?ÊCº#""hܸ1~~~}@�””ÄæÍ›IIIaôèÑÏÜ…BÁš5k(((`úôé?v»Ã‡sìØ1-Z„©©©Æ®W^%…'BX˜hÓÈÀ²“s?UÅ¥¨|:Õ5*‘)<» ‹¨”¤ä$âbYg‹êèj‹Q%‚ IÔ‚ À�;wä!ÝÕªU“‡t—¦†sy),,äÀ�>|˜·Þz‹nݺ=sæôÔÔTV®\‰»»;£F�zâþAAAìÚµ‹… j´Z€ ¼Jò $އ*p°Ð¡¾kÙOÿHyXD@˜‚vµ ±0yòòœ‚‡D¥Þ 9;g‹ê¸XÖ�µ Bµ o¬¬¬,‚‚‚ $//�Ö­[ãçç÷R”¡¡¡lܸ'''†þ\%颢¢øúë¯éÖ­ݺu{âvW¯^eýúõÌŸ?M_º ¼rò%þQàf«K-§²^³G¯åÑ´†¥{�–[�Mdê ’³ã¨fá�‹E ôt*6σ ›FÔ‚ ¼QT*•<¤;<<œ† Òºuë'&èªhééélÛ¶�¨¨(FŽI½zõžë8çÎ�cóæÍL˜0�úõë?q»›7oòõ×_3kÖ,ÜÝÝ5}ù‚ðJÈÊ+âxˆ¯ªzx:”}0]P(q$XAMG=ªÛ?ûÜè\e6Ñ©á$>|€“¹;®–ž"°A('" á�p÷î]8sæ U«VÅÏÏ�&MšhtH÷?©T*Ž=Êï¿ÿN‡èÙ³çsgØþí·ß8qâ|ðÕªU{ê=Y¶lS¦L¡V­Zš¾‚ðJHÏ)âD¨‚z®úåR º¨þU`mªýÂÃÈó”9D¥†“ðð¾Xë뼟y‚ ¯ P e"""îÝ»G||ëU+»áfUSÖ‚ eDÔ ‘$‰­[·ráÂÞ~ûmjÕª…���¨Åý†JII!88˜={ö0mÚ4¼½½+¼ *•Šàà`¸qã 6ÄÏÏO#mù/ÙÙÙlß¾�ëׯ3dÈš5köÜÇÊÊÊ⫯¾ÂÊÊŠ &<µ>vFFü1o¿ý6íÚµÓôm„WB|ºŠ37óiîi€})ç4?«à˜’2‹èPÛ�òø3ª(Ì#:5œ¸¬»T­ìŠ«eM tEyŽŽŽrÎ{÷îHPP´nÝš¦M›¾4CºÿI’$øõ×_iÞ¼9ýúõ{¡šÏ±±±¬X±‚V­ZѧO´žR777—ŋӬY3ÞyçMß Ax%ÜOUq!2?/lÌÊ'˜ŽL($ÿüs<<<:th¹]ã±cÇð÷÷'66ñ'FД²š‚�THð�ÚÖ2ĸ|F_Å¥«8w+ŸNu 11¬¸^ù… î¤E›y3gܬ¼0�µ Â3)ûlÂ%!!M7Cx µjÕŠ-[¶”ùqU*×®]# €°°0|}}2dÞÞÞOí™Õ4…BÁîÝ»9sæ   uëÖ/ÜÞ£G�òÇ0sæLjÔ¨ñŸ÷í›o¾ÁÎÎŽ!C†”ÛunÙ²…��FŒ�§§çs'V„õh ʧŸ~Êœ9sžëáÕÍ8%á±J:Ô1Ą̈|Ýôœ"ÎÞ̧µOÅÓº†Ô¬R7+/¢S#ºs{³j¸[za¨W©BÛ"‚ðªµðBT*::å3üMxµPXXXfÇ»ÿ>œ>};;;Z·nͤI“^h¨tE9{ö,¿üò uêÔaÅŠ/<=¢¨¨ˆ-[¶ÎÇüŸIÖ$IâÇDGG‡ñãÇ—Ûƒ‡ˆˆ.^¼È²eË066.·û)¥ammM‡066fÍš5,]º]ÝÒí ½¯$:±�Žu�06(Ÿ÷Ln¾ÄÉ0�=ô±6Õ\î}jV©‹›UMî¤Ý$(æv¦N¸[ya¤'ÞË‚ O#jA^ZÙÙÙœ9s†€€²²²ðóóãã�?ÆÖÖVÓM+•„„6mÚDVVÓ§O§zõê/|̼¼ÁAþG¥Rqýúu ¡~ýú 4Ÿ—zH÷?)•J~ÿýwŽ;FÏž=éÔ©S™ŒäHNNfÅŠøøø0lذRÇûöíãæÍ›,X° Ü‡_ß½{—¾}û–ë9áytïÞ�íÛ·ÿg@-#óIÏ.¢cCôuËç3§H‚SáùØVÖ¡¦ãË7-BOGŸ6µqµô$&ýgcŽac •7•ôE`-‚ðO" á¥+gé®R¥ ~~~Œ?#£W+ANpp0›7oÆÝÝ�eË–aaaQ&ǽuëß|ó ½zõ¢cÇŽ¥ÚÇßߟ   >þøã ¹�‰‰‰/uB8áÍU£F îÝ»÷Ôm$ ÎÜÌ'O)Ѿ¶!º:å÷ïÂí|t´Á×]ÿÅVŽôtô©n]«8°N»Åٻǰ1±ÇÝÊc}SM7Oᥠj¡BÅÆÆ €••...˜š–þ�òСC9}ú4Çç“O>Ñô%=VRR.\@GG‡¶mÛÊÃrÈùóç3fL¹fÀ.�[·n1tèP.\¸ ‘óçääpæÌIOO§U«V,\¸;;;�ޗ瑚šÊ–-[¸ÿ>cÇŽ¥V­Zevì   ¶mÛÆ”)S¨]»v©ö9{ö,û÷ïgáÂ…˜™™UÈ=9„—•®®îSs:¨ŠàT¸€¶>†è”ãtæ�{J2r‹èPLjWcÌ èjëáa탋e î¦ßæÜÝãXÛâní�‰~Å|¾‚ ¼¬D@-T¨Ý»w³lÙ2¼½½ ¥_¿~¬Y³¦TÃW·mÛÀ‚ HKKÓôå<ÖW_}ŧŸ~J»víP*•Lž<™€€ªU«ÆÎ�;˜={öKÑþ‚‚îß¿_¡ç,**’‡t_¿~�zõêѯ_?j×®ýÊ éþ'•JÅŸþÉÁƒéÒ¥ ï¾ûî3%>zI’سg§OŸfÁ‚¥®é}ýúu¶nÝÊܹsÿ3a™ ¼é U'oäc¤§EsOÊócèNR!щJ:×5BWs9Èž›®¶îVÞ¸XÖî�À²R<¬¼11¨¬éæ ‚ h„¨… צM~ýõW ¸‡²N�:øûûÓ¹sgyI’xøða¹õ¬ P(žxü¢¢"rrržÚ{ž››‹–––ÚPÚ#GްtéR.^¼(׿ ÃÉÉé™Ú÷_çÏÎÎF©T>u8qFFæææ�]———‡ŽŽN¹&¨ú·ÈCº­­­iݺ5cÇŽ¥R¥W·4KDD7nÄÚÚš%K–”épç‚‚~øá222X¼xq©ß ‘‘‘|ÿý÷|ðÁ/T{WÞ…'BX˜hÓÈà\{Œ3T\¹S@‡Ú†–S¢³Š¢£­‹›•ÎÕ¹—É…û'±0²ÁÃÚSX ‚ð†yŸ� ¯ccc¼½½å¹mùùùLž<{{{|||hÖ¬7nÜ(Õ± iܸ1·nÝR[>jÔ(> ªÓ¦MÃ××—V­Záââ‚««+cÇŽŠkOš4 ¼½½iÑ¢ò±,XÀ–-[0`µjÕÂÜÜœ/¾øB^¿jÕ*Þ{ï=9˜ž)™V^^&LÀÁÁ///Z¶lÉÍ›7åõ>¤K—.4iÒ„.]ºP³fM~þùgy½$I,Y²„ªU«âç燧§'þþþòúœœ†Š££#¬\¹²ÜÆÇŽcáÂ…,]º---æÏŸÏ'Ÿ|B»ví^Ù`:++‹~ø�ï¿ÿž~ýúñᇖi0�‘‘Á’%KÐ××gÞ¼y¥¦cccùꫯ˜Õ…WÒÍ›79}ú4 6ŠÖÈÈHbbb¸ÿ>'N¤k×®äççÿç±tuuéÑ£«W¯–—%$$pôèQÚµkÀÞ½{¹xñ"ÁÁÁ\»v�&MšðÅ_ðÓO?0oÞó}Q©Tdff–8¿­­­|þ&MšpñâE¶mÛÆG}Dxx8ï½÷³gÏ–ïß™3gÔ¾`ûøø`kkKAA™™™888”ÃOõõ•››Ë®]»¸pრ¢U«VåržC‡ñ×_ñá‡âææVêýòòòX¶l-[¶,u9­—…½½=üöÛoôîÝ»Äú¬¬,>ýôSΞ=‹¹¹9Ó¦M{ì50pà@ÒÓÓ™?>Ý»wЧ�¬ZµŠ ­­Mß¾}™4i’üp';;›�?þ˜³gÏR¥J9çÀ|€��………|óÍ78pµý‹ŠŠ˜1csçÎeþüù„‡‡ãããÃ×_�±±±|þGûëêêÊû?ÌåË—éÞ½;‹/–“ô­Y³€¨¨(~üñGΟ?�®®.ƒ bܸqœ?žü‘��rss5jÕ«Wgîܹ@ñC‹¯¿þšƒ¢§§Gÿþý™0aB©>ÉÉÉÌŸ?Ÿ°°0êׯ�B¡(ñóY¸p!/^ÄÖÖ–Ê•‹çÎΙ3‡5j T*ùòË/9tè 0@n?@tt4 , ::sss:wîÌ„ ʵÄ[zN'BÔsÕÇ­œ\I‚ æÆÚÔªöòÕš.OÚZÚ8[TÇÉÜ�ØÌh®>8�‰~e<¬}07²ÒtóAÊ”¨… gllŒ‹‹Ëc×y{{sáÂ<==�â9¿aaaj½°:::ò0ì{ï½÷hß¾=�7ÆÕÕU-8ÉÈÈ ~ýú(•J¢££9v옼^KK ///.\¸ Ï?ÍÎÎæÆ�%Îÿ$½{÷æ‡~`È�!r/xNNFFFj ÀtuuÉÎÎ.qMžžž\¸pWWW ø kDD„Z &WWW,XÀ‚ ˆŠŠÂËË‹�âââB�:uèܹ3ï¾ûîcÛgooÏõë×å$iO+##—«Ú¾}; 6dåÊ•å2ç[¥R±qãF¢££Y¼x1–––¥ÞW©T²råJ<==�¾ì²³³ùè£�˜9sf‰y•JEÇŽiР›6m’§@¬^½ú‰½÷=zô`òäÉ<|øSSSFŒAAAëÖ­£¨¨ˆ©S§’››Ë|Àĉ±²²âäÉ“:tˆ3f°yófù¡Ó°aÃP©T¬_¿•JÅÔ©SQ(Ìœ9“¢¢"~üñGnß¾ÍÌ™3±´´dìØ±¬\¹’E‹0dÈ´´´øé§Ÿ(,,dÊ”)( Þ{ï= xÄÌÖ­[ùñÇ™4icÆŒQ{OþðÃxzz2qâD’““éׯööö¼õÖ[¸ºº2bÄ6nÜHvv6#FŒ�ƒZ€Aƒ¡¯¯ÏÆ�ÉÏÏgÊ”)¨}>DDDÈ#p´´´hݺ5Pœ¯}ûö4oޜ͛7Æ´iÓ¨Y³¦¼ïèÑ£qss# €={ö°`ÁÖ¯_/?ìß¿?&&&lÚ´ …BÁäÉ“åÊ�Ú7pà@~úé'îܹömÛÈÌÌ,·€ÚÂÎ�ã¡ {àdUþC¯/EP$A“êe;’åU¢­¥M5sœ*»›y‡à¸³ë›âa탅‘µ¦›'‚P6$Axƒ z¦í¿úê+©ÿþO\ÿÇHvvvÒ¶mÛ$©k×®Ò€Jl·ÿ~©jÕªÒ¡C‡¤½{÷J)))jë‡ &yxxH¿ýö›Úò­[·JmÚ´‘Ž=*�8qB:qâ„”˜˜(¯ß·oŸdoo/mß¾]:zô¨Ô¹sgiðàÁòúI“&I‹-R;¦©©©tëÖ-I’$)''Gjذ¡Ô¾}{i÷îÝÒŽ;¤zõê•hÇÞ½{%gggéÏ?ÿ”öìÙ#¥§§K’$I{ö쑤;vHG�•:vì( >\ÞoìØ±Ò‡~(I·oß–¾ýö[ÉÁÁAÊÉÉ‘$I’.^¼(ÙØØH_}õ•téÒ%éСCÒ´iÓ$•J%I’$}úé§’»»»ôÛo¿Iûöí“7n,ÙÙÙ½4¿/‹ØØXiÉ’%Ò¼yó¤ÈÈÈr;Ovv¶ôé§ŸJ+W®” Å3í«R©¤•+WJkÖ¬‘ŠŠŠ4}Ë$Iz¶Ÿ÷íÛ·%kkkI’$©U«VÒŽ;¤Ÿ~úIêÛ·¯$I’tôèQÉÉÉI*,,”÷ùù知F�I’$IIII vßrrr$@ºwïž.YYY©­ •¼½½å×NNNRHHˆüÚÁÁAŠ‹‹“$I’nܸ!Y[[Kùùùòú��©V­Z’$I’R©”éÎ�;òúÕ«WK=zô�Ïecc£¶ÿµkפڵk˯÷ïß/Jׯ_ê½ÊËË“®]»&õîÝ[š1c†ÚºùóçKS§N-±Ïµk×$[[[©  @^våÊ©~ýúòëÖ­[K5kÖ”Ú´i#µiÓFjÛ¶­¼î�?þ�ÜÝÝåÏI’¤ñãÇKŸþ¹üÚÆÆFº}û¶üÚÂÂBJKK“Ïeoo/)•JyýÅ‹¥† ʯ7n,Íœ9Sí3¸<ý°w›òàö‹¨nÜ/�^Ε _Ž÷æË¢¨H%Ýψ–NF”Îß;!¥æ$iºI‚ /LôP ªiÓ¦O-!õöÛocccÖ-[HOOç�wÞ‘3pÿS�=ˆ‰‰aݺuT«V�F�aeõÿÃÈF�͉'xë­·Ôö«U«J¥’íÛ·ŽÇ���Ìœ9“?ü�^½zakkË–-[ÈÈÈ OŸ>Œ3FÞ¿{÷îòpÎGæÌ™#Ÿ»R¥J²víZvíÚ…¹¹9Ë–-S+ Å=Ù÷ïßgíÚµ8;;Ó´iSÌÍÍéÓ§¶¶¶lÛ¶�ŒŒ ú÷ï/ÏãøöÛoÙ¹s'›7o&--�êÕ«söìY¹ç´aÆœ>}šuëÖ±téRììì6l˜Ü;>oÞ}èСC¹ÍýNHH`ÅŠøúú2hРg:�$I¬[·•JÅĉ_ùùé‹/fÒ¤IòPe@}ñh¤¿Ÿ6_8..¬­­¹zõ*ÙÙÙj=ª€Ú焟Ÿ?ÿü3Ÿ~ú)ÿý7úúúrÝî[·nñðáCy´Ì#ÿ®ëýÏi+fffrÁ[·n‘••UbÿgƒoРµk×~ìõœ>}š%K– Iµk×&33“¼¼¼RÝÓ[·n‘‘‘A�5Ô–ÿ;)àœ9s>|x‰ýoß¾M�:užZZ¯U«VlÞ¼™… rèÐ!¬­­åò[·n‘žžNõêÕÕöùg)·ß~û�Ï?ÿœF�ajjJïÞ½™5kÖS˾ˆk�ÔªoÍÕIÔ¶o„®vù þ—RHD\q­i=�Wû½YÖ´´´©ZÙG3â²îšp]#<¬}°ªTv•A*’¨… Uš„IÍš5+Õvï¾ûî‡6ïØ±ã±’'L˜À† Ô†P÷Ýwȯ›7oNóæÍ{ÜGs3ÿiΜ9j¯�ŒŒ˜1c3fÌxjû§OŸÎôéÓK,oÙ²%-[¶|ì>†††Œ9’‘#G>ñ¸Õ«WgÅŠO\?vìXµ‡ï¿ÿþÞë7Á¥K—زe ^^^,_¾\mèlY»qãß~û-  M›6ϼÿ/¿üBBBsçÎU 8_UmÚ´ÁÞÞ^-ù ���\Nï‘{÷î=5KüÎ�;iÙ²%FFF8::baaAddäïQ«V­øóÏ?éÒ¥ NNNøûûËŸŽŽŽXZZõ\õÚ±¶¶~îý322èÑ£§OŸÆËË (~ð§¶�žžžÄÿûüUªT!::ú¹¸˜››ËÉŸÄÏÏ�€€:w‹ G�•¯ÕÑÑ;;»§žßÁÁ�5kÖ°fÍn޼ɻï¾Ëûï¿Ïºuëž¹½¥‘™ü�æ.‰H &èÎê94+óù¼)YE\Œ, ]mC*ˆ`úI´´´p¬ì‚Cegâ³î–p }]Cª[ù`elûâ'A¨@"Ë·ðZY²d ]ºt!44Tž§øO¾¾¾Ì™3‡½{÷rüøq–.]Êwß}Çüùó5ÝtAC’““Y±b¿þú+“&MbÒ¤IåLŸüðC9{ýë`É’%j£%:wîŒB¡à«¯¾¢¨¨ˆðñÇ—(«u÷î]"##Y¾|9+W®”ëÂûúúR½zu¦OŸ.—µ‹ŒŒäÚµkò¾kÖ¬aþüùœ8q‚-[¶¨Õînذ!nnnjûß¾}[mÿ§iÔ¨ÎÎÎ̘1CÞÿÖ­[\¿~½Tû?|ø¥R)�ˆ9}ú4;vì(±]­Zµ�+¤¤¤Å£�˜9s¦|þ›7o–({•’’BLLŒüïQÝ¥K®_¿.ÿL‚‚‚8pà€Ú¾kÖ¬á“O>áĉlÚ´I-7F‹-°¶¶fÖ¬Yr¯zDD¡¡¡$&&2gÎù|5jÔ F�åž×A[KoÛxÛ6àʃ ¢Ro !•ɱ³E†+hîi€…±øzUZhá`æL+·®8›{p#é gï#9'þÅ.‚PAÄ'¾ðZiÕªóçÏ'00ð±‰mÖ¬YÔ)S¸qã§N�ÂÉɉóçÏ¿u{…²UXXÈï¿ÿÎüùóñôôdÙ²erO`y�$‰íÛ·sàÀ-Z„··÷3ãøñãœ8q‚Ù³g—K‚´Š¤§§GµjÕä×-Z´ G�ò�j###þþûoŽ?Ž�� íÚµcäÈ‘L�:(NâçââBçÎ�1bѸqcù˜üñJ¥’š5kR£F Æ�ÏÇåõýúõ“|999Q¥Júôé#' këòÍ6›ŸŸÏš5kP(̘1£Ä<üÒ¸pá[¶laÁ‚%J«½,,ç'xÙݾ}›ÁƒsîÜ99(V(øøø°nÝ:Ú·o¯é&¾ÔÂÂÂ7nAAAò0ïÜÜ\<==Ù¹sg…Ô¸V�ûý”�ˆN çnúmjÙ5¢ŠÉ³—TÁß! l+kS×åõ5¢i c‰L C[K kª˜8jºI‚ �%æP /¤J•*DEE•Hü#QQQ%0iZFFÛ¶mãöíÛŒ9’úõë—û9ÓÒÒX±bnnn̘1ã¹æ<‡††²iÓ&fÏžýÒÓ¯¥RIRRÁÁÁøúúòðáCvî܉���Z/·ðx$$$BݺuÉÊÊbÛ¶m˜››WÈûª¬h¡…»•7V•l Ž;KJN5«ÔC[«ôøÎÞÊÇØPKÓeÌδ*v¦UI|ø€Û)¡ÜN Å궦"°áå"já…4oÞœ#GŽˆ€Z(áÈ‘#OLîVÑŠŠŠ8zô(¿ÿþ;íÚµcüøñ2ÿ8::š¯¾úŠ®]»>6¡]iDEE±fÍÞ{ï=œ��+úÖ½¶¼½½Y»v-Ÿþ9iiièêêÒ²eK‚‚‚Ê-Ëôë¤~ýú¬ZµŠ�?þ˜ŒŒ ôôôðóóãÔ©S¯äts#+Zºv&$þ"gbü©çØ }³ÿÜïê�ò $Ú×2Ôô%¼¶lM±5u$)û‘)aÅ�µµv¦U_üà‚ e@ ù^ˆB¡`Μ9tìØ‘nݺiº9ÂKâÏ?ÿÄßߟ¥K—bh¨Ù/š‘‘‘lܸF�õÔ,ÑeéüùólÚ´‰ñãÇÓ Aƒç:F\\Ÿ~ú)ãÆ�{%zý† ÆæÍ›_‹ÌãÂëåY¦ ÜψæVòujØÔÁÉÜí‰ÛÝŽWWH纆è늌Þ%9;ŽÛ)aI*ÜÿXk!î¿ š#z¨…bhhÈìÙ³Y¶l·oߦsçθ»»‹9Õo ¥RITTGŽ!&&†Ù³gk4˜ÎÎÎfçÎ�3xðà í-ÿý÷ß9~ü8sæÌyî^å””–-[ÆàÁƒ_‰`ÀÖÖ–¤¤¤ {h!¥õ,SPœÌݰ¨dMðƒâ!à�«Yý MEÈ=%�ê‰`º‚Ù˜8`câ@rN<‘)aD¦„âaåƒ�™“¬AÐÑC-” …BÁ¡C‡8wî<Ðts qtt¤iÓ¦tïÞ]cÁ´$I²sçNš5kF¿~ý›ñ½<²~ýzâââxÿý÷177®ã<|ø�O>ù„:Ð¥K— ¼{/æÛo¿ÅÓÓ“N�:iº)‚ fÕªUT­Z•>}ú”zŸ"©ˆˆ¤`’²ãÔjV§eq"TAC¬LE±MKÍIävj… <¬}°7«&kA*”¨AxmÜ¿Ÿ 6PTTĘ1c*tÎqVV_ý5æææLš4é¹çh+ >ýôSêÖ­K¿~ý*¬ýe!""‚ï¾ûŽeË–=W&sA(/:%);ŽÐ„‹8[TÇÖ¤&þ×4t7ÀÉJLmx™¤æ&™F~aîVÞ8˜9£¥%kAÊŸ¨Axå) öìÙCPPýû÷§mÛ¶úEêÁƒ¬X±‚-Zзoßç>·R©dÅŠØÙÙ1zôè kYÚ²e !!!Œ?žêÕ«kº9ÂêqSP^$C¾¢0�kΑ–]D5óÆø8ŠÄu/«´Üd"SÃÈ+ÈÁÝÚG3g´ž!k» ³µ ¯´óçϳuëVj×®Í�!C011©Ð󇄄ðÝwß1tèPZ¶lùÜÇ)**bÕªUèêê2uêÔWºg娱cøûû‹ø#hJYNA)’àDhú†‘(µ¢Ÿ»fµPqÒóRˆL #§à!îV^T­ì*kAÊ…¨Ax%%&&²iÓ&222=z45jÔ¨ð6øûûóÛo¿1cÆŒ>ÿúõëIMMåƒ>@WWä‹„—ÉÙ[ù( %Zy’™—JpÜYª˜8ü…ß/���ìÝ»—E‹iäဠO–�¡âÌÍ|:Ô1ÄÌèÉïõì‚,‚œÅXßô±5«…—S–"ƒÈÔ02òRp³¬‰“…:eXOž2™!ûccg­éKž +ã!›WocÍ·ßiº)ÂkBLÔ{Cýý÷ß„††²lÙ2Ñ+&”kkk:t耣£#«W¯fþüù8::>÷ñT*ýõ S§NL™2==Í|Y½uë«V­â�wÞ)“:Ë—/_fçÎ�,\¸PÓ‚ð’ÉÈ)âôÍ|ZÕ4xj0 `¢oFs—ŽD$tçˆZÍjáåefhNÇ<ÌÏ$2%Œè´\-=©fî�Žöó=ÎÊÌÂÊF|¦¿ÌLÌLÈÌÈÔt3„׈¨ßPGŽaâĉ"˜Ê…——}úôaÓ¦MÌŸ?ÿ¹ŽqóæM6n܈¥¥%‹/~¡’7/êôéÓlݺ•É“'—Iïø�7X¿~=}ôvvv»®²$2{ /]]]jÔ¨Áˆ#prrz¦}ó $N†)ðuÓ§JåÒõXjkiãmÛkc;®<ÂÙ¢:nV^h!æÎ¾ìL *Sß±9Ùù™D¦Þ ú.5p¶¨þ\�uQQÚ:b´ßËL[[ •JLqÊŽ¨ßP ¸¸¸hºÂk¬U«VlÙ²å™÷{øð!¿üò aaa 6ŒÆ�kì$IbïÞ½œ:uŠùóç—ɼð;wî°zõj¦M›†«««Æ®­,=ª==bÄ<==56Š@),,$((ˆO?ý”éÓ§—zúI¡ª8˜®n¯‡‹Í³Eªbâ@s—N\�;GjN"ušb¨ûby„ŠabP™zÍÈ.È"*å'£ábYg‹êb¿ O%ê7”J¥ªðÌÈ›ÅÀÀ€ÂÂÂRo/IÇ�g÷îÝøùù±bÅŠ®û" X»v-©©©,Y²3³Ïâ›��ÀŠ+7n\™Í/×´ˆˆ.^¼È²eË066Öts(î¡nÓ¦ 666òô“ÿz &Ip*"Km|œž?€2Ô5¢Qµ6D§†s&樨YýŠ1Ñ7£®CSr •zƒ€¨C8[TÇŲ†¬Ax,P ‚ qwîÜaÓ¦Mèêê2oÞ¼g¢YÖ222øê«¯°³³cÞ¼yeÒãš––ÆÒ¥K8p ¾¾¾½¾²äïïO�=D0-¼”|||èÖ­»wïæ½÷Þ{ê¶£òA‚Æ/^ºN -Ü­¼±ªdKpÜYRrDÍêWŒ±¾)uì›�[�]<<êÕ,¥Tí:zèí|;ãW·=¾îÍžºíÒ…+hZÓe�ò©Û ì6”G4rŸáYˆ€Z�8}ú4³fÍ¢°°�+V¼�æÕ«WùüóÏч¸™|�U~…µaéÂL9ƒ+‚Y<û3ÞõžZr­£‡ŽÑ¡I7þüý0W.3 ÛP‚Nœ–ׇ‡Ñ¡QW¶oÞEð¥k¼;ê=¶¬ÛÀöÍ¿²ñûŸÕÎwä ?«¿ø¾TmëÔ½Ç/a˾�ÿ¹ms¿¦ôÚ=}1„^x=ˆ!ßÂÊÌÌ$??¿Ä—æøøxÌÌÌJ5ÔóŸÉ—Ö­[GÇŽ»ÝÍ›7éÙ³'k×®}j€µmÛ6Î�;Çš5kÔ–gddpãÆ 4štmóæÍóÍ7ߨ- ¥_¿~lܸ‘fÍš=ßÁ_qqqqlܸ‘¼¼]àIÎ]àÀžƒ ú K òóóéÛi¿ÿú}÷âÁý8>š:�·~K“–ÅÉ<㓨lQ€¼<ïŽ~�É3'2pD?Š|²fб[{V.ùšY ÿjĉ£tèÚ®D[â$`TÉs ó纖ÖZѺC«Ç®ËËÍ#=-‡ªö”épA(G¢‡ZøO���´lÙRmYaa!>>>Ü»w¯TǸsçwîÜÁÎÎŽÜÜÜ'n§§§‡££ã&£zøð!ÉÉÉòk•JŬY³psscÞ¼y´k׎ÁƒST¤™²ÿnß#úúú8::b`Pöt¯]»Æ°aÃ4r½¥‘ŸŸÏ¯¿þÊâÅ‹iܸ1K–,y)‚i•JÅO?ýÄ©S§øä“OʬM’$ñÃ?```À˜1c4}™‚ üËü"N…çÓÜÓsãŠù:ô¨fµ�®!AwŽ�‘—ªéÛ <'C½JøØúÒÒµ E’ŠÀè?‰H ÆÐ¸|‚êC¿ÿÅ;ý{`ai'þ0¼öà·�дU9˜°µ¯‚¡aq{N ÀÀÐ@¦ °¶)®™Þ¼uSâ$pÿn,…ÊBΜ•ꢢ"V,þš¶ :óÞ¸èÞª ?ø¤Ôí¿~%„v¾�içÛ™–µÛѹYÉ[Û7í¤uýŽL>��݆ŠZÑÂ+CôP ÿ©cÇŽÄÇÇsóæM<== ÂÖÖ//¯2=—››ÇŽ{æý–/_Ž¿¿?7oÞÄÆÆ•Jʼn'ÐÖ~¹žÕ¨Qã¹®¯4âããILLÔô%>ÖåË—Ù²e 5jÔ`Ù²e˜››kºIäää°jÕ*ôõõY´hQ™fß´i>dÖ¬Y/Ýï¡ ¼éò•ÇCó©ë¢�½EÅŽ°5«_/†ºFxÛ6À©²—œ¢óˆårž»wîÓ£w7µeî5ÜØðÝ&nEDR·Á“óYÜ ¿MÝuž¸ÞÀÀ¿ö-9q4€áã†pñÜeœÝœ±w´ŠGzÔkX‡©³&addHNv�›õà­^iܢѶ¿NƒÚ¿|€«ƒ™=m¾Úú«ƒùúóÕìúk;®.¤¦¤Ñ¯óë9²KxýˆoyÂ244¤k×®ýáQÇní9ù¿$`'ýK ÷îØ­=)I)ìÝñ;kWý„¶¶Ñ‘1er}í?J÷ž]qõpÀÊÚ’*¶6år/¡¬‰€Z(•^½z•¨{öì)¿ŽŽŽfàÀ�ܹs‡øøx øä“ÒÚ¹s''NœàĉH’D~¾z’�>}ú`iiIjj*ÿýw‰`0##ƒÖ­[?µý–––Ü»w�7n̬Y³äõ={öÄÊÊJmý‡~(¯W*•\¾|™0~üxRSS ”{{÷î���©©©øûû“’’¢vþ={öÈ×WPPPâúbcc™:u*_~ù%ÙÙÙ4oÞœyóæ©]ãðáɉ‰!..Žôôt–.] @µjÕØ´iï½÷¾¾¾òy~ÿýwyÿñãÇ“œœLXX÷ïßÇÝÝ�‰'ÊëgÍšEÇŽå¡ù£F�*³2H,_¾ü¥ª»ÎÇÌ[o½Å�!CÐ*ÃyZ‡æüùó|ôÑG­£ý2:rä;vT{ض|ùröìÙSªýƒ‚‚hÛ¶-mÛ¶¥C‡,Z´Hí³àM±mÛ6Ο?ÿ\û*•J>þøc<==±³³£wïÞÄÄÄePoݺ•/¾øBÓ·ª 8s3SCmê:k¾ôÑ£šÕVƶœ‰9JRvœÁ²×ø€IDAT¦›$”R~¡‚ð¤`£ñ ó.U+»Ñνɱi/~ðǰs°#ö^¬Ú²Øûq88ÚPÕ¹*1Qw�â`ôøå#Ìûl¶¼mUgG¢o==!^ë­¸v%„Üœ\‚Nœ¦c·öòºBe!3Æ}Àç󗣫«Cç�ðô®AQ‘в�™ž‰¥�e¹Ü;A(obÈ·P*ݺucܸqddd�’’BNN�ýÿŸG½ÕQQQ\»v µ^äÿRµjUùÿººê¿–ááá\¾|™#GŽ```€���:uâäÉ“deeahhøÄÄHaaa\½zôôôÐÓÓã‹/¾ qãÆ¬\¹’ˆˆ‚ƒƒùûï¿åõË—/§iÓ¦¬X±BnO\\ûöí£aÆØÙƒ !$$„ãÇ�c``€�� ;väܹsrþY êIíüüóÏå!ôdòäÉòºþýûpûöm®_¿Ž¥¥¥|õõõqqqÁÆÆ##£ÉØ’““Ùµk—.]’‡„6ŒzõêÉ ¥<<<8xð õêÕÃÏÏ�.]º”ÙïÎ;ï¼SfÇ* ìܹ“©S§âããS¦Ç âÏ?ÿdáÂ…˜ššjúR_:‰‰‰œ>}š¯¾úŠÅ‹ʼnK›S 55•´´4þøãRSSùî»ïhÔ¨—.]ÂÒòÍù"väÈtuuiÒ¤É3ï;pà@²²²Ø»w/üüóÏ\½zµÌ“8nÞ¼…B¡é[UÂÕèò•íj¿<»DÍêWK~¡‚è´dÞÁHÏ-=ê:4ÁÊØ¶\ÏÛ¦£kVþÀä÷&È=Ñ÷¢mç6t}»ãOfÆì©XW±.±û.íX¶p%—Ï_Á·IyyZj:–VÅó²MLMðmRŸ_·ìA¥Rá^ÃMÞ.ðxq÷ãÙuøyÙ¿¿¯èêé¢,P"IÒ3=¬®æâĵ+×Õ–)—A]^„¨…R©\¹2~~~=z”ÄÄDÞyçµÊÀÀ@>øà|||hÔ¨U«V%<<¼LÎýàÁììì¨T©Òc×;::’��Mrr²<äûŸâãã±µµUë-tvv&//�ôôtyý?¿Ô;;;“››KFFÖÖŘÌÌÌä`úßí³··áÞÈγ544TËJ{ìØ1æÌ™C�:uhذ!U«V%.®t=ñññ1mÚ4µåMš4¡°°–-[Æ®]»øùçŸ9r$µk×fÅŠjÃÆ_u’$±sçN.^¼ÈÂ… ±··/Óã_½z•íÛ·3þ|ùwF(©{÷î¬_¿žéÓ§ceeUb}zz:«V­"&&'''¦OŸ®v?=@rqqaãÆ�¼õÖ[|ñÅ,[¶ (®±ºvíZ._¾Œ‰‰ 'N¤V­Zòþ|õÕWÜ»wOí};wî\ôôô(((àÇäÊ•+˜˜˜0iÒ$ùÁKLL çÏŸ§yóæ¬ZµŠ””ºtéÂÀ�åãçççóã�?rõêULMM™8q¢Úƒ›cÇŽaee…�� kÖ¬!!!�nݺÉÍî޽˖-[ˆŠŠÂÔÔ”)S¦P³fMþúë/.\¸ÀÅ‹ÉËËãæÍ›´hÑBžâ’ŸŸÏ?ü@pp0fffLš4I~P@`` QQQ˜™™0aµû¯§§Çýû÷åë{ë­·èÛ·¯¼>&&†-[¶�™™S§N¥F�@ñÑ�;wÊÛ:::2vìXùudd$×®]Ã××—Õ«W“––F�=èÓ§�¼Mxx8?üðYYYXYY1xðà2ûº§$.]E§º†h¿„Ó•Õ¬‰¿È™ê96ÃDßLÓÍþçŸ�tG t�0Ò3¢±SkôtÊ´C×w:³ç—}Lþ.Ýzvá|ÐE’“6v0õÕ£ÿо zk8#& C__�?vÀó8Ѧ­}æ>›‰ÃÞeô¤Ø9Øtâ Š<ßý¼J>OÇníY¶h%ƒG P;¿½£wïÜcÿžƒXXšóÇžƒÜ ¿M«v-þµ�=æ–•Yµl õÕÃÐÐ@-QÚ“ôÔ“Í붲⓯hÔ¼!ûvþARBR¹ßWA( âñ§Pj½zõ’K ý»Fï AƒX³f ›6mbòäÉj½×ÿ¤­­Maaá3�×ÞÞžøøx²³³åe’$Éÿwpp ~ýúlذAm¿GçqwwçÁƒjuHCCC±´´ÄÊÊJ^ÿÏa¨�Ö—¦×ËÞÞž¨e/ÿgû^”$I 8��7²aÃ&MšDƒ Jlg``ðØ!ôõõÙºu«<üÑ¿G´µµ8p »ví"!!�víÚ1zôè2»MËÏÏç믿&**ŠÅ‹—y0}óæMÖ®]Ëûï¿�ƒƒƒ¦/÷¥¦§§Ç€X±bE‰uééé4jÔˆœœFŽ‰ŽŽ 6|j²½ȉþ”J%�:uâòåËŒ1‚&MšÐµkWBCC�â÷R§N�Ð××gþüùÄÅÅ„‹‹ ÚÚÚ(•J:vìÈÕ«W1b�7¦K—.r΃˜˜,XÀ˜1chܸ1Mš4aôèÑòðë‚‚:vìȵk×1b�5¢K—.j�;ÆúõëéÑ£¶¶¶tíÚGGG ø3kèС3räHœœœhÙ²%iiÅCH---å¶ÚØØÈ,,,äó·k׎ÐÐPFŽIƒ èØ±£x>|˜®]»ÊÁô㤤¤0~üxš6mJ£F�6lW®\‘�?tèPLMM9r$´hÑBþì¬T©’ܦÌÌL~úé'µcGEE1þ|&L˜@óæÍiذ!C† ‘sfäææâççGƒ ˜1c 6dõêÕO,yõ,l]êrã¾’¶>†è뾄ÑôÿˆšÕ/ŸGC»OÝù wK/’³ãp±¨NÇ–LCñßéµÛ¿£}—v\8}‘ê^ì8¸•JÆÿßÙ0kÑL}1Ÿ˜¨®] ¡ÿ°¾,\úÿÓÇúëËæÝëIKMçÂé‹4nÞˆU?}©vžŽÝÛ3jâpúVÿžçU«&_­û‚‹g/tò,¦�eéêO©]¯–Úv::Úlص–ÌŒ,N9ùØk±s°cØØ!jËìíØsd…*'ŽždÔ¤á,þr®î.ráEˆj¡ÔÞ~ûmæÏŸ�ŽŽN‰ùʺºº\¹r…*Uª¢E‹;ŒÓËË‹]»vÑ AâããiÞ¼ùž×ÇLJ:uê0aÂ.\ÈíÛ·Y¹r¥ZоfͺvíŠ$ItéÒ…ÈÈH>þøcŽ?Ž««+½zõbذa|ñÅdgg3iÒ$æÌ™ƒ¶¶6nnnôìÙ“aƱ|ùòëÿK�:u¨Y³&“&Mbîܹܼy“¯¿þºT×VZZZèèèpùòeLMM¹rå Ÿ}öY‰Þ½Æ�ÌÑ£G©Q£÷ïß§U«V˜™™1cÆ zõêÅêÕ«±··'**Ф¤$ D~~>ýû÷gĈ4oÞ===ÒÒÒä/ù¯º´´4V®\‰‹‹ Ó§O/óšÉwïÞå›o¾aêÔ©/E°—]^^}ôuêÔaæÌ™jëÖ¯_�‡‡‡l·iÓ†›7o²zõj>ûì³ÇÏÎÎNÎY°wï^òóóÙ¼y³¼>--�µk×òí·ßKDDçÏŸGKK‹… ÒµkWFŒÀ®]»(,,dÓ¦Mòþ©©©¬]»–U«Š{prrrøí·ßäþþþœ:uŠ&Mš°{÷nŠŠŠØ¸q£¼JJ ëÖ­SKеwï^._¾¬6ÕŠ?GO�:%¿®]»6›6m"0ðÿØ»ïð(ª¯�ãßôÞ{o$¡÷B ½© �fCD@xAPº6,¨ bT¤H ½%„„„ôdCBzÝ}ÿÈ�Õ5”„”MÂù<ÏãîÌܹ3ÙÄ=sï=ç/}ôQ:uêD§N�X·n=zôЇ²\úúú�ljj*_~ù%Ë—/'%%¥B|¶lÙ‚‰‰ P„‡††Ò¶m[ Uï×¼ys¾þúkBCC2dê{¹cÇŽ9R®í‚‚~ûí7uû;vì 44”Ö­[“““CVV�5¢uëÖ´nݺÚê·¶wÃÛ=ƒ¦@ÍÕ ®.R³Zûþ="ífåCgÏ>\Uœãf^*�½B03¬ýe=†††<5n¤Fé«ÿ îDpÏ»ÿhÖª)ÍZÝ=§‰µ�5¯ÌœtÇm]{t¡k�.÷í§`#þoÉ;wÝîâæÌ3Ï•ÿÝöòñä­wg"D}#µ¨0'''^|ñEÊ­›Ù²e ,à§Ÿ~¢gÏžlÚ´‰�7–kã½÷Þcúôé<ûì³øùùѹsçrAëˆ#ÊMÝÞºu+³gÏæ¥—^¢E‹¬[·N# vPP¡¡¡,[¶ŒÝ»wcggÇš5kpr*[Ó´~ýzV¬XÁäÉ“122bæÌ™ŒýÏÓÑï¾ûNcûo¼¡±ÝÒÒò®_ìtttضmsæÌᥗ^¢U«V|ûí·wÍ’=räÈrÁðˆ#pttÔ¸×ÿžùûï¿óÞ{ï±nÝ:úôéæM›øõ×_5ÚðòòâÛo¿eÅŠáããC›6m077ç½÷Þ# € �ŸŸ�——Ó§—eþ422báÂ…|ùå—|ôÑG´oßžï¿ÿžúîúõë¬X±‚0dÈ�ª7ø))),[¶Œ &hL+w§R©pqqaìØ±,Y²CÃFwÂÃÃéÒEóËZ—.]سgÏ]ÛS(êÌñaaa\¼xõö¼¼<‚ƒƒpttÄÔÔ”'NЩS'õ·ÛÂÂÂ/w|·nÝÔ¯---5öÙÙÙ©“ †……qáÂ…rÇÿ÷ä˜1cÊÓ·:tH=ÚÅÅ…ììluFÿû #,,Lãü¹¹¹„„„¨û~¿$nVVVê`÷öõý{æË�øè£�ÈÌÌÄÙÙ™œœœ ÷ÀÚÚº\û·ïŸ££#¿üò ¯½öIIIôìÙ“±cÇÒ·oß ·7'ÿÜO÷®Mù+zÖ~øÚ6®µ‘Åu»fõ•Ô0B¯ï¢µk¬MìªÞ°¸§ÿÒÝ|’Sx‹“qq±ô¤�k:²¾]ñ/P‹JY°`Áßo×®�FVi€9sæ”ÛÏÉÉéŽ�ö¿-Y²äŽÇ}ùå—ïýûK.”�æ¬_¿þŽm0kÖ,fÍšõ@Û�œœøä“OîÚg—rÓï–u|ÅŠåÞûïô×Û™±oëܹ3üñ‡Æ>o¾ùf¹v†ÎðáÃïxÞqãÆ©G�þ«E‹¬^½š†ääÉ“¬]»–^x¡FÖ‚gff²hÑ"†NÇŽ÷_&4Ý¥4蟺ªÖÖÖå2ä+ õ”æ;ùã�?èÞ½;Pœ 2ä®cŒŒŒ>|8Ó§OÇÀÀ{{{�¥"¶¶¶ :” 6<Ð5ÙÚÚòÈ#�ÜõïÐmw›ùrêÔ)Æ�ÏîÝ»ñ÷÷ ÿþåöÓÓÓ»ã4h[[[†®1Âþo]»veÆŒi<Ȩ¨ãÇ�óüóϳ{÷nõlŒÛÁzu6lÆ #==�mÛ¶1zôh¾øâ �ª"?§€¦NmñµkB”⇢·ãeã�·M zuwäWjVמ;Ò†z†D¤] )ë-]:Öxâ1!Dý$�Ø„ Îï¿ÿÎwß}Ç[o½U#Át^^‹/¦W¯^ôîÝ»ê >„™0a‚ƃ¸§žzŠ~ø�«W¯Ç×_͘1cÊŸ››ËÂ… Ùµk—ºÞO<Áîݻٿ¿z¿ëׯ«ó/ܺu‹íÛ·ó÷ßsèÐ!6oÞ¬1Rüä“OòçŸràÀõ{ÑÑÑùîå©§žbÇŽ:tHãøÜÜÜ ùòe<<Eoçšâ"%Êâj;GM�šÕ5ç¿k¤»ù ¤‰ckJ”ʼnÝK^q6Á>ý+Lëéé¢,Ujû²Ä=(K•èêI$ª�ŒP !Œ’’¾úê+âããy÷ÝwÕS�«SQQK—.¥yóæu®$X}3cÆ >ýôSõë   V¬XAŸ>}055%77—9sæhLù=uê:::xyyѱcG>¬.KçååÅæÍ›Õ%çÌÌÌ000`íÚµ4nÜ+++qttT'æòóócäÈ‘Lœ8ooo6mÚÄäÉ“ÕÇòÕW_©3mß‹��¿üò “&MBWWŒŒŒX»v-���÷=þ‘G᫯¾ÂÇÇ'''Ú¶m{Ç6o¾ù&¤qãÆèééÑ·o_V®\‰ŸŸ?ýô/¾ø"zzz˜˜˜`bbÂÚµkñ÷÷ÇÀÀ€]»vñâ‹/âää„�� |þùçúy >œ¯¿þèØ±#½zõª¶Ïƒ‰‰ ëׯçµ×^ÃÕÕ•´´4Z´hQ# M ÌhîÜ_»&\S\äPÔ¼mð¶ñGO·n~5º]³::ý2GbvÓܹŽæ’ñAÝiDÚH¿,ë\fWÓ.àÐëÊ寰wp #=;LJ§”_}“‘ž‰ƒƒTãÕGGU�éˆE½1f̾þúk êîT7Q¿óì³ÏòÝwßÕÊù²³³ùðñ²²â¥—^ªpmãÊ(--eÅŠXZZ2qâÄJÕØl¨F�uße"99Y]ëýAdff¢R©4¦‹ïܹ“¯¿þšü===nݺř3gèÓ§¹¹¹¥ïît|eÜ®*ð ǧ¦¦bmm}ßiÙ)))X[[ßñ³ž‘‘�ŽŽÎ]*ååå‘——÷@%ÞRRR°±±y iãuãÆ œ��«í÷ûœæesMq‘ô¼|lñ´ñGO§zV§ÌütÂ�âhî*5«+é¿�´¯mcu ]\ZÄ…ääçÑÚµË%[µzöîÖtèÖpÊN64'þ>…".ƒW§M×vWD!�RŽŽŽDEEi»¢‹ŠŠÒH´V“˜;w.���L�:µF‚i•JÅš5kÐÓÓãÅ_”`º†U%˜†²õØÿ f¯^½ŠŽŽÅÅeÓ{ÍÍÍ9þ<]ºt)WGþNÇW†��ÍïèèX¡@ÒÉÉ鮟u›{ÎÐ055}àzéNNN5LxzzÖø9þÍÌЂV®�éèÑ‹Ìü›ŠÚFLÆU”ªº9u÷vÍêÂ’ŽÄì!§(KÛ]ªóî6µûv0�ž›Bèõ]˜XäÕç�³x÷ïן#ûOP�Wð@Ç‹šU�WÀ‘ý'Р¶»"�º9¯IÔ¸   víÚU¡iŒB<ˆ]»vU[é°{ çã�?fôèÑåÕU§õë×sóæMfÍšU¡rj¢î™8q"qqqtïÞ333òóóéÞ½»zÝ®æF–´q "»0“HE8×Ó¯àg×wkß:7 |»fu\f4Çc÷àÐk_mw«Î¹×Ôn•JY­‰Ç7nL§Ž�X÷Ñ<6j(NžÈdPí+-)%16…›þ¤sÇÎòýWT+™òý�*((à­·Þ¢oß¾Yv…¨;vì`Ïž=,Z´¨ÜÈ_uÚ»w/[¶laÚ´iZ£ú ¶lÙ©S§˜3gŽFÉQsS¾…¨Nú9Í*Èàª"œœÂ[e�µ•w�,™”S”EXÂQÌ -¤fõÿÜkj÷m¹EÙ„%ÅÄÀ”Ϋµ”ÚÞ½{Ù³gñññP×:::¸»»Ó·o_úôé£íîˆFê‡XJJ ‹/ÆÛÛ›þýûãçç'kªÅ+..&**Š]»vìY³ÔuÀ«›R©dÆ \¸p�™3gÖèÔò={ö°sçNæÍ›§Nd%þñÌ3ϰnÝ:ôôêîzSñp+--eܸq\ ÊÖ,G*ÂÉ+Ê¡‘}S\­¼ë\é*¥JÉ•Ô0RsêšÕ ¤¡j‰Ç6òàTˆ{“)ß1'''-ZÄöíÛY»v- Úî’¨çÜÜÜèܹ3'N¬±‘é‚‚V¯^Mii)óçÏÇÔÔ´Æ®çèÑ£lݺ•¹sçJ0}ÖÖÖ$''ãææ¦í®qGÉÉÉUÎøombG�dä+ˆL»@TúeÙ7ÃÅÒ³ÎÖ{ÍêûMí¾í߉Ç:{…<ðZi!„¸MF¨…õ†B¡`Ù²e2nܸ=þç�ÐÒµ3Æú w©JEG¤¡,ñØù¤¸XzèТNN߯‹d„Zˆ{“j!D½píÚ5>üðC†Ê€jü\Ÿ~ú)3fÌ�`ú>FŒÁܹs ÁÕÕU’¶ ­S*•$&&²oß>NŸ>Í»ï¾[­íÛ™:bç‚"7™HE8QŠ‹øÛ7ÇÉ¢nü½xjVWtDª?ñ˜Bü›ŒP !ê¼#Gް~ýz^zé%Z·n]£çŠ��çý÷ß祗^¢eË–Ú¾ôz!33“Í›7söìYnÞ¼©í­-mÚ´aĈUžò}?i9ID*. üí›×©àµ¡Õ¬®Ìˆ4Ôlⱇ…ŒP qoP !ê´Í›7ó×_1cÆ <üðCŒ��yùå—ÑÑy8êµ !jŸJ¥"áÖu®¥_ÂÜЇæXÛjµO©9‰„'Ÿ¬5«4�Iyyy¬\¹æÍ›‡±qÅG%ªâ÷ß'<<œ¹sçbh(S…µOWG/<¬}‰Í¸Æ‰¸ƒØš:âoß ³Z.k¥ƒ~vM±3u",±,aYMÕ¬®êˆ4Hâ1!DÝ"µ¸§ÒÒRI@&ˆ¾¾>%%%wÝž’’ÂòåËiÕª£G�®µ)×û÷ïçÀ�Ì›7SSSmߦ‡Ö•+Wسg7nÜ )) ¥R©í.‰¦ºªÔ4]=|lñ´ö#6#’c±p0w¦‘]3L Íkµ/Ö&vûôçBÒIŽÄì©ÖšÕÕHKâ1!D]$µ¢Ö]¹r…Õ«Wóøã�Ó»wïZ;ï‰'زe sæÌÁÚÚZ۷ᡤR©øî»ï8qâÆ cĈ8;;£«+#L¢zÝ®:°páBfÏž]§ƒj=]}|íšàiãOlÆUŽÆîÅÑÜ•FöÍ010«µ~TwÍêê¤A3ñX°OI<&„¨3$ BÔª¿þú‹~ø�É“'Ó¼yóZ;oxx8ß|ó ³fÍÂÉIF5´eß¾}„‡‡³xñbÌÍkwôM<\ìííéÓ§yyyüòË/LŸ>]Û]ª}]}üìšâiíOLFGböàdáN#»¦ÔÞ¬šªÖ¬®®@$ñ˜¢n“!Q§Ì›7�^½zÑ«W/Þÿý{îû /ðá‡ÞsŸ[·n=ðèsÏ=ǪU«´}Kîjüøñ|üñÇÚîF…©T*~úé'~ýõWæÎ�[«ÁtTTü1¯¾úêÕÆÕg×®]Lœ8Q‚iQk‚ƒƒ¹~ýº¶»QizøÛ7§»ï õ �ÙÅ¥”3–ä×ZÌ - òî‹‘¾1¡×w‘™Ÿ~ßcªšlìß$ñ˜¢>�€ZT›ÜÜ\LMM‰ˆˆÐxÒ¤I¼óÎ;jcòäÉ|óÍ7qùòå{î{ýúuï��´¨¨H#Óôĉ±±±ÁÙÙ&OžLffæ]ÛOJJÒöm½çõ×åþý[aa!+W®äêÕ«,X°—Z;wbb"+V¬`âĉjûV<ô’““ñööÖv7ÄCÄÚÚšŒŒ mwã�èàВÐÕÑãïër95Œ¢Ò‚Z9¿®Ž.M�ÚÒÔ©-gB‰J¿„ U¹ýª3�†²Äc¡×waj`A�WÌ -jåz…¢²dÊ·¨6fffôïߟmÛ¶i.Û·ogóæÍjÃÁÁlmmï›!zïÞ½÷mïN‰®¦N�ÊüùóIKKãõ×_§oß¾=z}}Í_‡ýû÷kû–ÞÓ¡C‡´Ý… ÉÈÈ`ùòåxzz2uêÔZ-Q¥P(X¼x1£F�¢M›6Ú¾‚²D‡R¦LÔ&]]]JKKµÝ�*3Ô3¢±c+|l‰N¿Ì_Ñ;ñ°öÅǶ1†zF5~þ»Õ¬®Î©Ý ‰Ç„õ�ŒP‹jõØc�±mÛ6õë°°0Ú·o”�öÙgôë׆ rß‘è[³f�zJx¯^½X³fM¹}¾ýö[ÚµkGëÖ­ùå—_îÚ–ƒƒk×®%--MÝçO>ùD£ý/¾øBã˜aƱzõjüüüزe ãÆ�£mÛ¶\¼xQ½Ï_ýÅÀ�ñññá±Ç#<<\½í‹/¾à�?þà“O>¡eË–´lÙ²ÜÆE‹ѪU+|||xüñÇÙ·oŸzÛêÕ«5ú·víÚr×µa‚‚hܸ1“'OÖ™Y³f Û·oç£�>¢E‹´lÙ’_ýUãø÷Þ{�–-[âããÃOù$ß|ó ß|ó Mš4!**Jcûúõë™;w.«W¯fçÎ�÷�m``@ïÞ½9zô(O?ý´ºý€€¢££5öß¶mYYYÌ�;—1cÆðÔSOѾ}{õZæÐÐPF�ŬY³ˆŒŒd̘1 <˜¬¬,¢££™2e yyylݺ•W_}•qãÆ‘›› ÀüÁ† 8pàQQQ¼úꫤ¤¤¨ÏÿÌ3ϨûçççWn]àÚµk™?>Ÿ|ò Ç�ÇÄÄ„¾}ûªGg¢¢¢˜C‡åµ×^ÃÛÛ›^xõƒKKK ‡¦  €nݺñÔSOUé3Ñ¡C‡*_YÅÅÅ|ðÁøúú2räÈZ=·÷rûÁ™ÕÉÄÀ”æÎòîK^q.‡¢v•~‰ReIµžç¿k¤»û¢W£¡”(‹9³‡œ¢¬jW� !ê; ¨Eµ{ì±Çؾ}; …‚¨¨(ºwï®Þ–››Ë”)Sæ‹/¾ )) === «åÜׯ_§Y³f•:&>>ggç>ç¿×iGGG3oÞ<|||ÔÿΜ9CIÉ?_lŒ�5Ÿâ›™™Q\\6¢Ð³gOÖ¯_Ï·ß~‹··7Ý»wç·ß~«p_bcc5Ö¯ëêêâïïOLLL…ÎÂ7ß|Ã×_�——=zô`ëÖ­Uü©Ô¥RÉÇŒ……&LÐvwD58uê±±±ê×%%%•ÊÆÁƒ9xð ÆÒŒê‚��,]ºô®û¥¦¦âààÀ¢E‹jä>ÅÅÅ=Ðq êûsûß½îïîÝ»ÕKxDÝbb`FK—ŽtöêMNa‡¢·�~…ReÕÖ�ß+ÙØíšÕ^6þ�ÝO\ft¥Ú–ÄcBˆ†@’’‰j÷è£�2þ|vîÜÉ Aƒ4’}-X°€ÂÂBõk€×_½\:::(•ÊJŸÛÎÎŽ¸¸8ÚµkW¡ýSRRصko¼ñFµ\»··7“'OfÒ¤IÜF¿~ýèׯJ¥’;v0räH.\¸@£F�î{¬»»;QQQ´lÙ(Q�ŽŽÆÃãÂç0` @©T²mÛ6ž|òI.^¼ˆ¯¯oµÜ£š´víZ ™2eÊÒ‰úçùçŸGOO�S§N¡££Cvv6½zõªð߇©S§¢««‹��Ç�ÇØØ˜ü‘€€€jéßíãÇ�¿ç~666¼üòËôéÓ§ÚïQNN;v| ¬ÿ[¶laÙ²e„„„¨ßÓÑÑ¡G�ÕÞOQ;Ì -håÚ™œ¢,®).r(z¾¶�ñ´i„®NÅóXT&ÙXekVKâ1!DC"#Ô¢Ú¹ººâëëË‚ 4¦{CÙ¿ââbŠŠŠHKKã•W^¹c¾¾¾œ8q…BAZZ999:÷“O>É»ï¾Kll,éééÌœ9³Ü>™™™\½z•M›6ÂÓO?]mÓ’_ýuæÏŸÏîÝ»ÈÊÊbݺu>~ÅŠ|ÿý÷äææªƒCCC *tüÔ©Syûí·¹zõ*Ì™3 �/Ë÷²lÙ2~øáòòòÔç700Àаî¯eûᇈ‹‹cúôéå2¶‹ú­°°°\ò¼ÿJJJºke€—^z‰o¾ù†K—.1hÐ {ì±Jg}...&&&F½<¤² X¾|ù]ÿÖCZZÚ·§¦¦CQQùÄSéé÷¯ ¬P(îz|›6mÔ¹nÏPù¯ØØX222îú *!!�äää:¿J¥"&&†˜˜T*¢z˜ZÒÚµ }úСCú÷ïOddd¹søúúâç§¹ÖjîܹôìÙ“��È“O>ÉÀ�ÕÛ8þ<'NdóæÍ¼óÎ;|þùçw¼__ßr£²={öÄÐÐ333:v쀛››zšy¯^½Ø°a‹/ÆÇLJnݺ‘’’¢žò}§>wéÒ ‹²in�?þ8§N�¢S§NðÒK/±qãF¼¼¼ÊõÏÏÏ�÷&MšÄôéÓ9r$Mš4!11‘={ö¨L??¿rç ÂÜÜ€‘#Grüøq:vìH@@“'Oæ§Ÿ~ÂÝݽ?=•·mÛ6Ξ=Ëo¼�‘QÍ—�µëÅ_dÞ¼yw ¶RRR ¡oß¾Œ9’V­ZݳrÀ¼yóHMM%44OOONž<©Þ¾{÷nZ·n­~ýØc�1eÊ:tèÀرcñôôä‡~¨pßÇŽ«^þajjÊwß}WnŸ… âååÅøñãéÚµ+#GŽT�À?~œ:зo_F�…��GŽÊJ�ùøøDZZšÆR“Û�y^^£G�&((ˆ &àïï_¡’ƒ·ÅÅÅѾ}{ D�=øðÃ5¶gffÒ£G^|ñEžxâ ôôôðññáÝwßÊ–ù<ýôÓ1~üxüýý5*DFFÈĉyá…ðóóã§Ÿ~ªæOÐÃÍÂÈŠ¶n]iïÞ En2‡¢·—…ê?�uuÔ‘¾_ÍjI<&„h�TBÜÃÓO?­í.ˆz¬6>?‡RM�:U•žž®íËPÙÏD«V­T‡VuëÖMõÃ?¨nÞ¼©ÒÑÑQo:t¨jêÔ©ê×_~ù¥* @UZZªR©Têãþ­wïÞªÏ>ûL¥R©Tª'N¨·íÚµKÕªU+õëG}Tõøã�«òóóU*•Jµ{÷n•¥¥¥*77W£ÍqãÆ©–,YrÏk4h�jýúõï}öÙgªÀÀ@URR’J¥R©JKKU‡Ro�ŒŒT…‡‡«_¯ZµJÕµkW�6Ξ=«rvv¾ã9_~ùeÕøñãÕ÷ãܹs*WWWUAA�J¥R©V¯^­òððP�?^ýïÔ©SêãCBB4îïÊ•+UíÚµS¿ž7ožê¹çžS¿îÙ³§Fÿ'Nœ¨zöÙgÕç?sæŒÊÍÍMUTT¤R©Tª×_]5yòdõþYYYªäääJ}F*â½OþOuüÆUtúeUvá­jo¿>ÉÌOW�¼qHuàÚª¸ÌhU~QžêRÊYÕž«[T—RΪ Šó«å<ùÅyªã±ûUÇc÷«² n©NÇÿ­ ½¾K•S˜¥í[ *I¾ qo2/RQo�>}šü‘¹sçbkk«íîˆR\\Ìüùóyùå—éß¿¿úýüü|¶oß®QÞîÙgŸeæÌ™œ={ö®¹tuu+•£¡OŸ>êY4}ûöÅÐÐ�sçÎÑ¥K—*_Ûwß}ÇŒ3Ô‰uuu596jÔH]fïüùó?~üŽ3vîæûï¿çõ×_××××çÒ¥K´iÓ{{{zöì©Þîàà@FFû÷ïçûï¿WokÒ¤‰Fû¸ººª_»¹¹qíÚ5õ5|ÿý÷Ìš5«ÜÈü•+WhÑ¢ `Ô¨Q˜˜˜Ð§O‚ƒƒqrªþ)ÀWŽGñüØIËIäTÜ_€ {3gÌ\°7sFO÷áù:delK{�î¤æ$r1å á%'±3u&ØgÆú&ÕvžÛ5«Ã“NzýO-ÜòꃎŽLŽB4,ÏÿA„ Ê¥K—øòË/yóÍ7«”¥]Ô½zõÂÅÅE#ë|nn.J¥õ{ºººXYY‘��}ÇvT*/^¼c~…Š222ÒÈÜ_·nÝÂÑÑñ®ÛwìØÁ›o¾ÉèÑ£éÑ£�:uâé§Ÿ®PÛJ¥’ÜÜ\2224 <ûì³A«‡‡ãÆ�»cß ,ྛ_|‘¾}ûbeeEAA§N�bÕªU@YFö¼¼�™™P6Þ¦MZ·n͘1cîxŽ’’\]]yå•Wxå•W8wîíÚµãÕW_­Ñdˆf†˜ÙZàm@©ª”›y©¤å$q&!¥²´lôÚ¼lôú^Ùªë“{eív²p#=7…«Š D¥_¢‘}sœ-ýôS ,e£F�èß¿?æææüøã�téÒ¥V+ èéèá`悃™ yÅ9¤å$Ÿy� I'±0¶.½6sÁÒØ¦Šg«}-egæD3'Òr“ˆL çšâ"Íq4w«Ôùâ2£¸šv�‡xXÿ“óvÍê¸ÌhŽÇî'À¡%Öu¿£BÜ�Þ¼yóæi»¢îÊÉÉáìÙ³tîÜYÛ]õÌ÷ßO³fͪ5è½yó& .ä‰'ž¨–õ«¢ömÞ¼™#FTê˜:`mm ”�è:::ªG˜›5kFHHÇŽ#>>ž×^{­Üh¨±±1ææætíÚ•O?ýT#{¯^½ÈËËãâÅ‹ôèу3f`hhHûöíøé§Ÿ7n†††„‡‡3qâD&NœX®�­ZµÂ‚ƒâèèHÛ¶mË…:::´hÑBc‰‚�� &L@¡PpüøqŒŒŒX¼x±z]ò€HNNæØ±c4mÚ”åË—£¯¯OPP�F»Ã‡'22’“'ObeeEÛ¶m133ÃÃÃ'žx‚ˆˆöïß�™™S§NUW01)¿n¶sç΂ƒƒ‡ÆÃÃ%K–`nn® oܸATT*•Šððp"""xûí·±¶¶¦]»vxzz2räH®\¹Âþýû177gÚ´iêÊO>ù$………„††ræÌÚ¶mËòåË«}VTe>wz†X›Øájå…�m&fdf�~™¨ôKdf¡T•b¬o‚žnÍÌ©…%D* O>‰¥± ­]»àláŽþ}Ö‹›Zàa퇱� WÓ‰¿ucSÌ -îy\qiç’Ž’ž—J{�îØ›Ýy)Ž•± Ž®D¤ž#=/sçJÕǵïAþn ñ0ÑQ©¤è£¸»‚‚Þzë-úöíË Aƒ´ÝQOìØ±ƒ={ö°hÑ¢ �ÒUDNNï¾û.Ý»wgÈ�!Ú¾Dñ€F�ÅÆ�µÝ� {ì±Ç0`Àƒh¶¶¶ÄÇÇ«§áL�:+++,X íî©U×ç.¿8—´ÜdÒr¹™—†…‘•zz¸•qÝHŒøßi_ÛÆ•*}õ_ÉÙñ\S„£§«O€}‹;Ö�NÏMá|Ò \,= thQ¡ÄcJ•’+©a¤æ$ÒÚµ Ö&vÚ¾uâ.êÛßm!j›Lù÷dll̬Y³X¼x1‘‘‘ôïß???YS-Ê)..&**Š]»vìY³ª-˜.,,déÒ¥´iÓF‚i!ê�0räH{ì1tuu åêÕ«üþûïÚîZ�010ÃÓÚOk?”*%yi¤å&s>é8E%…êu×öfÎêÕjß*:µ»²œ-Üq¶p')ëSÎ`¤o„¿} lMԉǒ²nÐÒ¥ãƒí»¹]³ÚÞÌ™3 ¡xÙøãk×tjõ¾ !DUɵ¨�‚‚¶oßαcÇHHHÐvwDåææFçÎ�wùÅy(r“IËM"=7s#Kui®š}­îé{Q¡"ñV,×Ò/b¨gLqi!æF–´pîˆ�Þƒ¯{/(Éç|â1Zºv®Öò]¢êêÛßm!j›ŒP‹ 166fĈ²†FÔ*•JÅgŸ}†‘‘Ï=÷œ¶»#ªA}«p·láâÁÁÁk»wõï¬é5ÉÄÀk_<¬}Q©”dä+HËM&<ù%yêš×öfÎÕðÖÔˆô½è ƒ›•7¥Ê"ÒΡ«SVÓ=¯8+½Ÿò~»futúeŽÄ즹su‰3!„¨ë$ BÔYß|ó ÙÙÙÌœ9S£�¨¿¤r€¨m©©©u·kƒŽŽ.¶¦ŽØš:èÐ’‚’|¹É¤æ$r)å f†êµ×Ö&v•šæ¬�@ú¶âÒ".$Ÿ ¿8� ï~˜˜ë:gcid�¿}ó΄®ƒ~vM±3u",ñ(ŠÜd©Y-„¨$ BÔI¿üò ÑÑÑÌž=»ÞŒfŠû b×®]P‹Zsá¼¼¼´Úc}Ü­|p·òA¥R‘ù¿ÑëK)gÈ/ÎÁþ£×fÎÝeº³6iÐL<ÖÆ5H�xÌÃÚ7+â2£8ÿ7Ö&vøÛ7ÇÂÈê�ÎcmbG°O©Y-„¨7d µ¢ÎùóÏ?Ù»w/ÿ÷ÿ§QÞGÔR9@Ô¦ÜÜ\fÍšÅäÉ“ëìCœÂ’õÚkEn2&¦ÿ›î‚�‰=E¥…µ¶FúN*“xL©*åFÆ5¢o^ÁÖÔ‘Föͪ ÇeFs5í¼Ô¬Ö2YC-ĽI@-„¨SBCCùù矙;w.öööÚ))),^¼ooo© jDqq1¬[·Ž-Z0vìXmw©BT¨ÈÌOG‘›LJv9EÙè ÂÆÔ‘Æ-x:õƒÊ-Ê&,ñ(&¦•JNæn8™»ýï¸,Rs’¸‘q�ó‰Ç±2¶U�^›YÕx¿M Íié҉ܢ,"9½ÛÆxÙ4BWçÎSÓuutiêÔ{3gÎ$„JÍj!D�“o´¢Büýýùì³ÏÔ¯OŸ>Mÿþý+ÕFll,S§N½ã¶_ý•äääû¶‘��À† ¸zõjµ_ãO?ýDóæÍ166ÆÉɉ?ü°ZÛ¿ví¯¿þz•Ú¸qã6l **ªÚ¯ÿß.^¼Hhhhµ¶¹eË"""˜1c†juLAA‹/¦oß¾L›6�Æ�ËÏHÔ{úúúôìÙ“©S§²zõjâããkä<…%\N ãïë;èæ3�&Ž­ëL0—űØ}xZûÑÖ-¸RY¼Í -ñ± ¤ƒGz7zÛ@òKr9Ê�¨?O>Irv<%Ê’ ·ù Ì -iíÚ…Ž=ÉÌOç`Ôvb3"Qª”w=ÆÑÜ• ï~¤ç¦pòÆA Jòkíž7999Œ7ŽQ£Fe¥³Æ�GNN޶»&D�#µ¨�„„–.]J^^Pö¼²SBããã9{öl•úÑ®]; 2dHµ^ßO?ýÄ´iÓX³f œ>}šÂÂBª³L{\\çÎ�«R]ºt¡  €~ýúUëõ×´={öʬY³011ÑvwÄlß¾ooo ¤í®Qíš5kÆ Aƒøå—_ªµÝºH—q&!”™Qtö ©ro=]=Ì]hæÔŽ~ƒéèÑ #+â3£9pm+Çoì'*ý2Y™5vMæFV´q ¢ƒGw¹)ŠÚÎ�Ì(Tw ¬�õMèàÙ;3'ŽÄì&5'±&oyƒbnnNçÎ�±²*›‰`hhHÇŽ177¯bËB4<2å[TˆR©¤oß¾|òÉ'Ìœ9óŽÛ?ûì3¶nÝŠ��Ï=÷�=ö …‚¹sçríÚ5"##™0aFFF¬Y³F£�÷ߟ={öàééÉÒ¥Kqr*[ã5cÆ ÒÓÓÕûÍ�;õëY³f1cÆ >ùä<ˆ——K–,Q¯T*ùä“Oøý÷ß±°°ÀÚڀѣGÓ§OÞzë-V­ZEpp0îîîÌš5KÝ~ii)Ÿ|ò Û¶mÃÈȈ^x�aÆ©·¿ñÆÌš5‹Õ«WsèÐ!¼½½Y²d ŽŽŽ¤¤¤0þ|"""¸|ù²úúÍÍÍùè£�€²zÌk×®åСCäææ2tèP¦N�ªžýꫯrëÖ-õùæÏŸ�§§§úõŒ3xç�wøðÃùûï¿ñññaéÒ¥ØÛÛ«÷ùùçŸY¿~½ú�Ä”)SÐÓ+›2WTTÄòåËÙ³g8::VÛgçèÑ£lݺ•¹sçbi)åLê"©K/ºàà`öîÝ[-mÕå©Ý·¥ç¦p>é.–ž´q B§ê3›Z`fh�—M¥ªR2òÒHÍI",ñ%ÊÌœÕ믫;9˜…‘5í܃¹Up“È´p¢Ó/ÓÈ®)nV>årsHÍê׫W/õ@€��!!!Úî’u’Žª:‡àD½1jÔ(6nÜXáý 9~ü8ƒ "22’sçÎ1qâDÂÃÃxá…¸~ý:K–,!??ŸI“&ñÜsÏñꫯ’——lj'øë¯¿Ø´i«W¯@OO�nݺиqc,--yñÅiÚ´)óçÏÇÎÎNÝÇcÇŽQPP”Á¿þú+;vT÷ïv8aš4i¼yópttdÆ ,Y²„ðý÷ßsážzê)¾ýö[Z´hAaa!äää`l|ç/EãÆ�#%%…E‹‘��ÍK/½ÄäÉ“™Izz:‹-"%%…wÞy‡6mÚðí·ßVùsfmmÍÛo¿�»»{Í|˜E•�3†¯¿þZ¦y‹K©T2nÜ8¾ûî»nã¿�´¯mã:Hß-ñXmË+ÎA‘›LjN"y ,Œ¬Ê›™9cel[íçËÌOçªâùE¹4²o†«•××L—(‹¹�t’Ü¢l©Y]A¯½öÉÉÉ888°jÕ*mwGˆºI%JO?ýt¥ö700P¥¥¥©Æ�¯Z¸p¡êðáêfÍš©T*•*>>^e`` JNNVïøða•­­­ª¤¤DýÞ¦M›TÁÁÁwl?00PõÛo¿©_ïÝ»WåççwÇ}}}}UÇ�×xÏßß_µuëVõëÝ»w«üýýÕ¯ûôé£úå—_Ô¯{öì©:xð J¥R©Ž;¦²²²ºëµ_¿~]edd¤R(ê÷<¨rttT)•JuŸ¶o߮޾sçNUãÆ�5ÚùþûïU!!!÷½×ñññªéÓ§«xÇíîîgÏj¼çåå¥úóÏ?Õ¯·mÛ¦þùdee©ÌÍÍUqqqêí*kkk•R©T]½zUell¬JOOWo_±b…jܸq÷íëý<ýôÓªÈÈÈ*·#jVeÿQ=èç¼ 8_u)å¬jÏÕ-ªK)gUÅùÚ¾”;Ê)ÌR…^ߥ:ÿ·ª¨¤PÛÝQ+U–ª9ɪË)gU‡¢v¨öEþ¦:—xL•p+¦Úû™ž›ª:»_u(j»*áVŒJ©RÞq¿Qª½WUÝȈÒöí©óvîÜ©zúé§U;vìÐvW„¨³dÊ·¨0•JÅœ9sèÒ¥ ]ºtQ¿íÚ5œ��ÕÓ«Ú´iÃÍ›7IMMÅÅÅ¥Bíßž† `ii©‘­¨{ß¹sg¶lÙÂСC‰��åòåËê,á¶¶¶dgg“——‡©©i¹v###qwwÇÎîŸÒ­[·&55•›7oªß¯Jÿcbb˜;w.ÑÑÑ4jÔˆÜÜ\õzõª^ÿõë×),,d̘1ûÛÚÚRPPÀÕ«WñññÁÖ¶úG 5jT#í !DMªS»o‹ËŒâjÚZTy­tuÓÕÑÅÎÌ ;3';¶&¿8En2ÉYq\L>�¹‘%fe£×U-qekê@'Ï^¤ç¥™NTú%üí›ãl¡Y6MjVW\pp0›6mRÏ(B”'µ¨___yä~øáõ{¤§§SXXˆ‘‘P–ÄÌÐÐõ~úúú””Ôl&лéß¿?3fÌà‘GÁÀÀ€Ÿ~úIè7jÔWWW~ûí7u6Ëspp 55•ââbõ”Ø„„Œ��ÕÉ:*â^×ß¿Þÿ}FŒ”­wþôÓO«åÚ�œœÐÕÕeëÖ­XXX”Ûnaa�B¡@¥RI]h!ÄC¯>ÒÅ¥E\H>A~q�½B03´¨z£5ÌÄÀ k?<¬ýPª”dä+Pä&q!ù$E%ÿÔ½6sÆPÏè�Îagê„�—ŠÜd®¦]àš¢,°v²pSïSÓ5«÷îÝËž={ˆ��¯Ö§Úòâ‹/j» URV—ÞŸqãÆ×j]zñp�€ZTÚìÙ³iÓ¦�: mÚ´)­[·æ�wÞañâÅóæ›o2vìX�5É�7æÒ¥K$$$àææFNNN­e‹\µj¯¿þ:#GŽ,·MGG‡÷Þ{�W_}gggz÷îÍ�7xóÍ7Yµj­[·&00�¹sç²páB yë­·˜0aúúÿjÒ¤ çÏŸ'99gggõõ«T*âããÕIÖbccùꫯªíÚ�œœ6l“&MbÍš5˜››“žžNLL íÚµ£cÇŽèéé±zõj¦M›Fll,6l eË–µò³Ÿ]»v©Ëä5iÒD#‚¸¿ÐÐP¬¬¬hÑ¢…¶»r_›7o¦U«Võb¦J} ¤¡v�Õ4]]ìL±3u$С%y¤å$“’ÏÅäÓ˜Z¨ƒkk»J×’¶ÿ_b´ÔœD"áD¥_Äß¾æ.êó×DÍêõë×v>ŒÃûâîãR©ï ¢f”–”rþôEÞ]ð.¯N{•fÍši»K¢‘ßpQ!^^^êŒÐžžž<ÿüó„……©·oÙ²…W^y777tttxâ‰'X²d‰F���Ìœ9“–-[bii‰�� û÷ïÇÚÚ777�àÛÈÈè®I¬ÜÝÝÕ#á·ÝïøÇœ^x�I“&©Gi›7oÎ_|�‹‹ cÇŽE__Ÿ—^z‰ÈÈHÜÜÜxã�7ÔÙ®·nÝÊäÉ“quuEGG‡§Ÿ~šE‹iôéßç766.×ÿ-Z0eÊš5k†••ÖÖÖüõ×_˜››óñÇ3`À¬¬¬hÖ¬/¿ü2?þøã¯ßÃÃCCÍ:¢ÿ½'ÆÆÆ¸¹ýó$þ›o¾aÖ¬Yêú·…µk×ccc¶lÙÂóÏ?Ï{ï½G`` cÆŒ©tY4ñðعs'?ÿü³úu£F�?~¼Ægî^’““‰‰‰aïÞ½´oß¾^Ô.\P'óû¯^½z1vìØïÃÚµkiܸñ}êuëÖβeËî¸}éÒ¥¼ñÆåÞÿõ×_Ùºu«úu`` Ï>ûl¥³ÿߺu‹'žx‚I“&ññÇWú:ïÖ¿êVß麒x¬&ë›âa틇µ/*•J=z})å4ùÅye£×ÿ›^™Ÿ‘£¹+Žæ®¤dÇ‘vŽkéñ·o޽™³z{�w?Î'#=7…–®�1Ö°�W®\áØ‰c¼4óYŒMëîçèa£§¯G›N-±¶±dÕê•Ì�3ww©ÕC²|?¤*›å»>ËËË£mÛ¶>|X½Þ¹  €�2räH^~ùemw±Áz˜>gõYeNË–-c×®]Ìž=›ÜÜ\<Èwß}Ç… ppp¨p;o½õ|øá‡Ú¾vóæMΟ?”=h;rä‹/Êìùûû×x&L˜@ãÆ�yóÍ7ï¹_ãÆ�144dÓ¦Mꜷ)•JÌÌÌÈÏÏ/wÜÿýßÿqæÌ^ýu²³³Ù»w/›7oæÒ¥K•.}wáÂ<<<4rdíþ¯Ü¢lÂ�bb`J çŽèV½Ñz¢°$Ÿ´Üd¹É(r“010ÇÁÌ3g¬Mì+µd));ŽkiáèâïÐ;Ó²‡E*TD§_&6#’æÎp4w­t?W®Z‰½‡5»µ×ö-wº÷(é ÌœQóìÄÃAF¨EƒW\\Lzz:¡T*ùûqã}ûöÕv÷„¨—œœœèÙ³'ƒæÄ‰ìÚµ‹gžy€¤¤$6nÜHNN  S§Nj·  €Ÿþ™Ñ£G«gÅ@Yé8š4i¢nÆ ”””àêZö¥×ÓÓ“^½z�˜˜È?ü@nn. Ð?räîîîðË/¿`ddÄ„ 4†……±sçNŠŠŠhÓ¦ ÄÀÀ[[[õu_¹r…+W®¨_ÿ[bb"7n$//�AƒѾý?_®·nÝJûöíÕýV(ú(ñññüðÃ0xð`Ú¶m«nçàÁƒÄÆÆª_ßžsÛßÿ�¯¯/·nÝbË–-˜™™1aÂõ>›6m"99™’’�þ=öØcÕR˾¾�HßV—�Õ#}Ü­|p·òA…ŠÌütÒr’¸œFnQ¶ÆÚëû�.»XxàláNRÖ .&ŸÂX߇ؘØW¹full,�ú´­ðþ¢öµlßœooÐv7DRÿÜQIVVVlÙ²…>ø€¦M›Ò¥K6oÞÌÎ�;ke4Iˆ‡A~~¾z)ÂÉ“'iÓ¦ ·nÝÂÑÑ‘ñãÇóþûïW¨ccc¾üòK~ÿýwõ{*•Š1cƨG bcc騱#VVVxxxðúë¯sòäIRSS8~ü8mÛ¶%;;{{{ÆŽ«EøöÛoyíµ×˜:u*ìܹ“!C†¨·;vŒÁƒcccƒ——[·nåÿþïÿ*|/Ž=JÛ¶mÉÍÍÅÞޞѣG³|ùrõö9sæpñâEõëèèh^ýuõ뜜zôèÁÊ•+qvv¦¨¨ˆþýûSPP ÞgïÞ½¼úê«ðǨÝÛ~þùgÌ�!C4¦çCYå‚ÈÈH ¬ÂÀíÅÅÅ÷üùÞ^Vò×_Ѿ}{ °±±á©§žbåÊ•ê}ÓÒÒÔm._¾œ}ûöi´õùçŸ3}útf̘�¡¡!¿þú«:!#ÀÕ«W¹ví*•ªÂý«ÐgË̈˩aü}}'Ý|Òıu�¦‹K‹8“Ê�Ì(:{…<”Áôé ƒ�‰=-òîKwßA8š»’ž›Bèõ? ½¾‹ˆ´óÜÌKE¥RÞµ WK/ºùÄÍÊ›ó‰Ç9wˆÌüt¬MìöéOaIGbö�S”Uá¾)ÒÒ°±³Öö-÷`niNÖ­[Úî†h@d„ú!¥§§§‘µº¡ëÖ­›”|¨eÅÅÅ#Œ¢aIIIáàÁƒäææòÇ�‘‘Á Aƒ˜>}:o½õÓ¦MÊF>ýüü=z4^^^÷mûÍ7ßdéÒ¥ >€}ûöáééIãÆ��²`±_¿~ꬳW®\Q�âL›6�9sæ0yòd† †¿¿?£G�V�òêéé±sçNtttxî¹ç°··G¡P`ooω'ð÷÷çùçŸG__ŸñãÇWêÞL�:•yóæñÒK/0dÈ5j”zTú^–.]Š‘‘{÷îU?Dxã�74ÙÙÙ±aÃttt;v,...dffbmm�J¥â—_~aß¾}øùùqóæM._¾¬ÝŸ5kqqq|üñÇw}P�˜˜ÈÁƒÉÉÉaóæÍèêêÒ»wo¦L™Â{ï½ÇsÏ=À AƒhÖ¬£F�ÂÑÑQ#ùã•+WîØ¾‰‰‰:Ð5jžžžäææbffÆÛo¿Íõë×ùâ‹/*õ ã~üZ•ýìëˈ44ŒÄcµÁHß7+oܬ¼ÊF¯s“ˆH;ONavfNêµ×&šå1uÐÁÍÊWK/âoÅ–xs#+ì›ÓÆ-ˆ¸ÌhŽÇî'À¡%Ö¾÷íKi©]=ù9Õeºº:”–*«Þ�ÿ#¿ñ)GGG¢¢¢´Ý Ñ€EEEU:‰‘¨?®_¿ÎºuëØ´iM›6åÔ©Sê¬õ'OždàÀ�ê}]]]iÖ¬'Nœ¨PÛƒææÍ›œ>}€¯¾úŠI“&©·»¸¸¥.EsíÚ5õTàÒÒRNŸ>Í€Ôû»»»Ó¸qcNž<©~¯E‹ê`ÕÎβ³³�²5ÊNNNxzzòÔSOñÕW_‘““S¡¾—””pæÌ�ó{zzâïï¯qþ{ å©§žÒXúß,Á-[¶TowvvF___ÝÇcÇŽqóæM¾ÿþ{Þ}÷]¬­­Ë�RßÏÕ«WY·n›7o¦C‡;v ### ¸pá‚ÆÏ×××///õÏ«"Zµj¥þo777T*U…ïñƒºxäZ½‘†²ÄcWRÏq>é-]:ÒØ±•Ó•`mb‡¿}sºxõ¡‡ß`œ-ÜÉÈOãHÌnþ¾¾“+©çHÏMAù¯Ñk]<¬}ËF»Í\8ÿ7gB±6±¥“Wob3"9›p„eÕfJ!¡~H±k×.õˆ�Õm×®]i»¢†tîÜ™o¾ù¦Üû:::’——§ñ~^^^¹ìüw£££ÃÌ™3Yµj+W®äèÑ£|÷ÝwêíO<ñsçÎ¥C‡áíí­-ÕÕÕÅÀÀ Jç·°°à§Ÿ~"++‹ýû÷³nÝ:/^Lxx¸F6ÿ;ÑÓÓ»ëùo«££sךôPV¥ *ɸnO÷ööö`øðáüôÓO£½ººº÷¬�Û³gO>ÿüórïëë룫«[¥û[÷ë_CöïÄcÁ>ýªÄc5ÁPÏWK/\-ËfÇÜ*¸IZN‘Šp² oakꀃ¹+fΘ˜¡«£‹§M#Ü­}¹‘y�“q‡°1q ¥K'âoE×HÍj!Dý&�;Rƒ&&&†;vh»+¢Ú±c111 ýôSõëC‡‘””T.y—••Õ]˳�5Š#GްzõjF�­±Sï¿ÿ~ =zô¨Pÿ�?NNN–––<úè£lܸ‘ØØXuíì{ÑÑÑaðàÁçß³g™™™e3„ng W*•|ûí·m<òÈ#|öÙg( õ{ÇŽ»g~›J¥bÓ¦M̘1ƒqãÆ1nÜ8fÏžMbb".\Pïgoo�žžÑÑÑ•úÙêëë3pà@�ëÛ¾};………ÕúÍÁÁ¥RÉ�7ª­Íú .3Šc±ûð´ö£­[°Ó5ÀÊØ–FöÍèìBO¿!¸Zz‘™ŸÎÑØ½ü½ƒË©gQä&*¼mèá7k[NÅ¢¸´_»&œI%*ý*êçCŸ³§ÎñÝWš•R“SùvÍú;ç•‹|¼ì3>^ö_¬^{Ï}Ïœ8ˆµ?Ü·ÍMßo!&*ö¾û QÓd„ú!ell̬Y³X¼x1‘‘‘ôïß??¿‡fMµ¨~ÅÅÅDEE±k×.bbb˜5kÖ}GóDôzõj}ôQÚ·o�››gΜaÓ¦Må24?ñĬX±‚Aƒ‘��Íš5khÖ¬P–zòäɼùæ›\½zUã¸víÚ1sæLŽ?”¨ÞÞÞ¼òÊ+xxxðñÇóÈ#�СC\\\ ã—_~ÁÜܼBý?qâcÇŽ¥E‹XXXpúôi^~ùeõˆïý|úé§ 6ŒN�:áèèȹsçØ´ifffLž<™§žzŠ={ö�••Å”)Sؾ}»úø‰'AÓ¦M ææÍ›äååñÛo¿Ýw öáÇÑÑÑ¡]»vê÷ 8p ?ÿü³ºvµ‘‘3fÌ {÷îôéÓ‡ØØXæÍ›W¡‡Ÿþ9Æ £K—.ØÙÙÎæÍ›«õ÷ÝÔÔ”éÓ§ÓµkWBBBˆ‰‰aáÂ…ê‡ Mqi’O�_œGg¯Ì -´Ý¥‡‚�ž!.–ž¸Xz�U�AZn×Ò/‘��‰�‰=æ.8Y¸ãi݈˜ŒH"Ó±5s 5'±Ê5«ÿëFLKç­à҅˘š™2tÄ`ž{y<úú¼þÒ›¤¦¤Ýñ¸õ[Ö¢££Ã§|Žo# ëwÏólýe¿þøOŒ¡žY’šœÆ7kÖ3þ¥±wVVVê÷bccqssS¯U.--%,,Œììlqqq)×÷ììlòòòprrºãµ…‡‡“““sÇëOHHàÚµk´k×sssâããqwwר'33“óçÏckkKóæÍÕï+ ÊõßÝÝ�¼¼¼;öéÖ­[–ËkE\\�5RŸ?33“ÒÒR�2bwrþüyòóóiÓ¦�:Ãû¥¥¥allŒ…Å?¢B¡ÀÐÐPãKLL å^»v�øøxüýýqss£**û9¯-ÿN<èÐBÖJ×%Êb¹É¤å$¡ÈMFWW3lÍÈ*¸E\Æ5L ÍÈ/Î¥…sGuÍêQ£F1oÕÛ•>ŸR©¤ç!Œ|f#F=†"UÁÚO¾å…©Ïâ؈”¤Tõ,•>òÝoßàâæ €›GÙ¹gLz“æ­šÝ5(V_[q 999XÛX«ß »ÈäñÓ8¶÷ŽÇ|õÉ7œ=Æ'ëV©ßûðýÕdgå0wqů7&*–ýžâtÔÑ»îS\TL^nV6V÷lëÉ�£™ôÚDzöí^éû=oÚûuòï�¨Ÿd„ú!gll̈#4J–!ĽT´ðíÑæûµõß©à\½z•7ß|³Üth([R°fÍÚ´i”%ûæ›oÊäw;ÿ�Åÿf×ÓÓÓå½ �@ñ¿þÿ—›››F€øß`ÀÚÚšîÝËQ¼ÓƒŒÛý¿[Ÿþ|ÿ›ŸŸ~~še˜þ]3ú^Z¶lyß}*Ôÿ»�þ7jÔˆF�U¨?õ�J¥$"íIY7héÒ;3§ª7*ª�¾®Î8[”e‡Ï.¼EZN"±7¯‘U��•±-:::ä(³8—x g wš9·àóÝʼÅ�˜8ž3kkììmYúÉ?å�\4†9¹8ªéŠHJHfóÆ_Õ¯-­-ûÂh�}tuõ¸ÅOë¡  �GF¥}粚Ú}…ðÉò5© Ø}ˆ·¼¡>^‘–ÎÎßwqùÂeÌÌÍxzü“øúûT¨‰ñ‰lùáŸr‰Ö¶Ö<óÜÓûdef±îË $Å'Ñ«Oô $Œuƒ<BQ§Œ1‚qãÆñÞ{ïѵk×rÛ?üðC&MšD×®]éÕ«íÚµÃËˋٳgk»ëBTHnQ6Gb÷’WœM°O ¦ë #+|íšÐɳ½ Ã˦&¦è•MIN¸u�½‘¿áâçð@íÛØÚоs[&ŽšÌñЊUD¨ C#CÜ<]qót¥TYÊw_~_nŸŒô›,�¿‚.Ý:ÐÄŸG½Ì¹3eù¼|‰ä¤:v){ˆ T*™úìkdßÊfÐcqrqäÉÁÏ HK¯`ÿŒÔý+))aÃZÍÑãœìFER|}ö&ìä9.ž»Tí÷Iˆ!�v„BÔ)ÿ^O|'!!!œ;wŽüü|Š‹‹+!j’ŒP !ÄCNOO�ââúW[ÕÄÄD‚iQ!¥¥¥ê A[ŠK‹8“Ê�Ì(:{…H0Ý€äe{óºèò×/«7'&¦&L™ù2�ÛÇ㣇óæ+o³éû-µvúú¿'�|IˆKT¿î;(„ƒ{ð×¾PúÑ8þâù˼1ùmÆ<ö,Ó_˜IÆÍ[äæEj:ÖÿJ Ö¤ycttt¸xþ2çNŸçÃ/—«·]¿ÃËc§ðÙwÑ´E¦L˜^®M�ë‹‘‘9ÙÕœ QÝä/ºB<äú÷ïÏúõëÉÉÉÑvW„¨{÷îU'±«M*•’+©ç8Ÿt‚–.iìØJ‚é TYBDÚyŽÆìåVa^Öþtñê[¥ºágNœeökóȸ™@QQ§O„áàûÀmVVNv.‘W®�®¸É/ßoaà°þûôÂ’yËiש-&&ÿT󈌸†ƒ“Mš7 âÒU®\Œ(w++òóòP¤**Õ·.=:óçÖÝê5ÙÏ]"&úáªS/ê.¡Bˆ‡\HH‰‰‰Ìš5‹aÆѼysœ��µ>EVˆªP*•$&&²oß>NŸ>Í»ï¾[«çÏ-Ê&,ñ(&¦ûô¯R°%êŽÄ¬X"RÏcjhèÐ̹.ÿË^�›b``@ߎƒ°´²$/7ŸNÁ˜üúK•jgÑÜe,š»LýºM‡Öü¸ý» ëî鯒y+P¤*HLHâÉ1�—«iÝwPß|¶ž%¿§ñ~·^]Y÷ùwôï<[{[<½=èÐ¥|¥kkFMxŠAÝÅÃË�î!ÁL{ó•ûö­ßà>œ8|’þ�‡àåã�“«3ÍZ6©ò}¢:Hj!„\¹r…={öpãÆ ’’’P*•Úî’UbkkK›6m1bD­Nù–Äc Ova&SΠT–bfhAf~:m݃±0Ò,I÷ u¨o+.*&5% K+K,,͵r­Š´tLLŒ137«ô±©É©ci}ïü7Ó3P*•Ø;ØU°å2Y·²)*,ÄÞѾRÇý—Ô¡ÕIF¨…Bиqc7n¬ínQo—q!ùùÅytö ÁÌТê� ­*.-"RNrv¾¶MHÉM¤¨´� ïªMñ¾CƒJÕ—® • rÿÍÑÙ±BûÙÚÙïø@äŸõÒíq²pÓv·… ˆÔB!ê•C‡¡T*éÕ«—ú½Ÿ~ú‰�biY±µ� …‚ï¾ûŽ˜˜š6mʨQ£°°¨Xâ©Õ«WsøðanܸA�=øúë¯ïºo›6mèÝ»7›7o.·íĉ´mÛ}}ÍÿŸ={–óçÏk¼§¯¯ÏèÑ£+uŸNœ8A»víjl}ºJ¥¢eË– :”~ø¡FÎQ“$ñXý—™ŸÎ¥”3èêêÑÁ£FÖåö)[/}En2�¼zan(륅ÕKj!„õÊgŸ}ÆöíÛ‰ŽŽÆÁÁ€iӦѺuë Ô)))´mÛ–G}”Ž;ràÀ>ùäÂÂÂÐÕ½ª… °xñb®^½zÏ}?ÿüs|}}ï¸mĈœ;w[[[�÷333‰‰‰!<<œcÇŽñüóÏc`Pùuž�>ú(—/_®±Ñc¾üòKk¤ýš$‰Çê·Â’"ÒΓž›B cK\-½îº_Xâôu d½´¢ÆH@-„¢ÞiÑ¢K—.eÙ²ewÝçäÉ“dffÒ®];� õ·ß~£I“&|òÉ'Œ7Žœœu0�‘‘���*•ŠcÇŽaooO›6m*Ü·›7o’••@ÇŽË´ £P(ˆ‹‹Sïëì쌱±1½zõ¢W¯^üüóÏÄÅÅñÿ÷Çß‘‡FOO�   õHôíöÓÓÓ¹qã†zäývû·]ºt‰øøx5jT.èOLLÄÙÙ•JÅñãÇÉÍÍ%((333ÒÓÓÉÎΠK—.w�Î~âÄ nݺE‡Êí“��€‹‹ J¥’'Nh´�ŸŸÏÉ“'ÉÉÉ¡E‹xxxTËçF�Õo*•ŠØŒ«D¥_ÆÝÚ—î¾ÑÓ½óWÙ[79›p7+üí›k»ëBˆLj!„õÎ3Ï<üyóxýõ×qvvÖØvóæM „±±1L˜0�%K–¨§L{{{söìY|˜–-[òÇðÆoOQQ/¿ü²ºý•+WÒªU+ yú駉‹‹£uëÖüý÷ß<õÔSÌ›7O}޾}ûòñÇ3mÚ4\\\(..fÉ’%tèÐ�õë׳uëV"##yþùç5ŽMIIaРAØØØàììÌ„ Xµj#FŒPïš5k˜2e ®®®±bÅ Ú¶mK\\Ý»w§wïÞXXX0gÎú÷ï¯q„¥�9Gb÷Jâ±z*=/…K)g0Ñ7»ïýø[׉H=O —ö8šËzi!DÍ’€Z!D½cddÄ„ X´h«V­ÒØöÆoиqc¾ýö[._¾LÇŽéÑ£îîîôïߟ9sæðè£�Ò´iSf̘ÁðáÃ5ÚP*•9rÒÒÒðóóã•W^©PÀûÊ+¯ðÊ+¯0cÆŒrÛ¿ûî;ŠŠŠ022â÷ß/7å»"8À®]»ptt$%%777pssãûï¿'??SSS¶mÛVn„|Ñ¢EèééqâÄ tttÈËË£yóæ<õÔS4nÜX½ß´iÓøé§ŸhÒ¤‰ÆñÓ§OgúôéL�:µ\ߦOŸN§N�øôÓO £[·ntïÞ]=Eÿvû›6m*7e|çÎ�øùùi<À¸="^�ÎxZûIâ±z&¿8�+©addÐÄ©õ=äÖK§ÐÙ«f²^ZQ dÑ�Bˆz§´´”™3g²qãFâãã5{ýùçŸL˜0AýºI“&´nÝš½{÷ªß{õÕW‰‰‰aĈL�:•^½zQXX¨ÞÞ´iSõºeÚ·oÏ©S§´}Ùj}úôÁÑÑ'''ìììP(:ö÷ßGOO�wß}—ùóç³lÙ2ÌÍÍ9}ú´Æ~³gÏ.LWÄŸþÉøñãÕ¯[·nM@@ÐØoîܹw\=xð`éÓ§Ë—/',,¬Â ãîåâ‘kL×#J•’kŠ‹‰Ù�…‘Ý|Þ3˜.,)àxÜò‹óòî#Á´¢ÖH@-„¢^²··gâĉ,[¶ õûÅÅÅjNç522¢¸¸Xã=kkk^ýu._¾LTTÛ·o¿ë¹”JeµfËÖÑ©Þú·ººº¨Tª µ_RR‚››ÞÞÞ꯿þ:]ºtÑØï¿Sé+ª¸¸###�÷ŒŒŒ(**ªPûnnn\¸p�9sæ�••ÅSO=E¿~ý())©Ö{&ê®ÔœþŽÞIvá-‚¼ûÑȾº÷Hw«à&Gb÷`oêD;÷`I>&„¨U2å[!D½õúë¯Ó¢E �.((ˆ­[·ªÄ””Ž?ÎêÕ«8xð þþþ¸¹•�v™™™aff¦‘I»  @ý߉‰‰œRRRhÑ¢ýúõS—Ízë­·(..æñÇçèÑ£´mÛ–=zܱ/aaaìØ±OOO† V®ö©S§ÐÕÕ-w~([¾}ûv®\¹‚——½{÷ÆÁÁ�³gÏrþüy�}õõõÕYÊo¯ånß¾½zûÏ?ÿLŸ>}4F»KKKÙ¶mxyy‚½½=EEEìÙ³‡ððpÜÝÝÕY¹oûí·ßèÒ¥ NN÷!<~ü8FFF´nÝZãýŒŒ ¶oßNzz:={öT�Vßö믿ҵkWõ:ðÿŠŠŠâ¯¿þ"%%…¦M›2pàÀªÅýo•ýœ‰Ú‘˜KDêyìÌœth‰‘¾ñ}�),)àlÂa õ�héÒ}]ªIò»#ĽI@-„B«êÚ—µ·Þz‹‚‚>üðCmwET£ºö9{Øefr1å Je)M�ÚbmbW¡ã2óÓ9›x+_Ù7Óöe<äwGˆ{“GzB!„¢V—©'9;û¸[û CÅ’ôÅeFs5í-]:à 륅u„ÔB!Ä¿,Z´HÛ]¢ÁQ¡">ó:‘Š 8[xÐÍg z†;V¥äbÊ2òÓd½´¢Î‘€Z!„VéééQ\\\å5²BÜMii©z�¼¨}™ùé\J9ƒ®®‚§�?~vM´}iBQ%P !„Bˆ;Ê.ÌäbÊ”ÊRÚ¸ambW¥öndF™N+×NØ›9kûò„¢Ê$ B!„ŠK‹ˆT„“œ‡¿} Ü­}ÐáÁ¦wCÙzé‹)§¹•ŸNïL d½´¢a�€Z!„B BE|æu"p¶ð ›Ï@ ô «ÔfAI>gâC150“õÒBˆGþ¢ !„B2óÓ¹”r]]=:xôÀÂȺÊmf䥖x/|e½´¢’€Z!„â!VXR@DÚyÒsStl‰«¥Wµ´{#ã×Ò/ÒÒEÖK !. ¨…B!B*•ŠØŒ«D¥_ÆÝڗe:¶R¥äbò)ndÐÙKÖK !6 ¨…B!2éy)\J9ƒ‰¾�½B03´¨–v Jò8SCóÿ­—ÖÓö¥ !D�’€Z!„â!‘_œÇ•Ô0² 2hâÔGs·jkûæÿÖKûØàcÛXÛ—*„µBj!„BˆN©R�~™ØŒH¼lüiåÚ]Ýjk?6#’¨ôK´réŒ�™“¶/W!j�ÔB!„ XjN—S°4¶!È»&¦ÕÖ¶RUJxò)² 3éâÕ3m_®BÔ* ¨…B! Ü¢l.§œ%¿$—æ.í±3­Þ‘ã‚â<Î$”­—îì)륅' ¨…B!�Re ×Ò/Ÿ�Ÿ]¼lÐÑÑ©Ösü³^:Û@m_²Bh�ÔB!„ DbV,©ç±3s"ØgFúÆÕ~ŽÛ¥¶d½´B€ŽJ¥Ri»B!„âÁefr1å Je)M�ÚbmbWíçøg½ô-Úºu•õÒ Xff&Ó§O§°°Pýž‘‘~ø!ÖÖÖÚîžuŠŒP !„BÔSÅ¥ED*ÂIÎŽÃß¾îÖ>èP½Ó»áözéPÌ -éì‚žŽ¬—nȬ­­ áìÙ³$%%ammMPP�ÓBÜAõÕKB!„µB…ЏÌhþ¾¾€n>ñ°ö­‘`úf^*Gb÷âjéE+×ÎL?$† BFFùùù 2DÛ]¢N’j!„Bˆz$3?�K)gÐÕÕ£ƒG,Œ¬kì\1W‰N¿L+×ÎÕž%\ÔmÖÖÖôêÕ‹?ÿü“îÝ»Ëè´w!µB!D=PXR@DÚyÒsStl‰«¥W��«TUJxÒIrвèâÕ·ZkW‹úcèС�ñç{8&œ'�áïý¡êíΆӧà ~Zÿ Î^dÚó3X÷ùwêí¼·Š)¦v‘m[vÒ·Ó`"#®•ëG×]xbÌ ªíÚúéËþÓ»X·y­¶o³U&#ÔB!„Õ¨°¤€ˆ´ó¤ç¦èØWK¯ZïC^qgâcelCg¯�¯g-ª×±¿�³ã×�lûûWllm(**âñ~O³å‡_ùÌâ™5e6Ÿoø˜Ž];ðòk/bae @~~Sž�Δ™“xbÌã’›“ @Ö­l¾üèkžÝƒ“‹#ׯÅàéãY®/ÝzÓ­wðû©HU`ni�±±‰ñ‰åFÈ232),(RŸ§2T*‰ñI˜š™`ck£í‹w$µB!D5P©TÄf\%*ý2îÖ¾t÷ˆžníÕRä&s>é8�ìšáiÓHÛ·E<€¿ÿɰ‘CÔA¤¡¡!OŽ\Ѽ89¦IDAT}œm¿îdä3#øõÇßéÜ­“:˜ppúgÂ�]115QÓÆÆF`` ���a§Âè?´>�¼Õû†‡]dês¯PTTŒ©© »�oWoŸúìkpöä9,,-hÕ®ûþÜÏáCG™7söŽö(R´ëÔ–÷>œ�ž¾$Óu‹<®B!„¨¢ô¼BcþD‘›Bg¯Zj%˜ŽN¿Ì…¤´q ’`º—q%õÍ‚ªçžÇ^�ÃÏßWã=?_n\¿ÀÕ+×hÕ¶Å]��¼r�–mî¾ÝÄÔ„E«0ûµyŒyt{wîG¥R©·7oÝŒý§w±ÿô.>þvå]Ú0eß©?Q¤¥Ó¾S;ÖmþŠ]Ûö¨·GEDñäØ'ؼûGœÞEÖ­,6~ýc…®?1>‰/½Éê¯?à‡mëùóÈäæäòúŸ«åþ Q�d„Z!ꩽ{÷²gÏâãã5¾ !@__Ÿ€€Æ�‡‡‡G��'¿8�+©addÐÄ©5ŽænZ¹ÞRe ’N�WœKï¾ë›h¥›e1×oFp#ãΖDŸ�ƒ'«Þ®R©Dç?Yµuuu))) ´¤ýÿ�Ô¦+n2²ÿÓäçåÓ¾s;>úæC ï;’;ø±�tëÕ•Ÿ¾Ûļ7òéŠ5|ºþ#œ]�*ÔÇ&Í0·0£q‹@,­,ÈÏËWo·±³¡C—v0葜8r’g_wß¶wý±‡F�~dßÊæÄá“4nÈñÐ<óÜÓÕñ£¢ÚH@-„õÐúõë¹páãÆ�#00°Z“ÅÑ”””ÊÂ… ™6mM›6­Öö•*%Ñ闉͈ÄËÆŸV®�µ¶N¹l½t(V&vtv•õÒµ¡TYJlÆU®ß¼Š£¹ AÞ}110#?§°ZÚwqu&þF¼Æ{ñq‰¸¹»àæéÆõ¨XììmÙzÛ¶ì`×e#ÄÞîœþéÌ}ÏcimÉ SžeÜÄg˜2a:/ÿŒ…Ì«‘{fdlHqqI…öÍÎÎ&77�GNi¼ßhßé›U!q…¢ž¹rå 'OždÞ¼y4oÞ\‚i!î@__Ÿž={2uêTV¯^M|||ÕýŸÔœþŽÞIvá-‚¼ûÑȾ™Ö‚XEn2GcöáiãO çL×0¥JIlF$‡¢·‘U˜Ig¯Þ´p鈉�Yµž§W¿ìü}ÅEÅê÷¶mÞNï½øHvoÛCZJÚ�Ћ+#8yô´Æû銛@Y9­˜ÿäP¶F»M‡ÖädçÔØ½;z’¦-4Ëvéèk\ãmÍ[6¥¨ ˆIÓ_ä•™“Ôÿ† TcýâAɵBÔ3{öìaèС˜™Uï8!¢fÍš1hÐ ~ùå¦OŸ^¥¶r‹²¹œr–ü’\š»´ÇδbSckJTúendDÒÖ½+6&öZíKC§R©H¸u�ké—°0²¢ƒG,Œ¬kì|†õcÓ÷[xé™W2bÇþ>AZª‚1Ï� MûV<1f$OËØŸÁÐÐ�­›¶иl ·£³#³ß‹—ÇMeü‹cpõpá¯}¡ñɺU„�<ÇÔç^ç‘'†Ò¤y ŠÔt¾]ó«×®¨¶kP¤¦óúKoÒh_Ξ ãìÉ0æ.~[cW7¬l¬øà½U´nß SºtëDÏ~=øyÃfžê%Ƽ0C#Cî>ÄàáƒhÓ¾U�Ýw!„ÔBQÏÄÆÆòøã�W½!!ÁÁÁìÝ»÷��/U–p-ýñ™ÑøÙ5ÁË&­]O©²„óI'((É#È»/F²^ºF%eÝ Rޱ�)­]»`mbWãçÔÑÑa͆�ùõ§ß9yô4Mš2gÑ[˜˜þó³ž9w:]{váÀîCäçåóô¸'ôèõö‘ÏŒ Y«¦üþË6Ž$еG}b�‚;ò뾟ùcóvN>‰­½ë]K@ÿr}qvqbÌ £5ÞøHÜ=Ëò<óÜ(ììí066â•“þ9ÎÕ‰gž{šßÙ†�­5›wÿ€½ƒæ½ÓÓ×ã럿`ã7?ñ÷þà |¤?P¶^üÓõ«ÙþëŸüµ÷oT¨êÞùž‰Ø„Еd²Bˆze̘1|ûí·èéIé!*B©T2nÜ8¾ûî»J›˜KDêyìÌœth‰‘¾±V¯%¯(‡3 ¡X›ØÑÔ©�Lñ®A)9 D¦]@OWŸ‡–ؙ޿Žò¨Q£˜·êí ´Þ°�?s�iÏ¿Î�3»µÝ•;š7í}6nܨínˆBF¨…¢ž)--•`ZˆJÐÕÕ¥´´´RÇdfr1å Je)mÜ‚jeTò~Òr“8Ÿx‚‡æxXûi»; –"7™«iP¡$С%æ®Úî’¢“€Z!„âŠK‹ˆT„“œ‡¿} Ü­}ÐA{Ó»o‹J¿Ä�Œ(Y/]ƒ2ò\M»@aIþÍq±¨¹rk �_€/~¹\ÛÝ¢VH@-„Bˆ‡ž ñ™×‰T\ÀÙƒn>1Ð3Ôv·þ·^ú8%ùy÷‘õÒ5 « ƒ«iÈ)ÊÂß¾9®V^üEOOe©]½‡{*¾™¹­ÛµÔv7îH~>¢ºI@-„BÔ�ãÇ�³fÍ øâ‹/îºïŸþÉþýûY²d‰V^UÕÂ… 2d­[·ÖvW*,3?�K)gÐÕÕ«ñìÍ•‘[”Í™„ÃØ˜ØÓʵ‹¬—®f9EYD¦…“‘¯ ‘}SÚY£SÅ{lïà@Fz&vŽ¶Ú¾|8S¦L ""‚eË–…‹‹ O<ñ�>ú¨úø‚‚V­ZÅÁƒ±²²bâĉôêÕ«Üõùûû³`ÁX¸p!_}õÿý7§OŸæÕW_Uï·páB DÛ¶m¹qã?üð]»vå£�>"//�±cÇ2räÈ ýl®]»Æ{ï½§~íààÀÒ¥KËí÷ã�?²eË ={ödúôéXXX¨¯ÿÛo¿åܹsXXX0eÊ‚ƒƒ�²Qï­[·²{÷nÂÂÂ8vì½zõbìØ±@ÙC—•+WrèÐ!lmm™4iݺuÓ8¿‹‹Ë]0ܸqƒ%K–põêU}ôQ 4¶§¦¦òÞ{ïqþüy<==ÑÕ-üä“O055%//�•+Wò×_aggǤI“Ôý¸pá|ð111¸»»óÔSO1xðàÊýüûóž—Â¥”3˜è›ÑÙ+3C‹n«º•üo½tQI�¬—®FE¥…D§_&þÖu<¬ýèî;¨ÆÖÇ7nܘN;±î£xlôPœ<Q©”Ú¾½Ò’RcSرéO:wìLãÆ�µÝ%Ñ€H@-„ \QQ¯¼ò óçÏ/7í8;;›   }ôQ>øàŽ;Fpp0‡ºã¥Rɾ}ûP¿4h^^^,_¾œøøx^zé%Ö¬YCHHžžžL�:U# þøã�ÕÓíJKK8p >>>¬X±‚¸¸8^|ñE¾øâ uP}ñâENŸ>Í•+W˜4iÆ S�°«T*úõëÇìÙ³™={6±±±üòË/ôîÝKKKJKK0`þþþ|ðÁܸqƒ^x�¯¾úꮣµÃ‡WБ‘‘ìÝ»W# Þ±cÍ›7§m۶ܼy“wß}—Gy„iÓ¦©¯ßÒÒ’þýûß÷gãèèȸq〲 Ë–-+P¿øâ‹œ={–yóæáííÍ·ß~ËîÝ»1bJ¥’7Þxƒ¡C‡2jÔ(NŸ>Í Aƒ¸pá^^^x{{óÈ#�pêÔ):vìÈСCpu-+T\\LŸ>}hݺ5+W®$::š±cÇòý÷ߤîCRR’z*¼¡¡¡úx…BAPPcÆŒaÁ‚9r„3gΨ�S©T 0€gžy†wÞy‡÷ߟèèh^{í5 )**¢wïÞtèÐ�•+WÅ3Ï<ÃO?ýD§N�())¡OŸ>|øá‡Í–-[èÕ«¦¦¦•ú=0³2ål² 2hâÔGs·ªÿrU£²õҡؘ8ÐÆµKµL?~Ø—sýænd^ÃÕÒ›î¾1Ô«ùQã±cDzwï^þøq'ñññ¨T*mߊ‡žŽŽîîî 0ˆ>}úh»;¢�‘€Z!¸üü|&OžL£F�¸té’Æ¶ï¿ÿ{{{õTãV­ZqõêU–.]ªž"0pà@ôôô¸qã^^^Ìš5 (=NKKcïÞ½èèèдiS.\ÈçŸNHH={öD©TJpp0¹¹¹lÚ´‰ððpõñ7oÞdß¾}Çÿ; صkgÏžÅÓÓS£ÿJ¥’œœôôôpssÃÛÛ›=z¨·oß¾�¬¬,¾øâ ttthÒ¤ óçÏç‹/¾¸k@íàà@zzz…ﯙ™7nT¿¾páëÖ­«P@mii©îÇ�ÄË—/³aÃbccqpp`Ù²eêíºººüþûï@Yðjaa���û÷ïg„ ê5Ïööö”»æß~û�ÒÒR>ùä ltmΜ9|ùå—õ¼yó077À××—µk×ðõ×_Ó¬Y3-Z@çÎ�Ù´i“ú¸ÔÔT._¾ÌôéÓÑÑÑaÆŒ©ûñã�?¢§§ÇG}¤>bb"_~ù%�:u¢¸¸˜¼¼ç}ÎPùšóYt®?qâÄVaŒ��qàÀ¼ûî»øÛßþ†Þ½{#>>³fÍ‚±±1222���­Ó~SS“Îxà?+--ëkccc�ŸðË/¿tÈg§P(*†é[9pàÖ®] •J…   h4Ô××·«ýŒŒ ddd@.—‹Û¥s܆ зoßVçgff"::ºÍö]\\àææ†½{÷"..?üðBCCu®¯P(Z]ÿf›–––8pà–/_Žùóç#** 3fÌÀôéÓïz&ôŒÔlÎ »«s:CŽ2W«/s¼tÐ ZTæàrE&œ­d]®K?=œ¨‰ˆº‰9sæàÃ?„��d2ÀÙÙçÏŸ×9îÚµk­ܰaÃ`mm�}ûöá�wÞÁúõë2™  ÀþóŸ6¯;sæL,[¶ Ø´i>üðCqŸL&ÃÀ�qðàÁÛÖ~»ðÔ·o_üøã�P©Tøå—_ðÊ+¯ ²²III�Éd¶mÛ†sçÎ{ì1dee‰]€�o½KJJÄŸmllðÔSOaÉ’%hnnÆ AƒÄ}�=ö233uº—gee¡´´´]÷”››‹ÿûßhnn†™™ÆŒƒððpTWW¦L™"vÁ¾éâÅ‹(++kÕÖÕ«W±dÉìÙ³o½õ€Ë^�9s%%%ëׯGff¦ÎyÕÕÕ8t耓Œ}òÉ'HLLÔ9F*•B£Ñˆ]îÚuÆ ƒƒƒþú׿ŠÁþ÷ß»y_¹rpsspc²ÔÔÔVíôèчC}cc#`êÔ©8yò$¾úê+ñØŒŒ (•J�óoŽ¡¾ùçfˆŽ‹‹ÃöíÛ‘••àF×üŒŒ ñ¼††ìرß|ó :„ÿû¿ÿ¿Ìn„ÿÔÔTlß¾]Ü–žžŽŠŠ ±–M›6A­VÃÜÜ�<òBBBPUUÕ®ç×UÕ«jq<ÿÌ�-1Àg$ôž(®¹‚_.ÿŒ’ÚBôõ‚¾žC¦‰¨S1P=Ä,--uÞ–þå/APPÜèž¼sçNÌ�;¾¾¾ˆ‰‰ÁÛo¿-N"&‘Hàçç'¾õööÆ[o½%¾e¶··GJJ ¾þúk¸¹¹Áßß/¾øb«À:wî\ìÙ³Ggr/pppÀ�ðå—_B&“ÁßßsæÌÑ ÔvvvmvÁvttDnn."## ¹\$%%‰ûSRR°e˱¾¹sçŠõYXX@¥RA.—cüøñ(,,Äo¿ý&Nš6|øp<úè£ðññA@@T*æÌ™£3ÞÙÞÞÛ¶mƒ\.ÇÀ�ñæ›obܸq:uZ[[cÅŠ2dˆ8�ÛŸ™››ÃËËKg›‰‰ RRR�ŸŸOOOx{{cáÂ…âóxä‘G///„„„`Ïž=˜={¶8øM¯¾ú*ÊËËáêꊀ€ñùH¥Rìß¿Ÿ~ú©øü,X€òòrñ\Ì›7#GŽÿÜœ8mìØ±øë_ÿŠÀßßß|ó ¦M›K˳S[YY¡_¿~ðööÇs÷ìÙ+V¬pcR¶}ûöaýúõâç³páBñúR©çÏŸGXXBCC©TŠyóæuÆ¿>÷EY]1N\9¹sÂÜ¢8ù˜žJj ñkÞ~Tæ Â=ý½c`oád貈¨28õ Ñ%!!Ag,2œ´´4L˜0ÅÅņ.¥KÚ³g¶lÙ¢ó:33aaa¨ªª‚��]§ÕÒþ½¹9^º¯ç†?=•×_Cv¹$�€ÔÚý[$"º7CMDDtø½tÛJJJP]]�ŠŠ 899¡¾¾ßÿ=†Þ©aÚÐZ´jœ+þ j­Šã¥õTÑPŽKåç¡Öªä7[¯{o”ˆ¨0PéÉÉÉ O=õ”¡Ëè²qýúuŒ; pttĸqãðÓO?º´NS¯ªÁéÂcp±–¡¯ë�»ž�¼»«nªÀ¥rTu’†ÃÝÎFà3$¢®ƒ]¾‰ˆ03gÎÄçŸÞj¹&"º5�FƒÄÄDlݺµS¯[VWŵSèáÚ ^öò{o°©m®F¶R�êÆJº„ÂË^ÎñæDÔ%ñ 5ÑF&“¡¬¬¬ÕÒLDtkeee:³‹w†le:ŠªóÐÏ{ÇKß…zU-r”¸ÞP §žèí1i"ꨉˆ0¾¾¾P( ÔDí¤P(Ä™Ûï·ã¥O E«Æ Ž—n·Fur¯g ´¶~NÁwëc ÿšJD]¿ò#"zÀÄÆÆb÷îݨ¯¯7t)D]^}}=vïÞ�ØØØû~­:U RóÀÒÔÑÞ\_º=Tš&\(=‹cùûafl�áþqpe˜&¢ÇP=€¶lÙ…B�^xAAA†.‡¨ËQ«ÕÈÊÊÂæÍ›�gžyæ¾^¯´¶é%§â O{?Cß~—§Ö¨p¹â"®VåÂË^çž0367tYDDw��šˆèuðàA8p………\º‰èOŒŒŒàåå…ØØXŒ3æ¾]G€€eŠªóÐÇs(ì- }ë]Z‹¶ùY¸R™ ™­]Â`abi貈ˆôÆ@MDDD¤‡­iÅ' Ñ¶ �ç ˜³‹w[´‚W*³‘W‘k7º„ÁÊÔÆÐeÝ3j"""¢»T×\ƒ3E¿ÂÅÚ=]{s}é6‚W«/#GyŽ–.’†ÃÆÌÎÐeuj"""¢»PZ[ˆô’Ó/}W_A¶26fv–FÀŽÝá‰è!Ä@MDDDÔd—§£¸æ úza@lõګÈ.O‡¹‰‚¥p´t1tIDD÷ 5ÑÜ/}Z­½=sFê[(¯+Æ%¥F� Xk7C—DDtßq‘?""2ˆ‹/âÀ�(((Àµk× Õj ]=d\\\ —Ë1mÚ4xyyéÝN]s5ÎƒÔÆ!RŽ—þ³ë e¸T~m ‚¤�Ùxº$"¢NÃ7ÔDDÔ©AÀÖ­[qòäILš4 ááápssƒD"1tiô�Q*•HKKÃŽ;°xñb½BuIm!2JN£§¬7<ì| }K]JUãu\R*Фn@�K8Üí| ]Q§c &"¢NuðàA¤¤¤`É’%°±á²9tÿíÚµ ¹¹¹X¸pa»Ïáxé¶Õ6WáR¹µÍÕt…§½œo퉨Ûb—o""êTû÷ïÇœ9s¦©Ó :l÷ñj�çŠ�C+h1Ø/–ã¥ÿ§^U‹le:*ÊàŠ>žC 1bÏ"êÞ¨‰ˆ¨S•””ÀÏÏÏÐeP7âàà€ÊÊÊv[Û\�3E¿Bf㉮‘0ß¼6ªë‘£Ì@YÝ5È�‚á c‰±¡Ë""ꨉˆ¨Si4ó/ãÔy$ 4Í�+©½ŠŒ’3/ý?Í-�ȹ~%5Wá㈘€ 0‘˜º,"¢.…�šˆˆˆºµã¥(®)@ïØY8º$ƒRkTȽž‰ÂêËð²÷Çpÿ 0563tYDD]5u[j� iÅÇ!@À¿GºuplѪ‘W‘…‚ʸÙyc˜|ÌM, ]Q—Æ@MDDDÝRms5Îþ ™m÷/­Ñjp¥òò*.ÁÕÆƒýbaijm貈ˆœš‘ˆˆº´‚‚466Š?«T*µûüÂÂBäç磶¶ö¾Ô¹\¹\޽{÷¶yÜåË—†£G�vÞÃk‡ÒÒRäçç#??jµZïv.]º„°°0;vÌзÔ.×j¯âdÁK#âÚ»[†i­ Å•Êl½üjš«0Ðw"Ü£¦‰ˆî5uiáááxóÍ7ÅŸ bbbÚ}þÀ�1xð`ôêÕ îîîX¼x1ZZZ:¬¾ƒâðáÃ�J¥hhhhó8‰Dggg˜˜t|ç°ììlL�:U¯sÑ¿Œ9r¹aaaHII¹ëv$ œœœôº¿ .àé§Ÿîðçr+d•ŸGVÙ9DûÄÀÝΧS®Û•‚€ÂªËøåò^(ëKÐß;½=ÁÚÌÖÐ¥=pØå›ˆˆº4‰D‚~ø‹-‚§§§^m|ÿý÷0`®^½Š'Ÿ|UUUX·n]‡Ôçë{c6h ‹Ûççç‡_~ùå¾<£’’\»vMïóW®\‰Ù³göîÝ‹§žz %%%07oÿúË���øïÿ«wý%%%÷åÙüÑÍñÒºíxék5ÈV¦ÃÂÔ ½=ÁÁÒÙÐ%=Ðø†šˆˆº4­V‹3fàïÿû-÷×ÔÔ`Μ9pssƒ��Þxã 477ßòXooo$''ãÓO?EEEÔj5är9ª««Åc¶mÛ†—^zIüyüøñعs'bbbàèèˆQ£F!//¯Ýõß|ó{óÏ©S§Z³uëVDGGÃÖÖغu«¸ïÂ… HLL„¯¯/œœœ��� Ö[XXˆ‘#Gâå—_ÆéÓ§Åk„††Šç«Õj¼óÎ; ‚��âããQ^^Þf½&L@cc£Ð+++1{ölÈd2øùùá�wÞÑé>dÈ�û;wî\«ûW(˜2e ìììЧOœ?�ŸŸ�‘#GbÁ‚øí·ßÄ6zõê%ž_PP€±cÇ" ÁÁÁHHH@ffæ]ÿ9Êì�š¶æèç=¼Û…éÒº"üš·ù•—æÖÑÞ#¦‰ˆ:5uy3gÎÄŽ;påÊ•VûÐÜÜŒüü|¤§§ãâÅ‹xå•WÚl+$$R©çÎ�ƒ ÈÏÏ×Y£¸¶¶eeeâÏÅÅÅØ¸q#¾øâ ”••!44‰‰‰í®}Û¶m8|ø0> ccc455éìß°a–.]Šõë×£¶¶?üðêëëÅý.\À¤I“�““ƒââbÔ××cÙ²e777$''ãå—_Fxx¸x�}ûö‰ç¿úê«ÈÌÌÄ©S§PPP€ÐÐP<÷ÜsmÖ{èÐ!XYYÁÝÝ0uêT˜™™¡  iii8uê-Z$¿}ûvñºZ­¶Õ—EEE˜3g–.]ŠòòrDGGã�7Þxzz"99sæÌAdd¤ØÎO?ý$žÿÆo ÿþÈÍÍEVVfΜyWoÎoòpýßxéî5ù˜²¾©ù�£LGi/ òg+WC—EDôÐ`—o""êò¬¬¬ðòË/cÅŠ˜;w®¸ýÊ•+HII�R©„……,,,°víZôìÙk×®…µõ­'W²¶¶¾íxç?{íµ×àååX¼x1<<¯ûŒ—®lTâR¹Í-M’†ÃÝÖÛÐ%=”¨‰ˆè�ðꫯ"88“'O·ÃÑÑvvvâ6???¨Õj”——ß2P«T*ë=ÛÅÅ‚  ¦¦¦]�úN®^½Š���6÷§¦¦")) 0`¡R©ÚÕvYYZZZtÞ(@tt4T*•¨'Mš„ &ÀÛÛþþþ022Ÿ¯««+¬¬¬Äsår9qýúu¸¹¹µ«cccñŸ-,,tzÜÉòåË�Ï>û 3gÎDdd$V­Z…¨¨¨{~ö£š¦J\*W NUƒ —pxØûv«7òDD���šˆˆöööX°`6mÚ$nóóóCee%JKK!“ÉÜè"meeÕfØÛ¶m¤R)"##!$ êêêàä䨫«»mçÎ�ƒ­­m«ö%‰^³‡àÌ™3:ãžÿèé§ŸÆ×_�ÁƒvïÞ�Çëcnn~Ëqã°´´ÄÆ�uÞzÿY�=0bĈVÛår9JJJPYY GGG@FFìííáââ¢Ç§xkmÕÜãñññˆ��GKK V¯^�3fè5ŽúaV§ªAvy:*•t E”ýPqdÑýÆÿÒÑã•W^Á‰'ÄŸÝÝÝ1}útÌš5 .\@ZZžþy,\¸PgÖí3gÎààÁƒxûí·ñÚk¯á³Ï>ƒ‘‘$ zõê…Õ«WãòåËHNNÆW_}Õêº|ðNŸ>�³gÏ⥗^Âüùóaf¦;©U�=ðÝwß!??'Ožl÷=-^¼ .Ä·ß~‹üü|=zO?ý´8ñ—D"Azz:JJJ°oß>qüôõéÓYYYøù矑ŸŸ�'N@«ÕÂÒÒ‹-´iÓpüøq(•J¤¦¦â‹/¾hWm~~~˜ø/¼ðÌÌÌ�˜˜ˆ_|QÜÿä“OâäÉ“8yò$¼¼¼ðûï¿#((HÜŸœœŒÅ‹#>>S§NÅ_|�ÿüç?:5Œ?ï¿ÿ>ŠŠŠ0mÚ4$%%µªó½÷Þ ðøã�#""}úôi5fzÊ”)â›ô›âããáää„ 6`Íš5ðööÆüùóÅs¿ýö[¼÷Þ{Ø´iÆŒƒíÛ·ãË/¿ÔiÃÝÝ[·nÅG}„ªª*áÿøœ��±téRÈår,_¾J¥���˜?¾xnll¬Îóø³­[·bÕªUxî¹ç`mm�¹sç¶9©ÙO<©Tª³íñÇ×¹g©TÚjÍl///|þùçX³f ª««Œ��8::bÉ’%ذaV¯^ ­V‹¨¨(lß¾ýþþÒ=šZ‘£Ì@im!|ƒ0Ü?&þµŽˆ¨³ ‚ º""ê>Z®,22kÖ¬All¬¡K¡{ð ýÞµE¥iÆåë™(¬Îƒ·Cü�BºÝ`DD] ¿Ê$"""êâÔ5ò*.¢ *v~î?fÆ÷Þ0Ýj""¢ÛX¾|9 ]uSm ò+/!¿âd¶žâ7–¦V÷Þ0uj""êTÆÆÆP«Õ·\“¹+š4i’¡K {¤Ñht–îzh- *sp¹"ÎV2 ô k3[C—EDDÂ@MDD�ÊÕÕ¹¹¹·]{™¨#•••µš ®«- «ó�£¼{KGô÷[s{C—EDDm` &"¢N5xð`ìß¿Ÿ�š:�B¡€¯¯¯¡Ë¸-®Õ »<Vf6èë5öN†.‹ˆˆî€‹Q§Š‹‹C~~>öîÝkèR¨¨¯¯ÇîÝ»»ô,í%µ…ø5o? *sá�þÞ1 ÓDD.›EDD�®´´+W®„ŸŸÆŽ‹€€€fL5=Ôj5²²²°yófDDDà™gž1tI­”×_Cv¹$�€ÔÚÝÐ%Ñ]b &""ƒhjjž={pâÄ ºzÈÁËË ±±±3fŒ¡ËÑQÑPŽKåç¡Öªä7[/C—DDDzb &"""êÕM¸T®@ƒªAÒp¸ÛùÀF†.‹ˆˆî'%#"""º�j›«‘­T º±�.¡ð²—ÃÈˆÓØ= ø†šˆˆˆè>¨WÕ"G™�ë ¥ðwê Ç@H¤‰ˆ* ÔDDDD¨QÝ€Üë(­-‚ŸS0üƒa,a§@"¢‡5QPiš�£ÌDqM>|!w �©1g¯'"z˜1PQ‡ªªªÂÎ�;qöìYTTTºêÆ\\\ —Ë1mÚ4xyÝ¿™´Õ.W\ÄÕª\xÙËáïÜfÆæ†¾}""ê ÔDDÔaªªª°dÉDEEaôèÑððð€DÂ1£dJ¥iiiرc/^Ü᡺EÛ‚üŠ,\©Ì†ÌÖ �.a°0±4ômQ'b &"¢³iÓ&˜˜˜`Ö¬Y†.…H´k×.äææbáÂ…ÒžVÐàJe6ò*²àbí†@—0X™Úú6‰ˆÈøÚ€ˆˆ:ÌÙ³g1fÌC—A¤cèСÈËË»çvA‹‚ªÉ݃ªÆ DûŒD/÷ ÓDDݧœ$"¢SUU777C—A¤ÃÁÁ•••zŸ/@@qõd+Óacf‡~^Ã`gáhèÛ""¢.€�šˆˆ:ŒV«…±±±¡Ë Ò!‘H Ñhô:÷ZíUd—§ÃÜÄ‘áhébèÛ!"¢.„�šˆˆˆèOÊëŠqI©€$•õ�‹5{^Qk ÔDDDDÿs½¡ —ÊÏC£mA�42OC—DDD]5Q;TUU¡¤¤2™ ŽŽ?{·`eeeè2ÚTÕx—” 4©äw;C—DDDj""2ˆªª*¤¥¥aذaâ¸ëüü|h4´»�sçÎáĉ°³³Cll,\\Ú7ÆõÈ‘#xöÙg¡ÕjQPP€ææf˜™™ÝòØuëÖá½÷ÞCXX”J%¶nÝŠÐÐP¤¦¦¶:¶gÏž�Édí®¿¦¦‚ ÀÞÞ¾3‡©®®†‘‘ìììÚ<æ­·ÞºuëPTT[[[C—¬£¶¹ —ʨm®F s(<íå0222tYDDô€` &""ƒ8{ö,F�…-[¶`æÌ™€äädÔÕÕáƒ>hWï¿ÿ>6lØ€'žxxõÕWñÝwßaÈ�!w‡{µvíZ888Üv�çñãÇC«ÕÂÚÚÚÐåŠêUµÈV¦£¢¡ Ρèã9#®&JDDw‡�šˆˆ &44+V¬@|| Aƒ0zôh¡¨¨ðé§ŸB.—cãÆ�X¹r¥Øþ‚ Ä6~ùå„„„`ÆŒ3f &Mš„††qÿ?ÿùO,]ºk×®EHHÆ�‡—_~YÜ¿jÕ*DEEaÞ¼y5jFŒ¡³ó‘#GУG̘1£F�ÂäÉ“uÚÏÍÍELL † †Y³f!00?ÿü3`ýúõ�ËåøüóϱbÅ ±þ¤¤$@zzº¸ÍÓÓ^^^­žQrr2ñì³Ï"""‹/÷¥§§cðàÁXµj† ‚‘#G"$$¥¥¥zý®YÚ˜#£ô4RóÀÂÔ 1àïÜ“ašˆˆî�@DDÔAâããÛ}ì¡C‡„¿ýö›àçç'¨T*aÉ’%Âk¯½&‚ \¸pA°³³222A„úúz¡_¿~¿þõ/±�””ÁÝÝ]èÓ§�°yófA¥R‰û®_¿.¸ºº ÿýïÅm/½ô’ðÖ[oéÔqýúu€ÐÜÜ|Ë:/^¼(ØÛÛßö^…3gÎèlËÎÎLLL„5kÖ‚ �F=z´°bÅ �ãfÍš%¬ZµªU›eee‚T*Ž?.n{þùç…¥K—Š?ÿãÿüýý…_|QhllÔ9_£ÑæææBVV–¸í�ÿ\ZZ*H¥Ráĉ‚ ‚V«fÏž-¼û ‚Z­‚‚‚têÍËËòòòt®“�� ¬]»ö¶Ï'--MðôôÔÙvúôiÁÑÑQÈÉÉAª««…°°0aóæÍ‚ ‚B¡LMM…�?þXAhii†*>Ï»µâãw„ÌÒ4AÕÒ¬×ùDDD·Â.ßDDd0jµÑÑшˆˆÀ¦M› ‘üÿŽS?üðbcc °²²Âœ9s°eËÌ�;‹ÜÜ\$''cÅŠX¾|9víÚ…ž={bÏž=°··Gnn.rssÜè¦}ôèÑN»? ñ�­D"ÁÀ�Å7Ôw²{÷n8;;#++ YYY''§Võ»¸¸`ýúõ:Ïîæõ&Nœˆ3f 11111:ÝÖwíÚ©TŠ‹/ââÅ‹­Ú?q⪪ªðæ›oŠçøùùuسùî»ï0iÒ$q:;;;üå/ÁöíÛñÌ3Ïìíí1oÞ<€±±1 Ðîç÷g©9x{^d‡ÕODD°Ë7uï¾û.V®\©3Žº®®®ÕòTŽŽŽ¨­­ÕÙfii‰¹sç"33C† `mm-$ òóóÅ?fffHLL4Ø}šššŠ]ÖïäVõ[ZZЏÝÔ*Lßôí·ßbÕªUÈËËÃSO=…ððpdffŠíé´omm-¶_]] ggç6Û¾W555­>_''§VŸ¯¾Ï�ˆˆ¨3ð 5\Ÿ>}…}ûö!::‰%K–@£ÑˆËj9rDœøK­VãÂ… ˆŒ¼ñÖÑØØƒ ÂŽ;ýúõCuu5’’’`ccÓæµoNru»e³î'[[[TUUµÚÞ¿¬Y³‹-Ò{ýæ––Œ9#GŽÄêÕ«1{öl¬[·ÿú׿Я_?|øá‡xýõ×aiiÙêÜÈÈH\¾|—.]Bpp°¸ý�ŸpãÍò­ê¿“Þ½{cݺuA\¦ê�Ÿ/у€�šˆˆº„eË–¡wïÞb ž2e >ùä<ñÄHHHÀ¹sçðÝwßáØ±c…B�qãÆáÑGÅðáÃQRR‚�>ú7nDGGcÒ¤I5j,X¤¤¤`Ĉ˜8q¢x][[[ôêÕ III3f ÌÌÌ0yòä;Ö[[[‹µkךšš°aø»»cÊ”)èÕ«W»ïûÑGŬY³;;;Ô××cúôé>þŽõ%$$`ãÆ�xúé§ñøã�ãÔ©S8|øð-×ö&""ꪌ—-[¶ÌÐEÑÃaçÎ�xâ‰'Ú}¼££#¢¢¢2™ žžžˆŠŠB@@Œ��‘��€ææfüúë¯ðððÀ'Ÿ|7föÙg¡T*qúôi˜ššâý÷ßÇðáÃÅö'Nœ¤¦¦"==C‡Åc�=Öªs\\ÒÒÒ�››‹ððpq\/ÁÊÊ C‡Õ9G¥Ráøñ〡C‡ÂÖÖгgOqù)++«VËEÉår�7¾��� Å‘#GpíÚ5 $$ðØc�A&“!55.\ÀðáÃ1qâDñ�.xyy¡gÏž­ž­»»;âââ�‘‘�C‡¡¼¼o¼ñÆ�'3yòdH¥R±ý#F ..Nl?&& ÀÙ³g‘™™‰˜˜,X°@ç upp0‚ƒƒqôèQ”––"00=zôЩÅÈÈ6664h�¸ÍÄÄÓ§OGmm-Ž;¬_¿®®®â1666:kŠÁßß���÷ýw“ˆˆ¨=ŒF""¢’��€/¿üÒÐeµÂßM""º8)‘¨‰ˆˆˆˆˆˆôÀ@MDDÆØØ�ÆÐeéøóÌäDDD…�šˆˆ:ŒL&CYY™¡Ë ÒQVV&NGDDÔ‘¨‰ˆ¨ÃøúúB¡Pº " …¾¾¾†.ƒˆˆB ÔDDÔabcc±{÷nÔ×׺"@}}=vïÞ�ØØXC—BDD!j""ê0!!!èß¿?–-[†ììlC—CݘZ­Fzz:–-[†þýû‹k{u$®CMDDîàÁƒ8pà ÁÿÍ�!ÁËË ±±±3fŒ¡Ë!"¢‡5‘Øå›ˆˆˆˆˆˆH ÔDDDDDDDz` &""""""Ò5‘¨‰ˆˆˆˆˆˆôÀ@MDDDDDD¤j"""""""=0Pé��šˆˆˆˆˆˆH ÔDDDDDDDz` &""""""Ò5‘¨‰ˆˆˆˆˆˆôÀ@MDDDDDD¤j"""""""=0Pé��šˆˆˆˆˆˆH ÔDDDDDDDz` &""""""Ò5‘¨‰ˆˆˆˆˆˆôÀ@MDDDDDD¤j"""""""=0Pé��šˆˆˆˆˆˆH ÔDDDDDDDz` &""""""Ò5‘¨‰ˆˆˆˆˆˆôÀ@MDDDDDD¤j"""""""=0Pé��šˆˆˆˆˆˆH ÔDDDDDDDz` &""""""Ò5‘¨‰ˆˆˆˆˆˆôðÿ_�KýÊ®M%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00ƒîînX­Öÿt<ˆÇ{ gœqFª‡2¯(`šcøãEg·ÃûØcp}êSèûÅ/Ð÷Ë_‚à$ –5k �Þ1̤¸¸wÝu×øŸ{zzpÓM7á�7ÞÀç?ÿy<öØc©~dž|ô£ÅG?úÑTƒ�9Ó™ŽgN>ƒ}Þ}¸¢ð œ“{άçx<žIÿ®஻ýmÜu×]øÂ¾€‚‚‚T¿µEéŒ3Θôw³ÿ~\}õÕxúé§q×]wá»ßýnª‡hÈ×¾öµTaÑ¢€i:ëg øöÛ`~?úÛ�žï},xb~>–¼ü2``Ú½  =ôª««ñÄOàСCX>a–꥗^‚ÏçÃõ×_Y–'�;öÜu×]“ÉÐ4 O>ù$¬V+®¾új<ÿüóØ´ic8ï¼ó°qãÆ¤ÝQ½ýöÛhmm�ôØÅ_ŒÂÂÂYÏÆ3Ï<ƒ½{÷"�¢¢¢W^y%Ö­[7åØþþ~¼òÊ+8x𠺻»a·ÛqÖYgáÚk¯�rwuìØ1ìܹÀÈ’´¶¶N D7nÜs™äرcxòÉ'qìØ1ˆ¢ˆsÎ97ÝtÓøçK²[D‹à’m—`ŸoÑŽŽÅ0ÅòïÿþïøÑ�~„`0ˆ;vÄ\’?õûvöÙgcãÆ�S¾oÏ<ó ¢Ñ(n¸á†˜3¦ÝÝÝxýõ×QTT„‹.ºhÊóo¾ù&6mÚ„ÎÎNx<lذïÿû§{}}=:„³Ï>•••غu+6mÚ¿ß�U«Vá¶ÛnƒÃá˜tNgg'þñ� ¥¥�@………8ûì³q饗NûïÇëõâ‰'ž@}}=TUEMM n¹åÍÛßñªU«ð‡?üøÀpÏ=÷àßøÌf3@×u<ñİX,¸æšk&�7Ýsýýýزe Š‹‹qî¹çâïÿ;Þ}÷]˜L&\y啸âŠ+’6öW^yÃÃÓ›xýŸI{{;žyæ:tP]]�믿K–,™rlkk+6mÚ„cÇŽ¡··ùùù¸à‚ på•W‚ç'§<ïÝ»‡ðÞ5·±±qÒ57''6lˆ9®={öàùçŸGGGÞÿþ÷ãƒü`z/c32­þßÿž5Ûl¬ `ûÖl2±&`üÏ‘C‡f}�üã [·n]Ìç/»ì2€ý÷ÿ÷¤ÇW®\ɰ¾¾¾)ç¬X±‚`===ã�€•——³Ï}îs À¤ÿ.¸àæõz§çoû[€ýà?˜õ=}ìc›òú›6mšõ¼‡~˜¹Ýî)ç`wÞyç¤cŸ~úi&BÌcËËËÙîÝ»'ï½÷Æ<öÔÿ4M›2®þð‡L’¤)Ç®\¹’;vÌÀ7‡dšO¾óIf{ÂÆð(XÞÓy¬'Ü3ãñ[¶laXuuuÌçËËËöÈ#�LyîG?úQÌïÛŠ+¦|ß®»î:€=ÿüó1Î÷¾÷=€ýä'?™ôøðð0»úê«cþ¸å–[X$‰ùz_ÿú×vß}÷±ÿóþÏ”s¯¹æšIÇ?ÿüóÌn·Çü97ß|sÌŸñÒK/±¼¼¼)Ç;öÜsÏÍùïòG?úÀ>ñ‰OLyNÓ4–ŸŸÏ°—_~yüñH$°ÒÒÒ)ç„Ãa€•””Lz|ûöí »âŠ+Ø%—\2åý|⟈y½sûí·3ì©§žšõ=­Y³fÊëwwwÏxŽ®ëì'?ù 3™LSÎ�=üðÓŽÿñ�<íuóÌ3Ïd���“ŽÿÊW¾2ëõ¶®®.æçù‰O|"æñëׯŸñ÷TªÑ.¹äÜ|3¸ÑÄ:Ýç‹FœÕŠòG�k)n6k×®0m'CGGxà<ú裃8xð Ö¯_�7ß|ßøÆ7’ò3~ùË_âèÑ£8zô(®½öÚ¸Îyùå—që­·" á—¿ü%ÚÛÛ‰D°ÿ~ÜqÇSv|ø|>\tÑExðÁ±ÿ~œ8qwÞy'ÚÚÚpíµ×"�óÍ7��é¯ý+€‘;°±ÇÆþ;õ.éW¿ú¾ÿý¨O=õÐÒÒ‚û·Ã�°qãF躞”Ï�¤§ZÀcm�! `,xú‚§‘oÊ7üz���ã»åV¯^=é¹ßüæ7¸óÎ;QXXˆ'Ÿ|rüûö�o|ÄM7Ý4)™÷Ö[o<üðÃ1ÖÃ? Žã&-‹3ÆpË-·àùçŸÇ¥—^ŠwÞy>Ÿ»wïÆûßÿ~<òÈ#³æVÝÿýxæ™gp÷Ýwã�wÞÁöíÛqÏ=÷ ?ÿ½ÏEQ|ò“ŸD8Æþð ‰àÀ�¸çž{bÎ`ìÝ»×_=ü~?~ö³Ÿ¡µµ½½½øË_þŽãpË-·àرcóöwÍó<Ö¬Y y×ÜÍ›7ãøñãxýõ× ñÎ;ï`ÅŠ¸ÿþûñ‡?ü!)?ã…^¿†ÕÄù{ç¿ø¾ó�ïÀårá�@?‚Á Þ}÷]|ä#Aooï¤ãý~?6n܈gŸ}G�E À�pÛm·a×®]ãßÅ1wÞyçø˜þã?þÀÈìêÄëí‹/¾8e\Ÿÿüçqÿý÷ãŒ3ÎÀ믿Žááa477ã†nÀæÍ›ñ¥/}))ŸÙ¼HuÄ–îN\wkæùñ™¥f›�u}ë[qŸ?Û Ó]wÝŰË.»lÒãFg˜°ÿøÇ“Žïîîf²,3Y–YoooÌq$2Ã4ÑG?úÑYg˜t]g«V­bØßþö·˜Ç Oú³¢(Ó¾Þ† ¶yóæ˜Ï¿òÊ+ »õÖ[gûàà ³ÛíL–eÖØØ8åùk®¹†`/¼ðBBŸ É{ö2ëV†GÁlOØØ¯þ:®óbÍ0E"¶k×.vá…2ìú믟tÎÐÐs8L–eÖÐÐ0å5Çf“&βƒAæp8˜ÓédÁ`pÒñ»víŸ=žhìš³zõj‡§ŒÁãñ0»ÝÎ|>ß”1ŒÍ0I’ÄÞ~ûí)Ïëº>þÿ��� ;÷Üsãþ¼×¯_ϰßþö·SžûÝï~ǰ¯~õ«ÆÿBÙÌ3LŒ1vë­·2ìk_ûÚ¤¿;œaÀž}öÙIϽöÚk [ºté¤Ïl¢Df˜&ª­­�u†©¿¿ŸÙl6&Šâ”Ùø1ñ^s£ÑèøŒét¿?~þóŸ3ì§?ýéŒcß¹s'ÀŠ‹‹ÙÀÀÀ”ŸS]]ÍA`­­­ }& …f˜f!¯\ nÂ:1‹F‘÷­o%íõÇrq�@Ò^óãÿø¤?`ýúõˆF£xíµ×æù›ª±±û÷ïGYYÙ”»”1N§sÒŸgÊ·:óÌ3ŒäoÌÅóÏ?¿ß�~ðƒ¨««›òü‡?üa#w�$ûDõ(>´ãCi!X >XüA|yybe(Ž=:^OÇd2áÌ3ÏÄñãÇqÇwL™zá…àóùpå•WŽÏrLëûf±Xpã�7Âëõâ…^˜tüßÿþw˜òoê‘G|éK_š’ã2–Sâ÷ûñöÛoOû¾®¾újœsÎÔ®‰ù%999Fò±â© ÔÛÛ‹-[¶Àn·ãsŸûÜ”ç7nÜ8åýÏ‹Å`d;òòòðÁ~pÒc]tÊÊÊpìØ1=zt^ßO,/¼ð�6lØ€ÓO?=æ1ñ^s%Iÿ¾Îõš;öÝü—ù¸Ýî)?ç†n€¦iغuë‚fñ ¤ï^}¿ûØ„Cœ$aàÏF~’–·Æ–•ÆþÏ•,Ë(//Ÿòxuu5Œ'é-¤¦¦&#˧.‰ÍäÕW_Åo~ó477£££‘HdÒós-F7¶¥·§§ߊŸ8qÀHÒ$É>ßoþ>ºCÝà‡RK)þzÎ_~ ‹Å‚ .¸º®£­­ ‡†$IذaÃxBñ˜±ï[___ÌïÛØFŠS¿oûØÇpÿý÷ãá‡ÆM7Ý`$ù‘G�$I¸ùæ›'?–€ûÆoàøñãS~NKK  ­­mÚ÷5–*0“²²2¼ÿýïǶmÛPUU…k¯½\pÎ?ÿü˜›8ÀƒÝnŸv‡š 3Ž+Æ®¹Éª·dÉ’)u�8ŽCUUÚÛÛqøða,[¶l^ßÓ©µµµqŸÃÃ<€ÿýßÿÅ¡C‡ÐÕÕUU'3×kîØw³¡¡!æ¿�½{÷À¼Œ¢€iÑãÇÑzÓM#;âp<¦ë`Á úþë¿àùüçÁ'áÜØ:r²ê0¹Ý <€‘uê…æõzŒ”Vˆ×Ÿþô'|îsŸƒ(Џúê«qóÍ7Ãår¹Ý´iEIʸêëëqàÀ�i?ÏT¹#ÉõÛC¿ÅïŽþ_«ùÎÍ;¿>ôk„ô¬¢Ï^ð,¬BâumJJJ&Õ/{öÙg±qãFÜxã�سgÏø� `üû¶~ýzáù矇ÏçƒÃáÀ›o¾‰¶¶6\sÍ5S®c»©ž{î¹ioPÜn÷Œ¹y±nºN5V¥úÎ;ïÄÃ?Œ|>ø €‘i=ôN;í´)ï``úÓŸb¾¦Óéœ÷�©É¾ææææÎøx¦\s¿ô¥/á÷¿ÿ=ìv;®¿þzTWW�¯€<ðÀhjjšó5w컹e˼þúë1�9uæ)�PÀƒ®ª8qÝuÐp`±€—$èá0X4 ‰ ÷®»Pø£Íùg�;ĺ#›Î©3- �16%h�¼»ªDŒmCŽ·%L8Æ¿ÿû¿C–e¼þúëS–::: Ùœn\?üá“–OÒSý`=¾Ýømôþ½ñßQ("¬‡aãmøÏºÿÄJçʤüœk¯½wÜq~üãã[ßúÖ¤-Öcß·ïÿû¸ãŽ;â~MApË-·à׿þ5žyæÜvÛmãË}±–¸Ç–ZÞxã�˜KÍñˆ·INN~ó›ßàž{îÁ¾}û°yófüñ�Äþýûqã�7âÀ�ãÐØû¿øâ‹“òïרææfñ_sgºÞÓϺŒ=žŠ“‰^s8€ÿûÿ/JJJðÎ;ï ´´tÒó§.5öÝ|üñǧ-7�Î(‡)†ÞÿJKËÈ9Žƒ�›‹êÆF`ô‹Ï‚Aôßs´9öòéïïǶmÛW]uÕ¤çÆòN­½¡iÚŒýª"‘HÌ%¤±iøªªª˜ç�}‘ƒ£3jÉ4vÑÞ·oc³ðàAx½^œyæ™1ó(öíÛ7ãùcûS§“§×twû${™‹ s#3*Ç¡;Ú �°:g5¾ZóÕ¤þ¬;î¸�O<ñvíÚ5þø\¾owË©ªŠÇ||&àT©ø^ ‚€5kÖà«_ý*víÚ…êêj?~|Ò¿Õtø÷öÖ[o¡££6› —\rÉøã²,Ãb±ŒÏÌLtj͹S�8qbJ›ÆØøn¿‰³Œ�5óyÍ g³sçN0ÆpÝu×M –4MÃÁƒg<ìš;[»–tøÌL§íÙƒþŸý l4 ›³X°ä©§ UT ü�ƃ&Žç¡�–0"ãöÛoG(Â¥—^:¥¤|II L)�ÿÌ3ÏÌ:-úÐCMús?^}õUˆ¢8é"1ÑÒ¥KŒô”K¶5kÖ`ÅŠhkkOú›ò¹OÈ‹uñª¯¯Ÿ5!pìülÛ“¯¾újX­V<ñÄ8yòdÌcc³Þa’ôWh)D�i¤â¶OñÁ¯úaâMxô}�‚ç’{t8øÒ—¾Æþó?ÿsüñ«®º 6› O>ùä´7=Ó}ßÎ9çÔÔÔà•W^Ác�=†žžÜxã�1g/Æ’§ÿûßO»ì–Œïôt7?V«u¼åÄ›–±âšíííxê©§¦}Ýùú÷ÖÓÓƒ/|á F’ŽOMz.--…Ï翹3[†ÞÞ^¼òÊ+“Û¾};Z[[QVV6© ñDóyͽꪫ`µZñÊ+¯Œç �jâ5wì=Ö5÷ïÿû¬ÉÞñ^sǾ›þóŸ§ý{V%}K¹¤z›^ZÑ4vhÙ2ÖÈq#e,Öù•¯L:¤íãgͲ̺¾ñ�¸^rl‹oYYûãÿÈ~ó›ß°/}éK¬´´t¼cKKË”ó~ö³Ÿ�O|ûí·Y__{ê©§XII ³ÙlÓ–à8Ž9öÌ3Ï0EQØñãÇÙ•W^9ã6[ÆF¶Î3ŽãØ×¿þuö /°M›6±æææIÇ ²£G�Žÿwíµ×2ìþûïŸôø©Ûž{î9Æq³X,ì·¿ýíøöÔcÇŽ±Ÿüä'ìË_þòø±º®�>?üá™Ïçcš¦±W_}•UWW3§Óɰ_ýêW1ßK$/�ùÝï~—½ñÆlçÎ�lçÎ�SŽýéOʰåË—³§Ÿ~šuuu±p8ÌêëëÙ¯ýk¶råJ¶mÛ¶…øö‘yöŸMÿÉ,OX³?ig<úGï5[áÊþþ~f·ÛÇq“¶uß}÷Ý «©©aO=õÔø÷­¡¡�ýú׿f«V­b[¶l‰ùšßÿþ÷€ñ¢�/¾øbÌã4Mc—^z)À®½öZ¶}ûvæóùØÀÀÛ¾};û·û·˜Ûç{¯¬ÀÿûÿoÖÏ`ëÖ­ìâ‹/f>ø ;vìÓ4� ±»ï¾›qÇŠ‹‹Y4�tÎŽ;˜$IÌf³±ßüæ7ìÈ‘#,�²£G�²Gy„]~ùåì;ßùΜþžÇÊ ¼ï}ïcüãÙ=÷ÜÃ>õ©O�_7Î9çæ÷û§œ÷ñ�œ`—_~9;pàëììdøÃXaaáŒe8ŽcUUUlÇŽL×u¶g϶zõj€ýüç?ŸvœG�e²,3‹ÅÂî¾ûnöòË/³M›6MÙRßÝÝ=éÚZSSðwÞygü±'NLyýÿú¯ÿßÂÿè£�2ŸÏÇTUeÍÍÍì _øûýï?~ìÉ“'™$IL’$öàƒ²p8ÌÂá0{衇XNNÎøg7ÝwóðáÃŒã8fµZÙï~÷;öÖ[o±�;wNùýÁcùÈGvñų­[·²ÁÁA6<<ÌÞ}÷]ö½ï}/fÉ�tAÓ‘cÇØ>»ý½jÞùùL;õ–®³Àk¯1-Šë5ǦSÿ³Z­ì³Ÿýì”ê©c¼^/[¾|ù¤s8Žcwß}÷¬•¾ÇþáOüïì³ÏžõK¸mÛ¶)x?ó™ÏL:æ¿ÿû¿ãª¨Ýßß?åõï¿ÿ~æp8bÿ­Sj[½ð Ìb±LªL‹Ñªºÿñÿ1cÀÄc�?þxÌŸuj §ë:ûÞ÷¾³ò2f³ÙØ®]»æéG’Wñ²K¶^ÂÊž-c_Ý=·Z?³LŒ½|L¬Ç¤ë:ûþ÷¿?ã÷-V`Ïc‡?®°°pÆZe쪫®šößçÒ¥Kgs<ÓX­¡Sÿ�`¹¹¹lëÖ­1Ï{î¹çbVú{�{î¹gN7cÓ©ÿy<vç�wN©g5æàÁƒÌårM:Çl6³G}tÆ€iýúõìÜsÏ�YQ}¦¿#Æ»ï¾û&]ç°_ÿzr-°Ûn»mÖëmYYÙ”×Öu�Ýyç�1¿kDZx`Òñ¿úÕ¯ÇqSþ.¿ð…/°›nºiÆ€‰±‘íÔŸ«Òw0œñ=ååå¥mµoޱ8’J‰hK ެ];ÒX×fCùßÿGœ•¬§sòäI¼ùæ›ã¶X,(,,Äi§�³7ÔDCCCøÓŸþ„ 777nÄûÞ÷¾˜½ä‚Á l6ÊËËqâÄ <öØcضmt]Çyç�‡[o½uÖŸŒÔƒzã�7Ƨf—.]гÎ:küùƒN;Å;Q¬xÀÈ–ê§žz ƒ¨¬¬Ä† pî¹çN9öرcxüñÇqøðaX­V\rÉ%¸îºëpðàA477ã´ÓN›±êm /I0¶40]/¹ãÇ�ãé§ŸÆ¡C‡�FQ^^Ž3Î8—_~yÒJ>�ìÑÓÓƒ×^{ v»}J ž1}}}غu+8ŽÃ�7Þ8i÷›ÑïÛ³Ï>‹p8Œ’’\pÁ³ŽsûöíØ´iNœ8»Ý޲²2\rÉ%8çœsbþ;8µ—ÜlZ[[±eË8p===ÈÏÏÇòåËñ¡}hÆÝN>ŸO=õvíڟχ¢¢"ÔÔÔàꫯžs³âýû÷�o¦»ÝŽòòò¸Êšœ8q÷Þ{/:::PVV†Ûn» Ë–-‹ÙKî­·ÞÂùçŸ�«¯¾�=öþú׿bçÎ�°Ùlذa®¾úê¸ÆÛÛÛ‹;vŒ—;8õºöÎ;8™N¬xcŽ;†gžy„®ë¨®®Æ�7ÞóÚ¹sçN¼ôÒK8vì<®¹æ\|ñÅxë­·ÐÞÞŽK.¹dÆ¿Ÿ��ìß¿���`ŒÍØKnïÞ½xá…ÐÒÒ2^çüóÏÇ…^˜¶;“)`:EÛm·ÁûÈ#ÈýÔ§P<ÍÖ×t41`š-I‘BÈÜL ˜ž{î¹T‡,*+pŠò€þ‡?€?¥#7!„B/Ú%K„B™ˆf˜²Ïó8óÌ3QXX˜ê¡BHÖ³Ûí8óÌ3¼í IÊa"„B™-É‘ŒT†Ñ<WÕpB!$hIŽd Æú#è�ct]E‰mEÌíÑ„’jÑþ~„Oœ€½¶ü<7&ó�–äHFИ‚ÿ!x•Éýû<–R[ª ¾*!„Ì�Hw7‚‡ƒé:«ŽuëÀÇQ �¤/ ˜HÚ *Ãh ÅîÝWh©D¾¥"ÕÃ$„@¸­ ÁSúª‰N'µµà(hÊX0‘´uêÜLЬUÈ3—¥zÈ„�EŒ1†à‘#ˆtvÆ|^ÌÉ�£®\šV²&3£€‰¤%E�¢#xþè`\Çó<�bK5ܦâT�²麎СCˆôôÌxœävÃV[;k›’~(`"ig¶%¸éð<�2Û*8%Oªß!dÑU�æf(ÃÃq/çåÁ¾j@V2 L$m$²7�Qn[ »äJõÛ!„,z$ÿ¾}P}¾„Î3ÁZSC»|3L$-$º7�Qé\‹@-n!óG ákl„‰:ßRZ K5íòÍ0‘”óG‡Ð:�ðÜLDNÆRçZ˜kªß!$ ©^/|ûö�Eçvݲ,YË’%©~;$0‘¤ÑuíÁà9Åæ*‚<ãñÉX‚›‰Ì›PéXY0§ú£!„d‘h?‚@×’sݲTUÁRF»|ÓL$)T]E{ ~e$éÑ$˜Qb]›”óød.ÁÍDæ-¨r®ƒÈËs1BÈ¢7± e²ð<KUL%%©~{d0‘9Sõ(ŽûV“çy¹ – pÜ{[hçc n&ÑŽJÇZu"„« e²pÛòå� Sý6É4(`"sÕÃ8îmDTM{ŒEt¢Ü¾gF¤=áГxw‹äÄRûðŒ#„$f¶‚”É l+WBöPi”tD1,¤úÐêk†ÂfŸ)âÁƒ`XØ@i"›äÆŒ#„Ä/Þ‚”IÃópÔÖBr»SýÖÉ)(`"†ø•!´ù÷Acê¬ÇFõ(üj4M…I´Â)åHMÐâ�<¨p¬ª}B™Y¢)ÇDõj?ìb>$>ñÞq¼ À¾f D§3Õ™€&’0o´í�ÐãØÙT‡Ô¼`ú{_3^àó 󦔌ßm*B‰• ÆB¦g´ ePF`ôš'ð\rÎ@Ð$I#A“Ýžê�‚Œ¢€‰$d0Ò‰ÎàQèlæ¥5Ætx•>DµpÌç9žƒYpÀ!º�Š/ ÇTŠbŒ#„Le¤ %c:¼j"êäkžÀ‹p› À#ñM'¼,ñv-+Õ“K0‘¸õ…ÛМ}‡ÈÄ%¸ÙH‚ v)¢�;°¹*°.E�¹|Á.!$})HÕ#ð)ýÐôØ×<‘—à– ÀØt›Lp¬[ÁLõäR�&—®P úBí³k n6<ÇÃ"9a~½¾ÈZ…<3Œ#„+H9q n&² !G*œTb%^¼ÅçÚµàM©Ic #(`"3b`èÄPdæ"³-ÁÅCÌpÈðX¸­ÿ<Ï£ÄR—‰jŸ²˜%Z�rº%¸™H‚ ·TšD»ö5kÀK ?OFPÀD¦¥3 ­�}³VãŽêQÔ>¨q,ÁÍFàØDL ØÎ„ãTØVÂ!SíB£p[Â'â¯7ÛÜLL‚9R>``Ó‰ètÂQ[ Ž‚¦” €‰Ä¤1­þf”™·ÓY‚› Çs0óvØeÀf'›À‹(·®ù™„�E�1†ÐÑ£Ÿ<÷9ñ.ÁÍÄ"Ya<†vêŠ99pÔÕ�¨ïB£€‰LQÃh 6Oiu2Q2–àf#ð2œ’¢�:&†~'¢Ò±ѱ ?�’:º®#tð "½½qÏ0rÍKd n&ɇ˜kè\É톭–Šð.4 ˜È$-ˆ¾FDõé·Ó&s nV›è„UÌ™ûkÅAäd,u®…I m¼„d«D RÎe n&6Ñ ›ä2t®œ—ÛªUTOnQÀDÆU/ÚûflŠ;Kpñ�x3œ¦…I—y*ë /`!da$Z�2Kp3±KnX Îj›ŠŠ`­¡"¼ …&ðEûÑ<M�½�–A‡O@D ¦lŒ/À!y ñóÈȼUÎuy9eï—’\‰¤LöÜL² ƒeU,¥¥°TSÞ…@Á`¸ 'CGÁ¦iu² Kpq°HvØD¸yîGgí¨´ÕA(h"$Ó%R�RÑ#ðÎÃÜt8žƒSôN°,YË’% 2ÖÅŒ¦E®/ÜŽîÐ1L÷5HÕÜlD^„CΟ÷ áɉ¥ö5à Tè%„¤‡D RÎ÷ÜtxŽƒC·Éà º¥ª –2*Â;Ÿ(`ZĺƒÇÑn�ù\:,ÁÍŠã`“ræ½B¸Mrc‰�v¤’‰â-H¹�KpÓáy.¹"—ø¬6Ïó°,[SQQÊÆŸí(`Z„cè Æ@¤+æóª�OíO›%¸ÙH‚9‚�æ–ñÊ1å£Ìº’’+ É ñ¤\è%¸™§œ‰O¼ Çq°-_¹�:Ì ˜]×Ñ<€áhß”ç8ŽC@JË%¸Ùð‡œ ™Ÿ¿rnSJ¬´#…�toAJÆ‚šAm8­®y/À%@0�rÀ l+WBöPç‚d£€iQõ‘êÝAuj푌X‚‹Ã|'„ç™ËPd­JõÛ$„L#Þ‚”é°7�á6€72sÎópÔÖBr»Sý6² L‹„¢Gp¿aují‘L[‚› Ï pÊy†¦´ãQd]Šø”ÁñÇT6:­gçtô|0‹VØE·¡q§²ˆvTÚê 4’ ³¤Ìö%¸ép<§è1œ çåÁ¶jµ{ŠLLÕ£8îkFX©ÞMKpsÃó²27÷%5›”ƒ%ö:ðIÀYÌf*H¹˜–à¦ÃsrLù� ^·LEE°ÖP�ÌxPÀ”¡¢Úhõnm¤z7ƒŽáH}qLGÏ—±„p»˜`n‡äF¹�¦¼ 1j¦‚”Œið*ýˆhtÍãy.¹"glVÛTZ [uuªßFÚ£€)…ÔÚüMˆê#Z‚K>�‘c*€`¤ñå9rÊl4åMH¢4¯¾}û Ç(H¹X—àf"p<\¦BÃ] ̰VV¦úm¤5 ˜2LPõ¡-Ð E‹ÒÜ|ã8ؤœ9'„»ME(±Ò”7!ñš® %-ÁÍL8¥ˆƒ&kUÌee©~i‹¦ â‹ö£=xš®B‡o¤Ÿ–à€I0Ã.{ÀÃx>R¾¹ …ÖªT¿BÒÞt)i .>/Â-€7P.…çyX–-ƒ©¨(Õo#-QÀ”!#=è ‚ÎtZ‚K�`=0Í¡ÆR‘¥ yº{#d:Ó¤¤%¸ÄH‚—Thh×/Çq°®XS5?L /ÜŽžðqhšFKp)Äñ̼vÙ0½œxÅ–ep›èî��‰¦+HIKpƉ‚·TÎ@ïLN`[¹²‡‹ODScŒ¡'| ½¡vZ‚K#/Ã)y ò‰ç p‡Rë ¸Lt÷F0}AJ *|J?¢jÄà+Y0Ã%åj8΋"l«WCr¹Rý6ÒLiŠ�á¤ÿ£ÝPô¼ -Á¥ŽƒMtjMÀq*ì«à�Œ5Ð$$[誊À¾}P††&=®h +´— &ÑŒ10°é„EØëê :“Ó !ÓQÀ”†t¦£Õ¿¾h-Á¥9I0Ã!ç&\~@àE,±ÕÂ*ëEH¦‹U�’�!¨Ò\²Y+ì’ÇÐN]^’`[³’Ýžê·‘r0¥M‹âD`?|j?Ê "j(ÕC"³à969f>±ö'¢Ò±‘.DdqÑB!šš †Þ»¾ÑÜü²JØE·¡s9Y†síZVc-X²LiDÑ#hõ7Ãí§%¸ d‘ì°‰.pˆ?_@âeT:ÖîEH¦‰U�’–à†]rÂ*º �Ë›Lp¬[Á<÷ÖQ™Š¦4Ñ‚8îk„Wé¥%¸ & ’'¡2oÂû:˜ÄÅ{!"‹ƒ20ÿÁƒ`Š€–àRÁ.¹`�å$ñ œëÖ�—gcq ˜Ò@Hñ¢Å×€a¥›–à²V9Þw΀Y° Ò±"¿8/D$ûEzz<|x¼ ¥utç/-Á-$ŽçàÝ0 ÆRD»޵kÁ‰sk•‰(`J±€2ˆ#Ã{0¤tÓ\–‘E3bnÜwÍ¢Kmµ šHv ··#|üøxAJZ‚K-Žçà=†S$§öÚZp’±,™Š¦Šöâˆ÷]ø•AšŽÎR<ÇÃ.¹alqo“r°Ä^Þ@…^BÒ c ¡ãÇnkù3-Á¥ žã�cʇÄK].ØëêÀó‰×xÊT0-¯×‹ŸÿüçÐu_ûÚ× Y½8ìÝI;B ³dƒMpƒ�£€œCr£ÂQÔ¬—d.]×:t‘ž´—Žxž‡K.H(çr"9/¶•+Á-’ ‰¦ ë:>ò‘� ©Òm²Èøÿ~ñ!€ÓçøÊ$“ð‚§˜)Ž<%—œ�2ûªT™C˜¢Àà”ÁAÔ .� —©glyMÎ˃mÕ*C5ž2Íâ Sì�wÞ– Qp`wKª‡E˜®iŽt#¨yÁ0ó}ÊP´�Á#©2! Ó#ø  ‚�! z1¤ôP°”¦4¦cXé�ÊCçGûúF’ùÁÜ L  ¨¨hÒ:/ǹ…Táy1b`D‡0í†6˪?|]¡c©2!qÓB!ø Рb(Òƒ€2DùJiNÕ4 +=ЙjèüHW‚-Ù? @Ó(ËÍÅÅK—Âi2Á&IÀaÇ �©I!U‹b(Ò�ˆîŸñ¸¾PúBí©.!³Ò¼^øê롆BPôÃÝ”¯”A´Ñ ‰œ Œtt ÜÚšê·1¯(‡ižE»º0ðÚkД÷f¼Á ~ºåU¸*¸þ‹—‚Ïþ¥_2“h…SÊÅt÷/<ϣز nSQª‡JHLc)u%J»à2œ(HpI…qmP‰ÅZUsYYªßƼ €iù€w÷n0}jr·/ÆO_}ö%lüò¥©*I1^àó ó¦ØÏóòÍË!›(h"Ï pÈȧô|’x*íë`�õ‚"$z4 S†‡NÒÜ"d—\°ŠÆ‚^’`[³’=³gÅ)`šÆü ð55%­Ê©®ëøÅÖW1$©¸õ[W@¢ ‰`4!œ·Ã.»öÞ’­Y° Ò±bíV1J …0ÔP�!o-Á-RÏÁ!ºaŒ=œ,ùv-kæÎŠSÀdÓ4 ½ñÂíí3î„3B×uܳm+zXûΕ0[è—!!ð2œ’"ÿ^ m¨´¯�ÈÓ†’|Š×‹�Æwá öÐÜ"ÇñrDdƒ©¼ÉûºuÍ™9+N“Z(„¡×^C¸¯o^Î/¶nF�ÄÇþãJ˜m4‘Q›è„U|o§œMÊÁ{xN˜Ã 2Ytp½�oà%8à99¦|Hœ± G°XàX·¼œy¿Ó(`JPt`C¯½%˜÷ŸÅünÛVœˆøpë·.‡Ý•¹S™$ùL‚ö áN9å¶Õà Vè%‹›ÏçÃw¾ó ⢋.Âm×_…îæˆ(ṿ8É*<ÏÃ%@äŒ=¢ÝÇÚµàÄÌš§€)¡¶6 ïØ-²pkø Àÿ¼ñ:Žú‡pëw.‡ÝIAy�À pHHüÈÝžKÎG™}Uª‡E2Ч?ýiô�Κó‡›.8 g¯«Iõ°Hš8.¹o,ÏVr:a_³œ�9³ât+ÆüûöaèÍ74XFj¬~þ‹Q›“‡‡~ò*†ûýs~M’=4]ÃP¤~u :†¢½è Iõ°Hß¼¢3†íMô="ÓÓ˜ŽÁht(†ÎW¼^ø÷탣uXº¢€iº®cèí·áݳºª¦lŸ:ï|Ôåäáá»^Å`¯/Õ I3!Å�¡HT¦ ?|=Ác©É0V›÷ÞÌ®a?þøÌkØ}èxª‡FÒ”Î´Ñ ÉØfepÁbö[MGÂ~ðƒ¤zéJ�D0øúëµ¶¦z(€ÓÊËÑ?8ŒM¯Ô£ú´RXl¦¹¿(É:ÓÖà8Q=¬Ræ‹#óKgº½GPR!àHKTEƒ®10ƒÞŽ´w£s`kªËS=T’†cPXfÞj(R ¡ƒ�òò&ìéˆr˜¦¡ù|èÛ¶ êðpª‡2Åßßy;:Ûñáo\†‚2c%ëIv“3rLy(³®„Û”}]ÃIrT/ÚûáënF ï†ÃQüù6ap0žçpýûÖá¼Ó—§z¨$͉‚—TÞà¦sq1,Ë–¥uÐDKr1„::Ð÷ÒKi,ÀGÏ9—,©Âc?ß‚îÖþT‡¤!E c t-¾½ðFzS=’ft¦£;xGO¾ ×ññ` Ìf•U°ZMX{ö<ÿn#ZZ»S=d’æTM�7Ú œƒ wv"t,½S hInƇcxÇ花D¶…²ª¨‘P/¼´å+óápÙR=$’f"ZÃÑ8ä<˜©ïP†qÂ׈ÁþcPG¶âž¢´,Ç�õà–›/“9<óòN,-ôÀ�“Ù­-ÈüÒ˜ dÁ ‰Ï©^/Àq�rr>w!Ð’Ü(]×áÛ»� J@€Ô×ãՖøî‹¡byaª‡CÒ”À˨u_�¹$ÕC!)¢3½¡Vô…O Ò×=šñxEQ!I#ur¶¿{Û^lÂ'®8+«KSýVHš3‹68%�áó­UU0—•¥úmLA3LMî~óM[Z O'¦ÊŠ¢"ˆ:ó/îBqµ9º$S1¦¡'Ò ‘“à�ñÝÜŒ1hƒƒàÌfˆ¶ôI7YÔS¸§CÛ¶AñzS=”9«Ê˃S’ñÔ ;‘W–ƒÜB šÈTŒ1´aU/dÎ ‹˜^wp$y¼ÊZýM(ÃÐüDûûmné¥Å¹pxÌxú•Ý4‘Y)zÇA24©ƒƒl6ÖôÈ¿\”c Á£Gáݾ}Á+wϧŠÜ\äH2ž~a'Ü¥NxŠ(h"S1ÆÕƒˆ²0= ›àÏgN{2³±Y¥®` t¦Aõz¡Ijž[Tà†«ÀЧ^Ú·ÙŒb šÈ D pDÞ@ß¹± Éá€`6Öì7™]À¤ë:| ð××§´r÷|©ÈÍ…ÇdÆS/¼ {žù¥t1#SéLG”…Àx•>X$!õ$27¾h?ÚüÍð+Ã`ºu š7ù� ó]ð9ðäK;áE”Oð%YŽQ†ÄI†Ò˜®Cé“Á”ÚbÍ‹*`bŠ‚áwÞAððáŒÚ —¨R·Vž~i'¬¹f*nIbÒ™•‹ÂÄ™0¤ô@ÓUØe·¡íÀ$µ4-Š®ðQt�Ac ªPúú gOî6*?/Ee9xêåݰpÊ‹óRý1�tÅ€¨‚Ä™ ðbâçë:Ôþ~ˆn7xÙÀLU’,š€Ióû1ô曈´·c1TR(q¹Plwà©—vBrˆ(^Bw€d*]W¡@ƒÌ›Ò|ð+C°ŠNˆ”ž1†"=h ìC@)´«G£sJîN„'׉¢27ž~y'8EÇÒ²‚T$M1Q‚,˜Ás‰§0]G´¿rn.x)5×§E0Eûû1øúëˆô÷#ûC¥÷åä`‰3O½²¢U@q%Ý’©4]cL¢ ŠÁ°Ò¬"åÀ¥3U�¢Ý½áVèl¤R· Bé›{rw"«m.+ƒµªj^Æ–±“ bxçN„ÛÛ³ºÍÉBp÷ÖÍ(X鯵·SдX˜EqÞÍIœŒJçZ˜„ôèžMÆf•:C-Ðõ©»z™ªBéîNËäîDøCaÜûÇM(2Ûñ/¢ ‰LÏ&¹`›Ã¬¶¥²–ŠŠ¤�+#&e`Þ�;éí͈uüLà ñÓ-¯ÂUéÀõ_¼<µËj²hBŽT$�/ ñ&T9O›’ëDŒ‹j!œ †_Šù¼CéëKãäîD#Ü÷§W‘'ZqûM4‘éÙ%לR¬UU0—•%uL0Eºº0¼k”ÁÁ¹¿™Ä㧯¾û6~™.fÙJäE¸å"€K|G‰E°c‰c õšK‚ÁH×´³J z½Ð††³î¦0Qð§?¿“ñù�—‚¾ÅI#ù•n˜c©<ÏòlLEÉ+�’9c> c#ÔP(Õ£ÉZÁHwmyæR+6~…‚¦lÃñÜr!Îø/)‹èD¥£GA“!5€“ÁéÞiŽ`Pú¡eñŽß¨ªà/÷m†9ÊãÿûðàiJ›ÄÀñrDdƒ©<Ïò|9LÉ)�’“�"ØÜŒÀ‘#Ðh'ܼ‹( ~úê&À#â–o\�î³ÇÁm*„ÈÉs~)›ìÂëÂ‹Ë ýávô†Z¡±iò‘t ÑÞ>èáì¿Îiº†{ïÝ. ãK·\I¤œLÅsr¤|H‚ÙÐùœ À¶r%d�ñÝw㯕î“ Á»gÂ'N@£�p &¢(¸kó&0·ˆ�ÜAw€™Žã98%d>yIÛ9öU†ë¦,&!Í�ÎÀaUß´Ç0UE¤»ÈðäîDŒMèøâ‡¯€I¦ ‰LÅó<\r�á›=^a]½²Ë5§q¤uÀ¤ Á»{7Â]]´.4MÃݯnBЦãÖo^‘.fË.»`’_KÉe*D™m~‹Åe2ÆtôG:Ð<1cϬlKîN„Îtü寛¡*øâÍW@–è:C¦8.¹‚ÁüINa¯«ƒä4~LÛ€)ÒÕ…áÝ»¡Q›“”š¬ ùæå�Mt1Ë4fч”;o¯ï1— Øº,Õo3í„4?:ü‡Ö|3—­ÉÝ‰Ð™Ž¿þu+½A|åæ+a±Ì}Ù˜d‘à2‚‡±4^’`_³¢ÝX"yÚLŒ1„Oœ€¯¾ŠÏ7÷$s¦ë:~±u3†$·~ë H4e Y0Ã)çÏû²Y�e ,KRývÓB¼³Jepª7{“»Á<øàV �ôã+7o€ÅBå+ÈT"/Á-€ãCçs² çÚµ¬‰§'¤UÀľýû<|í„K+º®ãžm[ÑÂøØw®„™îÓžÀËpÉà ”0¢ÐZ…|srëždš êEGð"jpæQrw"€Ú†¾6/¾¼ñr8T(•L%ñ2\r¾á ‰7™`_·¢9±Dò´ ˜´PÞúz„[[¡G3³üÿbð‹­›Ñ£që·7Àb§;Àt%"Ür!8» Áó<ŠÌË�kN^Ý“L¡ë:zíè�¶CŸ%ß’i*”žèQ5ÎW_\€‡y½Ç‡ð¥�ë‘ã°Íù5Iö‘n¹€±BÁb�cÝ:ðrü7ÿi0©^/¼»w#ÒÙ �vÂ¥5à÷¯mÅñ�·~ûrØ]t˜nxއËT˜’:I<ϣIJ.Srêžd‚€êEgð Âêì³â‹9¹;Q�?µm‡úðÅ›.ƒÛI} ÉT&ÁŒ)0ØlW´Ûa««ƒgДò€)ÒÕC"}}´.C0ÿóÆë8ê­߹v'Méb¤|@dÞ’º1€ÇG-ì’ñš™@gzCmqÍ*€ðCéR�š1þñüÛ8ÜЉ/|h=òÜŽT‡¤!³h�CÊ3œ§)»Ý°¯Y×±) ˜c�8�@SÔáaÚ —�þ÷­íhîÃÍw\†Ý¦»ä†ELý/›äD¥}8ƒw~é.¨zÑ8ˆ¨6û¬Ç”¡!¨^ÚÄbÄHÐtŸ¿þ2äå¤z8$ ™Eœq6ŸH4›a­­…h‹oÙ7%Ó4ø@èða(Y\þ1øß·¶£q°7ß±îüÔÿ¢^Ì,’vÑ•Ò1ð�© ù抬¬®3½¡VôEÚâ*Àé:¢}}ÐBáT=£=ûâ;Ø·« ÿßõ—¡¸0»g.‰1VÉ»ÿwCÊÉ�}Õ*péœÃ¤‡Ãð75!pìtjs’zçmìì=‰[îXwAò‹#’Ù™„ÑiéÎè˜+ʬËa‘²ó;T†Ñ8„¨ß^JîN®W¶ìÆžíÇðùÞ�’‚¹·¹ ÙÇ&9a‹ã¦Q.(€uùò„oê4`R½^øêëî耮ÒE$›üý�·±£³þÆe((£;À…$ &äÈùà lŸUÒ˜†îÐQ E{âÊUŽ Ú×KÉÝIöÊÖÝØõF >{ÍEXRZ˜êá�4ä”Ý0 ±W;xž‡©¼–%ÆjÆ-XÀí¹‘înÚ —¥žÜ³¯µÃƯ¿…t¸^DŽ©‚ÁÊ·seí(±.‡EÌÎ6¿2ˆŽÀ!(zü³áZÀu`L§¼Ìùðú›Mؾõ >ý� QUAA™Œã98D7ÌÂäk/а®X1§&¼ó01Ænm…ß>(‹ºüÿbðÌž=ØÒÚ‚}õbWæ§z8Y�çx¸ÌE) –8N@ž©Ö%YÙ|WÕUô„[šUâCthš×›êág½îØ�765ã3W]„ªr šÈdÏ!Gô@Fvpó&ìµµ†[¢Œ¿î|LLÓ8p¡cÇZÐŒ¤ÎK x¡å0®ûÂ…¨XN³yÁqp™ q _<Ô,ÚPf]s–Î*ù”t#šÀ¬t %w/¨íïÀ¶›ð‰ËÏÅÊeå©I3<Ç!GʇÕ]ÛêÕ ¨œÎ¼Ýšê‘üÍÍŸ8%XÐФÖÖ®… IøÇïþ‰ë¿xÊ)hJ:‡èZð`‰çX*à1•ee¹€±Y¥�pWBç1E�Òß=B Òùg¯„$ŠøÛsoã6¬ª¡ ‰¼Gg ÃΫ—$%Xæi†IõùàojB¨½�vÂ-b›ÀÓûšpõçÎCUmiª‡“5¬²6Áµ ?Ó&å ÄZ“��EJ}Ñ~œ †¢%ô°HÑÞ^0ÊËL™�{�à•g÷âæ ÏÀiµU©IÏC-vB+qBä%TÚ×$eF<éS¤§Á}ûê윷‹Èñþ~ìnkƒ/†E–±47kKKa’¾™ÙGŽà‘†½¸ê³ç¡z Mse–lpˆ —P/ð"òÍåY;«¤°(zBÇ0îNø\JîN ÍÇñÜ“;)h"€ÈC¯ô@w¿×í@d,µŸYH¬Ùî©’0�%wGNœ@¨£cÞvÂ=¶w/¶:4åq“(â̲2\][‹Ü8«v’…ñæ‘#x¸a/>ð/ïCͺÅÝÍ~.$Þ4Ú£ma«˜ƒR[öÎ* EzÐj�¢'8«ÄÔa/´ááT¿2Aãþãxöñ�ØxÁ8£Ž‚¦Åˆ7‰P–åƒY§NžÈ¢Kík!ñÆS’01MCðÐ!Dz{š×;/IÞ{ÛÛñÇíÛÁ¸º®µ……дôõáŸG�¢Ûï‡$¸jõj|`Õª¤ÿ|bÜ;--x`ïn\öñ3±úœ¥©NÆ .¹pAj- ¼€|sòÌÙ™¢êQt�`8Ú—øÉº¥¿Z0¾â•daí;؆§}7œ»眶<ÕÃ! ˆ·› .˃. Óc¬¨rž�3–¾=ç¤o=A`ÿ~(¶Ò „`Z4¹I�o?¸tùr\µzõøãK=¬_±ï¶¶â¡�;q´¿?©?—ÌÝ9UUyÿû·�Ðu†º÷Ñ`¼8^€SZ˜Â”v)EÖ˜³yV)Ü’p®@Síí£äî4¶zE9¤[y<þ÷Pu†óÏX‘ê!‘ÀåÙ¡,ÍÅl³?-ˆã¾&,u¬Ï q½öDs ˜¿�ææ©‰ÝÉã�ÞÝ g “xôøFšW®(Œ½ëêìŠ TºÝè9¥?]}GžnhÀ†+p^ý¢N•3*+Á þòàÛP§_Dw€³â8¸¤<ÃwDñ8ù– 䙳sÉTÑ#88ŸbìfŠE¢#3è”Ü�öjªK±ñÖóñØCo"¢¨¸ôÜÚT‰Ì�ç¡:ÀÊ]q×x ©^œð5c‰½.áΆoY#==Ô×O» Ž“$ˆ9Éí,-޾¹��Ó“ïp ¶¸xÒc�'O¢ËçÃL—º{ßz /îÛw‘:bÌiååøÜ¹çáÍG±{ÛÁT'­q<§” qkîñ°Ën,Ë93kƒ¥¡HŽxw–´€Ñžn –2HMU1>úÉ‹°¹á6ooHõpÈ<àj¥zYN±ê:‚ûÁf�“:åg&:HÆÂmm:4kb·èp@°Xâ|åÙmX12½ºåÈ<ðî»ÌR² ‰@QU4wu�P7ÍÌT¯Ï‡]mmxëĉI§®ëˆ*JÒÆOF¬.-ÅçÏ;ÛŸhÄ[/5¥z8iË"8aæoƒÈK(µ-Ç[Ýœ!ÓUD ㄯí�ÐôÄÿ3Æ  Cé �phiY!>öé÷cKó!l¢ )«ð&ÊŠ"hã×G…E¡&¸áCøÁ~ðƒxÖu¡Ã‡no�;¢ÌfèÁ`RZ¢”¹\8{zÐ64„¶´€ã8,ÍÍ�¹åùoヒ¿í܉@4 §ÙŒ‹—-ƒ9Fé�>¿�^/V`uQÑøãGz{ñãM›R¬šð8™»|‡Ës=xzËhºJÅ-Oaí°Kó×ÄØ.y°ÄQ ›äʺrŒ1 E»ÑØ�°f¬h.Óu(ýÐ}~Cç“ô�ã°¢²&ÿxe7Âþ–WÏýEIJq6´`fci ' ß\Ž2ûÊ„Sâ˜Æ*w+‰�ŽçÁK´`0)VM~>ꊊÐ20€Á`º»±·£UrN™Í²È2:½^ …Bˆ¨*6:„†“'1 ÂeµÂf¹«vY­8¿ªjR°¯>ŒÃ}}XWV†ê¼¼ñÇO  ×çƒÛbɺ_6 )×nÇŠ¼|<½e7¢ª‚Š”€,š�#ÍO>‘—Pl]†bkÕ¼çE¥c ­þ&ô…; ÃàòºªBéëƒNmN²BŽÃ†š•ÅxaË^†X^Y’ê!ƒX®u$XŒe™E*lµp› õÀŒ;`òïßÕ`ÝN’ÀT,IË[.«—,[†|› GûúÐàÝÖV¬+)�Ãü^aª|»Û�Ã`(„OœuªòóÑçóáݶ6,õxPš“ƒ¨¢ ¾£.«’09kþ±={à�FqËi§Á>áuŸØ»O44 ÄéDI’ó´·Í†•yùxfën‚!,]½¸/f/Ã-óˆ;å\TØë`“\©~›ó†ã8ð¼ŸÚohV[�FéîIÚµŠ¤»Í‚ê•ExqKúzQ[��%3²•ÀóЊœ`K= f�à9…ÖJ”ZW@Œ§Ä¦Ù–/‡h6^%Sr»!‰oã›É¹••øÎ† ȳÛVU{öu÷à�çÿ™êá�Yp’my!˜�än�Qd]ŠJûÚ¤u+HèL°X`_»Öpç_Þd‚àp$tξînüúõ×á M_YW †N ÆGƒ¡5Ó̱Ñc8L ˜šG¦)% F_³6�Ù¥`4ŠMñϪØíÆ·/]�»:ñâÿ¾•êá,Žçà�=¹ätÔ‘—Qa_�2ÛJH|ò^7“ä™Ë�o™¹TÓuDûz¡¥z¸d�¸sløìç6àèÀx–‚¦tÅÙ$(« ¡Ù¿~YÅT9NKʬÒD Ïý V+ìuu†gšÄœ ÌÌíëCK?~¼iv·¶Æ\¿|ëÄ À2Ï{MIu]ǾÑrÓ-�µÂ£Üåš”0UêëƒI±<ròmS÷H“Î5 ìš{íÈ|ãé§ñLc£¡Ïl1És:ñíõW £¾Ïþiq\Ìì¢ 2Ÿ¼ò.Sjr΄SΛû‹e¸óRäš§ù·ªªPz{¡¨ÍÉbãtXqûç¯DËð î{zkª‡CNÁ¹,PWr‚»ØxEÖ¥¨r®›—˜†’%D»¶Õ«Á‹vÙp/£¾Ö¬Áµµµ+ þ¼c~øÂ x¦±;[[ñVK ~ÿúëãËj—­\9~Þ±þ~„Uyyã»áN5ÝrÜÁž(š†•ãKw0 sx› Å ${7vvBg î9ä€-&› ß¼ìrôijÎî É":`›u�ÎȬR-Êl+“¾´—©8ŽC‰uùhÓâ÷èÑ(Â]ÝÐïL2�ÓjÆg?¿�A?î}’‚¦´Q䄺¼ŒOlfÈ.å`©ãôyí�i8»Tt:a_½œ�Dn^’ :�ñË󸪶ßûÀ°~Å ø"¼´?îÛ±÷ï܉¦®.ð‡×®Åê …)��–?XY8}}Ÿñ%»’É;³Æò—Ny|,¯©.�å8ÿhâ9Ô•,î`‰ðØíøÎe—£ïÀ žúíVdcj‰I°$mÇÚȬÒYpÊž¹¿X*µ.‡]ùlô@ÑžJî&°[F‚¦^%ˆ??AAS*ñ½Ê5�6'ÀH[§"k*ëæ½朶ãˆ.l+W‚Kp7 0²4'šâß±“g³aãºu¸ëÚkñ�K/ÅͧŸŽkV¯ÆGO??ºê*l˜0»½�‘‚u…¶ØÉbc�ŒÃdBå„¥< it)¯ö”`«i–œ¨XšGÏ)ÉÉA®mþª6g#§ÕŠÿ¸|†�ûðäo³ëb&ð"ì’ÇP-�‰$AÆ’ñY¥ì««”,ǣܶÒ° ¥¿Шa5™ð¯ŸÝ€~-ˆß=ò tMMõ�N ,/„ž`r÷B·ušóþeÙã�eÙ2C‰U¢Ç“p°%‰"ªóóqiM ®®«ÃÅ551‘ÂÑäò͇ãxÿÔRÍÓ$o· a(B™Ëׄ×UT{{! ”¼¦™ŒYµT)܇ٌï^q%ÂíA<öëìšA„ÛT~åxžG®¹ËœgÃA³J³Òu¡ƒ‡‘ß.@Ög<™žl’ðÙÏm@XÖñß=§´Ó•E„ºº,�äîTµuJJÁsQ¬UU ŸÇ‰bÒô޹¤º,]ж¡!ܽy3¾ûüóxýÈ‘ñçÇó—N dš§Yv;ÐÝ EÓ°¼°pR^ÓLÆj6S—÷6<ˆg1J,át1ö¶³šLøÎåíâ¡»_�–Áw€<ÇÃ)惃ñšd’`Æ{J¬Ë!pÉ­m–�ôHþúzD{{Æ¡8˜™Ñl™L%Ü~ûˆ˜tüêï/BQßµv¡±3´UE` $w;%ª�#¥RºÓFÒ*ä™JKa©¬Lø¼d7èc<�ÛÎ>?¹ê*\WWÛ„]}3Ÿœ.¯©©«käñÂø{ž�Õl²Jª=“gþyô(^Ú¿ƒÁ 6<ˆ¿îØ�GwïF}GÇŒ¯ùç·ßÆwŸ�«®g*“$á?.ßn@Å#?ËÌ;@Žçà”ó òƲÇf•jœgÂ&ºRýv2‚ê÷ûw/TŸoü1^çQ,€ šÈd/à_þå 0�ß<² ‘(Mó¦È µ&?î6'c³JŽÚ”àMjIaKEÌ Ÿ'{<à“\|ŒËfÃW¯Æ·¯¸/[èõ�4Ô<µøäXep»É„%îÉ�OǾזſV:|­>¥pf¯Ï‡n¿€?mߎ÷ïG}g'¶9‚ÿyóMülóæ˜u›UÅ¡înxÃax¬ó›Ü–ŽL’„ï^q%ä!üäE¨v1³ .H¼±�’&ÁŒ%ÖZ”X—ƒ§Y¥¸Dzz௯‡™ºNÔE Ìa¦�d'�pûí ¸%üþ±M‹rV>q<½2jyü�¿�rîø¬R*%·Ë’%0'ºŒç!åæ.Ø›.t:ñ‹nÀ§Î=wÒãÍc•Á '8�Ãà …P’“W³aã5›N™Å›­â8×ÕÖâg7Ü€_Þx#¾w啨p¹ÐÒß?¥fSKo/OžDTÓ°ýÖCÊ5á—½„P(šê!eN ­(€žo�ëøtkë”ô€‰ã8Xª«!'°t¼ÅÉ߇˜”7ÎóS‚›É„•……X{JÀ7¶L¶6�Ýqc5›8Ĩ>:[umm-Ϋªß'Uœ“ƒOŽqõííãÇ£QübÛ6üyÇ€Y’00º p1ߺbr¢"þ~×&(i4™D«¡%4Y´ ÂZG³J ÐuÁC‡ù—B’áxŽÇ'ÿÏz¸JìøÕ#/!¢š]sÁ[E¨+  Ûã |Ò±­Ó¼\%8Žƒmùr˜ :o>ô&¢¶¸_¹äœqʲbóèŒP"õ—Æ‚¢¥Ϥ™QEÁ‘Ñ*â—ÔÔL9/otgž:áboE|ñâ‹!�~6»ÚÚð�çŸÇ¾ü2ž¬¯GdNó<�»t=rUîÿÑK§é $HpH‰Ížò�©ËgÂ.»Rý2†‰ÀßЀÈèÌn¼ÌªŒÂp~Â}.Iöã|ìc—"w‰ ¿|øex}ÁT)#qn+”•E`æÙWFÒ¹­Ó¼ÝVqÛŠ�<ñoyf1?ý.\7Ÿq®_³Kx/ÓUß?ZE|yAAÌæ½=£3GEzîñ<—Ù EÓPìpà??øAÜ|úéÈ1›ñÖñãã�ÔbÃó<þí²õ(à­xðÇ/#äO¯;@žà” À%ðÏÌ"رԹŶê9•XŒ¢P½^CçZòÞßuCÒàÖ[.FþR~óø& ûïì¾!¨Õž¸’»Ó½­Óü.Þsì«VÁߨ%Î]]¼,Cp8 ¼ð͇r— å.WÜÇ�Õl¦LãÉãÓäyíéÿ™“Λ0Ë•ïpàR‡—ÖÔ@×õñ|+]×±§½{::0 Án2ai^ÞWQç<ìDL_¿t=~ÿÚVüíG/ãÖo_»+õ ñ<ÇÃ%‚�3©xdV© ùæŠIùs$~æâbè‘­­†Î·E­ÈãtôÊ©~+$Ípn½ùb<þÔvüêÑMøÒÆË�›_·ŠÅŠã9èe.h…³çnмŒë²´ ”ÆÌû•™ãyØjk!ÅÙ H¼Aoº«Ùä²XP6a·ÃÈÎ9@Ý49^c�Ñ©yOÍÓ”;ûåRüæõ×qïŽØÕÖ†nŸ 'Oâ©úz|ïűÓà/èözñ¿;vŒ�!Ýp¾pÉ¥¨¶»ðÐO_…ß›âisŽƒÓ”!Îdb‹hÇRç:Z+)Xš#ke%ÌåÆ{I9"vxJ®'±m¼ñ|Ô¬-Æoß‚¾AßÜ_0K�%wÇ,½×Ö)½ƒ%`&àE¶Õ«!Æ»žãFª€gèôx_0IP[T4©ñEûà ¼áð”*âcUÅÁžž)ÕÄCŠ‚#½½0‹"ªób©î{ë-ìéA•ǃ~ðƒøïë¯Çooº ·ŸwL¢ˆ¿ìØ�–ÑY¯DÕwvâíÖVL07d!q>áŨÍÉÃC?yÃýþÔŒƒçà�r!q³'6rœ€|sªœ§Ã’¤¼°TVBžCeýœ°nu~ ê’ÌwÝÕç¢fm1~ÿä«èé[\õðâÁ,ÔUE³&wËØÖiÁngyY†}͈æøêÐð² 1�e°triM ~~Ýu¸¶®nÒãMÓ´cs ·7f5ñ}��ЛRÏiÌÞöv4wuÁe±à«—\‚‚Ñü'žçqFy9>}î¹`^Ü¿Òyº®ã§›6M)ap*€Ëb™vÜéäSç��3<…øûO_Å`ïÂßZŘ…Ùû!™Eª#³Jsí'G&ã8¶šš„7�LäåÀ©RKb»îês±ü´RüöÉWÑÙ=˜êᤧúÊB0Óô©<ÏÃm.DµýŒŒkë´ ao2Á¶f üõõТ³ïj°`j$½’yã!KÒ”ZI¹V+ª<žió—šFó›Öœrw¼otf§nš»æ7Ž8ÍfÔŸ<‰ÕEE°N¨l¾¢°³‡ûú&�w¨·­ƒƒ0 vµ¶âÝÖVø"9�8§¢+F— ׯX�õ+V¤ú#�Û­gŸ ¼ó6¹ûUÜrÇz¸ &×À,Ú`fþY' ÏTŠK8Jêž7ÇÁº|9˜ª":`,'ÉtA·éð ”äK¦ºöƒçÀdñŸÙ‚½öý(+ά_þIWà€Vá›aeHÌ(³-ÏØN >&X,°¯] oCXìhmŧÏ9gè˜J=ç\˜öHxìç[°ñëïGaÅüÜ ‚§˜LRòœ€K<¦²ŒÍËËTœ À^[ _Cä~r ¼ ƒùè´õ"ÄQÐD¦Úpé0Ë2þüüøô.DUÅâ š8‘‡Z•–3}ª�I4£ÄR›”ù›)„üà?HÅæebN”¾¾Yg�xYeÖà*“É¢ˆK–-ÃyK–L)Þy°§}�N#ÏfCŽÕ:þ«9¢ªØrø0r,\ZS—Պ帨ºUU¡Äå‚¢ë ±²°§�öÂëñùð|s3$AÀ¿_vÙ¤`Ìm³Á5š ÿà®]ˆj>vÖY�ÅÌHÌ›hUq1¢¡žiÊWæÃáš=¿(/À%L[‰Û&å`‰½N9�‚¥áxr^”¡¡¸fµc±)„¤4N3t>ÉnK*  K ϼ² K =pç,\׊Tá,Ô•`¶ØÉÝ<ÏÃm*D…­6kfÕSúPt:a[¹þýûÁ´™/Dbn.ôHdÆÞPÙ V�¸OžsÞ½õØÛѧٌ/^tÊÝnäÚl°É2z}>"‘IUÅ� Ϋ¬Äy••Ðu}RCß±å¿3ËËcÎ\Àñþ~ø#‘)ÕÊ`w7^hnÆÑѼ¨âœœU^Žõ55i×çîúÓO‡IðÄ=¯ãº/\ˆŠåIºä8¸äü˜;<^D¾¹œf•Ò'IpÖÕÁרÕ@[!žñ(æã¤µ QNMõÛ!ièâój! <î}þŸøÄåçbå2ãå-Ò³› -ÏŸ¶¥,ZPb®ÉºN)›a€ÅÁj…ÒßÌÐû‰ã8ð² möP3KΪ¨Ày••p˜L«*.]¶l|&*4Úne0ĺÒÒ˜¿ 9Ž›4Côls3úܰfÍø®ºS½qô(÷õá¢êjÔL(sðúáÃøËŽQ’“ƒj�¡övtàݶ6¬).ž`¥Ú²ÂBˆŒÃ³/ìDqµ9ž¹Ýr<§” ™ŸlZEšUJGœ @òx ô÷ƒ©‰=ã`Õ¬J!èÈüœJ’|å¥ù0;e<ýò.”ä8�ïɾòz¾lYXŒÛ<Ï#W.A…}LbvÌ*M”ò€ ÉiâÍf¨ýý3lj" iÐ N«g:‹,cY~>Ϋ¬œ´lWíñà@Oš»ºÐÔÙ ›$ÁeµNÛ2%ª(xdÏH‚€�žqÆx¾Ò©žhhÀp8Œ­Y3¾D×68ˆ?nßà¦uëð©sÏÅY¸lùrpŒ¡þäIéëÃK—N t]¸™7ÐïïîÆƒ;wâ¹æfl9|û»»ÁsŠޤÕùù�9O?¿ùKræ´{Î&æÀ"N4^@¡¥¥¶åùôše##8Q„äv�¤˜­æ«jA@‚aöæ¾dñ)-Î…%GÆS/ï‚ÇbFQAæçî#7‰¬4z¹ˆq=¶vT8VÁm*ÎÚÀi0€h³�E(ƒ3×´L&h¡�»æ’Eàyœ]^ް¢ áäIìjoÇËàõ£G±õÐ!<×ÜŒË&ÌH5vvâ�ÖV¬.*Âû¦Iäö†Bx²¾³O?}<Ðyp×.tû|¸péRܰví¤s– ±£mCC¨ÎÏG¾ý½YœÇŽáwÿü'¬’„ wì È?q¸·n‹ÏãX_v�¶z9­´æ$,õUåå!G’ñÔó;á.uÀS”ø Y´Ã~J£UÊA¥£i‘o-μ$Ar¹ ö÷ šÆÃªY�(h"±•å"'Ïš5A'òЫó¡åM�™ç9yær”ÚV@⫳˜©Ò*‹×TZ:’ksìØôñ<äÜ\(==Ð]¬ÆÈ’„[Î<×ÔÕaO{;Ú††Ðë÷CP–“3)¯h¬œÀºiêA#­XFJŒK�Hd¼VÔ•«WÇ<¯ÊãAëÐŽ÷õaõ„2M]]ð†Ãð†ÃøãoàH?8ŽÃ— O; …N'n\»Ÿ9ï¼ñsÜ·cZúûñÀ»ïâ _œ”Ïê‚eËßû6Ô�+X}NUüŸ3o‚SÊÿ5)p"ЬUpÉ…´ü–A»¶ÚÚ‘�º–çdMBa¨]–Zž#1­­­Ç�>¾*ÓqVݲTÉÎ"A«ò@·ÊSž³ˆv”ØjM§‚´ ˜ÀR^¦i36ÐäM&ðN'ô8ú.&6“ VWOûüÄ~vµ…Ó'?7ÄhÜÒ×`©Çƒ<[ìÝfc³@Ê„;w]×±o´GÞsÍÍXæñ`Õh�§¦®.Ü4øæžòš¹6>qÖYøÁË/£©« E�)I å,[‰çñÀßvà°úœ¥#ce?MÜ#ð2rþx°d—Ý(µ.‡Ä§W¾‰�èpÀ¶z5üÍ͆fšÌªŒ‚Hz,½Ðuºy#S­YU ñ#"ž|xEÃy§gN`àœf¨Ëò¦$w�àµ.YT� Ò.`Ë’%`Š‚È Í^¥œ°`Z—˜ªªbýŠèözcö³Fœý==ଚÐ^¢{´TÉ �”»Fkݸ&ì¼;Úׇðè]ügÎ=gTTŒ?×ÒÛ‹¢œ™ ž#Ž’}NUDžÇÿþm't�¡î}Uxð¿^ÄM_¾VÇä©eAáóÀsŒG÷ìÁ%Ë–á#gœ1ëëÿ×+¯ mh+ ðÑÓOGaÎü~Óó{÷bOGzB!0ÆÀÇspç¹ð×ûîOégNVèØ1„ÚÚ Ÿßg„W4Ò·Ž,'{qÿ½[p^M®¾äôTœÓ ¥ÊHï¥[ؤ”Xký¬ÒDQ]ŠãyØjk!N“¤ Q„èr¥z˜‹BU~>¾}ùå8­´{ÚÚðTC^;rŒ1\±bn?ÿüIÇ7�æ/ÕÏúÚº»Ñ64„<»_¾øâ –€ç8\úéøÁ5× 4Y�ã8€�áàÂ$Õ,K—Â4ÚsÑOлžÜž…$»”¸ñɹ onÁ³›w¦v0ÔåùãÁ’À‹(².E¥}-K§Hë%¹‰xQ„}Íø §þl6Há0”EØ:e¡:�ø× .@TQÐáõ‚é:Ê\®)KxQEÁ¡¾>H‚€•3$w�ièèœS^>¾;n¡�]Q�ß‘g·/¾� °.]:2s=Z#Ç¡ è³êð¡T¿’¦Š Üøäg/ÃßîÛ†ðËQ|øÊóçþ¢ ˆ•ÜmsPj£Y¥édÄ Óø`eö5k šcW\.ðÓìà"É'K–z<¨ÊÏ�Ùp÷`OMÊ‚Hâì±ù9K–`ýòå8­<5M+³¿ývœyöÙ°Ùl(..Æ=÷Ü“’±�Ôâ8Öš˜âôcb@a0f�òÞÈôŠòÜøôg×£¹«�¾´}á~°ÈC©òŒK/ ÈºUÎu,Í #r˜N¥…Bð××C‹ÑSN ‡¡ööRð4ˆDÐÐѧÅ2ë’ÜP €¨®OÛx>qÉå‚ãŒ3F Ã|ûö�47@çttÚzá"©~'$� pߟ6aYž·]}ÑÜ_p&&jµ°�óV)e¶å1‰“É22`5@ ±1fФ BõQÒe&y®© ÏïÛwrx²ð¢SQuu�&ÔŽ"d Ó4ø›š¦ßt2 ]ÐqÒÒƒ(·8›†“øxAüù6¡ÊåÆÇ¯MN¨)æ‘`I¨­“µ$7‘h³ÁVW>ÆR�”“>Ž% ’>ÆZ±”/Pò>Ïq�œNX–,�ãôÓ)X"Óâöº:ˆg?y�GQ(£t2=§ÍŠÛ?%Ž á¾§·&ýõ¹<;´•€$À.»±,çL¸ME,% cg˜Æ¨^/üMMSh²hÑînZšËõhèèÀukÖ Ç2¿S @Ì˃äpÀ^W�»I˜¢ÀÛØm´EP¢4AE»µ¨ü ™ž?ƽÜ„"³ÿò¡KçüzÏC)t@/ËoëD³JÆd|ÀÊÀüû÷Oi © AõzS=<’F$› ‚Û Én‡}ÍðóX“d=…¿±ªÁݸQAE§µ ZÒ;#’lŒDpߟ^EžhÅí7šx�ƒºÔÝm¥¶NI�Dûú8p`rMÆíçDŽç!çæ‚·Z!9�°×Ö‚›‡Þt$û鑼{÷B�K䎜´õPL2£hDÁŸþü ìLÂÿ·ñ2ðBbi&¼I„R�Áa¥fáI’5Dzz|xžƒª¨¥™ƒ'f“Àj `·åS[§$ʪ€ "=:é1Í륽‹Çóˆ£ÃÍÅŰ.[ÐÚ=IÕïG ©Éð ¶O  Ï2@A™‘¦k¸÷ÞMà:¾tËhÙ׻Êҥ±gŒX®\u1 mÕp› R=ü¬’u„Z[:~|ÒcÑžjлˆ² Éã_v3WTÀZY™êa‘,£ú|ð76NÙt/ŸÉ�^y Õoƒ¤9Mg¸÷¾—¿Žó a’%œyñ䯽cÉÝΪe(´VCâåT;ëdlY�™X**`9¥”œ›KUÀŽƒ˜“¹¨œ$�çyØ–-£`‰Ì Ñá€mõjÃK¼Žˆ¹Ñ…é™H2—ÀsØxËùPmÀ¶Öv øÐÙÖ;þøé�(.\ ‘§�,ó)k¦1þýûí}/Wúû o &éK²Û!º\ÀhÓ^A–a]µ Rݽ“…íîFàÐ!Ã9I}æx%c5žHöS™†£�8Úv»7�€®�|ÏDAÀŸï½�'ÕCÌzY¹$7‘måÊI3 ¢Û �–æ²/0@ÌÍ�,Ùëê(X" J.,„eÙ2Ãç{BnØtj|Jb9+ÊÊ�gu�K ¨*ŽŸ’³KæGÖLÇÁ±jd·{äÏ<)/<í”Êx‚Ù SQx³yü1Ñj…ãôÓ©z7I sq1¬UU†Îå8…ÁŒHW—¡óuAÇIK¢µvZÌ8Žƒ'êFqåY0P!ÊTZt0Ò Ê__5¦*à€—eÈn7¸�r© %IgŒ1@dÂNÝD¨‚†NKN3t>Él2Q)„gÅ:H¹¹©΢·(&ÐB!øëë¡E"Ô 7MñÞnÙíÆOÞŸÀó<,UU0•”¤z˜„ÌŒ1øöíƒb°\Tˆ¢ËÖ •Qд˜ØT+Šôb8j×@¤M,iaÑL 46B ¡½i…ˆóÔCT�’d¦ið75�o:ITTPÐië†Æè•í8Žƒ'”ƒ\±¶º:Kª‡DF-ê€ iÌëmn†20ep0ÕÃ!) ºÝ1¸© %ÉTLÓàkh€jpwnDˆà¤�r.³™ÌD„òaµy`_½z¼kI‹>`Õë…¿© áÎNh¡Pª‡³hq<Ùå?Íô³ ˰ÕÕÑô4ÉXLQ૯‡ :?(‡Ñm) ÙT+òù0¹<°¯\IåQÒL£”�ø>yºF¹ M4›!ææN)0þ¼Õ ûš5àc$~’IôH¾úzhá°¡óýR½– š²ÄØœSqB.(€mùrp|Ö×”ÎH0M ô÷ch×.D{zR=”Eƒã8ˆN'Ä–ب %É6z$ïÞ½Ð#ÆŠS›|è—)… ÓÉLFAÈY“`*-…µªjJÙ’>(`:E¤»ƒÛ·C£½óŽ—eHø!*HI²• Â×ÐÝàÝyC&oªß1È®Ø�vCäE˜++a.+Kõ�È,(`Š!ÜÖ†¡7Þ€FKsó‚ç8ÇÈ¬Ò wS¦¢"Øjj¨ %ÉZªß�@S“á²&æa IÆvÞ‘Ô˜¸Ç ¬55T�2CPÀ4 ÿ¾}ðíÙ�>ž¤b^Þ¬¹HT�’,c›NŒ¶iê³À+øSý6Hd&£0œIÁ‹"l+WRAÊ BÓ †¶oG ¥%ÕÃÈ’ÍÁíž1¡‘ R’ÅH‚¯¹ÌÀ¬6c }öAøx šÒÙØ¼,ÃN;~3L3Ð5 ƒ›6!Ü×—ê¡d4Žç!¹Ýl¶™�£éi²ˆEûûØ¿ßX]è´ô $ÛyGæÏÄ%8-ØëêÀSAÊŒCÓ,TŸý›7CõÓÝ›‚Ù 97˜¦\ÀøqT�’D»»8tÈXÉ8iíF˜7¶óŽ$ßÄ%8�N*H™Á¨ØÃ,D‡ŽÓNƒhµ¦z(…ã8H99� â –luu,‘EO.,„eÙ2c'3 (˜Y§òéÀ®ØPâ/–$·ŽÚZ –2Í0ÅÉW_�ÀáÆ‹Í-&‚$AÊË‹«n¤$dªp[‚ÇŽ:Wtœ´t!ÊK"'ssê*H™%(`Š“ch÷nD:: ›Ëv<Ç�w:ãž)¢‚”„L/ØÒ‚p{»¡s5AG‡­ *£ i!�º€ Rf ˜9y�C‡íí…FAÓ$œ @ÎÏ�{º™ R2»PK Bƒ&EPÑië†Ê¨žÜBpèvx.ð£™.<ÏSAÊ,#Îý%SI ”�0¬§Çp…Þl#Ùí]. Îéf*HIH|ÌK—BWUDºº>WÒD… Ði醯 ì¼#q‰µž‡eùrÚñ›eh†)A,ÅÐîÝ`Á Â==`‹Íe^ åæ&´=– R’Æ‚"b°ÇeDŒà¤µ‡šõΙ‰( LZ‚£‚”Ù‹&¢ýýð77ƒ) ”Þ^h‹0hÌfÈç’¤$dƒoß>(ýý†NÊat›{)hJ¢S—à€‘þ˜¶º:HT�2+QÀd�ÿÀD{z «*”în苤ïÇó�œNNgüçPAJBæŒé:ü��P†�õŽóKôZ(hš£˜Kp ‚”‹Léª ßîÝÐÂa0EA¤»ÛX…Þ "ÈòH¹1þÔ7^’`[½šj,’LÓF‚&¯×ÐùÃ&úåÁT¿�Œk  ‚”‹Ls  #ÐØ]סG£ˆöôdgÐÄq�NHNgB‰Úc)©_!Éþúz¨Á ¡ó‡Ì^ HC©~'Ö0R�Ò¾r%•GY(`š£@K "£Û~Y$‚HOv%Wò¢Ùã—`aI*HIÈüÑ#øêë Ò0aH26KµØð¼€Ü cÊ@) ˜æH×uø÷îï5§‡Bˆôõþ±òÞnYJKðb@) ™z$ïÞ½† éö™à•¨GæL¦[‚¨ åbDS¨~?¼{÷£ËqZ mpZ†.Ïñ‚Ñã�`6'|®œ—ÛÊ•tÇEÈЂAø Õ„cŒ¡ÇÚ�€hli/ÛM·G)/ ˜’äÔÞOj `x p*‰V+D·ÛPn*HIÈÂSý~šš )¤Ë�–„ê‘9†çä…ܰG­±ž„� R.Z0%‘¯¡ÊÐÐøŸÕ¡!ûYÇó�].ð´© %!©£z½ð75A7RŽNÚzæ(hši Ž R ˜’H ‡áݳLQÞ{lxQƒuSŠh6�Ì*È9âyæêj˜‹‹Sý6YÔÔ¡!øš›Á Ô„Ó¡¡ÓÞ‹·xÛ=M·PAJ2‚¦$‹tu!pèФǔÁA¨>_ª‡6Çq�rrÀ;†© %!é%Úß�Àþý†Ê›è‚Ž“ÖnD¡$|n&›q T�’¼‡¦yàß·Ѿ¾ñ?s¥¯J �ê¡�ãe’ÇÞàN6*HIHz wu!tø°¡ò& § ÓÑ •-ŽvO3-ÁT�’LFÓ<УQxwïž¼s…1Dûú …B)Ïqˆ99†“³© %!é-ÜÙ‰àáÆÎU¶nè,»Û=Í´PAJ2Lód¬AïD€HO�ábss%ļ¼9“¤‚”„d†Pk+BÇ�:7,FÑeé�ŽÌ,�2“Ù–àÀ\XKM •G!“PÀ4�ü"ÚÝ=é1@¸»Ûp±9£$› ‚Û=§ ¤$$³[ZíD�¨ˆÁIkvu.� £(˜I›¾&¤$Ó¡€i1MÃðîÝÐO]†ÓuD{{¡-@ÐÄñ<$·‚Í6§×¡‚”„d¦PK Bƒ¦ B·­/+‚¦Ù–ਠ%™ LóL†´AïDL×íê2V7%N¼Ù Sn. Šsz*HIHæbŒ!pèДÙîxù¥zmƒ`Zf.Ïñ¼€ÜPœQûLQAJ2+ ˜À´wxªŠpOX’ƒ&Žã :�#‰Ýsd®¨€eÉšž&$ƒ1ÆųPAJbL L�DàÛ³Z4v“K‰ GÐÄ ¤ÜܤM'SAJB=É­4RH—ºm}p©šxðð„Ýp(³—N¡‚”d.è[³Àx“ æ¥K§}ž3™ çå�ŸaWš`6ÃTT”´`Ir:áX·Ž‚%BÞd‚mÍF–¥�È…IKí,�¥Á¢¸‚%Si),Ë—S°D £¦ 80ã_-€68mBNÇó�œNNgÒÆA) YÜ´`¾††É½/ãÄx í¶^(Hüܹrèväs�Y~ƒQAJ’,0¥S ïÚ5ãEJ Æ· ² )/ÜËLD) ! úý45M›*0ã¹¼Š.[/¢Pd¬‰,ÁQAJ’L0¥�28ˆ@só”*àé>4]‡ät&5°¡‚”„�‰T¯þ¦&CÝNA§£*›¿ÎÀÈ\a0²6û2"¤$ÉFSŠB¸«+æs¢ÅÛÊ•ˆööîu**HI™Ž20ÿþý±ëÅÍv®¨¢ÃÚ �¯'7“x—à*HIæL)Æ4 ÞÝ»¡MhÐËó<ä‚Xª«Á c>ØljKp ‚”$õ(`"„’]Uhj‚âõÎýÅâ@)I: ¬`B! áE¶Õ«!Z›%2Br»GÊ£P°DRŒf˜!„¢G"ð××CÝt’l¦ÂBX© %Iô-$„bo2Á¶f „y˜ý1•–¶bK$mÐ !„�9Q¡E£s~-*HIÒL„BæLõûáol„®(Æ_„ça¯©�\X˜ê·CÈ0BI Õë…¿© ºª&|.¤$鎇 !„$…ètŽô°L°&/˰¯]KÁIk0BI)77¡dmÁl†cíZˆT½›¤9Z’#„’t‘žÄL¿bD‡ƒj,‘ŒA3L„B’ÎTPkUÕ´ÏKn7uu,‘Œ!¦z„B²“©´º¦!tüøäÇ© %É@0B™7–Š 0]G¸µÀhAÊêêT‹�„QÀD!d^Y–,T¼Ù 3¤$Š’¾ !„BfA È„B!³ €‰B!d0B!„Ì‚&B!„�YPÀD!„2 ˜!„BfA!„BÈ,(`"„B™L„B!³øÿ³�¨cÍœ%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00ôœÖÍdšL{:™´™$mœ¸–dI–eÙÚ%j!%‘ZHŠö¸Ë<@ %‘E¼ùÿ<%&þ.p/~ÿõ÷—LÓ4A„G$[€ ‚P�DAæD$AaNDAæD$AaNDAæD$AaNDAæD$AaNlVP-Òy�ýg£\Ê�+šø\2O®®ås«ýH’ÕÑ Bå3Mø¬/ÎñËq’Y§*±~™‡—ºƒØm¢-[�$QÊäárƒw}ƒ\QÇ0îf ›"ÓÑèä«Ï5Z¢ T¼ýx”�Ñ,º~÷+GU$ªÂ½Ú‚Û¡X¢ðˆDÚŸ…÷Ž�“+š÷$M7ÍrîzÒê¡¢�»žäê}É ¨›d ¿>¶:DaDyˆ|ÑàÒPغ£¦é&G{ãV‡)íh_MŸú2 ¸t3M¾hX¦ðˆDyˆTVCbæIŽdV·:LA¨h‰ôÌψ"Kâ9ªB"�<„Çe›¶÷q›*&aF®‡Ìohš‰Ë!V£TñÍ7ƒ‘hž=4ÂC: ÄÒÿçÀMÆby«C„Š’Éë|p*L8Yœù%øßûnrq0muÈÂ#«°¦�Êj:ãTirÜaSÐ óžÞˆ"˸6òšF±h K°¥ÃÇ ›bE‰°¤†É‰+I>:!_4‘$p¨ EÍD7îÎuȲ„"�Cµ‘Ê•’ÌŠ»»ƒÔר­¾ á!D™D7LN^Ir°'BA3‘%‰öfkÛœí3<‘Æ0MªÂªe~:[jÑtƒÞQ†“˜˜8ì2ÏoðÄJ/²,:yÂÒru4Sêu$4êk]lîáq©ôǸ4” PÔQd‰æ�‡Í�!lŠÄõÑ®G)u$ ºDc¬â‰rËåá {N…‰¥K7}cÀÍæÎnçƒ{- ³”\î—Êé3Íô©ìîÒÙä¶úò¡ìÂÉ{OEéÉàu©lìÒxðþŸî*j—†bô%0L§*óÌÚZ¶­õ£ÈbޤÒ,ùNÙs:ÌÀHéKßëVÙÜ¢>àšókŽF2œˆ�¹Õ%_Ùìâ•­uÔzÄÆañÉ >:åÄå¦YZT²¶-@G³iŽeRÙ"ç"ŒFKÉ(èSÙÙdU³hŒU’%›@¦¿éç§4‰iš ÜLrñzM7�eغÒÏ 8T1¬%T?Ã08s5Í�žÙ¼�„Äò&/ë–p¨ó3ì4ËÒ3&™)5ÆÚœìÞZG�_µúò–`1 “3WS8![0�$‰å�^Ö/`Ÿ§›~²\Q§÷z”k#¥ y�Sáù�º:|¢†–PµF³ì;f<^úb¯¯q±±3ˆß=ÿß4Æ$غJ4Æ*Á’J WG3ì9e"QJ“{›:‚øÊpÓß/–*Ð3&’ÈÐp°»;Hk�Óê·Ef-š,r 'zg¹­Ç©²¾=@KÈSö¿]Ð únDéNà´ËìØàÉU¢ ©U–D ' ì;áÊÍ[ó3Lî•[i~$L&Wš¬_Ùìâ•îµ^Ñ%*WA3øôbŒ#½qtl²ÌÊe~V·ÕN9^Nñt©1Ž—c�µvvwi«Ÿû¼¥07‹:�ä :GzcíK  *2«[ké\æ_ð›~2Ý0NÐw#†f؉§Vûؾ> ÊZ Å4K…÷�Ž�ÉH´Ö{Ù°"ˆÃníòÚÑH†ž�0éI�±Ý[C<¢1¶Pe™î¦ßØ,Ë<Ç\e :¯E¸1–Àë’yis�M+|V‡& Eòì9æf¤Ta¡®ÆÉÆŽ5žÊÙàw»1Ö{#†>©1öìúÑ+»E—@®ŽåØw*ÌX¼4ÏQWãdSg¨,“{ó%–ÊÓÓ&’,=¨MA;¯v…hó#‚’�ý=QÎ]+5lœvëÛ´Õ{­mZ¹‚Nï�(×F“`‚ש°C,V)»E“@i�çîÞô.‡�u+*û¦¿ß�ñç"ä‹¥ª¤WxyyK¯Sìʯ¨›¹åÓ¾šn¢È«–Õ°ªµ¶j6ñÅSyÎôGˆ&o/V±³»;$«”IÕ'�BÑäÓÞ(Gz膉¢H¬j©®›~2]7¹<ãÒPÃ0Q‰Ï­ñóìºZl¢K.”ÉÅÁ4ûNGHdJó -!:‚¸ÕÙx§97!›/]ϺV;»‚øÝÕy=•ªªÈÅÁ4{O…ïœ#ÐÖP“{ó!�+ráj”ápi¹d­×ÆK›ƒ¬k-ÿrIaé¸-Ís …Kç5^›;‚ýÕßb× “˃wc6EâiÑ›WU™@n†s|p:Âð­›¾Öç`SGˆ Ïauhón"ž£§?L"SšÓYÑàbgw�FQ©Tx ɬÎÇç£w*N;í kÛ,o\|sÙ¼ÆÅëÑ;‹U|.…7Äb•yPU $‘Õ9p62irOa}{°ªæ9æÂ4ap"Ź�…Ió#;»xªtˆA°Æt§×-`Sw«<œ(5ÆâéRcly½“Ý]A‹¯á¹Pª"�hºÉ±¾‡/FK7½,ÑÙâgMkí¢¿é'•J…Ç1UÅéM�!·¦Öê�„i˜&œ¾šä×Ç&p9l¼Ø½ ûc¯tW†âœ»¡£ÉÍ[;—ÜÜnÙïB»M¦¾¦´¯ÀëREò¨’ö[“´»èuT2I‚¦[‡Ùm²HÄykI¯Ó./¹ä �@A„ÅI$AaNDAæD$AaNDAæD$AaNDAæD$AaNDAæD$AaNDAæD$AaNDAæD$AaNDAæD$AaNDAæD$AaNDAæD$AaND„ôõõ�Ç­C*’H ‚0ƒ?ü�•+Wò7ó7èºnu8‚PQD„‡‡ÃüÉŸü Û¶mãàÁƒV‡#C$A˜¥“'Oòâ‹/òÖ[oqíÚ5«Ãˉ"�è'?ù ëׯçÏÿüÏI§ÓV‡#– Dæ ›ÍòÝï~—5kÖðî»ïb†Õ! ‚ DÃðð0ßúÖ·xúé§9|ø°Õá‚Z DÂvê#Ô“±]9 Fõ¬–‘2IÔÓ‡P?þÔ#ï#�Þ°:$aŽ;ÆŽ;xë­·¸~ýºÕá‚°YÀc1 ìýåÆe0 0 L›Šíè^Š/½q¹ÕÎÈvþ(ê‰ý I k IØ®œEëØ@ñÙ/”þ»P5LÓä'?ù ¿üå/ùÓ?ýSþìÏþ §ÓiuX‚P6U�@l§¡ ^)}ùÞ"iE ˆº÷'¿õ6¦Çou˜SRF®•’ÇäÞ’i‚®a»z³&„¶ñi«Ã|l}ôû·kusvåÊ•Gþ7™L†ï|ç;üèG?â¯ÿú¯ùêW¿jõeBYTo)°�? ZqÊK¦�íÌÇ蛞µ:Ò)ÙŽïŸ~¨M+b;ûÉ¢H üøÇ?¶: Ë®ýí·ß¦®®Ž_|ÑêpaÞUm‘S±™A×±]:�íÒi«C�©˜Gʦ1]«Cy,/¼ðÿò/ÿbus¶wï^¾ÿýï?ò¿S…wÞy‡¿ú«¿¢®®ÎêË„²¨Ú‚¡óÐEÁpû¬ŽtJr:[ú©(V‡ùØÚÛÛioo·:Œ9‹Çã�œ@^~ùe¾÷½ï±e˫IJªÚbÔÖc´IÄTl蛞¡ØµÃêP§¤~öA©w4iþæžøý!L»˜€­&mmm|÷»ßåë_ÿºÕ¡‚¨Þe¼Š ­ëy�§h¥K’ME[ÿ”ÕQNKÛü,HòÔ+­d…â3¯Z¢0K�‡¿üË¿¤¯¯O$aI©ÞhëžÀ´©·®D›ŠiS1}µä¾ðÝ‚7]^ò¯ý¦·¨ö;Éд;0BÍV‡(<„$I¼ùæ›\¸p�oûÛbÉ®°äTí€Ús©�Ã4 m؆¤k˜5!ô†¶ªØCaÉ}ù¿"O #¥`wb;±9<‚íüg·$­ˆÞ¾£©²wœ? £¡}Å:Ð5Ô“¬G¸Åårññôööò»¿û»HUÖH„r¨Ê"�¡\½Š�â/Yμ+nÛ…iSQ΋ÚXàõ×_çܹs|ç;ßÁív[Ž TŒêK ¦‰ztÅMÏ”&¡Óí»³ ]=º§TâD°ÄþáòïÿþïtttXŠ TœªK Êå3È71Ý>ôEPêc:Ú­ä(GFQ.Ÿ±:œ%ËápX‚ T¬êJ Åê©�Jÿó©�w—ð.FŠ�âÖRý$õä(æ­ŽHáU•@Ô3#eSõËÐÛ×[NÙé0Û�rÔ3â°"A*KÕ$)ÅváHÒ�¥®KAqÛîÒ9!Ž!%"V‡#‚pGÕ$ûg{ÀÐÑWmÁ¨[:»´�`#úª-`è¨ÇöYŽ ÂU‘@ä›W‘‡®€j§Øý‚Õá,¸âÖAu  ^Fê·:A ˆa`¿½l·kGÕŸ�1¦ÓMqËvlÇö–ŽïA°XYˆi‰+qŽ^*•ä¸6šàêHãö5Øz�#Å&0}´uOZûnYH[ÿ¦?ˆc»pü±^+“ÓøôÂ(Cã)~ub‚}g"hšHL•èêXŽ_› ™)ÒÓ!_ÐóU…Ç¡&ç¯F9y¹ô¹\¸žæ_�Kó•«‹dšåÙ¥fÿ÷£QÃy4ýîŸPd�ËÆó›[P”™ËAH…ŽŸþR!G~×›ËVZý~YJ¼Œ}ß¿bÚ�äÞxœ�¾+:WÐùðä ºn`LúäUE¢!`ç^n±ú2…I>ë‹qàl}ÒácŠ,ƒ;67Sã±[â’ôqÏMbÉ<ú¤‡H’M6…o¾ÚŠÏUý‡ÁÍFÙz =×Ó Ý—<tà •-rþÚÃWÙŽï/UÛmn_òÉ@o]…¾¬©�»³æQ�ìG7Ì{’@Q7�8ÙŸ´ú2…[’�ƒ=Ñ{’”ž!Ý08zaT)°ÀÕ‘$ñû’€iH4ƒÿ8:fuˆ ¦l äHoœ¢>õÝm&×Çfþ¢’£cØ.ŸY¦°„–í>ŒöÔ.�dl—N!…Géß5ƒ‰xØúsÑt“WV_¢pËÉþ> òE�X*gu˜KÎÕ‘š1Ýw\Í‘+,�áà²%�Lvæ1Z]7)Î0ænû¬TJ[û$fm�uïP…1jBhëŸÓ¼³¸`¶òEé!Ÿx&«ÍîÅ„²‹§5´#I’H‹ÏkÁ=lþɦȤsKcŽªl D~HµkI*½ÑSQ®]D½N7Z—8Té~Ú–çÀéFD¹vqÖÿΡ*C&0ËÒ?œ o0ÆÀÍñ”(�3ßìêÌóš©ãu‹9�Dz©Ã�2Ù ¦ ‡Î ½ÿ×5ÔãPì~¡¢�¥µŠiwÞÙsû\”‡™ˆç8ÜssÆ1sÅ&ñÔj¿Õ—'ܲa…Û ßC¦irúÊ7ÆShºÁÀ…’'�©CØÎF¿ÔÃØÍ0Ãá´Õ—²(d :'/�“̦ýY†•M¶Êß!1ÊÖÜ|nC }ƒiRYmÒ$  ÈŠ„j“‰¦ò:3Lk½— +‚8ì ê¹O‘RqŒ`#Úê.«ßŸŠ¥­îº32Óñ·Ù¼ÆÅëQnŒ•–ìz ši¢éæ= l6™UM.6­ðY}iÂ-mõN6´º9?”}`‰µ,C­W%’(r²oœpqŒšÔø==L9�dŒÌÊ $]*>·X±5ºa20œ ïF Í0°)~·�DF»÷R$Ü…מX:Cîe[Æ �+||>ÆÉ+qtV6»yõ‰:œ6™O{£é�£`“eÖ×)¬?úc$­HþÕß]T' –ƒ<6ˆã×ÿŠ�Üï`zîötÃäò`ŒKCq ÃĦH<½ÆÏ³ëjA’ø¨'ÆÙ« º‰ßccûº‘<*Ô©þ$�‹’)è`Bȧòù'B´Õ»è¹–äÓc×i M÷(ÛTÔ'¶ÓÖ(z—3I׎�7'�%~y-Fâ).öçÈäKsMëZ=¼Ü Æ­Òs-Éá q ‡ª°i¹—ç7ÕbS–Îi•eM ·†A®hâPe”û&G¢©"ÎF¹8˜æÙÑOXžºNªyÊ+_³ú½© ö?C¹v½s#…_`8œæÜ@„줛~gW¿˜ß¨j™¼ŽM–±«÷>CƒâT_tú(+H�ëèXßiõ%T¬¡â- �M×PÌ{ÀÕ‘AuÅî{‰:w�ÝÝAZëÄ�úd ò�"Ë2îiÎå xUÞx¶�kgûѯ\G—öÛ×áîacg¿èvϨøÔNä¡+(ýçȶnäXÂE4YZÚÙ°³»;$núEÂí˜zBDMEúomE±Üw: £�‰ìÉð &/ZÈgTò™:לåËkiét,f­2fzLÛñƒH@qýãñ,NsúÊùâÒX7¦ÇOní¶Òÿùl±d¯Sáµ'ëøÆ®e"y,Žúz|ffÚŸ›¦�C]«‚æ"\8&œ(òéùQêk]lêás/â3ѧO莗ƴkíìîÒVßÁð? �$úÉ'„^zÉêP…’»z•B$‚*ËtHQôèuL›Š³¡žàÎÝ8[[Y•,°ït„+7³œ¿áúX’�A�^�³Ú5ƒÞQúo&À¯Q‡Ã3ÆÔ)UÂasáµ{­»"-È*¬é£Q¿ÿ}Ðuš¿ñ œÍÓŸ4h&'®$ùè\„|ÑD’$:š}¬]@U,ïH•]A3軥¸TÉi—Ù±!À“«üw†ª ## ýã?‚,³ì›ßÄ Y¶Pn¦ÉÐÿú_ÆÆ¼ðµÛ·cj’¢0ÕæÕÑ {NE™H”6ÕcÁ%±GÄ4M®�¦8=J±¨#K°¥ÃǶÕ~þ³÷©B }Òïƒ"Étú»y~} ªMŒ ßOùö·¿ým«þøø/‰ãíê¢fëÖW’$ZBº:|h†ÉÍHžh2Ïõ‘$²,Sëu,Ê1Ó4¸™ä³ £„9d žXíçkÏ5²¼ÞyÏ5+^/z"Aad=‘x G',>‰S§H�9ƒâ÷Óð¥/!) ’,3ÝÃPëUéîôásÛ 爧‹\MQÔt~çËì‹ñX–Ï.Žq},‰a˜´78ùÊŽº:ü¸ .©–t^'§§1)mÚ”€Vßz6,k"àµ|°¦"YÖÉ 0òã#Ùí´¾ó6ï£uGböž sc¢4”Sã±³©#D¨fñ¬:�eé“Ì”æ4ÚœìÞZG�ú¡;-�fðÝw1óyßz w§Xû¿X¹7þþï1²Yêßxïºu�ôïsƒ�ÎG9q9�i‚j“YÛ £Ù¿hc©l‘s‘;s§¯��]AV·óÌœ_ëòp†=§ÂÄÒ¥•�7›:CxœÕÛb¸ÿ¦úTvvYÕ<»ñêø‘#DöïG …XöÍo–Z¤Â¢3±gÉcÇp¬XAËïüΜ_'œ(òÁ©0WG³xÝ*›ÛCÔªw⸨\Œqe¨´zÓ©Ê<³¶–mký3ö²L³Tó Šìýrzš§ë‹åÞõV_RE²d+yü8©žÔšêó7ë .èSéîôcWd†#9™"×F“h†AÀç@®¢.ùíɽ“}¤²Eœjižãõ§ë©óÏ~ŒÚÑÜLê´HÅéıl™Õ—&̳b8ÌÄ{ïÐø•¯`óxæüZn‡Â¦^š†#y�Áñ±T� ÏyOÅßJgš08‘âÓó£ŒÇJ qã /_ÛÑ@g“ù!]+I*õÄT› ›äàfö2‘ü0þnI쥹߂÷@Œ\Ž÷w¹�_ûîU«æíµ“Y��ÏG9uëT=§]am[€å�•½'âöäÞ…ëQ EI‚®/l L»ûøaÒ}}Œýô§ÈN'­ï¼ƒâ^z«m³‘ÿ˜ìÀþînB¯½6o¯«&'¯$9Ø¡ ™È’D{³�µm�ŠO$ñ=aéÒ�õvu…h8æôz&&{‡þ‘ha”��l¨Ýaõ%Vœï�LìÙC~pg{;Á^˜××v¨2«Zܬlr1‘Ј¦ŠŒF3ŒÅ²øÝ*.Gå kMij½PšÜÓ “ .¾ú\#]¾Çz`í¡ù¡!Š˜ùü¼&jÁZé¾>âŸ|‚ìtÒ𕯠«ó·œ]¾µXes»—‚fr3ZZ¬28–¦ÈÔx*o±J6¯Ñ3æÜ@„|QÇçRxõ‰»ºëð¸æþÌKHøíõ\M�!’f…g#ª²xæXçÂö@òãã ÿà´ü—ÿ‚£¡¡¬ïâ`š}§Ã$2¥¥y-!;‚‘HÒ¹"®FïœÕPëµñÒæ ëZç>q¿b8ÌàÿüŸ`š ò~ ågê:ƒßÿ>Z4Jh×.üÛ¶•õï�Dóì9fp¢tnO­×Á¦Ž A¿õ_¤ºnryènÅiU‘øÜ­ŠÓ¶yì-û7ÒYî]ÏÓõ¿eõeW”í�Œÿâh±¾mÛðoÞ\ö¿Wç·Ó½Ò�ŒÉp¤@"SàÚhÓ0 øœ-]7¹4ãxï8‰LU‘xv] o<ÓHCíü®ÅWÜnôl–Âð0…Hß¼çBy%>ûŒôÅ‹¨¡u¿ñHe¾‡½.[:|ÔÕØŽä‰§‹\K‘Ì©õ9,Ö§ùìÂ(#‘ ¦ykžã¹FV/óÌû¼gбŒþä)b…Qœ+ð¨5–\s%Z°’¾x‘ø§Ÿ";4¾ñƼv»g¼@YbEƒ‹Í+¼d £ÑáDŽÁñvU¡Æ³0¨&Oî�F³˜Ü¾é›ÊrÓßæli!yú4ÚÄj]öº¥sØÍb£¥ÓŒýüç ëÔéK؃ÁûÛ·cEf(’#ž.pmdá«Ä’yŽõŽqe8�¦4ì¼±½‘m«ýØÕò$3Uv :ùÄ ctú»‘¨°q<‹,Ìy šÆÐ÷¿�‹úüçñ?dÓ`9]˲÷T„±xi¢-äw²¹3„¿Œ‰$šÊÓÓ&š, 4¼Ò¤e�*å&Nž$üþû(~?mo¿�´@É[˜_ï½GòÌÜ«VÑø5ëÎËIf4ö÷D9w­TwËi·±¾=@[}ùÊ}d :¯Eé’yispÁAÓM�_¾KFKðTÝèð‰ÓRa�Hôðabb¯«£ù�þÙâ} ¦ ç®'Ùw:B&o IÜs¬î|É4.\»{œ¬Ï¥ðâæÀŸü7E¹ ¡ºTb™š›‘<œ 3¹;?²¹3DÀ7·UOS¹}œlï�ú­ãdŸZícûúö>»–:Ïgã¿À!»ùBÛ·Påù»ÎjUö!,=‘(u» ƒúßüMì�€Õ׌$ACm©, R©,J,Uàúh ‰ZŸã±Æ–uä(Á±‹ãÄRyl·ç9žm¤iŽK ÷‚í�©žòCCx7mBvˆ›¿šŒþìgè‰þ§ŸÆW!%j|.]�>j½6†Ây’™"7Æ’drAŸÛcÖ¨�døôÂ(Ãá4¦i²²ÙÅ›Ï5²®ÍkIÉ•Z{=c¹k$‹aLL] C¥){dì¿ }þ<îuëh|ã «¯wJÑd‘=¥cuAmj¢õß "ƒîˆ–ú;š1s'­¨ø£æÎBón܈£µ#“!~ø°ÕáSÈ’¾xÉf#XåÇ;í2»2ãè›]G; K [/Ð=DNKY’5ïÃ|¿ ‹‘8z€Ð+¯X}}ób6% ­(‹ò8B»w;z”b4ju8Âd¦ItÏjž}›ßouD�ÍöÐö•„¢T×3ÔâYM“³Í,ÐýÈêp,1ï $¼w/è:¾-[pÌpÆy5YÞàœ¶õ$IÐV殺¹Í;MMx6oà üá‡V‡#L’gu8óbM‹gÆa˜°,TyË“¦+´ ™�Ôi¢ù«ÃYpóš@²d.]B²Û©­’UW³ñù­Aeêê76Yâ OVçZðЋ/"ÙídûúÈö÷[ŽÀ­ùÃC‡íÚµhÊÎli÷ôÙ™j”ʦH쮂ùéøí!V×< ÀÉðV‡³àæí3 ƒð¾}¶oä3Î+Y­Wå·w4áq*¨Š„Ý&¡Ú$<™¯VɤßT¯÷NY“ðÞ½˜†ñ˜¯(<®È¡C¥ùÃÖV<�xÆy%“$øí�´(²‰]•°Û@U$vuéî\àò>óhC휊‡p~ˆÁôE«ÃYPó6ó›:~œâø8jMMÙÏ(°B[½“ÿþm †ó$Ó^·B[�³ªŽÌ�JͶm$OŸ¦“8y’š'Ÿ´:¤%«“<~¸;Gµ˜x] ¿ÿr ã‰ðßuC#­%86ñžÕ!ÞÑŸ<ÉÍlÿ�ä¥#.tSãZú,Cé¾Y¿Öc÷@Â{ö€iâòIìõ‹hlg É�Œ�<~ü�Uf¦®cærŒÿìg´|ãV‡ ”–¸fúû15íÞX5�ÜÕ«$NœÀÿÄV‡ùHâG�RŒDPƒAüO=eu8ÂôÅ?C—u¤)öh §/1˜ºˆZ½�3áýè¦6åÏtCãlt?Ë<³Iz¤bäó$Ž#qôh©†,cê:²ËEàùç­~_„9J?Îtu&$à 72BâĉŠhG÷ï yÜfjÑC‡*>�¤/\ |ð z<¦ÉíRk¡]»�ªh7¶pW¼�2yÜfbòÉøÏ¬sVRÅÙ�8Ì:�˜…C?ü!z"q÷Öou� C,­bÅXŒ™jjJ¦Iø?ÿÓê0gÅÈd0u½brL¼ÿ>é³g1&%Á;=¿*¬'”8e7‰™~A‚�£k?cÉ4Íß`¦â~6iöýŠYÿfäÐ!ŒÉÉcCÓïßOÿhé›#Ì�âñÌXlX’$+V TÀdzª·i¦d§(›<²ƒƒ¤NŸž¶±5þóŸ³üü�ª]°”­ðm&œF7 SþÜ¥xØÙüu«Ã࣑ÿÃhæ:¦ôà}(Ë ÍîÕ³~­Y'�Ô}­¦{è:™óçA$�ªäíê"sù2LóùÊÍ¿ýÛñÅ&ýüç¤z{aŠ/aSQp¯ZeuˆÓš)y@i9|vh—8è«ê,w¯§W9LZ‹¡£ßó3Ù´±­®rN}¢î‹¼?ø¦‰9©Ù(I26ll Í~Ò¬\§wžüs³P˜å« •ÄÝÑ�£µéþŠw’„¤(Ô¿þzE$€àÎ�ȪÊ51dEQ*z% ù°Òù²Œ‘ZšU]«�,˼Üò4»W#›Ф"™2~µŽç›ß|äýåä±ùÙÙò{xmA$SƆ�ñÛêØÙühË�gÝQœN´bqÚŸK6[Užû!”4½ù&±ƒ‰;†išH€½±‘à+¯àli±:¼;Ÿ�Ö·ßfâ½÷È «*F±ˆsùrê_½¢Kè(55˜’4íœdØ|Õ[Òc©³+Nžm|ƒ¢‘'UŒ¢Ê¼jeã]koâµ¶·I£dõ8n¥¯Zûȯ3ë ÇŽ™nŒ,ãëê¢îó³ß€"T&Ã0Ðãqd‡£"V]ÍDÏdÐR)l^oÅÇ ¥R%C?øÁÝÅ'“H€ì÷³ü¿ý·Šéí ÂÃÌzËÛÝ�½®î�ê ²¢`«­­úCo„Y–Q�ªøBVÜn U+€=¢vÛ¶ÒÜd² ªJ׿,’‡PUéLtS׉>LêôiôT Ùã¡fÛ6üOùcŸ-w÷æ&›ì:ÙÍ&vlEͲ,ËV/”(’’Ø € ADïƒ6½œsîCP¢�(3sfçó<~k8ó;ï9¾ó+ïû}]×uLLLL²ÑèLLLL’�)f&&&9�)f&&&9�)f&&&9�)f&&&9�)f&&&9�)f&&&9�)f&&&9�)f&&&9�)f&7e"2D—¿™¸7:“yÌr&“ùÐÑ v3îÀ*9¨qoF­F‡fb2 SÌLæDÕãôùÛðÅ&®{]‘,T;7a“]F‡8'º®ã�ôá�O²ÆÑ„(š‹�•‚)f&³ˆ¨Azm„ã�9ÿ]ª\ ¸”"£C½Ž˜e pñšXJ©r5–Iš0ÅÌä:ü± úˆk±¾O@¤ÊÕ@¾¥Äè�¯Æ=É@ðQ5zÝë[%Ž:£Ã3I¦˜™\c,ÜÇH¸ MÓô~Q)¶®¦Ô^mXÌ3ËÊ‘p÷¼q—ÚÖPê¨1,F“ô`Š™ š¦1ºÌDdhIŸ/²”SáªG@HkÜ1-Jð"þèÄMß[n¯¥Ø^•ÖøLÒ‹)f+œ¸¡7ÐF 6½¬qò-V97 éÙpŸoY9¢(Rn¯£ÈZž–øLÒ�)f+˜`ÌOo •˜IÊxN%�*çFÑ’²˜²¬œQ©²7�gÍŒ}>“äbŠÙ e22Â`誦&u\‹lg�³ ›äHzÌ‹YV·€Hµ» —R˜ôøLŒÅ³†®ëŒ†{‹ô.zf³PÉB•s#N9/icú£“ô‡.[à²òFH¢Dµk3Ž$Ægb<¦˜­ 4]¥×_Ì›òk‰¢ÌjGn‹gYã,gYy#dQ¡Æµ9c“M�)f+„¨¦Û×BD ¦íš¢(Ra¯¥ÐZ¹¤Ï'cYy#ÁBMÞ¬)X›¤SÌV�Ø}þ6búò—hKÁc]E¹£AXxêF2—•7Â*ÙXë¾Ù¬7ÍzL1Ëq&"C ;Ðõänô/–BK)•Îõ7IÝH,+û u¡é©ÙÓû,VÉqUÐCŸ‘Éò0Å,GÑÑ tâ�ôÊ5ÜJ!«œ�EyÎOõ²òFØå<Öº7# ’Ñ�Éd‰˜b–ƒÄµ½þ6ñI£C™…]v±ÆÕ4ËF(]ËÊá” ¨vm2�6²SÌrŒH<@O°•HŠb#O.F$ýy`’(³Ú±—¥ÀèÇ�U˜bvÂj�¾@+áxfÖ.šËÊÔ"‹ ¬%ä¢I‚L�{³¡{xÙ†)fóà�Mи@\ËÌe›¹¬L²$ãVJ‘ ¨¥” kM§�cŠÙdºã…¹¬L/‚ ’§c‘Òo#d­Ô¸o1äÚÙ†)fŸBÓ4C—™ˆ ÊÜñ™ËJãò•",’3í—¶ˆvjónA60±70Åì*1-z5vÊèPæŽÏ\VŽ‘6BvÙE�s’d Ú|˜b„ã~zç‰d¨ã…¹¬Ì,l² —R˜öq§’ŸpÚ0­ƒædÅ‹Ùdd„ÁÐ%T-óZªé‚Ž?6N80:“Ï`‘�ä[<�æ¿·RÈ÷&ÓicV¬˜Í8^Œ„»Ñ4ã7ú§Ç}¼úÜ{Ä£*w=º‹âÕ…æ²2Ñ% –R„4ç¢XJ¨rm0úö3Ž)fš®Òlg*2jt(@BXÿúßü”¡þ„G~±‹ßù×÷`µ›û#™Ž,)W}ÑÒ›ºá±URá¨3úö3ŠgsÓ"tNŸË!˜™fjÒí¿§Æüô¶�–Ɉ«1&"ÃÄÒl<à 0¼bôíg+JÌ‚ñi:§NV}F‡rn�§óûY‘ðTä–ÉÑ4•éè1-½H#á^ÆÂ}Fß~ưb–™‘!2ÔñB‹F¹r²�·^?‹¦«€€èPxäû»�³‹O¶ ˆ.¥›˜¾f¿¢(Rn¯£ÈZnôíN΋™ŽÎH0s/´@�ظ]ûäÇ é/¿t‚1�G°‹ÅØŽÜ&‹#Ý6B ë õXK�¾uCÉi1Sõ8}þ¶Œu¼ˆOOŸ˜œóßtà•ßždØ;ÅÃt'V«)hÙ„]q¡ùÞüålv ÷=~'Š-u?C‘jw.¥Ðè[7Œœ³P<@oð<Ñ t¼Ð5�ظ-pãØtàõWOÓÝïå±íÃî0O7³…p0ÊÓÿé&GÖêkÖUð/ÿíï¤ôš’(QíÚŒC6¶Ñ±QääÀtlœnÿ¹Œ2âqb££72øÜÛ¨YãáÅ¿|Ÿp btô& ¤íÞkB0>:ÉÔxj{F¨šJ�¿•pÜ¿üÁ²�œ›™�…û]ÉÈÖoZ4JtdÔÅW:ÔÊÅËý<úÇûq8­FߊÉL�h>ÜÉP×8Ã]ãDß$<—òÇÿþ›HrêK‘ÁBÍ ´Ê™™™¦iôÚ vf¤�©¡ Ñ‘‘% À�M4Ô¯âÿù�é œqšÐqº�îÖAz/ _2›E¡ª´€÷nANSo̘¥ÇßB\[Y3ùœ˜™Å¯¶~ dhë·øÔêÔtRDöÈ8}¶‹ÇÿäNÜé·£1™IR¸òñ(¿úÇ·PU�¢<'ôÅ{pڮΤí´†4%=…âVÉAmÞV$Œ%� ëgfÁ˜ŸŽé3*d:Ñ1/ñÉ©¤Í÷ìmäÖm5<÷ŸßcjÜ,@ÏÑʹ7zxë¹xlß­Ø, ;k>2€PéÂ0B8=õ¶5H—¯åjîbî“Õ3³Œv¼ÐTâ#£¨‘Ô”¹||üG�¶óäŸ ¿Øœ¡‰·ñÚÿ:BÈ;Í×ïÛ�Ófåoõß{ä‚0{¾ (j} š3=§ÓN¹ a$fýÜå†d¥˜éºÎh¸‡±HoF8^|-#>:‚O­Èž<ÑÉá#xüGwRXb6¾H7‚(ñê<÷×oR[\ÈãwÞ:§x͉,¢¯+AÍKÏaN¾ÅC•kcN[e�˜iºJ¯ÿ¾˜×èPæD ‰yÇAM�Èž>ÕÉ;ï¶ðÄŸÀS¶2ó‹Œ@eF/xñ¾Á;7³£¡fÑcˆ’@¬Öƒ^�žSÇBK)•΄4D¤›¬³¨¦×wž�š™y4ñéiÔ$î�-”–æ^ã �ÿh?Åf�zÊ‘…ó‡û8üëã|õî¬[µôä‚( V¢§§žÓc_E…}]ºUZÉ1 Ħèó·ÓÓkµ²0tbÞ T¿q"ÛÒÚÃë¯�á±î§d•)h©BÐÞýùi†;ùÖý»Éw.¿REb«òÐÊÓ3³.³×Pb_“–k¥“¬³‰ÈÁôL<•ÑT¢£chaãszZ[{xõ•Ó<üƒ½TT{Œ'çˆMËÿý%v'_:° YJnʃV‘�V•ž/¢rG-Ŷª´\+]d´˜éè :ñFú�eîøâq"ÃÃ�â�þÅÐÞ>ȯ_:Îø‡ŠSÐ’�€€·+Ì/ÿöMîܼž·¬OÝÅJݨ5E)ߪH8mÔS`]ú9ÓÈX1‹k1zýmâ“F‡2'Z8Lll =Mý‹áÒåA^zñ8~çV7äÎ/«¢DDZ!Þyá#¾r÷ê–±?¶` í¨ëŠÑS¼Q/kœ�¸-¹ñ¥—‘bRýôΉgfë7£6úÕ®a^xþ#SЖƒ&ñþ3çèoï盟ÛC‘;�ù|6ÔÚbt)µ¹a’(Síl¡dÿ>kƉ™/6Nà"q-óº ºNlr’øtfÙnÏGOÏ(Ï={Œûïª7˜‚¶âA�ßþÏ#Øb:_½ûv,Š~rn j} º”Úò'I�©qoÆ.gw®bƈÙLë·áPWFÎxM#:6†ÊÌÙâ|ôôŽòÜ3ǸçëÛY·y•ÑádÓƒ^ø›·ÙZ»†ïØdl0v jC1zŠíÓeÁÂÚ,wÚÈ1Ó4�Áð%&ÂÃF‡2'º'62‚�Ê’ðòô?ᮯm§n‹)hó"tŸñòúÏ�ðÄþílª©4:¢DX6u})š5µ‚f­T»nÁ*ÛŒ¾å%a¸˜ÅµÝþ6BñL,=!:6š‘ý‹ahh’§~þ¿¼�ú[s/Çh¹ˆ‚ÈG/µsáã¾õ¹]”fV5…`‘PÊÐl©4›d§Æ} ²˜}®Æ†ŠY0î£/ÐJTÍÄDXP~âã×5Éf††&xêç‡ÙûÄ6ÞQct8C<¬óÛÿñR4ÎïÞu;6K†þ!Ë"j})º+µñÙe5ÎMHR†>‡y0L̦¢Ã ;PµÌ[ºéºN|r u:3g‹ËatlЧ~v˜]�n2 ŒEùåß¼G]¹‡Çöl]x¡¸Aˆ’@|m1Z¡}ùƒÝ§’ŸpÚÒã½– Ò.f3Ž#¡n£ï}n4�˜×‹Ì]7×±±i~þ³ÃÜöÀznÙWot8†1p~’ßüãa¾°k3Û××΂Dµ¦Í“ÚT·RÈ÷¦¬qÚH«˜©zŒ¾À%|Ñ1£ï{N´XŒ¸×‹–"²Lbb2À?ýô=¶ßWÏ-ûWš  4¿Õʼn·[ùú}»¨*ɾöl’(¢®Î'^šÚtŠK U® Fßî‚H›˜EÕÝ�V"ñ Ñ÷<'z$Jtt}‰ýÙÈÄD€Ÿýì·Ü½ž[® AS£oÿÓ)ü£~¾~ϸí©]®¥štÔszl•T8ꌾ՛’1 Æ¦è ´Ó2sÆ“ký‹aÊâ§?y— »ªÙù`“ÑᤔÀD„—þæÕ¥E<¾{ b†ï�-½Ì�V�ÚzÎRÛjJk�¾Õ’r1ËdÇ ]׉OM£NMŠ¡ø}!þégïS{UÎ Úð•i^þÛ÷¸sëzln0:œäãq¢®-Ji=g¦;m¤LÌtt†‚xÃFßãÜñ-°«øJ!Šð“¶Åèp–�Wyÿ™ó uŒð{÷ïLŠ‘bÆã¶¡Ö{RVÏ™°ZO�µÔè;�EÒÅ,¤úéñŸ'¦ff ãrºŠ¯Âá?ûÙû”ÔpðËÛ³ãT~!_”—|Œb§�/í½%ÉFŠ�º¾]IÍž €Hµ» —’Y§ÀI3_ÔK_à"ªžy‰°Z HlÜ»"7úC8㩟¿�§º€»¿ºÝèpÍP×$¿ý»£ÜÑT˽[�Ç»‚ZWŒfK�Û‡$JT»6ã�3§ì+)b–éŽ�ð ‹OLFÖ‰Æxæé#äUº¹çw²GÐ.Ÿâ�g�óÅ»v°qõì½�ç/Ð5<ÀîÍëæmFr¦½‡æÎ>6×U±µ.ûêY‹D|})º=5‚&‹ 5®ÍØäô4c¹Ëž‡jšF°�¡à•Œ2]ÓˆyÇL![$V‹ÂW¿ºÿ ŸWþñCÔ ìOz:{éÇ^:Ç÷Ù?§�t OÐÜÑGsGGÎ]šw¸·Oµ]{ßÐXvžvëQùâ(‚?5)Qq-F·¯…ˆš¹£Ë³˜¡Ë–ÉHfZ÷�EõgÆÃÎ6EæË_ÙCt<ÂëÿøqÆ Z$åWý“ãü𱃔Ü|éSVèæü•sõ{öNQV˜Ýf…z,Žrqq*5{Ø1=J�¿…˜füaÚ’Å,Ÿ¦cú4Áxfº®jÑ‘áóÄr™(ŠÌ—¿ºÍãõÿõz† šwÀÇ3ÿá]ªó ø½ûvc³,lIµ}ÃZ4Î^ê™õoÇ/t!Ûªo8F\�sep”s—{¸28J\�{¯8�Ž~2;öNÑz¥Ÿ�щëÞ§ëÝÃ^Z®ôÓÑ?B4ž·eMÓ�:F'Ró¥QÃtùš ß+_ÒÏTt”�ौt¼€ôwÏuIæ_|e¿xþC~ýã#<øÝ]()v>]§‡xó©�xôÀv¶Õ,.™sme EyNN^èb÷æOJ¹bjœ3í=4®)ÇíœßuõãÖN~sô,áè'‚c³(|a÷-ÜÞT{Ý{_x÷§Û{ùþãyíÃs\ð°©¶’¯?°€ã:yõh3þÐ'_¾Eæ��›Ù³eù¥fºª£tŽ_G-Mþ¦}D Òåka­{³aN‹ú�Ôu�‘P7£ážÅ|,­Ä§¦P§¦!÷ï²Qyò‹;yé¥üæÇÇxøû»� 4M‡³ovpúÐE¾ûð~V,iœÛjxãxkbIéIÔ7ž¿2@8c{c ‘yZž¼ØÅ/� ßiç‘ýÛ(-t32îãÕcÍüâÐ $EœÓ…ãÙ·ŽS�çàÉ·‘ç²_[¶k¾Ä‹ïŸÆ“ïæ�Ý›)-ÌgÊäÍçyéði$IdgÓò»�«š†Ð=‰ÕSRÏŠOÓíkMX‰é/[ðU=FO -ƒ…L':æ%žá]“²Qyä‘ÛpÛ¬üòo> MÓ™XLå•¿û�î3ýüèñ»—,d·m¨AŽ_¸ríµ“º°[6®­˜ó3š®ñÛ£çøÎCûؾ¾†Õ%¶7Ôð�‡öðÛ#çæ\rÚ-2ß{x·7ÕÒX]AÓÚUÂ^>rŽ¢<'?úÒ=ìh¬¥ºÌÖºÕüÑwárØxããV4=y« qp ©g!¥O�ø$½�6ô”Õ!Üà¾úÆ>ÿ…ŒµîÑ5•ÈÐ0Z `t(9ÏŒ »¼ô_§UÐ&Fü<óïß¡P¶ó/Ø‹Óf]Öxn'kWsª½]×ð…B\ìbëúêy»•_Å ³¡ºòÚln†rO>ª+ðÃt�Ïúì�ÛÖÏ2lîè'®ªìÜ\‡õ3û}EáÖõÕøƒazG&H&°©c !_ü¾˜—ÿÅ´O*¼N¨t®§Ë6ãzYêñ8±áaô ê*žëˆ‚ÈC�ÜÎk¯žáWu˜G~x'Vkj[±õœᵟ|Ä{¶rûºÕIwÇÆZž}ócÚz÷¡·m˜ãß;™øÂ¬(ž{™¶ª´�¶îAF'§Y·êú’Ÿ²9ú Œ%DêrïÞ‰ÙÎÆƒÞÄk“¾ÕeInÖë i ®K~�úDtQR¨°/y¼P<3SD+5Ö¹E …ˆ ¡™B–vàþ¶RUVÄ ñ¡`jr™4N¿ÙÁ[?;Áï}a_R… `sí*,ŠÌɶN¶]¡Ì“Ïê’ùE#KÌD�¶¹ýñíWgWáèìßɹNZ#Wg¶“ÓAÆ&gýO×5V—¦®oçDéâB ˼¡~Fý©‰{µƒ«ˆVÖ8¶Ð8gxíåLWqs£ß8à¾û·òÆgøå_â±?Þ�ù¼¥ß§‰Åâ¼ûÏg˜è�æ�ÝE¾#ù_¤YaKÝjN´%öÍÜ}ã{‡=qSó¸­Ì¼î\`ֽÚÅ{îh2®ÊÀAjE]_’ôêÃÁ+i±ZtäVÙF�s ŠdÔ M'æ'>1inôgð¹û¶ÒX·Šÿò=‚þääõù§B¼ð_ÞÃùÁCûR"d3loHˆˆ lo¼qnYUq¢¸úRïÈœÿ>óú�fwŸ¦¦2aIÔÑkpâ¹?‚Ü6ŒNþèH¸+-‰õK’a«lc­{31yß BS‰� úýé½®ÉM9p ‰ÍÖð‹ÿò.þ©åyÄ txyæ?¾Í-ukùÊÞ[çÝŒOëV•ñÿüá—øOðÅ›Úh—yòY]ZÈ w’ÓíןìŸlïbÐ;IUiåž…¥>4­­¤(ÏÉÇç¯p¾»Ö¿ëºÆ¥4 �Š¡´�"†’›?š(y¼Œ/êMiüKþ-±ˆvÖ¸7Óãk&š†R-':< æþXƲgo¡ⅿx�ÇÿäNÜ‹÷k9Òű—šùêý»©+Mò†w’xâÀmüøÅwyúÍi½ÒOEq>ƒcSœ»Ü‹U‘yòÀŽ�%K2¿sÿNþþ¥÷ùéoŽPWUFeq>’$1ép¹o„p4οûîãi¹7-Gº8õÅhÎäõÍÔu•¾àEª…&JjzHþçþçKý°,*8•"|ñ1´Úbká0±‘3£? X³¦5®òÆó§Y·­›}aª¦qèéÓtžêç»ígUaj~áû†½hšÆ-ëVãºÉÒu*À;é§¶²˜ÕŸ:It;íl®]…?ábï »‡˜ôiªYÅ×îßEYÑõ±÷�NWU¶5¬™³Áp¾ÓÁö†¢q•îÁ1.öÓ5ä%ŠR]^ÂÁm� žé%MC˜¢;­`MÞ¬X×5¦c^\JJ VuI±Š¨Aºü爥 3ùÌF¿¹?–]œ<ÑÉá#m<ù£}ä—ܸ`;è�ðêߌSRøêÞíXSur—"4]Kjs]×2¢± h5Ô"ÇòûŠh¡Æ½«”Üq“fΘlAt�Øä$ñéŲxô"Ç?¾|Ýk«‚Ãa¥¬,Ÿuõ¬[W¶èqMÇŒ =þ£}Î#h£}S¼üã#lkªåÁ-+ÓH1“D­ÚƒZœ<á‘D‰r{=…I¶ÞNªÓlD Òí?Gt™‚&hѱ1ÔÐÒÒ?Þy»™ÞoÃSì"//±o‰D™ž á÷'Æ,.qóðc·Sµ*3÷er…3§:yûÝÿÑ~Š+®_*]:ÙǻϞæñ{ogs…ùå’©H¢H¼Ò�Z±ü¥®SɧÒQŸôY¤ ÀrMWãÄFFТK?Q™³ûÜÆíw\ï8à÷qøP+çÎö +ßüöA*+Š’ùL>CKk¯¿væš éšÆÑ—ÏsùD?ßúü^Ê\+ ÑH.PžG|uÁ’>*‰2%¶ÕÛ’›ôüi’~æm•T»¶pÅwŽø"›þêáѱQônô{ŠÜ<úøN\nG?hç•_ŸàÛß»�™bŽ)_ïØ4¥Åy8\V®tŽ248‰b¹}GB5]£¯ÏËèð4�@‹"SU]|ÃY^8ãb[?S¾ N§�†† \N;�ÃØm2••³?;å påÒ0Ó¾6›…5Õ%”—ÌzŸwÜÇÔT�ŠŠB¬V™K—žÂjQX»®”’yJo†G¦èëó„±Yœ.+µëʱےwа©i ðÂ_âÁïìäÄëQ4…?yâ.¬rví�­h†¦‘âZMá¢ÊŸr>•Îzl)˜�}š”$ðX%kÝ‹´twß×&Μêf``’Áï51¹x¾�×^9ÍÞʹsÝô÷%rc\.·ï¨Çñã¿y}Îò�Úº2¾ø¥Ý³êûú¼<óÔƒŸ¤°¼i‘yü‹»xæ©ÃT®òð�ïÞ}ÝgŽ|p�÷Þm%þ™T”�›VóÈã;®ë6tætGÞoãÑ'oçØí M^û7A€¿pÛoûÄcKÓ5~ù‹�hkí�U@!+ÿúß<‘ôçÝÔ´†`(Ê/þê=š6Ôð�{nOÅ�Õ$Åc~$UE]W|SA“D‰Ûš”ÎÆ>Mʲ*hº®ŸœB�ž^ÄèËG‘djjK9ßÒK_ïø¬™Ñ»ï4SäÉãkßÜ�§8ßÔU—N-!Z[n©¡´,‡ÍÊäT�÷ßk¥õ\/o¾~†/<üIžQ(å™§> Šðù‡¶³¡© MÓ8ßÒǯ^ø�¹~Î�íâí7ÏQPèâÑÇwPµÚƒ×ëã�WÏp¾¥E‘yäÑÙ¹L¯¿r†µkËxä±äå;¸ry˜—}‚×_=�˜ º ¡çÎtq¾¥—¦M«9xÏŠ �„ÃQÆÆ|œoIM-Ý¥Kƒ~»•{7l䨕Nº7z“_8m’&BˆGÐÖ—¢ÏӋЭRn¯Ok-wJÏ­’ƒj÷&daže‹¦K»�ÍPìIt•™žžm',Ëßøö~j×–‘ï¶SU•øÃs¹í<ñÄ.êë*Èw;Q™’â<žxbeåœ;Ûs�÷Ô©�ƒvß¹�í·­Ãa·ârÚ¹ýŽz6o©ž53Ò�÷ÞmàÉ/ÝÁš5%ˆ‚HIq>_úê\.gO_Á;>û”·¨ÈÍ_ÚEyy!»•¦Íkر³žx\¥«kôÚûN îÞDQab¿Êf³PUåá¾û·&õëÀÑÚyõ¥Óü`ßAß´‰oÞ¶ƒŸþæý#ËßÄ_ñâЬuI�Yå\Ïצ´›R¤<™Å.¹¨™CдXŒèÈjpy¥/ËARö¾±9¶l]sÃÆ±:à„ðÒye˜Î+Ãäç;ˆÇU¼ÞO„¦³#Qвu[ͬ1¶m¯�õšwlš‰‰«ª<³f‹Š$sË­kèèšõÙ­ÛÖòÙïɪՉÃ�‰ÉOJÀ\®Ä íÄG×\RA$ã—Ï~Hgó ÿæî{¨ÎKXà4UTðÝ;îà©×?L[©ŽIòü1¤óCˆ±Äß�ËRH]þv ­å)1~¼iñ=¶É Aë´S£è‘(±ÑQtƒ»ŠG‰å¯uŽF©……óû¤|üj»–æ1{ÜONb§§WÇ›}b7×kWý²ŠKæ¾~‰'‘¯5é�=›Ì+˜]W8³™?s¯·îXÇ™SWøèÃvNžè`UU!µuå4n¨¢¤89þðãã>žúCÖ{ÊøÊ¾�³D¶¾¬ŒïîÜÅÿxó_¹÷êW›©YI8Žra„¢-·Sä¬1DÄfH›‰»MvQíÜÄå¡cD½#ÑU|x(±¼-*š-*ŠuîIëɼö›Ó”•p×=[(.qcµÉH’Ìá÷Îsöô•ëÞ¯ióþ|çx]»ê ¯(s7…�”D\sÙ2K ´oq9¬|ïïãÜén.^ì§§gŒî®1½Ý¶[×òù‡w°œ_ÉžžQ~ùìGÜݸ‘ûjkç}_}I ßß¹‹¿yŒ'ïÞÎÆêU˸êÂxñýS\ì¼î5Yp9mT•xØPS>oc`“ÙØ$;N¡éÂj“9ϸçi3]×ÑúÆ(î—rŠÄ1vV65 óêRmmíÂyOŸêDàw¿¹ÿš·Õ ¡Ðì‚û¼<;ã>¦¦B~¦ðzrröìÊéLì3LOÍÝÌwՑ•wcw‡›aµ(츣ŽwÔSãt]åÍ×ÎpêäÖ®+£©iiÞZ'OtrøÝó|wÏ�¬Ë¿y’emI ?ؽ‡ÿööô:Mµ©õ½ò#ŒO¨ðàºúóS5•±É�ýc¼æ"U¥|ùž;(MQ}h. "N¥›”ØwÖb1ü--8QŠŒÉÛL‹˜éªJàâE¢ccX�) ”2èIiqú�ˆDc¼üÒ t=‘ê�Ÿ¿ð¤Í`0ŠÃa�%dápŒžOm²Ï°¶¶”Ïv³oÿÆëþ­ùl׬÷—•çc±Èt]!ŽbûLÎW[[«W'ï$P‘dêë*ˆŒóÂsÇš¢©iqcÄÔ8¯¾|†±¾)þ�{î£Ð²ð\µj�‡?ºsÿõÝ÷‰Æâlk¨IÚ½ÍÇ»6ÓX}}Ó’aï¯k¦­{€¿xˆ?þâ=¸Í„ÞÏb“ì8-…HŸ‘-ÇßÖ†³¡KqqÚãJ¹˜i‘�óç‰ù>Ù·ª i´p$ÆÔT�ž+£|x¬�‰ ?žb~áÖE�ãñ¸é¸:1Ť?LuyÐÒÙÏØ¤O¾ûZ¼ÑxŒK½#ŒOú˜GȳYYWUFeIá¼×÷hë`Ú¦0ÏÁ–ºÕ(²H×€—<‡mVã€!ï—z™G(p9X_UFÉû¼CÞ)|Á0k+=¨ªÎ¹Î^Æ&¸l Mu«)šG¬/õ3ä�ÄŠb·Y(ÎwR_UN‰«ôÚll.tU%xáZ]¶òò´þüR*fñéiüçÏ£Egç™YU…Ê@)®Q´5~í•Ó¼öÊéY¯[,2;vÖq×]›݈ãÎýè¸<Ä?ÿì=Ö®+C‘%úûÆ�¦M«iýLž–Ëmçɱ‡çŸ9ÂóÏE–%Ô«�noRmÕª"¶m_{Ýkv»»ÝJyE!U«‹fµõš¡¤,�mÛ×âñÌíò°fM ¿÷Ý»ùðH;##X, M›Ö°g_Ý]£X¬2ÇõK¬uëÊøÁ ¥¹‡‰©yn;�«�%]»ãú%«Õ¢ðõoäÔ‰.\ègpp »]f÷Þvî^�Ëyý~YåÕûu»gçõ8]6¶m_˪Õ%×^;p÷&*+ éïŸ`râêik‘›Ûw7°å–§¤|šsg»xëõf¾qÇ.6'¥CY~>?Ú·Ÿ¿|ÿ=bÑ»6/¿›÷bÉsÚ©ôäÓ?6I× wÖrôÅC§ØZ·šÝÖ“ç´ã$B`÷æ:nY_EYAŠ,12îã·ÇÎr¦½—ÊâBlûÄdÈ;ųo~ŒÃnåwïßͺª¢1•£Í—øå¡SsÆöÊÑsœhë¢vU)OÜNq¾›aïϽó1Gš;pÙíܽcã¬Ï=ûÖÇìlZÇ®Më°[-œ¾ÔËï�âïœäß~³âš:ÙFïÈ÷îØÀ¾­�8­6ÁÅà¨�Ë ~†š¦ììD‹ÇqÔÔ¤åç–1 uwêî^Ð{-š•ò@1ƒŽô$5:mh\ECãÒNÆÖÖ”Ýt WµÊÓ_Ú5ëõ¦¦5ónœ»Üvvîn¸îµsW÷Ì*+go˜*ŠÌ»¸cW7cCã*6Ìs¿ž"7=|}µ@eEѲŠë5]ã�7[¸Ü6Èÿv×=”Ø—wñYJÝnþÕ�ƒüÅûï¡é°gKúÍ“ï¦l’iÿì<ÈU%ë—0Ë ÷ô Çb8ëSÿ3LjÒ¬®ªÚÚ,d3Øâ*‚¥aH— :¯ ÏÊØïëóòÖçØ´¥z‰#§Ÿ`(ÂS?}ŸÉþ ÿ×]÷&]Èf(r:ù³}û9z朽”öû”¥Äff\›½§»£©ö†Ÿ�«qƦ|tôs©w˜®/ùN;#¾ë¾°/÷ #KÛêgîØ°vÖk£Äâ*[êV_²ò�N6ÔT‰ÆéœÝ€øÖÆšY¯U•%lÜ÷Iól—Ê|x®›ž‡ Ì�"´"ƒƒøZ[¯¥¥Š¤ÍÌ´H„@[±%–&ÍÚ°c5‰­è3� çû8y¼—ÛŽÛí`z*€ßFzø¶k%E™ÎðÈÏ>õw¬­ãѺõ�âÉB§“?=p�ÿïлDâ1îÞ¾qùƒ.�P$±í1מê|›æš®ñÊÑs|ÔÚI$6÷¶I(Çaµ$:¨Bå»çü/šãfâê]iáÜ[ %îëÞ÷iò]³+fúx†>e·õàÎítôŽòâòò±ã¬_µŠ¦5k¸­±‘²‚‚%?Ϙ׋¿¥÷† )rNš˜EGG—,d3ØâÊrPÐvín¤¸8�ÁÁ BÁ(Š‹]lÞZƒ§È½ü ¤�ÖÖ^}ù4_Ù¹›ÛJJ–?à)°Ûù³ùËljFUص9-×íKÌnJ fÿ|dyîġÏp¤ù2�ÕåìÜ´�Û…bIü‰=÷ÖGtŒ!|f_q1_êÕÏ*òܳ¥™DkuŽÙäÍò©EA"ÏRD©ÝÎüÎw8ÜÚÊÙË—¹<8Èùž~yô(íÜÉ£»w/ù™Æ''ñµ¶ânjJ‰ %MÌlUUèÑ(¡¾¾å�“ƒ‚VXèœe™-$ Å/pâÃËüéÝ÷²Ê‘ZOª¹È³Ûù³ýûùß;�rA»Ô;Ìt ŒÃf¡ê)ŸåÄ….ò�v¾õù½³f[Ÿ>E—ÃÆ¤?8§çÿøÔìÙ•ûj–¹f^“W?ãv-îgd,xlWw�V+Ÿ»õV>wë­ÄU•s��üô­·øÕÑ£l_¿žÕËÈ!‹OOã;{×æÍˆÖä65Iê&•½¶krKfML}¼É ˆDc<ûÏÐ}~”ÿûþÏ"d38­VþÕ�ƒttóʱs)»ÎT À ‡N°oëúïãÆÔ8ÑXœB·cÖg†½SŒNÎîõZ_UJ\U9ó™þ›'/tÍz­ºÜƒ@"¿í³‡e15Nk÷ $òà€$&frVÉyMÈ>‹,IÜZ_Ï=Û¶Ð;²|§“x0ˆïìYÔ`pÙc}𤫅£¾kéòØâÊC¦ …wÜÇ?ü�·)Qòø³=wâ0°€x‡ÅÂ�öí§«{„_½wrYcEc1ÂÑ(áh_(Ä•ÁQÞø¸…¿xú Ƨý4V—sðÖ…7XQ$™Â<'ýc“ z'¯½>ðÜ;Ϲœ‚Fn,9³�K—ùõ/�óøm·±·|Zµù³+ ?Ü·Ÿ¿9ü>/:ɶ/iœŸ¿þᜯç9íÜsÛFöÞR¿èÓõûîhâ™7?毟›ÚŠbTtz‡Ç)/ʧ®ªŒK}×§Z”{òùÒ=·óËC'ùû_¿‡(€¦ƒÃfá‘}[yþí³öÇž<¸�¿ø>ooãì¥^Šóóž˜f|ÚO™'ŸÇö߸¢E$ò”bÑŠ(Ì6â|ãÄ žzçÊ (+*A khˆ©@€� KJϘ-ÅßÜŒsãF”ÔñÞŒ¤74™A×4üÍÍÄ>£òK!,GMAK3ûcÇ?êàöï§ÚîZö˜©"‹ñߎ¡ÀãâɃ·-øs§/v10~ýï¤MVp;lT”æSU\8¯ˆµ\é§{hŒ;·Ô‘眿 èÃÖN&}~E¢±f{6¯ãÌ¥F&|Üw{Ó¬¤äI_€æŽ>ü¡(…yN6¯[Eïð8ÿð›Ã¼uì=Âh<ÆÑ–N.uáEpÙ­‰C‡Íëf�}ª½‹Aï÷îØH�½—œÏÌ‚¬chˆSííܶ~=k¯nµ÷õÑÒÕE÷è(Ó�² P\XÈ®�Ù’¢äWA’’RÏ™21ƒDái ¥eÙ§œ9Ê )h)#‹óÛ—OáòñÃ=ûÉ“Óf¨²ô˜ãqþû‘°åÙøÊ½·çTžâ«Çšy÷T_ûÜN¶Ô-ÍÁdYTp+E)é"ž,DQľnÖŠŠ¥�‘ÒeWSr6Ž­q eáDqùI|&×35à'ÿð–°È¿>xoV€"ËüÁž½D|þù��’VA’NÎ\îaÒwýéäé‹]>ÛŽÛacÃÚÊ%�-ˆÅM‘¥,£… åO¡Ž"ËȆHéÌìZ ‘þ³g‰‡—ÖÔ÷Ó„”CöÒöŠ §g”_<{Œ{¶láþêu†»ÿ.MÓø»�“u~÷þ]È ¬-ÍþçKïq©o·Ã†Óneb:@$ÇfQøæöR[±´œ>YTp)EX2\ÄæÂ¶fÍ’ê9Ó"fj(„ÿìYÔèòº�ƒ)hÉâä‰NÞ{§…ß?p�õÎìHÞ�MÓøû�>",ÄùÚƒ»\,o4£Ó\èdl:€?ÆjQ¨*)`[ýšY%K Aì’ —”Y¼ì¶UV⨫[ܽ§KÌâ��ææäšfÈ1j ÚÐt�ßþú$½“üpßAвäÿ¦÷¥iüäÄ |j„¯>»fhÉ@ò,žù»¡e–’œ  ôÇK«˜Ħ§ñ·¶¢Ç–ßÈ´ÅãFxáÙc¸d+ß½u¹ñkÿ š¦ñO'O0 ò­‡öÌr�ÈEAÀ!¹q*ù,®@*ó±–”àܰaaÏ!ÝbWMnèu¶PLA[8CC“<ûôÜ^_ÇkÉÕ'¦iO�<É`ÄÇ·º3§M-¸­drï%»׆ H®…¥"f±ñqümmIÙpÉa†£•Ü™i´4÷ðú«§ùÚ�w²5ß“#ÅLFž;sš+ÓãüþÃû°¤È©Á(AÀ.åá’óRî^b�GCâ"NÖ 3¸j ÒÖ†žŸ#SÐæFÓ5Þy«™‹çøÃýwS¡äÚÂr~fíòä8¿ÿÐÞ%m¨g"Š(ãRJPÄÜhA±WWc­ªZtNCÅ 23�—[[91ÐÇ÷ÛwÓBìLÄ")¸•b$!÷fcJ~>ÎÆÆeÙe„˜„ººõô, h 1b_¹‚ÖÞ>ÈË¿:Îã»v°§xUR–ñ¹Àë.p´·‹ï=¶?kMl9<E¥¢ÇÚµ NÁ˜�Œ3€à•+„{{—?�ƒŒ:½+JÐ>)¿ÌÜ}µVª)d×ñÆÅ‹|ÐÕÁwÛO¾3³íÊeI!_.FÊÁ½1AQp¬[—Ë0È01¶·JÊX%Ȉݻ"Ò6"Ñ/ÿê�é0?ص—é7/o]¼È;�—ùÞcæõó7Q°Ëù8e7¹–76ƒl·ãljBJ¢ágƉ™®ë/^$’GKX‚6>îã¹§�RSQÊ76Þ†˜…õ•éæpG¯¶_à»�ìÓŸ9¥\Šd!OñäìÞ\Íì_¿AJ®iDƉ$¼ÐçÏ_þ`€_ 2š£‚v¥k˜ŸÿˆÛšx¨j=š)d 惎^¹ØÆï?ºŸbƒME’»”·è”„la&í¶zujÆÏD1ƒDN_k+ñÉɤŒP‡z»Kâä‰NÞ{·…oßw�&%ïZ÷“…s¼«‹_žoáÛ_¸“2�1›ìɆK)DÎáÙ˜hµâÚ°9I¶Ûs‘±bW­¹™xÌ!w-¦Æyå7§˜àÞ�G5=ޖéžž9{†ï>²?­‚¶fcrA®ÆFDKj¶3ZÌ´X _s3j’ä #Žì]rú}!žyú(Å.¾}Ë.,qó´2œêíåéÓ§øÖÃ{Y]âIùõÑJ¾Õƒ˜ü6ƒ(ŠXªª°WW§E¬3^Ìôh41C –?Ù+h}}^ž{ú»oiàñµMèÑåê›|Bs?ÿtê$ßúÂV—¦FÐffc97óÆfdçúõËöõ_Ô5³AÌ áVë;{5 nµ~%À¨}¤$)‘͵e�!1d›˜ArÍ!3mhh’çž9Â- køjý6´ˆ¹?–nfíÉ»¶³±f¡pdAVB’ âT °I™Û{4YˆV+î �R˜v± 8Œ~KAÎËõqcÒ2ˆ]'žpaÆ�·¶öð³ŸâÁ½·òÕµ[M!3ˆu%%ü`Ï^^xç$­WúÑu�ÿþ«Ch7iig“ìÚ*V„�YŠŠÈß¾Ýp!ƒ,�™Íõz $ÉÜ`ÚâÇk›0l†6S(~âxß¹ÿ õº3£f‹+•Þ‰ þúðûÔ­)åL{/ŸÛ¹‰»¶oœõ¾5»šv±”–p)‹Éè–ƒÅãÁ^W—´U^ÔEI؃ ¥ÿ±D¢1ž}ú.]àÿ|ø ÔiSÈ2„UùùÜVµš3í½è@kgÿ¬†Ã6ÉN�­|E™`±àܸ1£„ ²|f6C¤¿Ÿ@’Ìü– £Žqt5=éÞqÏþóaÖV•ñ­-w „Ìee¦ iñî»ôLNûTÝ«ÓneUI_¿/ÅÎ’!bJ^ŽÆF¤4§],„œ3€Po/¡+W’6^ºíÒåA^~ñ8÷ïÛÊÝ…k!fŠg"—†‡y¿³“S}}×¥ÆìÝ´‘ïÜÿ Ñá¥[y9ŽúúŒm ’3µöÕ«!#Ô×—”ñ\QšÇëœN‰ Íì�}üÑ%¾ùð~6i…è¦�e,õeeÔ—•1òÆô|Êü`Ò4:´”#Ê2ŽÚZ,¦],„œ3{m-šªLÊxy±<˜u2©qÆbq~ûò FG}üé#Ÿ£2j½é ™IfpûÚµŒ´¶ŽF±Y,ÜÞÐ`tH)e±½+�$g–™ŸÆßÖFtt4iãM[¦“&hSSžæOß¹m7–€¹?–-ˆ’„¥´”“]]œjogGc#ÛÖ­3:¬”a).Ʊ~ý¢zWINŠ™®ëøÛÚˆ��%mÌi‹�1ëIJÆèéåÏcÏí ­¼¦˜ÍA ½�ÈÐPRÇÔc1¢##hæ -­¢ˆR\œ‘ 8’…âñàjhX^k7³9Ðu�à… D’èV  ÅbÄLAK¢$¡g­¥ÍMï/{W‰)fó¡ëøÎŸ'æõ&wXU%:<Œ7í²S‰$I(¥¥9›C&Y,8Prü0c1˜bvtMÃßÜL,‰æŽz1AÜ´YH²Œ\R‚˜ƒÉ°¶òrõõ9yˆ‘L1[&1¯7!h)("�ON&?¿-‹ÉÕdXQ–±×Õa--5:”¬Æ³$&téRRÍgP§§‰NN}‹†“«É°²Ó‰£±1gzW‰)fI"ÜßO°£#%cǧ¦’^R•Mäj2¬âñàlh0Ó.’„)fI$ÔÝM¨»;%ck~?±‰‰×W@q¹ΰ9$d¹Ü»ÒHL1K2¡ÎNBI6wœA ˆŽ�¯˜¾¹˜ kš(¦SÌR@°½�p’ÍgЂAâ^oN7¹ )Ç’a•‚œ��9™R’ ˜b–".IÉØj8L,G¥äb2¬(Š(8Ö®]qMFÒ‰)f)B×4çÏ'–…) û ¢ˆµ¤!‡FYƹ~=–âb£CÉyL1K!ºªâkm%ž¢ÔŠ\4ñª3l.%ÃÊnw"›õ®4SÌRŒ‹%-Eɯz$Btl,«û HŠ‚R\œS×Ö²2+°w¥‘˜b–´x<á…¤æ±ÑÑQÔ,t­•,–„WŽüѯôÞ•FbŠYšÐ£Q|ÍÍ©´xœèð0jÍÐD› [q1zŽ™™va,¦˜¥-ÁwölÊLµxœèè(zØpçZ2¬\P€»±ÁL»0 SÌÒŒ â;w-Ùnµ×.�ù}”¼¼œñê2{Wf¦˜€ê÷ãoiI¾ýö ºžXr¦jü%" r~>RŽ,ÃÌÞ•™…)f÷ùnµ©Ú´¿Ú(%Ù X–J®%Ú½+3SÌ $>9‰¯µ5éæŽ×Ð4"cch š Š(ÅÅ9ó‡oö®ÌLL13˜¨×K EæŽèzb† r¢$a)-͉2A’p¬[‡Õì]™‘˜b–D‡‡ ´·§¬ÖÒ¨F)’¢$ sÀ¯K´Ûq›½+3SÌ2„ðà ÁK—R6¾®ëhDÓÔW@²Zõˆ9°³a_¿ÉL»ÈhL1Ë B==„ººRz�tô�l6¬%%Yï kö®Ì.L1Ë0‚]]„{zRz�TÚpËŠÇ“õɰ‚Å‚kýz”¢"£C1Y Ù¿™‘c8jjÐc1"ƒƒ)»†|Õ½5Ù‚–+ɰr^^¢ÉHŽœ¾®Ì™Y†¼t‰p  ¹nÚÔê2ORs)Öì]™½˜b–¡èºŽ¿­�ØØXJ¯£ƒÄ¼Þ¥7J,……YÊgö®Ì~L1ËdtK щ‰”^F ‰x½‹n”"ˆ"Öâb„,_ŽIv;Î�ÍÞ•YŽ)fŽ®i ë ÷ÍÔÂá„ãÆDIÂRR’õ.fïÊÜÁ³,@‹Çñ57£ú|)½ŽñzoZ^%HÖ,ÏêŸé]i­ªB0÷ÇrS̲-Åî\ê³ø£QÂ7è+ Êrb_)‹g2’Å’XVæÀ�…É'˜b–E¤ÚÜq=#:22«¯€hµ&––Yì «äç'zWæP(“¦˜eZ(”´{•éWm¸g-Û“aÍÞ•¹�)fYˆê÷ãknFK±›¬®ªD‡‡‘ìö„Åu–"( ®úz³weNcŠY–ŸžNx¡¥PÐDQD)+C�œ4ÌBh¹ÈÎ�‘rÄÒd~L1Ëb¢ΟO‰¹£(Љ$ÒòòÄ^]k+jš7’…µ¬ ‡i¢¸b0Å,ˉz½.\Hª ‰’„£±‹Çsí5=M43NqzH20{W®LL1Ë¢cc/\@K‚[í�ÒÔh”àùó)·Z¢ÕŠkãFd·ÛèPLÒŒ)f9Bdp�PGDzM²XpmÚtÃ:K]U3´ÉI£oy–‚��ˆY^•`²4L1Ë!Â}};;—ôYÙáÀµyó‚ò¯tM#ÐÚšòšÑ…2Ó»Ò^]mfó¯`L1Ë1–bî¨äåáljB\LyÒUW�hŠ]=n†¨(8Ö¯¿nÏdebŠYèì$Ò×· ÷Z<œ��K:ñÓu�à¥KD†† ¹OÅíÆ¹ab–»v˜$‡ì-°3™gmm"ƒÿ&"c«¨ÀQW·ä¬~Ap®_�7½V²1{Wš|sf–£èºNðÂ"££sþ»mÍ55I»VøÊB œ .³w¥É|˜b–Ëè:¾óç‰y½×^E{m-ÖÊʤ_.ÜÛKðÊ•”ÝŽhµâܰÅt»0™SÌr]Uñ·´›šJÌjêëSj �*A3{WšÜ SÌVZµN÷¦c¤ÓI¾uÈWìM,+y‡þ>šGo0Òì³}úµäj†O‚QîÏ%Ø×açÐ6':�ªØÿ“¨ ·&œ¿Æf6ÐÑâÂnÑú½•T†÷‚üÕ-ÅÞ̲’÷åy6’¢k‹ã¾fÐiØÑ꡵ÞÁðXˆÁ{AŽírÑÕl-öÿ%Ê܃H’Óý!’I…][½xÆÏýŒQ¯!«R‘XNË'Íä½§’©,Ýß÷3´ìëô‰¯py8ÌÕ‘^ÛëÁï6ûÿe&±’æÒÇ>™Yfk“‹fŸ Õ><uj–’ }òÞS)%‹Vóä›ý.›‘ÞÝõL‡ùÏËs4x œØãÆn–"ž,›U¸6çòp”†Z GzÑiŸþpI£V‘NËìðBä�Æôª‚&Ïñz½Ç‚×iân0Æ/ÏLsp›�μ_T—Ñé%Î „±tôîöc1êòþ]�ZM2#¡/DÞ¡Ï* *ò­V£f{‹‹@��‘‰0×> rl§“î[Þ¯!*[(žâÝ�0s iºn|nsá/¢¦€³R@¡W­sÏš Zvwxy]áòPˆ�{qNî­ÁçЯïEÙ[Ieùðv„Á±E~G{ì¨×{‚© +ú‚äzEYðjœFz÷4œOð« 3´ûͼºÇ�Ù )ö>›DQ`h2Á¹�µ.GzÐëžíøçNII}!6õ›JM^+un3w&Ãüý;A^îrÑÓfE­–ŠàJ6>·Â¹¾j­š»ýØÍóIO¥RÉ•¾@E¹­®Óªén«!àwðñX˜+w8¹ÇM»c:QÒÓ\ 3J²­ÉE“Wj8Š­¨ÏÒ¬&vø˜�.sº?ÄG#1¾ÒSƒÇžÿÝ[QšV3 ÞŠpýnœV¿�c=µhÔrË­”ÄôZ§‰£»›‰óOçgè X8ÒåúÒb QÚnœïc·x¥§“¡$N3ñHÉ •ZE[ƒ�F¯…Ñ`„¿ùm�—»ìkw<Ó D±yf"IÎö…XNÁî/n»ñÙ_Tl¸’ ý½NÃŽÖêkSô�‡�sª§†Æ9�JUb9Í¥¡(£SËt4;ŸZ:+Š«äB¿ÆiÕs¸ÛOp>Á¯?˜§ÙkàÕ]nlRÒ[2Òé,WïÆøh$N“ÏÆ±} O-ÕÅWò j¬µâ÷X Fù‡ÓSìï°q¨Ó…VJz‹jtz‰3}!ÌF½»ê1KþT�”őҨUlkvÑRgãÖx˜o9ºËEw‹<þÙl¡…gB„ãºÚjðºLÅÞ$Q ²ý£^KO‡—‡±.?*éíqãsÊÞçm%•åÒÍ0·&—hor²«Ý†Jîe©¬B¿¦Æa¤ww®¤÷ß.ÍÒæ7ql§«IJz7Z6›åÆx‚÷>Žàu™9²·Ã3–Ίâ*ËÐÃc%½3£÷#üâô¶98Ða—)¼d|n‰³}ÔZ »ü°T•(_eú5:�šíM>{nÉ®ñNöxh«“’ÞõŠ$V97f6¶ÊŽ€›ºõLy%«ìC¿&WÒ[Ç|t™·¯‡qYcœìqSk—ñ~¾R« ¿‰p}$W:{d�WJg+PÅ„~M­ÓÄÑ=õŒÍÄù—ó³t,¼"%½Ous"Á…aÁLh…3!’«*z:}¸mòɨÒUdè×èMámò¥Ë=â{m¯‡¦Zy¶¼°œáÂ�0sËtÜ4ÖJÍCµ¨èЯqXô¼Ôíg6¼Äô¯CÏɽn\–ê›Â›Î(\‰qåÎ�uVŽîm”ÒÙ*S¡_ãs›©qš�Šñ�çfØ¿ÅÊ¡í®ªéÊói·«�Ã{ê1˔תTuG]£V±­)7ìöxˆÁß9º»²KzDSœé ±¼’ýÒn1¢zT]èטôz:¼DãI>¼âÊÝXn ¯§rnd-%3\Špsb‰­ÍNZ;ír#SToè×8mï¬'8Ÿà¿~7K«ßÄñÝ.¬eó}‹QǾm^ºÚjxw0¯.> ´°ZìÍúB+© çBüó»0™Lëi�À—¹á‰Ó ~x¼þó�ĨWó§‡|x�zÞºú° ×—Ð?A®¤·§Ã¿^œá­kó,%3ÅÞ, ×-ææD‚¿};Èl,Ñž¶4:PI­|YËdΆyý`m^ÝŸNìv3M21·œ÷ß��÷O¡R©ÔÙh¨±pg2ÌÏßžâp—ƒ½[lEëÊ39¿ÂÙ¾¨Õìòã�)¯ãîÌ"5vu®üž"iµj^hw08§Å›_¥©„>OŸuåYåæXˆë£›?…7¾”æü`„‰‡+t6»¤t¶M…R¼…�S-uF®Ü�åýóú­Má� /ñÖÕ^gœS{=8-ÏoW®f®Ý�ñÑíšê¬Ý#«ÎVª•TšGaåá6£ŽÄJþÃN ý:ùÜfj]&ƦãüòÌÝ­ÖçÒ•'·êìC,&=½R:[ñŒZ5ËÞ7J¦³èµùßË‘3è¨U*¶4Ø©¯µp{<ÄÏßžâèn'Ý-¶g~í™H’Ó×C¤VsÝb\6)�­~·‘¡û ^Ü–ÿïç—©så~Hè7ÀZIo,‘äÃ;a®ÜYàÔ^Ϻºò,%3ün8Êðøb®tÖ/¥³Õ¤½ÞÂÙ�¡…{~7h¯Ü]àà6GÞC†Èa5px§Ÿæz'¿ùpž_0ÇÂR:¯ßÍf®Œ,ðwoO±° Ç÷7ÒV/�¯6z�ŠÞ.¿½ú�ÕŒòéדiÇŸ«ùp8ŠJÛò/ “+ýsPï±às™ FùÅé)ömµñRç——KŽÏ.ñN_ƒNÇá�~¬æê›ç/>³¯ÝÎƒÈ ÿþÞ ¯¿èci%Ío>˜#¶”ÆlPóJ—‹]­VÞŽr{r‘ótqP)Š¢äóƒýc¼ÞÛZìýQv–“iF&„’ôv;‹1M£Q«Ø°ð0žÎ•Τtv=®Ý~ÀK�vÚý•µï>ºå÷wb8Ì:f£ÉO¿ç±kH§UÔ:õ|mM^E<�“+ýsf2hÙÝáe>¶Ì¹�9Òé,�«¼º:š ½Ñɱ‡t‹@¥‚;�ìlµræZˆÙègßÓiÔüÉA/uÎõeɘ~“Ô:LØþèc»¢(ØÌ: ¼øRƒ–“{k¨s°Ô¸l:Nì©YwàA®ô›f>¶ÌÒò**`m<¥BÅr2�¢(|ñ¥¬& ?9QÏÂR«QƒúçWH蟳ÇÇô'{Ü,¯f¹>²€Ù áå.'Wï.p¡?.czñTvóÆÄUBÿœd2 £SQƧØ·ÕÆw×|z÷þ…öÏž©¶Ö™ŸÍõz›Y «Õó¹a€IBÿL‡¹5¦ÁcàÍמúð™ùÙk¦ÜWÏÐPka[³K–¸Ï…„~ÅInŽ…Ñ�å‡j ªÈS«Uè°ÓÝbáòP„óׂR‘'ž ýXNe¸="K>sí½Ù áäÞº[sµ÷Ós º¶¸¥ö^l ý3È* cÓqîÞ�ÐÝbåÛ‡0lÐGr¿ËÀONÔ3:½Äéþ9,F=Ým5˜Ëx•^Qä Z§ÙðC÷Bx�z~zªá¹Í§o¯7ÓâkâÚÝïߘ¦©ÎÊÖF§Ì§ë&¡/Pby•á±ÉÔ*_{asVÎÑiTêtÒÝlåü`„‹}Stdå±>ú<­¦³Ü™ 33¿ôh�<羚‘g3kyãÅZ¦ÂIÎ^1>½@W›—´—�Ð?…¢(LÌ&½¡½ÞÄ_|µ¡à ­ÁmàÇ'êšLpáÆ,n‡‘}q·K” ýÌG—¹9ÂeÖòçGýxì¥S4£RAw‹•v¿‰÷‡£\êŸbKƒ#7_–ÁO ¡ÿ‹+«Üžˆ_Lòj‰w¸1ê5œØãaß;gûC\è�ÓÙ⢾¦t·Y—„þ1�—Îîßj祗k˦—�˦㻯Ô}ÚËnr6NW«[zىϑÐ?œOpë^˜VnÜ^®]k>3ožZ+é}@c­™Ž7:yÄ')Ï3{EãInŽ‡Ð©á;½^ê×±˜e©Y+éݰréf˜óW¥¤W|¦jCÿ‡¥³.º[*ï™·Q¯æµ½5ìiKrº/ÌÔ\œ­<ŽòcëWu¡ÏdF§bŒÍ,°‹•ïöÖ¢+“qûzùœ~tÜÏ­ÉçoÌa³ØÑê‘ÆUªªŽúlx‰¡±^‡žŸ¾êÇi-�Gp›a{³•­ ®ŽÄ¸<0M£”ôV¥ª}l1ÅÐX²Þ8XCSm~Ý=+‘V£âÐv'ÝÃ\ì ÒpKIo©èЧÒYF&ÃLÍ/ñr—ƒ}í¹‘õˆÍ¤áõƒµÌ„V83�+éÝÑæÁ-%½¯"C¯dÆfâÜ FéXxã@ã†7–¬~�‘¿ÚÀ͉çg©qÙÞ"%½•¬âB?]ææ½0.«š÷Qk—+W>º[¬tÔ[øýH„‹}AZýv¶49ÑHIoÅ©˜Ð?>åõ«û6gÊk¥ÑëT¼Òåfg‹�sa. L±#à¦NVé­(eúÕL–Ñû‚s‹èpp ÃW6¥³¥ÊeÕñ�^ãsKœí‹äVé ¸±[¤¤·”mè%W:{{žÁë2ÓpcÐÉ~.geú‡±†ÇBX�j¾ćÏ)ãöçE­VÓÓfg{£•÷†Â\ꛢ½ÉI«ß&]yÊTY…~%•æÖx˜ÈB’£»*³t¶TõjNõÔ°oKгý!.öçsx]Õ[óP®Ê"ô™¬ÂhðÑ”×ßë­E+ãö¢ðØõ|ÿˆŸÑé%Îô=dܨ£{‹¬Ò[NJþHåÆíš½~öZ¶ êç%žM{½™€×ÈÕ»1Þœ¦Égck£CJzË@É&(šH24F­ÊòÍ— ë#6‡V«æÐv;6. E¹p}ŠŽf'Í>›T>–°’ ýJ*ÃÈý0ó‘ez»œìi•9à¥ÎjÒòõý5<Ø’äL_ˆûâìhsã¶Ëu)*™Ð?^:Û°ð�ƒR:[nê\~ôj=·‚ Þ˜ÃaÉMá5ÉÞ’RG#7å5Œ×¡ã''ü¸ªlÊk¥ÙÞh¥ÝoáÃ[Þ럒’ÞSÔЯ•Î.§Ò|uŸ‡-~yüS)t¯t»ÙÓjçÂ`˜ ýA¶5¹hòÊcÖb+Jè׺ÅL?\äå.=mÖMï#6‡Ý¢å�C^ÆçV8×bj>·d—]Vé-šM ýZéìðXˆv¿™¿üJcѻňÍðyóµ†&œ˜¡Öe¢+àAÿŒ%½Š¢ £†Âäz•*ÚõÞI]áÖX‹IÅŸóãsÈ;}µy¼+Ïwb\êŸ"àw°¥ÑŽz�'–¢€d¾0y‡^QÖ÷–“iF&Â<Œ'9¶ÓIw‹­Øÿ³(2£^Ãñ�nv¬œs±?NWÀ�oSx�9Ê;ôj• Užï«éL–»Á÷Ä9¸ÍÆw{˧[ŒØ›žï½\—+é3ùèù¾ÅXÀÓ›, Zç©Jåz­NE&£ Ö>=¸Ó¡En�…iðøéÉzì–’x2(JT{½™¶º\Wž÷oÌÐPka[³ �öé7wÓ™,:­Ü*DÞiÔkÔ�vð—ˆH|…¡{aôZøöa/~·LyùYëʳ£ÙÌ¥�#\ê²µÙE³÷É%½é¬‚^®)É{w™ôj’«™/¬®ZN¦ [Lql—‹®fy+ÖÇjÔòõjyIr¶/ÄäôÛÛ<Ô|IWžd*‹Iñ,HÞ¡÷¹ Ä)œÖÏ®ÞÉÕ ŸÜ�r>Á¾v‡^ñV|·±9ê\~øj=·ƒ‹œ˜Ãf6ÐÑìÂñØ’]Ë© *•R¶ÍF‹E¥(ùÝ—¿9çÊH‚vÔ±°˜bz>Npn‘íÍVzw8°šdÇ‹ç#“Q‹sùV§Í@C� ¯ËÄ'S1”LŠoò{ËJÞ¡Ïfþ÷ÊCF¦¸,:¶5ZÙ°ÊM:±iÒ…›“ †&L‡VpÛô|ë�·êÚ“=«¼C/„¨ Rð.D•‘Ð Qe$ôBT ½UFB/D•‘Ð Qe$ôBT ½UFB/D•ù85Ïæ±×N%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00þÿ™llb"™ªy*;95ýøÆ¹Øtf&3{s‘X¬ÿ‰3w{™Pl67¿pw©Hìb|,œ¯³\ 6²Š÷Õ]#»¼òôYƒUÒ°«ÎZ´áJYØôúX&Ýxµ(¬ÛçÏ›­„uû<Ñ| 1Ø}ÞX·Ï_´ÜHvc3Vhc3 ØÚ>Ž�„gjú\661Ñüt#;¸Õçr±[wû\,v»NŸ Åfs±�»pÅ6ês�ØÆ}.[lÜçÒ°¥f}. Û¢ÏEaÝ>©¼3/lp§¼ÛÁÕ>÷|ºá‰Í·Õç2°›¯”N7 ±ÃΞâé†ÖCŸ³Ç&^·ßç̱“�^}ÎëµÏ9c=÷9_ì~.öFçñc•úœ'V±ÏYb‹+oßi?(MlÉ9Ø6pXŠØêϵTûœÖ_é Ïyaƒ;‡Ë¦ŽM »¯ùtC«¡ÏÙ`7>|<2út°Ÿœ6¿?ç�ÕÕç°Úúœ>ÖíóϯC»• ­kësâØí5�}N»Ÿ;ÖÚ焱'ñ½%s˜Ha«—S-ÂQQ±§e}N[r¦Mô9E¬±>'ˆuûü œŠƒ &Íõ91¬Ù>'…Í__ÞØBÌpŸÓÁô9¬û�©ßxŸÁú_P©pX¨>'€…ës|lô¬Ï±±…‹ã¯ØL ,pŸcbÁû{ZN~ÃaÏú ‹Óç8Xe £Ï1°©äáwl±Ï¡±ùèùZŸcwË—GØ* ,vŸbgÑû믠÷96H¡Ïa°Dúëö9ÍÓ�~láâŠHŸÇžÄGÉô¹a,­>7‹ýñ“TŸ›Äþšòr»ìé›Öy9q,Å>7„Í^Îìs#Xý—S‘ÅÒísýØâ æ÷ç ØUåÛ�`�g,ñ>׊uûà÷í$°þ]ßñ‚Ï´¾)éñ€eÑçz°ƒWCØo;×îíHIO[XF}Þ1Öíó”âáiMk,¯>ïË­Ï;Á²ësu,Ã>WŲìs5lµÏO°ß–kŸ«`Ùö¹ VèôرcÇŽ;vìØQžßÖ ä£>%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00Þb—BDDDDDDDÕУ»' êð±K©s Üê˜zóÁ¨¡÷–¡½Õü{á»5!HKËT­ÚÙˆC·{÷îlÚ´»"""""""ª†æÍÍàââˆÄ )b—Rç¸Õ!Y¾\˜40äÓ%Õ*éåáŽðŸ7¦ÍFBR²Ø—U+ÔsØY[5­.§DDDDDDD�I'''±K·:"Ë—cJÐla…Žÿ^Õ>–];[l ] xcNp£ Ý4¹•Y‰ˆˆˆˆˆˆ¨ácàVÔa£-‡+µ¶ÂŽ­àÛÓoÌ Æ�ƒÑb_&��[­KHJÆÓcUCG·„®5Jئּ¹¾ü||{zcéòlܼMìË%"""""""jòš‰]@c–�”Œ7æCÚJŠ-¡kke Üf ¾ü|Ö¬Û€ÐMa€©“Ÿ7x!"""ªßrnä"1)R."_®Z0ÉÚÊ ÝܺÀÅÙ .ÎNb—HDDDDe0p«%á»vcÕêõðíé�/?_V«X3‰oÏ™++ „n Ãù„ µ~N"""ª] IÉøâëo‘––©óõðGÿ/m%ŸgFò·’åË¡P(`cÓ†÷‘ˆˆˆjŒCJkÁÆÍÛê,lÓ4}ê$¼ýæLÄÆÅãÝ÷>ÂC¥Rì[ADDDÕ î%_6l2x \\µž“Ý‘!tSÞ}ï#Èòåb—Þ`Í�·^œŽ¼¼[b—BDDD�{¸ÑC¥kÖm@øÎHM›,Ê'ÍÆŽ†kg¼1'Ï>÷r­ e%""¢Ú¡ÛÔŒþ}ýµVî~¨T"33 çÎ'bÕêõ€Ø¸x,ùd%¾ùb¹Ø—Ðàu’hü<ÜñÝšÈîÈ0%h6?í&""j 4Ã6G„ÿ¼C‡j…m€j: g'L;!Ÿ.ž��‹Çñ“g >ßýûŠÕ[Óö†x¨TV»×¾¡õ±W{¸�:l‹�‹ÇÛoÎÄ„±£Å. ^îøc×6L š�)A³±béB£®�JDDDÆuÿ¾B«gÛçŸ,†];ÛJÛø÷BдÉ8Ÿp£†?·®®z÷͹‘‹õ~•Œ ¡G—´•={xaØ�'àß«Âséj¨†º:vì ·wÿâOV<»¹aÂØÑHHJFÔᣈŠ> Ù|{z£_<;f$šI$x¨Tâô™³Øð0FÅu¾òÒó¾Ï’åËñã–_�‘y±qñZõyvsޝ¹ÿ×ß~�+ÂsŸ}±Ö�F,ýp>Õܼ‰R„玟<ƒR/á|Âa_µE Þ­ðC×ã'Ï`ÿÁÀ©“žã¢DDD�·’åËU½ÈîÈðÝš�zjI­­°%t-¦ÍÆs‚ë]}DDDTêÜùDa{Èà�…mjÓ§NªtŸ£±tyH¹çewd8ƒƒQ12x ÞÀH_{B(}äo|óŧ妳P¿@˜úBSl\^$ôT(Zµ©kQSn‰R„ýf¾ú2‚,Ñú^9vì ¬?þÙ§+|¿µ~Ã&!¬\´à]C¿ÅDDDÔÀ0p«�ú¶©I­­°c뼿èc¼1'¸ÞôÀ#"""mê^O€ªç“1%$%k…eAÓ&cÄÐÁ€+W±"ä!xJƒ&}í O7ØØ´Aff"÷ìGøÎH¤¥ebî¼ؼa�Î:âÎ% î\‚PÃÀ~ˆùû¸V…ïŒD¾\ŽƒQ1�¶’âÍ7^…‹³6oûU¨-tS^œ8Nk˜mÎ�\­OóúònÝ‚¸Ø¸xL|éUü±`cÓá?oÄÞQB !Ÿ.A'§Žzïåú ? çè`o�víÚ¦Mk¡}è�azçÑ“åË…°m¸1\ •ˆˆ¨ãnÕ”�”Œ)A³ìÚV/Ã6µæÍÍðåçËàÛÓ«V¯ÇÆÍÛÄ.‰ˆˆˆÊPQТEs£û‹¯¿¶ÕsÍÚµ³…];[ø÷ÂŽ­àÛÓ€ª7XÙù_5Û·&C‡®�­0—ÜÛsf`¸1€´´L$$%ë¬CvG†VRKü±k¦O�g'LŸ:Ik:uO»[7`è�@¸8;aé‡óñö›3…}Ž;©u\u¦ëú¼<ÜñÛ¯?!hÚd¡u}Í$ص³E{{¡}'§ŽB[]FÅà»5!˜>u† „—‡;ìÚÙ «ÇÆÆÅë�;.êða{̨aFýQýÂÀ­4'4n(«€6“HðåçË4m2B7…aÕšï«=1ŸæPȪ '­LBR²V¯*]Ã1›77Û³^ïŠÜ#lçÜÈÚûöôÖû!ã+S^¶C Ó[ÏK/ê•5«ÂÚÊxï FÅ”[µ:ôÕ4dð@ôõ÷3èf¦¦F».5õâ ii™ØùûŸÂûÆ´ô !ÄÿìÓF?/Õ? Ü*ИÃ65/wl ]‹)A³ñôØIønMH½^q•ˆˆ¨±j×®­°½yÛ¯F ¦À³››Ä�:¸Ê=纹uAx5Ϋù!Þ�Á+ «Z“.}ýýt†‘ÆTv¾¹²f¾: Á –@vG†´ô ¸8; ÃIõ-¸@DDD�W)ÕC–/Çôs/,ýÞXI­­T½ÛZIñÆœ`$$%‹]Q“ãîÖÒVRªž`iéF9®¥……°}%ãj•Û››·4¸½¾¹ßj“æ" š«—֖ʦÑ\–|²RXQ4xÁªÀ¦»W7XZX ñB ®dd”[‘s¸1˜3ëÕrÇœùêËÂj«V¯ÇªÕë4m2F ŒÄ¤ìÙ÷—p¾ ãÆ”›M³ýs‚4m2|}¼aÓ¦5®d\Åöðß„öC4Ú «†zqâ8á}KøÎH„ïŒÄ�Á1uÒsȽ™‡SgÎ"|g¤p§NÖÚ©Ù 0tS˜°°Dÿ¾þÕZQTsñuï¶ W&×é=!"""q1p{ä¡R‰×f¿Û¤Ã6µf‰²…n ƒ¥…&Œ-vYDDDM‚ÔÚ ß|±Fcéòáùظx!Ô*צ•ß„|¢i²kg‹Í¡kUÃT@¡›Â„�JÍ·§·ÎÀ®l{]mý�_mkÞÜ ìÚ¦TŒŠ)·Pƒ´•Ÿ}¼¨ÜÍ'"""n�H­­°ôÃùxë?3 P(�wë6nܸYn¿ )…Pη§7>ûxQƒšÛlãæmB ¨ž³EOÕ¼% éÚˆˆˆˆÄ Ë—k-Ø òé½óÚQãÆÀ­ Õ‚ V°kg«sβ¡C1gÖ«8}æ,‚,ÁÄ—^m0«šªÃ¶ i“ñâÄq ÓˆˆˆˆŒ@¡P” Û‚¦MF€/±K#"""‘0p«†f ü{á»5!X¸x¦ÍÆŽ­êu€uüä„n Äqc0}ê$±Ë!"""j4¬­¬°øƒ`\ËÎŒ:˜ó¶5q ÜjÀËÃ[B×â鱓ðóŽ�õ6Ⱥ_�àKàÛÓsf½*v9DDDD�Jóæf:$Pì2ˆˆˆ¨yLì:©µ&ŒƒÐMa¸_QóÖ‚Kié€7g½ÆÅˆˆˆˆˆˆˆˆj7#3j _.»�¢…´•”“öÕnFТEs@Þ­Ûb—¢SøÎH ì/vDDDDDDDDM7#°±i¸qã¦Ø¥èÕÍ­‹Ø%5 ÜŒ€ó¢Õž‡J¥Ø%U 7ª—Úµk ÈË»%v)DDDDDDDTMqçÄ.A ܨ^rèÐp%ãªØ¥Q5ÉîÈÐ×ßOì2ê7ª—¤ÖVpqqÄöðßÄ.…ˆˆˆˆˆˆˆª!-=`nÞRìRê7ª·ÆŒ�ظxá?P"""""""j86oûÒVRøõò»”:ÇÀ�ê­Qß‚´•sƒ?„,_.v9DDDDDDDd€‡J%V­ù£bðæ¯6ÉÅ&¸Q½Õ¼¹¶„®L š�û÷b—DDDDDDDDx¨TâÝ÷>BøÎHM›Œ¡CÅ.IÍÄ.€¨"Rk+¬XºoÌ Æ�‘ã1dð@ôõ÷ƒ‹³Z´h.vyDDDDDDDÕ¢‡ÛÃCl\< äÓ%ðï%vY¢aàFõž—‡;þ�ŸwìDè¦0ŒŠ»$"""""""*CÚJŠ i“1bè`ص³»Q1p£¡ys3LŸ: Ó§NÂýû äË9§QCw5ë:6lÚŠe½'v)DDDdM=dÓÄÀ�œæÍÍм¹™ØeQ }üùWHN¹È7çDDDÔèpÑ""""EÂù €ô+™b—BDDDdT ܈ˆˆˆ¨Î¡¤¤ðSØ/b—CDDDdT ܈ˆˆˆ¨Î}ùõZa;æèq±Ë!"""2*nDDDDTç4C¶ÿ=xˆ‚¢"±K""""2nDDDDT§ ŠŠð¿µžÓìñFDDDÔÐ1p#"""¢:¥+\ã°R"""jL¸Q�Ò®qX)5& ܈ˆˆˆ¨ÎèNªÆa¥DDDÔX0p#"""¢:SQ¨väèI±Ë#"""2 nDDDDTgNžŽÕûÚƒ8¬”ˆˆˆnDDDDTgŠ ïUøúæ­ÛÅ.‘ˆˆˆ¨Æ¸Q�øv}h¥ûìþsŸØeÕ7""""ª†„i•õ€#"""j¸Q�04L3¤'Q}ÆÀ�ˆˆˆˆj]UB4+%""¢†Ž�Õºª„hVJDDD 7""""ªuU Ñ8¬”ˆˆˆ2nDDDDT«ªžqX)5d ܈ˆˆˆ¨VŒŠ©r+%""¢†¬™ØQãÖ½{7¤§g–{>÷fîÞ½çNŽ:ÛÁÒÜ\ìò‰ˆˆˆªŒ�Õª¥¾§óù)Óg!ýJ&¶l\'v‰DDDDFÅ!¥DDDDDDDDDFÄÀ�ˆˆˆˆˆˆˆˆÈˆ¸7"""""""""#bàFDDDDDDDDdD ܈ˆˆˆˆˆˆˆˆŒˆ�‘1p#""""Qd]¿.v DDDDµ‚�‰â*•b—BDDDdT ܈ˆˆˆ¨Î%$& Û™™Yb—CDDDdT ܈ˆˆˆ¨Î½·h™°ó÷q±Ë!"""2*nDDDDT§æÎûòBØÙÙb¸1ØùûŸ�åËÅ.‹ˆˆˆÈh¸Q�ùvýÄÆÅã1‰?…®Å+S^L šÍ¹Üˆˆˆ¨Ñ`àFDDDDµ&;çEÅ·ë7`Ј±øyû.˜˜ûvoGËæÍ!µ¶ÂŠ¥ !»#ûï}„û÷b—LDDDTcÍÄ. 1)yôEM�,_ލÃG¹g/ÒÒ2Å.‡ˆˆ¨Þêü„3V,û-›7žóòpGȧK¼` †Œ� i“ÑÕµ3:9u»\¢&ÅÆ¦ šI$b—ADÔ(0p36&nMÊC¥kÖm@øÎH€oOo¼ýæXZXˆ]ÕÀéØ³Ø»? ÐÖÖ=½½ÐÜÌL첈¨�(..Æ_ÑGð@ñàÒÉÒVR±ËUŸÞ¾hkÓ½{ûjmšü{!üç�X¿á'„n »d¢&k¸1èÝË~½|¾Õ·zŒÙ]ýöP©Ä»ï}„ظxM›Œ'ŽCóæ e²‡J%6‡mÇÞýQðíé�%·ÔÚJ첈¨IKÏÀÜàѲEK|²în]økص³ÅÒçcé‡ó‘s#÷îÝGZz†(µ´k×6mZ‹}Kˆê̽{÷ó÷qìüýO„oOo|ùù2þ#"ª&nFÆ�¬ix¨TâÙç^†ìŽ !Ÿ.A€/±K"#Ð P§O�$v9DÔÀ¤¥g`jÐlH[I±%t-û²kg pqv»¢&ÃÅÙ Ó§NÂñ“g¼` ž}îeþ>#"ª&.š@T ‡…ìŽ ß­ aØÖH¤¥g0l#¢Yºb%¤­¤Ø±uÿ8%¢-À¿¾[Ù¦Íæb&DDÕÀÀ͈JÄø*©ü‹Œoõwàââ/w±K!#‰Ü³ÒVRL�ü¼Ø¥Q”�”Œ´´L¼ùÆ«œ^€ˆ/w„ÿ¼²;2=vRìrˆˆnÆ$FâFuîþ}dwdxé…çÄ.…Œ(|g$öç<%DT-7nÜ z²¿Ø¥�];[øöôÆêï6ˆ] QƒÃÀM$Ìä®|¹ç”iŒº¹u»"j ®egC{"jtF  ²;2‚³ç�~%SÔzFňvîž>^�J¥èëï‡þ}ýѼ¹øAÑC¥É)uø(222{6Aì’ªLÌïiuøúxÁZ*…g77ôíã»v¶b—D$�åËuø’Rp6>²;2±Kª«V¯»„Z%m%…�·¤ÖVèÝË~½|ÐL"»,"""¢z‡�›qфڳqó6„n ˜[·€«›3|Úyˆ]–hJð/NÆ�¢·ßœ‰ cG‹VÏñ“g¼`‰ðxˆŸ7†øy‹|—š†+Sq0*«V¯Ç�A°há<þñK¢’åËñæ; „EìáÒÅKì²Èˆä÷�¨C‘ß i+)V,]/w±Ë"¢Zbme˜ðât;¼Gìrˆˆ nT¯=T*ññŠ/pðÐ æÿ@Ø;°�Úí¼|Äì;�U«×£ °Ó§NªóÔa¨¯›+‚ž÷NŽ |êØýâbüüW4BwïC¾¼_~¾ŒßEÎ�\¼6û]ÈîÈðʬ`xùøÃ”Cµ¥i³ç#-5¿lúoÌ ÆwkBº5@ié8w>GŽ�@\Üy±Ë¡ ï“£Ä.�꩞>ÞðîÞ ûÀÅÙIìrˆê“’’vÊ2‚¾OŽÂ¼ùÁ ¬p?1nöè‘£°øƒ` XãcÕ¥‡J%ÞyoââÎcøø@ ;Pì’ê­}»b°/"ºÎ¿Ï‹?þÁ„Aý1gÂ3 yDv<1Áßþ€ ãFãí93Å.‡š˜´ô L š Kk)®X K+±K¢: T*ñáÜ—!y غRk~ß‚‡J%~‹üSݹ‡:usB»V0ÑÜñÑWõs&:Že •´3ÑÑ•¶ƒŽö&û•îkR¾]™cënWþúÛé8GE×Ræ9]­ o§£R�íLtÜ»ªÜƒG[eŽ]¢çÊKLJÛhÿ�cR¦mÙíòUêû©&šßÝu”Ý_çq ¬µÂs™è¾í ý×Y…:ôÝ3¡>Ýûë¬Õ•œË¤‚ã躧åÏ}37—R/àb’*¸Ÿ0n4æÌz�P“ÇnFTR¢ú"ã8tø(ââÎãõy“àîÝYìrêµ§ÆôGúÅ ,]‚^¾=êäž„¤di˜þô0¸t°Ãöð]b—BMHBR2Ò¯dbò«s¶5A–V˜üê\ÈîÈ�s#Wìr¨Ÿ}ñ ÒÓ21ë‹WðìŒá�Høç‡D"Á¨±/âƒO¿…쎋?Y)vID¢â¿°FVR¾ƒœ¹�Ý‘côó s ejö8\=œðûî½ur¾ƒ‡Žà•O±«x=Ø£;bãÎãþ}…Ø¥P‘z) àæé#v)$’Î]=ÇNœ»ªÀñ“gpðÐ<óÆp8¹w»"j¤Ú;8aÚ¬yˆ‹‹Ç�ƒÑb—C$nõ€\.Gnn.rss�Ø3g„Ǻ¾šÛö6b—Рôàƒô+™�åËkõ<ê Dze ±/™tØCõ‡ovÎ ±K¡&"ñB ì!aßd™š™¡‹‡7’RÄ.…*ð݆Mhש-üGùŠ] 5r½ÑÅÃK—‡ˆ] ‘h8‡›‘ÚÃL¡Pà·];ñóÖ°*Ÿã÷?ÿr܉�Þ°›šþŸØ¥4(vm¨~¾€ÚÖ•/Wz.ííľdÒÁ¾MkªIì¹JÕ…ÿì;8‰]‰Ì Q‡b°lÑ|±K!*•HOËÄ óǪ†‘6–aDTo þ,.&ÅC–/ç\nÔ$1p3¢Çt*•JÌŸ÷2¯dŠ]r½gnÙRìS3Ó:=_ S3±/™thnZ·?DDTÿååÝ´sj+v)DÔDصW ]Ϻv��5I ÜD°oïŸZa›µµýô‡«k—JÛ6¦yÚˆˆˆˆ¨n¨G´¶“Š] 5­ml7nÜ„—‡»ØåÕ9nFdh–’R:¿É÷¡akk+véTCÅŠH:{àÔÙ­m¬Å.‰ˆˆˆ¨œÇÍ»""¢&��›ˆ;92l«¥ò_ÄŸº ó5§Î¶u+ËZ_ò¾¨ð¶¬Û ˜2k·º_\Œü»Âck‹–&IÔDÈqóÆuXKUs>nj Ëú5,¥X¡@ÔÞ�ØQ:/ë+³‚Ñ+ PìÒˆˆˆˆH$ ÜŒ¬Ä€.n–�þP7þ9ƒö'Ýòï!WeÌ­[`ì¤áðîÝ­Ö÷ÚPTpÅÅÿ«“ðP,9·î`ïÉ3ØyädòÂr¯»t°Ã˜~}0Ø·¤æb—KDµH©Tbäv­«,Kk)†�y}<S3qç“ܺ±'bD­�ˆ¨)˽¥š£ÐÔÔ VÂóòÂB(Š‹Q �T ‰¤þÿù[PP€âÅ€6m8ç"QCVÿã4B=||°gw$vFüŠÅ.§I(ÊWõ@ÛµmÆNŽžžF=¾u+K,Z5`nÑÂèõ¶pŠòïaѪ¹�²÷\Âåt¼²¦Â}Ò®å`Õ/;±ê—�Xô†úõ»l"ª…r¬X8ù² ÷+È—aÇæõع W¬­×[a�\Û,­¥è?x$:vêŒÎ]�ûï QCQ¬x€[92dgæÂäÑs-Z6‡�ƒ ¤­-!‘HÄ.‘j‰j„B’Ò3æÍ›ÃÑ®¬,,j}¤Â+ï/ ìí‡÷^{MxþûŸF̩ӀÐÏ?ƒm±oS¥~ÚöNœ<ûñ±Ë!¢`à&‚nª7á™W2‘’œ 7÷Ò $Ùá­z|úx`êìñZÏ+ ¨ðä²ìØ´9Y7…à €QC7‰ä±Z ŠP”¯Öî�Ø6þ±¡»÷ �ƒFGWGt²k¸’s§’ÿAT\¼ÐómièVܽ‡ Oö»|"2"¥R©¶Ù;8â™ç§ÁÑÙUÔnçå"ýR Nù “âQ�/Ãû³&á« ¢ôt{P¬¶]ݼ0rì$±o#‘(²3rqü¯8Äì>Uá~O¿ø$üŸôF›¶\¼¡±H»ž�­{ êôY½ûø¸uÁ„!ƒàïÕMìr‰ˆêLã›&’¿LḬ́üóÀ÷ë¿Err2*• ÛŒÌÔìq´¶±†³kG¼÷é?u„ðš¡CQëƒëWoˆ]B­Ñ Û¤V_¾ÓŸ†Owصi»6­à鎷Ÿ‡?V.ÄA¥Ûª_v"çÖ±/�ˆŒ(#í¢V϶™ï,†‡w/­Þk­mlÑ+ 3ÞZKëÒ?ØOùKìòáÑÃOìˆD‘žrŸ¾¹®Ò° þøù0>|}ï9)vÙ ÚÐéóðÔôyb—�‰0még†mp6å"®ùó¾Z¥R)vÙ¢ûdå ¼ðÊ$ܼ•Wîµ—'½Œo¾X�o¾X-v™DTCìá&‚›¹¹ÈË»‰~âï˜|ð^0ÀËÛƒ†<¥·]ìUwèwæÍgW¸jðà�ˆÍ{…Ç·óòuöJKO½ŠøSpãúM¤&ePõ kkß½úu×Ù¦¨à.vnQGýžêg׎Âk›×F:uv@ÿ¡~(*¸‹‹Ié8uä,R“2`nÝ®nÎ2¦ìlµêøû¯3ȹvSxn{èï04YÙ} ÍñÄd­°í·O£Y%ÃLæLxçR/#íZà—¨h¼ýü8ªa GÏ'<�;Á®M+�ÇH¸œŽwTÐkKÕÕþ~q1²oÝFÚõtî`�Kײ+=¾Ú�ÓqÂvÙᯕJdÞÈEÚõ\¸’‰ü¢Bôõô€K{;Ø·iÍ"¨Éºs«ô÷ݨñ“ÑÚFÿÂB¦fføÏ{Ÿ "ìXXX¡MÛvZ¯§¥& Ç«hñ‚3Ç£­Ú´…‹ki�suO:Íö·ór‘/»�;·n¹³Ò/¥ #í¢Ð&éÜiaÛ¹³›VýJ¥i‘•‘†+�Žkkß6¶öðòñ7¨w^±B�¢B9 çúUÜ¿w× ¶Å ®]MÇ�[7‘tî4Ì-­àäÒÎ�Ý`ݪ ‡øQ�¤'_Å×ï… �GNzÝ{»¡M;)ÌÌG±ânßÈÇ¥¤+øû¯8dgä¶ÿð'Zš·@ï^b_Bƒ“_P$v €ÿ؇�‘¥ï­ç¾8}<»¡�TŠf ò ‘’qg’S°3J5ôþlÊEÌøä3¬ÿðý&ý»'19Iïk–––À£Ùü“�¨acàfD%%†-š�’’‚o¾ )÷|B|<âã+mÿö»óžÔÉÔìq¸z8 !Z±¢Xëu¥ò_ü¾m?Žì?]®íÙª÷EDcʬq冣ÿOا[WÀµ|[pïáŠ�ßþF«mQþ=œ=‘„³'’ðú¼Ip÷î �Ý’kµ Ô4üÀmýoÛoNx¦Ò° šI$øæ­YØs {xÂ¥½½ðZ~á], Ý Xô’Þ@,"æ(žŽ „•mŸ˜~Ex ëæÍûº¹â›·ÞÐ[§¬°Hk_ÍóÈ ‹0÷ëuBh¨¦®Ije�æ¿Ui GÔÝ-*]0åòÅ P*•þAÖÞÁ o¾¿\çkGþúC˜[­¢ÀíÇuª�}û Ô ÜÒ/¥¯yùøã‹¥ï ;+Sxý•YÁÂëj±'b„s¾2+XÜnçåâ‹¥ïV8/ÝÄ©38t´ÞׯgeàÛÏ?,w Kk)þóÞ'hïळ]Rü„møFï¹»xxcÆ[‹D_x‚¦ô䫸æ½�sksÌY6í�lµRS³ÇÑÞÉím1`x/¬YºÒW…ÃÛ¯+LÍøASU¤fd‰]6ý±w«Â6çöXõölX?Z¬ äQXdmaÏnð÷ô@`O¼¹r ýZ6¢cÏbpï^b_†(tõj#¢Æ‰�5)…òÒ¹Ð,­´Wº [¿K¸\=œÐ{€œ:; XQŒœ¬›ØµmŸ0\ófB0f¨œk7±jé;‡¶˜8m®gÜÀþÈa޶m~ÃÒoÞ…Dòœ:;`ʬq8¸ûoäd©zi Û†ÄÈ ‹„ÀIje�A=½ n+µ0Çô§‡Õj}wïáǽÚÃÓÚJ­áÒÁi×r›’ŠûÅÅz{¢íŠ9&l??x °�v=S—•þ�îÒÁ�ìmamn!ôÜ“É 1áƒ�ñ]ðx=á\«×ITßxöðÃŽÍë“â±yý—˜6[ü™¢öîÔ ÛU�8ß>‘}-Cx­‹‡7,,¬„×ÕÂBW �Wo<ÑE5‡ÑѨ?…çwl^�Înž:ƒ³¤ø3øî‹%TóÚõð뇻E…ˆÞ‰‚|V,˜�Qã'cؘçµÊè»…û©YŸ¹¥Ξ:Š‚|.&ÅcɼWE]x‚¦"ù]!l€y!¯¢µmÅó²I$ÌY<k–nAÎÕ›ðéç�‚»z·Bù]\8 q©ÈÎRõŒëÚ­œŸp€O/7˜š=^áù î")á2ÎÅþƒë×Uí;´·…kG¸¹wBG‡v:Ûý},àêê[) Š��˜†ÃGbaeÑ]:;ÂÝÍNí3³rp!%>++ 8´·Å˜aýÐÎFÿû6EñœŒ»€Ôô«È¼–‹ü»pjo ¿înèÖÙ ¶e>|»që’/gàÔùdá¹C'K‡rî­ú€/êÑsíZKáùD'ܸuIiȾy Ýœ;!¿Põá†E‹æèãᎊ$\NGÎôïî3SS$\NÂ6øî½·aVIï|Ï'\ðʘ‘ø1òOÀñ„$��Ûýâb�OÀ‰„Ddfg#¿°Ý»vE7gxºº¢S‡0¶Ü[·ðÏåË8�pW³¯ÃÚÜÚÛÃÕÙ½{øÀÔ€‘gâq÷Þ}ª¼ùFn.Æ=ýŒÖïdE±gÎÅáRzšðÜ‘cGЮm;&èÛ§/à⥋¸õhÕÕ€>ýtž/+ë*R.&ãÒ¥‹Hþ' ì;ÂÒÒÞÞ=Ñ­›,-­Ëµ).VàìÙÓLÐÃǦ¦f¸•w—/_ÄùøXü“’€®n^hg×#ÇLhÒ=‰Œ…�[RØ×«·?Öý°±ÆÇ¡ª)*¸+WvmanÙRxív^¾VØ6#x $’Ò)ílÑÅÃÎú°{ûÁªnY7anÝo~4MrêìÚý‡úaÝg?!5)Eù÷�›�{[´¶±Fkk\8—*Ô­oHkCs&¥tVÏ..õn«K?îý 2ya¹ÐkL¿>Xõ‹jþ¿s©iðÔý&uç‘ÒÀÍϽ‹°½tci�9_7W|9çuáÚ*•8/ôŒûâçpl^$~Ð@T—ZÛØÂÒZ*„P±'b`kßý�5 Ú¦³'˜‹«;Î�zºMz³Ü0ؤø3¸˜@5LVsQ…acžÇѨ?…P,"ì‡r=ö4C³²íÇMz›×‰Ø1؆--„^rÅ …VØV¶í˜‰/#rÇOBhw4j| *9{´´¾ÏÏJÃ65‰D‚·–½¢êUa%Ó²ã.bõò­åž¿–‘ @5ÿÛÂO^ƒkWG�íãÏ^Ćõ;Q�¯=ü2+3'Ž'^ž6Æõ)×vÍ·Û' �§‡ >Zò½Öë?øê³·àèС›#±gÿq�“ä"!é2öì?†oV¼'»rçÈÈÊÁ¢��_¦¾Ì¬ÄœŒÌŸñ"õñ^K¾œ�Ͽߦµÿ§ÿ-}¬ÜVüÔÛ6ÖVxQã÷ʇ¯Nƶ}‡�þèƒÏýk>­p*‹…ÿý2y!¤Vê×%vÅ^Ÿ>fš›šô÷ÉäÃàêäˆî®�ut§“ðÅO[„E²Ô¢O�Aô©3€)όƋ#Gà1#½wŒ9y_þð_íï€ó)ÉØƒƒ°¶²Â’wçÁ±ƒƒÎöJ¥Ÿ¬ú Éʽvàp–¸6�VF-(,Äšï×ií¾+BØVn¢«”– Ü”J%¢ÿ…Í[6i=ŸœŸ8yò,­­0gv0:»vÕÚ§° ÿýN5Òæ­w?À½{wñßï¾ÖÚçô Õ÷6öÌq,\ü9LMÙû™¨&¸™!ÿؘ™™ÁŒC7êT±â�0Çt÷ÓJbö�¶‡�{R+lS3·l‰ÃüpdÿiädÝDzêU­¹Ú Ño°ŸÎ6Î]J‡ºædÝԚ˭±ót®½¸dòB�^®‡Ù¨?!pÛ£3pK»ž-¼Qœ0¨¿¨%\Nzõ• ÛÕpÙ¡~=Qp÷Vý²i×r�p9�½Ü¨ÉY¸b­ÖJ¥{"°'" –ÖRøôî7O­UKëÊøÉ¯UkØeJâYøöˆÔ” 1Në5‰D‚þƒGjõêÓ¤T*…×ìËb‰cž{YÆzìð^!p‹Ú[º8PÙ° PÍ�7qÊ ä\¿Š‹IñØV®‡QEöo/ ]†N0îªá§ŽœÇ†¯Ã…ǃGùù³*ðHˆ»ˆSGU�ÙŠÀÛ § {í`!õŸL|õÙfáñ¸çÃÙ¹Z·¶Â?ÉW°k×aäá§M»QTtÆÖYÇÉS‰Ø~Ð7 ;º¸:bço‡„�lÙg0l°¿¶½0^5ó/¥½ä¿úîg¬^ñŽÖqsóî`Ϋ„ÇÝÝŸÀЪÞ^Ó¯"ò€êƒ»•ßÿŒ¢»÷1f°*ˆq ï͘„_ÿ<Œ+Yª÷ ^¯8(ÿà[Õ‡ü>nO@jiÛÖ­0iø |²AÊýyü4ÆëYõ]ó=͸ªîã Æ /�x †’H$ð÷ìÀ¤ÜßLI—ÓðÁêÒ0j꘧áêäi+$\JŶ=B&/Ä–ßw£ è.ÞxñyƒÏ«ÏQQø~[i`ùú¤É07W} ðèßHHIF¾\Ž·>Z„¯—} ÇÚïáå…XúÅçÈÌÊ‚µ•†=9.�:áò•+8p8 ùr9f¿�7gÌB?ÿXZX`ÎŒYˆ;ÇOªþö˜0v¼ÐÃÍ¿ïÞ…�»v,­­ðÌèñpìèÀ’±kׯ(È—cùò±ðƒOàZ&tS;°w7’“Uÿùõé�îÞ¾ø;& )�žËÎÊı#QôÔ¨ßg¢¦Œ�›±‰Üý¬©ö~+*,Âí¼|­çä²ÈnÉ‘—{û"¢…çÍ­[ W¿îZûÞ¸^:Q·£‹þ®êÞ½» s¼Énɵæj3„—¯îô\»uÒª±)±lÙÂ(ǹW¬¨r›Š†…ìáYî¹æ¦¦ðusElJªÞa¥1ç…í1ýü…mõB ôô0½½úz¸ºÛQqñ ܨɱ°´ÂÂkq4j�Ö�Ë‚|¢÷G"z$ÕðÈAßE箞µ>ÿ˜½ƒ£Þ9Ò*3qÊŒ _—H$°wp†¥È…01%±ô�Ú~º‡µ¶±Å²U�æÐ²( !s³¯ Ûeƒ>M^>þBЗ’xÞMsN%ªº"�žYöNÆû P©Tâ×K?$ó <3q�ð¸OÿîèÓ¿;6®Û…‚ü"ì; ¸)•J¬þ²4DY´ìu¸vu„ L€ cÇvððÄ{Á«Q�_„ˆQxzT˜éÖš•• [Ì�ý;ªz©�€¯¿ý?�üü"l�8ˆ~ÝôÒX[ª¦+™0æI, Ùˆ„¤ËÈÌÊ…¼ Hx 6‡—^ßä±Oáùу ‘H`<ÙÇc‡À²o~Ä•¬¬Ûú†öë…æ¦�£]›VhצN�O·Aþ>¥QM™?�Š|:÷Uø{º ÷ ³C鸻�žÔ¸Eþ]º’ì³U¿ƒò K¿ïÎì�6Já›°Ÿ…íUï̓Ç.�.É�Úc`/_ÌX² 2y!~�:„iãž­tkEÅÅZaÛgï/€[gW!÷àß1'ObÓö_�/—cãÏ?cið{ZíßùèäËå°¶²Â—Ë–ÃêÑïî^Þ÷ôÌ|w.òår¬þ~:vp@ÇÑÏ_\ª·} maÞ»Šh…mŸ~ü%,--}ÛMàêÚîîžX¾|`óæðÉ'_êû °gÏQŒ?Dg=¯=‹ŽµçzëÙÃMV ASFÃÊ¢4P“H$èÖ¥’.²oܷܼ;8r"0 �7^|ö©rQ‹m›V˜=u,æ-Wõø:q. ƒü}PÎìàïé¦õ\sSSŒÜQG‘~-9·îÀ¾Ì|q•J„Rõbôus…Ô¼ܱ;Ù·ƒ1$]NÕG+Á�(„mš¬-,°è�xç3Õô.þÂäÑOWûœÿþ[Ø~÷µ×áÞ¹s¹¿ãú÷Ajz:öü )ɸy+OzúÜYäËU¿W_~áEXYZjµ•H$˜úÂd¬~4„ôtÜtìPµ‘1eý¶»tøéÜÙï>ZÍT›«kW<5tþ:°ײ2‘šú\»¸é<Þ “§¡�M[­ç:8”þ÷R�/Gq±�›6¯QÝDM7��=ƒ­[6!+#SçëÇŽ”¾YžþúL >’C=ªÈܺ\ݜѩ³Ú;µÓ9œS©üWØvu3¼7ÑÍì[UªÅ§�G…a^SâÒ¾t.“k7«vëB'{ýŸÔkÎÉVvX©æÐ‹WÊ ±È/,]°#øÛľD¢ÃÂÒ �CG#pèh(•JÜÈÎBvVìþUè¶'" 6¶ö®FZž=üjÔþv^.Öµ´Ü Ua×Þð?Ô”J¥Öã�Þž^+÷…š®bÅaÛg`ÅÊïâŠÿÐ1hîÑnmÚ–†=â/ Ûý‡ôÔ{Ü.îNÂvrRš¬Ý¼Yú�–¯ŸþÜÜ: ÛÙ×õ¯éäXþ¸.�Kÿ{´¶6‡•¥y¹OÝÛÙ¶¶oÞ’ÁÝUUoÊåÒß~ÞºƒpéØ^Ø>u>¥Ú�Ûkãu÷PÕ¯7"¢T�Úþ“g0­Ì‚TÉWJëÔ\¬*)=CØvlgœž�¹·K¿g}õÏ]JçQ˺q£FçLI+ý9óî¦ÿç¤_¯^ØsP5DøŸË—…Àm×Þ=Â>ÝÝ=t¶ èÕ½zm¾¹kׯ—Þ ýÂøõ À_T‹Zܾ�@÷ÏYG��Eüúôær+,�£µ 7¢êbàfd†öpû'%Ÿ~¼Äàãnüïz\ü'sßå$êºøôñÀÔÙãÅ.ƒ ÔJã¹ÌÜš½aªkÍ$LÔᇎ"6%•Ja8…æpÒÁ¾=´Ú¥eW½ÞÁÓñXô²Ø—LToH$´wpB{'xùøcɼW…!§;·m¨µÀ­&vlù^ ¨†§Úwp‚¹¥œ\T¾fx¨)/7»Zç¼w·¨Zí2Ò.ÖË{Hõ�¹UéÂS7®Þ¬pßð {{$±Â}¾ßõ±°]PPÚ{îâ… \ËÌU …|D½ØÂÝ¢ûÂs9�Ùå‹W…m+k èc¦1Ú¡ Pw�=[Õ~¼Áèí¥óù®�u/æPTTú\Nî-DŸ8§7ˆTË|´ÂjutwÕýa²K{8w°CúµìŠ9^.p‹Š‹¶Ý;•^‹‡³Si]7ª_—¦”+W„í6ÖÖz÷ÓBzþŸjtÎÌìÒ߯ñT«¾–Â�WÓ¼q³ô 5~·ffe ÛV°NmêŽÆšò'9Yõß‘¥µU…�0¤ÒÒû®ž† Õ?TÔ剮BàFD5ÃÀM …_}¶BxüܤÉððòF«V­ÑºMH$ÈåP(8{Ø‹¬ŒL;ƒþŸ„�¯žùUšên5¤Ùë,çÚMƒÛµµoS+õtëQʼná Ía qÓ´B+CT4÷Z]ÜÓ[f‘|%S˜gM=œT×Ћž]\pðt<à�/>Ö94ƒˆ gjf†É¯ÎÅw_, šãMsþ3C”í flÅ …¶YZK1ùÕ¹:çHK:wZgàfc[Ú³F¡¸CiÞKk)>ýv«Ám‰ ajö8Ì­ÍQ”_„ì+Æ ]ÔRKן7ì©r{ÍÀÎRcEúŠ$%¦é|ÞÁ¡ò!“�Ÿ¨Ú0AÍna;ÿ2¨�z¾¶ê¨èýÒäáƒðñ†0Èä…H¸|^O¨zýi' =\ë=šu-¼‘iÌ gUÉñ;u°Ç•kÙåV2­ªÌ¬Òy.Ë®RªÏÅË—1r°á‹DÔ–n]»¼ï¥K1ä©‘åžw® ‡\Ks¾G%2nÆf@è{ê$ò}"¿ìÓtus/w KK+XZZaøÈÑxjØH¬Xúâ¶ezôä„ÆÆæê¡Z%4'ë&”Êõý”Ë „mÛV†€ja*¥î%&“bóÞƒZÃ*r¿¸-G+ sÌ{qB•ˆ»˜V¥ýuñzÂR+ Èä…šÃIŸ<°\k�y’Å ƒOGÔd+¸v5ÖÒÖ:ç%+Ëûºxx s¹Èe:·b…Bç ikõz®]M¶û©wA‚B=ó«9w.”�•Q¥…,­¥(È— =‰ŒÍµ»Îƨæ'-V<Ðê1¦i«#ðÌKªùÑ4{mmùöw\LH/·�Æb ~ýÕÃUË÷pÓÔ¹KièU(o8ï·º»?+Kó §Ë7líÊêéç]:òp\¼¸i'á¯ý{K3À‹:}‹_5nOüÇ›Uüç©•…%€êõþÕg@ïÞ*ÿ3®ËOõ¼U¡¨Æâ`D$>nFTÃ:™åä¨þ‘þôtqs¯´Íc ^ÿÏ›˜óút½ó½QÍ´kßVX8!3íšÎ¹Þ þÔa[ÚÆð^@é ¤òÊȡ§§¡»÷aìÀ¾•öúz¨Tâýï6B&/„L^ˆØ. �›æ¼pÇ“0Ô¯ü š¡XM�С»÷!üÐQÌ™ðŒÖpRÍyÞÔºurD8T×›˜~vmªØ5vIñg„Þj–ÖR,ùbC¥«�ÞÎËÂ6Kk)ÚÙ—Îïc®¼ÝÊ»¡3¬ºx!¾V¯éì©Ò!9Ý}*½†²¬[•ö¤>qä/½Ã=—/˜ +),,¬0uæ»�H$puóN¸�—kP€IT�º:�[â©Ðk î¡•V-abeRn˜¤…µîÞg¾ý={TõojЛã!yL¢sH©‰ÖãÒ×Û;Ø"+SÕëNQA¨ÉÁ±îþûè`Wº€Ö›A`Û¦•Ƶ”ŽgÔ¾¾Ú©Esñ„𨣘=a þOÒ ;cT¿»\:ØÁ®M«r§â烃§U«(§]φKûöŸ3¿°ŠâÿÁ¶Mk�¯çÉòaÛFÿ(’ø”š %U³¶²@þ£÷„ó^W­&]“rCJK·U�ÕÛýzûãïS' ;™˜™–þ{xíú5ƒÛÙÙþ½!"ãã î"¸þè—d÷†O~Ú¶mé�›7�ÛuŸ€�ÃûÛûvÖZHA­¨à.ŽìW­$kçÐVo(glæ–-„íŒKY58Rý"µ0GÐèáÂã)¯DÂåt½û?T*±yïAa…P_7WLQº¢˜½Æ7}½Ø4C±šÒüÄ7ùJ¦0œt þ:‡Çöï^ú)òêðßq¿¸Xçq�'&£ïŒ·±8ô'ƒV2%j,:w-�x½ _†m¡«+m³þ«¥ÂvÿÁÚ ©çG€K)åÿÛW*•8õg­^“›gé¿óúj+s�šCG% ‡� Z•5-5¹Ü1ÒR“‘�•‰‹Iñ°µï ܃O•®ÞùëOz‡ÏnZ» þóvlùÅ ö  ÃuëU:ÆÎÐýµ2D[v» ÊmžÐìíV 5UÍzÚ×]àfg[&Ý–UýúŒmPOoaûLòEÜ/.¦À˜ù¬îU@ÂæÝ ߃¯Òßÿ÷*ø=¤ù= ì]³?^]K{+ô¼'«HW�ÞnÕi_îîªû”•uµÂý4ÿ±µ5ÎJ²DT= ÜŒ¨ÄÀ¯ê´)©fNëf˜Ö6Öðé£ DR“2ð}Ȥ§^E±ânçå#9þ>[¸NØâ´QÕ=U•uõ,ý}×¶}ˆ;žˆ¸ã‰Z+„5T/>—ªži2y!ÞYƒÅ¡?áÀé8äܺ#|OLÆô_"t÷>€ÔÊ_Îy]+Øjnjªu¬UÛw"íºª7iÂåtLýx%BwïƒÔÊ8c9íÚ´ηð¿? =çÆôó×¹sSS!`”É 1äÍ÷±ñ�ýBðv¿¸Ç“…Ló ïÁFZµ^”D ™©™&N�)<Ž=ƒÕŸ}€è»q=+CøCëv^.Î�Ʀµ+µæ=ë?Xû÷²æpÌý‘Û}`7Š +øs×6¼ùò˜Z¿&ÍñØá½¸�Wú�Ùõ¬ |öá\LŠB58{\냆?+lµ,«?û·ór¡T*‘–šŒ_6}+¼>xÄ8aÛÅÕöŽÂ½üpîË8söb…Ç(�—ÔÚj¬xzî¬þÞP—/—~ˆiieØ\oÕÕ²Eé*�m[K…í?¢ŽWØ.·>xó|¢“ðÞè׃шO-ý⇫‹Î6OùùÂ¥ƒjŽÉôkÙøët¬Açzoõ:­‘êÌ5îϱsñzÛÿ£±¸‚•yÍÞÏYY”¶OºXñÏ™¼°|0Ú©céB.¦èl›y- §½„禽„MÛ6ר^è Ñ“°¢Ð-.î´°Ý¢EíþlQÅ8¤´¶éH¼, s9î,zøöéŒf¯¶Ö­Ú0I«“gŽœ=‘„Ô¤ ¤&mҹߔYãê¬wtt.�4»(ÿ¶¬Û X´j.L &QŸ575ÅÆ…ïbMøïÂðÒƒ§ã…OVu‘ZY`Ë¢ù:{‘Í{qÞY?tT8¦Ú„AýÑ­“#–†gñ1ýú`Õ/;…7�R+ ¸´·×»ÿÔC�™{C¸¾ÐÝû„Pó ¨ÔÊK‚¦Ti! ¢Æ pèhÀŽÍë¨zuén©fi-ŸI¯–›»­µ�-|û ¥›× ÇU{õÍ…øjYp­]�©™‡�AôþHdge⣷§ÃÞÁQ+(|cÞxx÷BjòydgebODöD„ Ï·¶±ÅÄ©3µîÉGoO/w®Qã'— ÌÞ\ð)VºÙY™(È—áÇu!عmhÍíÖÅÃÃÆ<_k÷�¯þ3FVúç¶ÃHKÎÄ+ïN€E‹œ>’€ˆ�û„¹Ú,­µ§“ðö+ Ë÷„Ç {Ï.°i[~†?vÆà·í‡`imŽàEÓàÐQÕ“Ç£û°´6GA~~ß ÿ¯r‹'(•JDìˆ�Ù¯Vï“Cû¶Â¶»«l‘™•‹#'âñô tsu*׿ð‰³XùýÏ�ZYàíéÑÛËM籓.]�gçN5ªoêÈ!øæç]ˆM¹ Ù£[' ê_á‚ ï¼8³C¾|¼a3’¯d`Ö„±:ß»(•JlÝ»gSTÁ–�[LY:w¯¯»›ð^(2æžk ‹rÇØüûÂã±O ®Ñ5?ÿôhì>¨úøig8ìíѶ�M¹ý¾Þð_=u ްtÞ{°´°¸:»ÀÚÊ ùr9Öm żÙsе³ö”"»ö”®P=þéguÖq6þ,†1lãÃFáÀ_ªŸ·nû óç-,·ZiA�Q‡÷P­fêáѽF÷‰ˆj†=ÜŒÉÀîeO<úe|üï£(�Ë+l^ÕPºÿ®U 9qprÄc {¸05ý?øôñ€OtêìPããI$�aêìñx}Þ$øôñ€¹uéPNW' æ‡OÖÍCÏÏrm5k);·›úyuºÊ®¥l{sË–X´j®Öq|úxÀÔôÿÄþE3‰o??›? Æ?o½ûI­,°8è%üöéb½s½y=áŒÅA/él4z8æLxƨµ� ðÓzüʈŠW®j&‘`iÐËåjT‡m.ì4z8¶,šÏUL©É :Ÿ­Û†7æ-Ao½ûÙ;8â•YÁøä›ŸôÎm6uæ»ðíS~“.Þx磸¸ºÃÒZŠÚ4fâ˘8u¦ÐÛL¶ùö(„jðʬùZµÜ¿WÚs'pèh¼óQˆÎZ-­¥xeV°ÎÀÌÂÒ ï²F«�æB ]<¼1qêLÌ^Vî�6"C˜š=Ž·>_ŒOÇ‚)+±éËpÄì9…´”«HK¹Š31 ØøÕ|üÖZlú*\Û|û{â“ïÞ*wÌ_UõX-È/Âûo|…ï¿þ—þÉ„R©ÄµÌø}Ç!ü¶ý w€‡¶ª^S“^)´_0o5²®Þ€BñJ¥y7eXùé�Âʤ}¼`cS»¿Êšõòxa{þòu˜õá—HNÍäæÝAäÁcXùýÏÇö¶èÙM{ûnO8 Û«·îÄ�[wp£½áFj¼ŸI»¦ZU_�}5¯'œ1}ÌáqDÔ¼¶<«·‡ãàéX¤_ÏÆÉÄ Øu8ßÿ?Fª†ðK­,ðùÜÙZ¿s$ fNœ@õžèõ¥#érîC©TâÆ­[Xðõaþ¶À޽Ю‚yÞ aea�IϨÞff]ÃkïÍÇÿ]�Ü[· T*‘q- ?l ÃÑS§}zú>Z°¡´æ—Ÿ�/—ãßàëï×âæ­<üs)·mÁ±“'Ï=;––¥mÛ´.­}çîßpóVònåU:,Û¦M[ôñWÍšœœˆ•_¬@^ÞM(•J+�••‰½‹‚|Õß—/¾ð ·‰Œ=ÜŒÌ�€Ë³{ª7½óÞš�qŸGŸ¾`i¥´(•J\N½ˆð_Â�”üÔÎÐ4˜[¶ÄÔÙãk~ 2ܽ;ÃÝ[µTv±â�A½È*ªÅ�+»–Ö6Öµr­õ‰K{{, zKƒ^ÆýâbäÞE^~>l¬­amѲÂOY5 õë‰þÝ=�_xWrnÀÍ©£Vx5Ô¯§Îìڴ±ïWU©ææ¦¦Un£Yƒæuvvhoð55v–Vððîï^(V(P¤cOC�H$˜6{>&L™�Å äËn£CGg­ž`Ÿ~«»Çk¯€@½A^Uö353CàÐÑ:…rÈehgïPî� öNzkTCD?ýv+Š ÜÊ»Åý{­æ*‘H0qÊ Lœ2C8?�5U‡³{G,ß2›¿ ÇÅxÕ\¬qGwDÿ¼©–Öæ˜2çYxú¸ê\…sà°^¸[t‘¿¨BµÓGpúhB¹ýܽ\ðÂËåß÷îã�ÜœÛØõk ò‹°pÞ�uô ðÂk¯�C]swu»o¼ˆ/¿S…j™Y¹^¾®Ü~R+ ,™;­Ü«^]J‡z^ÉÊÁKóW†~Y­zš›šbˆŸ·Ðߥƒ]…=öÕ^yz8ú÷ðÂ;_«†Š¦_ËFúµlGtî/µ²@èbU¯¬²3 îÝ Ù7oâ§È=�É ñöç_è<†·[W¼=uŠQ¾Ï�…‚»wñÇÁƒ€£§N ›ÖývsÇócž-÷|ß^½qãf.¶ÿ¶ ð÷É“øûdù…ž>R뱓ÆpÔ¹oΛ XýÅjØèèe§)hú È ‘œœˆääD¼3ï?:÷{iJüü@Dâbà&K++üçí`|»*D5Äã‡õøñÕPKk)¬¬-u®Fêáå�!ÃFVõtT }ÈfCÕÜÔÍMM«½’gMÛ7”ë$j LÍÌj<·˜j¸©•è+uZXZ•úZ�û¡kÅÕº:?‘.V-ñŸe/ãBl*RÎ]Æ�Ì<\L(¿R/g ñAw¿®ªÕCõ|R-‘H0ú¹'áæéŒÃûNáôÑÒðÎÒÚ~ððî �îO¨Â¨’òíÇNgçö8v$'�k‡už.Ø}ûz×ÉýùçR&ÚÙhÿ[اÜŸpÄO;ö!ñŸË�=êõý½Ñ»»úøxÀÌ´ü}êÔÁ_-˜��×mF÷®.†”P©¡½}…Àmt¿>·sio�_>ù?…¤´tœ½x©ÜŠð>n]ðÊè‘ðxÂ:ÖG¦Œ…n]ñÛáD—™ÎÛ­+†õ À Þ½g�D"Áë/N‚O7DŸ<�#a›£CxtqCxwóÐÛþ¹1cannŽÓgÏ"1ù‚Öë#žŠI㟃©©ö¿af¦fXóÅ7øàã�àáæþèY˜>^ù¯f¦fxoÞ<|qqg�œ¬lûû÷ÅÓO�…ƒƒS£éDÔP˜”””ð¿E#èûä(Ì~;}ÜæØ‘h¬]bо}úÄk³Þ„YUÿè(&�…ÅcèÃkÛ�ƒÑXº<_o],v) Êí¼||üö7ÿy#ìÚÕÞ–97r1áÅé_¾ˆaQ=ÕwÆÛ î¿{j¸-[‰0mö|±K!mZ»±'bpìð±K!Ôï­>ßû‘*ó(Qgÿ[Rš‡¨&åžÓÌLL`¢§P$¿‹Š�¶±‚ä1I™vÚ5h¶+>+àAñÿT ”;Ÿ‰žv¥ î%€•¥y¹:ËÖ »N=íJkÐ}•ï£T*q÷®BU_‰¾k©à{UæøUý^-Û°YÜþZýZhôº/Ñ8‹Ö¶Ié‘5ÿ üŸò_äÉòa#µ~Ô;O£­IùýË>.y´ÿýâb(üÖ–zêÐß¶´¾*ìÈ‹ `ú¸)LMM okRZÛÍ[y°°°€™©YÅíM*ª£‚ºMÊï3ï&,-­`jjf¼s™T¾¿Îö徿&˜õRÃû[”ÈXØÃ͘ª8iZßþ�èÙË{"w"ûú5\ËÊz¶YZKÑÍÓ ––V9úYØ´µ-=Q=gaÕ°j)=5ajöx�FX> ²ê+‰D"„�u-çÖ!lâç]ã).šI$°kÓ@ÍnysSÓGÁUÝQÏÓVݺ۶±©ó3›¶¨°ë ‰†�[Ñ÷‹×ÔÌ ãž›TíöDDDDDDÕ‘_X„ëB…ÇS*YŠˆˆ ÇÀ͈ûª DDDDDÔ°Ý/.ÆöÑø-æ¸Ö|k+缪Z,�зZ¤T*qçö-ª‰ŠÕó¯) È«}\axiü·‘ˆˆˆˆˆ*’_x›"÷k=7}Ì0ôñt¯æ‰ˆHnF¦zݾ} oÏœ˜õV0-¨wú$Ö}mØb ºl�àdÄDDDDDTuÍMÇ`?oáñ¸Àþðz¢“Øe5: ÜŒ­D϶®ÇDDDDDDuÈÚ½6Uk•R""2>nFTv·ÇMÍàß  µM[áµÖ6m…ç«{""""""""ªŸ¸Õ"K++Ì~k~¹ç]»ºÃµ+çH """""""jŒ¸‰@½h‚æB †´‰;sÐ?PìK """"""""=»€Æ¤¤Ä°¯¸Ó'ñÎÓwú¤Ám är¬ÿ:ë¿)»jèWv;/_칬 NÏw¯X!ö%“²Â"±K ¢&JÚJ*v DDDDõ·Bqÿ¾Ø%Ô)O7u 5t²[r€�M›Z=�ºgæ¹Ô4±/™tP?PúßQmk%µBjJ‚Øe�È åðñö» """¢z�CJ�L_‡²¼›¹Âvî�láÿoj<¯Ï±˜(ìÚVé9u`êœ];Š]Nƒ‘—{ÐL"©ÕóH­­àÒÉ‘ŸÀ„'û‹}ÙTÆ±Ä `ð�u¢šêÝËá;#q=+íœÄ.‡D T*q1)ý¦M»Ò£]»¶€;¹ùhmk-v9DÔ+8†š6nudÞ¬éåžÛµ=L+H3„¥uÓªÑL"Á„q£±ïPž™4  ;cV¦Xñû"¢TGìŒ=«V¯‡¬°R s±/Ÿ4Dþ}.�!µ¶»j"zt÷œ�=ÎÀ­‰JI< ðõñ»ÒáC{ÀÍ«y ܈¨NÜÊ»€£.¨ébŠQGüû 4JX¶hù—Ïû¦þj¨ÆŒŽ¢ü{ø>d ”ÊÅ.§^S*ÿEè×?F \'ç5ü)Àܯ×á¡R)ö- G6þ±i×r0ï�ÿˆ] 5!Í››aÈ �؆´Ôd±Ë¡:VX G؆oàÜÉ^\…½¾R“Çé ˆ¨n\JIPûÓÝÕWìáfD%ÐpÍœ;€ª[íÞ?vâ·íaèÝo ¼{útì�`ßÞ’Z*XŸ¸8;añÁXº<EÅð±Å.©^**¸‹Í둚”�·ßœ »v¶urÞæÍÍðÝš¼1'ï®ù/¾œóz­e%ý*•øøÇ­8x:Æ�†»[±K¢&fÑÂw!Ë—ã«eÁXøéZötk"ÒR“ñÕ²`H[I±ú«OÅ.‡*1aÜh„ïÜ�þcýѪ­µØåQ#VX ǯ›×÷§7ÿF &‹�[353ƒm;{€wO?ôé(vIõÚÐ!�¸–��ÐMa¸™} ýžêÅ9Ý)*¸‹s'/`d Šòïá»5!uÞ³ÀËÃ!Ÿ.Að‚%˜¾âKÌ{qÜ;9òÕ:t¿¸çRÓ°þ·?�v-AÓ&cúÔIb—EMP3‰KÍÇ” ÙX±`6F�ŸŒþƒGÁÂ’C›¥R‰ÙY8{{"ÂàÜÉ«¿ú”ÃØ€9³^CTôü¸ôÌ]ý:šqÊ"ª%×…–|8_ìRˆDcRRÒ�Ö}Ÿ…×ç +(,�ÃÂÒ ¦U˜ÔüÄßÑPå�nÚÄQXüA0†©Z»ú$|×nü¸õgÈîÈ…ç|úxˆ]–hΞH¶{öìŽóæÖYÏ6]ŒÆêïþ«õýñus…µE QïScw1 2y!À¥“#æ½óç"ÑÉòåøzÍ÷8x(FxÎÞÁöœÄ.�Œ ûZ²³2…ÇÆ�ÁœY¯òƒ–$-=Sƒf£]§¶˜öÑ he«šòÄJý¿ÆcÀ¤Üs&Ç3�‰žvšÏ™èh§y,=íÔû˜èi§~l¢§]Uê4ÑÓN»ýušTp}†îóh«Dßµ˜è?v™ãó{U¢±‡Ö¶Ié‘K´ö7ÑßÖ¤üþ·7�Æm)SG%mMª¸uÏe¢½íMªpÏ4ÛšTqÿêžË¤òýu¶7 º.“âüß D5ÅÀÍHª¸UGA�sƒ&¡w¿�ÂðTC5†À P ™;}æ,ŠŠîâBÊEäËå5?heme…Þ½|У»'š7¯?+Q&$%ãÆ�›¸–��Ì«× n÷àÁ<þøãb—ß õõ÷C/ßìYBõŽ,_Ž3±çPPXˆÄ )µz®à±Çš¡Y3öÖ© Ž;À×Çîn]´5PÇOžÁŠ�U�Ý‘cèK�x»Ú¶o sË– ܸ1p«ê¹¸¡°@ŽÜב•™Ží›¿€Fñ÷'QMqH©1•(Ñÿ’>·næVxØË©)ø;ú/ÕƒöB5ÑL"A€/à/ïzÊËýZ=¬æÎû/^À?܈©µ•ð»zÂØÑµz®ÐŸÂÐJj�±cF‰}ÙD B€/ìØºŸ}ñ l�Æ�­Ñb—DD�„oOo,ùp>? &7£34 S*•ˆþëO„m\/vÉD¢º_�ظx$§\äpH"ª–_#"ѶMknDUм¹–.zK½‡œ¹HLªÝž¨Ô°í?xÆ<)vT�yz¸ÁƦ ?@'ÒÀÀM$Ö|‰SÇcªÔæ™ç&cøÓãt¾ÖD;½Q#pî¼j¹ðƒ‡b¸Q•ݑ壨°E…EPQ�U6O[ÌßÇÅ.‘ˆê1}ÃIÕ8¬”ˆ¨æ.]Ö=ýG�¼PìÒˆˆn"153ÃëoÎÇG+×âÉaO ½ÑZÛØ"hN0,­¥ZûÛ;:â?ï-�Kw.š@ ž¾á¤j;vFŠ]"Õc•­DÊa¥DD5£o8©ZÙÕK‰ˆ¨¼fbÐØT5àjßÑ©Üs~}á×7·òr‘žš7ϰ°´ªÞ ˆê™Š†“ª©‡•º8;‰].ÕC»"ÿ¬tŸˆßþ@à€¾b—JDÔ éNª¾k7^˜8Vì2‰ˆê5nÆdä.emÚØ¢MÛÒc5• 'U‹ùû87"Ò)==³Ò}8¬”ˆ¨úô 'U+»z)•Ç!¥FTÕ¡žUùR(8u,§ŽEsH)5h• 'U‹ØÅa¥DT^ô‘c()©ü_7+%"ªžÊ†“ªqX)QŸ‰àô±hÌ|qæ¿ñ äµ),”cã·!ØømˆØåU›!ÃIÕòó¹Z)•W•Hÿ20à'"¢R• 'U ßµ[ìR‰ˆê5nu@_¯³‚|‚gLÂå‹ÉUê¥ÆnÔP:œT�«•QYU*zìÄ)±Ë%"jp.§_1h?+%"ª7#*)ÑýUY öÅ’`ì‰ØfxrÆÄ�(C‡“ û>"vÉDT�:œTí"#3K첉ˆŒìœ(ù×ðß³VJD¤7Ù;8ÂÒZ ø#< ¡ß®„R©¬òq˜·QCP•á¤j™Y�å6욈¿ª 'UûaÓ±Ë&"j0þ»qs•öç°R""ý¸YU:œÙ;8aéWÐÅÓ{<+ÎAA�¼J܈‚ª'U‹b/7"z¤:+�?qZ첉ˆŒƒ‡ªö¾‹ÃJ‰ˆôk&vM�©™þ3"Â6 z_$²³2±üýÙ˜óþ'hßÑIìòˆŒÆËÃÇï)÷|Î�\Lxq:Œ¡CÅ.“ˆê±¿éîá6ö…W»~ùQ쉈¬ª'UKHL†—§»ØåÕ;ìáfDÕ™V­Àc &N��WfP-¦°üýÙ8},ºòn%•UäÈß'`jöx¹¯Ç&&&xüñÇu¾~ä¹""Ò…=ÜŒ­ª—Æþ½ѪM[løf òeøqmòndcØ3Ï—O܈ˆˆˆˆˆŒä…‰cñÂıåž?}‹–~†E ÞÁ Àþb—IDÔ`°‡[=ãâꎅŸ®…½ƒ#`ODÖ®ü2Ùma.RJDDDDDDDT1p3¢ª†`ú^3·´Â{Ë× ‹‡7àbRýâ¬þb…Ø%Q 1p«Eæ–V˜ò†juÑN�Ý„ç;uvž'¢º÷P©Äšu? |çn ñóÆ¢W^â'ÖTcÍMMàé?÷.xwͼ` ¾[Â!�ˆ:¤ïâá�ÙÁË áï ¢FM"‘ÀÅÕ.®î°µï š³Ë˜>•¡[Stðp Ì­[À»w7±K¡FÌܲ%†�ˆˆÍ{qÿ¾‚+˜6p Üj‘©©zj¬Fªî˜¦¹Bu°ƒ5F÷îݯ³s:|á;w#hôpLz˜Ø—N�L3‰_ÎyÏ.XŠ…‹?ÁŽ­ùf©–ýïðÿ÷x­ž#!)¡›Â0jüd ó<Ã6¢&fäØI¸|ñB7…a`¿Î×ÙŠ> W7gÎÙFµ®‡7DlÞ‹sç9Z¢�ão #+)óED³¶R Å:w>±ÎιuÛ¯pé`ǰ�jM3‰[͇ìŽ{öý%v9�žìNõ"2TÈWßÂÒZŠ‘c'1l#j¢f/ƒ¥µ߬ûAìRH²;rtëá*vÔ˜[¶ü“zIìR¨†¸Õ¥ã•ðETŸ5onߞވܳ·NΗs#iW21ïÅ b_:5rR s¸t°CäîºùÙ¦Ú#Ë—#ýJ&†�y^ìRˆHD‰ý�D\\<îßWˆ]5b®N\½à�R#*�vÀUT GDØ÷F?ÏËoÌûR‰ŒjÔð§°tyrnäÖúj<ê¡«6ÖÖb_65cúõÁª_vB–/‡Ôšë7T …êkÏ~b—BD"ëî€=a¸”–Î9:‰¨Ö˜s!·F��[-zP¬@ü‰£—�56ýûúCÚJŠ×f¿‹-¡kk5˜HKÏX[´û²© èëÙ «~Ùù(°aàÖP%&¥7å\|DM];{À�7¸Q…8¤Ôˆt�ú¬«óTôETß5on†oB>�ìŽ K>Y‰‡JeíŸÓÔTìË&¢ÆÂ’¡)QSÇ9©1;zà46¯�Àæµ(*¸kp»¢‚»B»ôÔ«b_†^é©W«u}DÕÅnµ¨•�-¾Ú¼Gì2ˆg'|·&oÌ ÆôsðÒ Ï¡_®îHDDDD�BQÁ]ìܲOxìÛ× îÞ� nŸžzÿuFxø°8è% õë)öí jÐnçå⣷§^™Œ^�5>æ™ãÑøq]ˆQ�Y6­]‰ØGóê.[µ­ëøÃ˪ž¿°@ŽŪÅ:Ì-¬`jVÿz{ßÎËEä¯? ×eïàˆ>]'vYD JQþ=dgåÂÞ¡òßIEwµÂ¶ºvýê lY·>}<Ên­m¬ñõÖÅ•ÃΡ-ì:´Õz.çÚM­ëÚ�}Ñðéã�©³ÇõzxÖZVTp[ÖíÎC0pkîäå"öX %ç�¡&ÂÅÙ .ÎN€ cGí¸5íáÖB ûÅÅøù¯hì¶ö0xĸz®Pí+V(µw'ŽFý‰‚|™Î}|û Ä€§ž†‹«¸“õ+•J|±ô]­:³³2E­‰¨¡JˆýÇ Àíï¨XQ뼞q£ÆÇ2ºŸÞ0êv^>öü%ô†;{"©ÊCnÅt5=[ì¨bàfDUQz%5Gý�ó' ¸QÍ,þ Xk¸j]?°?úzzˆ}ôJ¸œŽ7BÖTºßÁÓñ8x:¾n®ørÎëh¦céUÛw"¿¨Kƒ^®V-Ö-±8è%€§s'±o Q­‰ÕXÑ|OD‡�Á áÏÖy/,OZj2¾ZVù°²Ø1ˆ=ƒ.Þ˜¼L´ üÏž:*„möŽèá×6¶ö¢ÔBÔP æ‡#ûOc_D4žÓIÅëþ¥~éêá„Ô¤Œ:¯÷Ê¥¬Z=~kkL�=�:; bó^Àîí+ ÜŠPTx¦¦ÿgÔùìԔʑ§ Òã_½ÂÀ�Êcà&’¿îÆo[ÖW©��ƒ#†ŒzމQæõ„3¼Ä.BYa‘VØæëæŠçD'»v°kÓ ÷‹‹q)ë:bÿ¹„Ðݪ cSRññ�[Ë…j•J„: ÕÜš›š6Ê„T;Ì[´»„JÙ;8bèèçm;!;+Cx-éÜi!x‹Þ‰èý‘XøéZ´wp»lªe·órµÂ6ß>ѫkß­mlQ¬PàÚÕt\¼�=a€‹IñؼþKL›=_”š“ΕλôÌóÓàáÝKÜ›Hu"ûF®Ø%4*Þ½»áÈ~ÕK™i×*œ-=õ*Šòï‡è Ü6¯�zˆU4Äó­—–€AÃ65� ¨zž©O™5=>[·M^ ?®[)vÉUÒªMÛš¤ :´ï7aÛÒZŠ©3ß…‡w/¡‡£©™\\Ý1rì$¼1o‰°oì‰ÈÅ.ví Ÿ<�&+kÕ”6W¯^»”FÅJj‰Ãü@ç*žšÔ¯Û9´…m{±K¯Ue{‘ÜÕzœžzÏûFgØ©IX¹`=Ž8�êÚ·+›÷ê 6ÿûÅ6¤§^û6QÁnFdhÀuæè_Âö‹3‚ááã�ÇMÍpöD4~þ>�#ŸƒOŸ@À•KÉØµù[ü¶u=ì]Щ³¸svQÍh.B ²Õ¼iù…ª76R+aˆfέ;HL¿‚ W2Ñ­“#Úµ’V:oÚC¥y29Ó¯àÚÍ[°lÙömZ =Õô99]Ø^ñú+:‡‰ªxº#hôpDŸ;�Nö¶¸÷hroõuÄœKöÕ ãÔçW?gfú8¤æÂ½Éʽ kkصi%\P~Á}íS2®âTò?phkË–-0¨§w…סy�À¥½\ÚÛWxªŸîÝ¿/v 5fai… Sf=ݲ³2QX ‡…Žù[•J%òïÜBú¥äåf£EK ´4·€sg7X·jcðPCÍÉù+k§>'/lÿç½O*üxx÷Bà°1HM>ûN(�Ë´îëíG+ÚëúþTt͵/,�ãæ�ëZßßÂÂÒ O¡¸/´+{¿•J%RÏâþ½»ÈH»ˆ–æ°±µG«6m ž‡Nógòe· j«®ûέ›H:w=ü`ïà„66í8Ob©ÿ�ùûÎKìru/·³'’ð|Ðh�+s+=¨ž¬ûžÿ㦠Ǩç =À\=œð|Ð3s ã÷.× ØÌ­[hpJå¿Ø¸z»ÐÛoøø@ôì sË–P*ÿEnvÖ}¾Eù÷±y/Ú;µ«ÒŠª°kÛ>å߃¹u Œ�4>]pýê ìÛyXàvlÚƒ÷>}CçýT½çÀÔôÿjûÛCõ7\¹¬ZqÑÜJ*kútêìŽÿ|ø>�ÿ*Ö-Æ;¯…]†—°‡Qýòõ¯:W)Í/¼+,ƾ|òòóËÍ¥ÕÍ ƒúãíçÇé<¾¬°s¿^‡´k9:_÷usÅ’ ):Ã#Yaé ©Y×+ ö¦?= ÓŸ¦õÜÑóIXºUë9õui^³ú¹!~Þxÿ¥0äÍ÷…}½»6­�'“ë] B³ý¢W^»kþ‹Ø”Ôr5nÝ…oÞš¥çz‹0åã•:†ùÏkðtoô d4æ-[ èÞ=±Ë0 K+Ø;8 З TU˜õíçê�XßÞÁo.ø´Ò€ âNÁŽÍª^÷•­2š’xß}±¤Â}+š‹ì�yKô=¬ìš*›³ìÏ]Û„á–e}¶n›ÞkÊ¿sKkåVª«€jEQu8£T*±6ä#\LŠ×:†æ|£ÆOư1ÏW{n5Ùí¼J‡Oœ2Cïkêkñí3PïpӲ׬ù}Ôl?)èM¼ójéP¨Wfkݵ f Ûk·î¶“âÏ?/ºòsª¹ ®&ß>1uæ»zïsô�ÝÂϵšæ÷©>¯¨[Ÿ!çF.ìÚq~Icqvísë(Ê¿‡´2uÎW–tö¢°í7ÀE…uûï�¹eKh¾‹2·0†bÖ†s'/Ûýûi½öWäQ­°møØÒ^áÉc°w°Åû+fáÃY_ÐÆ U”†ùá™IÄyõœ];bÖû/ CEs²n¢¨à®êÞ”¹?jõþPÃÂ!¥FV•!ž£_xUïÐOÍçÿÏÔ Sÿ³�xö8‡“5r¿DEcá Ú9ÄÏ[ëõðCG‘ ÑM-íz6žž·HÛ\:ØaˆŸ7†øyCje@5çÚ”�WBVXT®ý˜~}„íU¿ìÔyŽÊ´k%Õ:¡†²×¡öó_ÑÕ¾Wù…÷´Â6_7W­s§]ËÁ׿F”k—sëŽVØæÒÁA£‡Ã¥ƒ øÛ°ñ�ýÕ®‹ê–´•5nææá¡R)v)FáêÞ]ØVÜ×þÃêÌñh¬X0[¦ºxxcÔøÉ5~2ìMM‘�•‰÷gMÂu�9âôé3à)aûÀî_+ÜWs裗�¹×Ï�Â6Kk©ÖðXøî‹%(V(ʵKŠ?Sîš|û Ôj1)Î}YçÊMkWj…m¾}â•YÁðí3–ÖR¬X8æ„�w‹ ±sÛ½¯Ÿ=uT+lóí3§Î„¥ué {"Âp4êÏJÏ¥©‡_?­{”–š\¥öµ%jïÎrÏ©¿/š×¬~NóûU¬Ph…mêŸÓ.ÞÂsÙY™Xýé(uüw«T*ñç®mBØfïàˆÀac„ŸñØ1øpîË:ÆWö�Vئ®MóÜ?® ÁŽ-ß‹}‹s s¼6û]ÈòÅÊܘ¨C¥ÝÛê|ýàz–éê×X(•ÿ"îx"öG–†ã^¾]µöÙ-l?9¢�Îã˜[¶„«‡€Ò`¬ªü}t.báÓ§tá³yQUIM{¸[US.ûßÊÍ.÷¼½ƒª§É‰Câ©1“ľJ"ªEᇎBje�ÅA/ C"½ò~;r«~QýôÅÏáØ¼H»÷ÂÒ�¥=ËÊ®z¿¸ëÛƒðCG!“âë_#Ê-fÐÃÕEëñ!kð]ðœJ{ºiòzÂ^O8cqèOBO¾ŠMPï3aPÌ|v”Ö°QC¨ƒ¶!~Þ˜ùÌhaÈjÚõlÌýf=dòB<�·ž¯ÕËmýï»…°-hôp¡§ÞÔCp(.«Ã† ú϶m[dee#9å"¼<öÔ J¥Ñû#…ÇN.]´^Ó „Þù(DkhÝȱ“´zzˆüµÒIõMÍÌàÛg bOÄT8„µX¡Â&ß>uÉÛ±y=ìñ´ÿÀÉ¥ $ &½‰Gþ�Kÿ$jõrS*•ÛP: gÔøÉ9¶ô}Τ 7±-t5bOÄ  _†£Q{´^/V(„žK–ÖR,\±V¨¿W@ äX±p¶Ö=Õgävº{â+Bøci-Å'ßü$ô®ê?x$2Ò. aãŽÍëÑgÀS[ìî ~µ,Xô3RS{"�ÃÆ`ÌÄ—…kQ÷ Û´v¥pßuýŒm ]-l—ý9½�—‹È_~æÎž:Z®·™fOB]í?z{: òeX±`6>[·Møž§¥&k…¢eÛjö¤ŒÞÉÕ€«hÑûïབaî¼ØøýšJ§l Ãôê×û"¢µzM©ÝÎË>îI±K­± çÊ�FÈL»†¢‚{HMIz¯ªU\míKç«S*ÿ¶}úxT>öà# ÿ,.þª:)ˆæy5uêì ïÍɺ©sa"MìáV‹*ëu–|þ´Öó¶œé©ʵù?SÕ�"¹ …rör#jä¾™;Cýz of›I$xv@€ðzÙ!£ —Ó…çʆm€jÁƒ·Ÿ‡ ƒúP]÷‹‹µŽáÒÞA£‡k=÷FÈô�ñ6æ~ýÂEÚõl£÷"’ZYàíçÇU9lS›0¨?–½¬5?�K{{ îé-µ†Ì�=uTè6qêL�óX�;IèÉ{"F˜[«"žzZØ>µGç>—þIÔ¹Yo.ø.®îBݦffZ½è4¯¯ì5• ÛÔí§Íž/\Óžˆ0­Q'Ž”Î‹;ùÕ¹åÂB K+¼úæBƒî}A¾ ý�Ô9ì5áìI¡†q“^Õú¾H$¸¸ºkõ **4¼P{'Œ?Yë¹ fcöK£°iíJDØmPoEc*È—ÁÒZЉSfTy¾3Í^ŒöŽå~N[ÛØ¢WßÒà #í¢Ö뚡٨ñ“u¶×¼_q'�Û¿lúVØ.¶©ïõÂk…Çš½6©ræ¹$pp€IDATønMÒÒ2ñìs/ãÀÁhäp‘¤kmc ;Õ¢3GÅj½væïÒ9]:ˆ]j��=‘„-ëvj}©ç°S‡mæÖ-0ÿÓ™7e„V/³ü;Õ:gÆ¥¬*íïÓÇCgï6ha^ÿh¢ú…=ÜŒÈЀËñ 7œ?ƒ´”œ; ¯^ý!‘H`a©êžŸ–�;·rѪMibžq©txÁãÕü£”ˆGó£4“HàÒÁNÖrnÝB¦¨¸xa¿7'>£÷SçÞî]~H5ÜÑóIåæ%›þô0tutÀö¨­9ÑbSR…ÇR+ ŒÐ{xj-0P]ãô­QûÞî]u>ß­“£0ï]‘Æ„úçRÓ„íÀÝu¶•Z˜c þ½¢úÍÄľ=½�wßûß|±\ì’ªD©TâFvDþª5Ï”f(IçJW\ëé?@ïñ V,Ò/¥TÚƒÇÅÕ–ÖÒG=Èþ,z¥Á„¥µTï„õöŽ:{Ç™š™ Ç�Þ©5™æ5õþÂ5¥$žB±+—R„}:wõÔÙV³—`ez÷¬óyõj²y¢K·*ÝwM#ÇNBÇN�qhßoZ=´bOÄhõàë?x$ºûÔIï·þƒGV«�:$­¨w¥æÊ¦Ee† Ÿ=Uú{·»o€ÎöƒGŒCwߘ™5Çã�>”.,� svñðÖûsª9ObÙŸGªœ—‡;6‡®ÅÒ+±tyHÍH€!£ûa˺�ø;ê´0/™Rù/þŽRýŽ>>Po¤)çÚM±/¥BvmaסüŠÖmíÛÀƶœ:;Àº•e¥×Ú­‡k¥ç!ª¸‰ W¿§¹u=Šä2üò}RΟƤóanis+)Šä2¬ýä] ý<ܺû!åüiœŽÙ pq÷ÞX°÷Qã4ÄOÿÊš�ìmu.ˆ�_¤=ñ¿æÊ ú\»yKçóžîðtÇýâb\ÊºŽ¨¸x­àI&/Dèî}ݽR+ |3wf•ƒ7_7W!À;°f�[Ù¡°jžÎ�„íc‰¥á¢føæÛµ³ÞãjvTÿY[[!hÚd„n ÃÆÍÛðâÄqhÞ¼~­D¨žTæ•YÁåzZe_˶+šh^3ÌÈËÍ6è|ÃÆ<�›×£ _†ëYZ�Na�\�†�y^ï14ç"+ËÕÍKçµ§¦$ÛŠ¸�§ÐÙ¾¥yéÜŒ÷ï•ÎÇ£yOôõÄ’H$°يØ;8’©WTT«fÞ¹u¹Ù× j«�‡w/xx÷B±B�Kÿ$"%ñ¬ÖPØ‚|öD„aODX¹á³µ¡¢´ª4{Z¦k„¤ºh®Úª/X453+÷šæJ¦Vöî´ïà$„sú†Q“~.ÎNؼadùr¤ü“Š¢¢»¸�rùòÆ;·ÛÁ(Ã~wW—‡�êƒ�¢ü{ÈÎÊ…½ƒ-r³ó„^_½úu¯Éáë�!£û¡g€g��“—[ñûÜüÛÕë Gdl ÜŒÌ�ìÿLÍ0sa¶®]�"¹L«Ý„isñã×KP$—!rëzDnÕ^a©ÿÐgQ¤�¨QëëéQå6ê!’0u™aŸ8gæÞ¨ðõ榦œlo??²Â"¤d\ũ䙼2y!æ~³[Í×¹¨>ÖËÈW¥]Y¾n®ÕŠ 6ÖÖz_k×Jjø�¨^˜>UÕ3+tSB7…!hÚdt°·G»vmaÓ¦uµ�ûï¿ÿV»mUƒáϼ 3Pê‰ã ahÔÓ€0ÏÚñèýZ½~4‡ìUÔ³N_o¤Šh®Jª^!³*Ô÷ÄìMí¡�R©ÄþÈízWC5S33!|›8ençå"çúU¤$ž†àä˰bál­ÐMׂ5QÓ*)þ ~ß¾©Êߣê~Os®—NP•p[Ô1p«©µüU (v9µjé‡óÑ÷Iã…Ðe™š=Ÿ>8{" '£ÏbÜ”Hˆý€ª·–¡«^Úuh+Ìù¦OvVÃl®ñÞñfö­ ÷½¯ô÷aóõëÃ7jZ¸S&Msz ¾ø §¢ÿ,m  «W/tï=çO•“0d :wóû*‰¨‰’Z˜ ½ßz»wEð·?PõxÛsLk.´º¢ÜêÂÃþ˜«(Œ£úkúÔI1t0Öoø ¡›j7©ª.Þ4üY­ZÍ[´„]ûްnÕFk^°ŠT Y·jSåÚ,,­ÐÅÓâ½?Rkž²c‡÷ õ³'Pu¢¤s§Ë ï,»"ª±iN¶¯ÖÅÃÚ÷ÃÐ�§*ZÛØ¢µ�-<¼{ÁÍÓGXý³ _†¸“G8t4€ªÍ§�zèoM(•Jl^ÿ¥Ö½°´–ÂÕÍKxlkßÁèÁ¥æWD Q¿§záì‰$ÙÏL& '2º_µŽWvµ´ã}PQ—4I¨lè¬f8Ûö6¨ N�ľ%Ô0p3¢ª.Rð˜D‚>ƒG mÕ^˜1OOš�ËÎáŸó§áÝçI8wñäPR"ÒKje!¬ºyìûUµ~¾Ow ñózÖEŸ;/Jàf(GÛv¶¡CE¯ä”ö¼p%³Ü|wTÙµ³ÅÒçcé‡óñP©D^Þ­o‹Uïy¥‹……•Î ù«Js¦.ùwªw½£ÆM.7Ošæ¼X£ÆM®°}v™¡¨•);tíÖ=·-+öDL¥+²ÖDDØBUvåNµ3Ç£k%pÓäáÝKkxlÂÙ“Bà¦~ŸX™|Ùm½¯éú[)‰g…c¨W­Õ5Ÿš¾ÀÍ�Ὼ´jS:gÓ+³‚+�s�¨¾qtésë(Ê¿‡ß·í†“ª‡›ÂÜR£Ø�Û:·ã‡ãjTgQa‘h÷HÝ P׊®šÔa% Ý3ލ®q•ÒzÊÜ Þþ�xaÆ|tõêeð›("jšzv)�Ǭì꣆º_\\¥UHßéa[×¼ruAs(mE:´ÕÝãG3T+Ks®·²säQÃÑL"�];Û}-þ XìËa̪ô@êÔÙÍà}�\ºÀÒZ5”Z½H‚z8©¥µ´J‹J}¾ê2tx­æ\oú˜ëé½W¬PAduWî¬H±B�ëYZ«¯Vd‚Æp_Í í}xñB¼AûU—æJ´¯Ìš¯3l«h~5[ûÒ•«Ò ÒZZ:l¼ìʧD �Dòú öÙ¯ Œ óÓêÙU™®žOÛñ§.@©,�¡XñûvÅT:ä´2©I¸�—/Ê=õ\éÂ6›×…k]ŸÚ¾]1BX9||`•î_Mh.Ô�žzµG¢Æ„�›voû ¦�Â/߯¬p¿#}Qãg­1¡ø¥¬ëUn¿8ô' yó}L]‚5á¿Ôæèù$a{ˆŸ·Ø·À`æÍK—tÿ'SÿRñ[÷G‰]*‘Íá‹×³2ôî—¨±ò§æb•‘H$ÂÊ”“âQ¬PÃIûið�תÐfXQ£�æðÚÂÝC*‹ ƒæÓ(^»š.lW´rç�Ý¿V¹þÕŸ}€w^� fcävƒÚü“tNØ6Fç>õ;õg•ë¬ Í…ôõx¬hᄎ�J³Ñ¼÷šŠ lZ»›Ö®Dô�ÝTV«i.¼@Ô�xùj¯¼îÝ»[•Ú»t-ýâÈþÓx÷å�±oW öíŠÁ{¯~Š}Ñ>>°Zµùô)�cxÃW?cóÚ=pºZǪ®Ö6Öpõp  þ¾øð{=pé©Ww<ë>û û"¢æÖ-ðäˆ>uV[w¿Ò6®ÞŽÍk#°ymD�Þª¸QI‰a_:©ÞЕTÒ†‰UÄÌ´ô» Û¡ì×ÛKíÀé8<=ÿ#lüc¿ÖJ¦ãö¶ÃÅñÄä Ï}¿¸«5‚9Íöe²bj]òs/ý£zç‘c:ïÕñÄdÑzíé3à©§…íãÑûuî£T*…� ¼|ü«tÍ•)·…®‚ªÞýWé8Õ¹¦È_һߟ»¶aù‚Yøs×6­^O=ü„í}¿ÿ¢³—XÂÙ“5ª±m»öÂöå‹tî“F+Ô»k`¯ØAß¶÷D„!-µâ߽Š~\Wº0N@ öP~ͺÌëY5ž£­2Ꞙêzu]ÃÎm„Çe‡H»y–ÎW¼gg˜ÎcDíÝ),Œàà¤êámjf&Ìå—�•‰¤ø3:ëS*•X🗰ú³pæxt­Þ ¢ª²w°zJ™[·€£K‡rûd\Òÿa¡©Ùã˜2kœÖsû"¢…ÊÕà O�Ñÿž­"CÆ”Î%—“ugO$áJµÔ–ÁS„Ð0'ë&"6ïÅêe›°eÝN¤&e׹苹÷n³neY㺼|»ÂÜZ5|µ(ÿΞHÂÙI5<*5tœÃMí}›þO”Je­|bLDµïÚÍ[…If¦�×h%N}4�iצ•0§ZlJ*ž]°oNxƒzz£™D‚‡J%N'_ÄÒЭ€ó—Ó1uÄ¡½×ÎðusElJ* øÛ4z8|»vFg‡öÂJ 9·î 1ý ö?-Ì'µ²€×ÎZµy:; Ã=×ÿ¾Kƒ^®ÃïLÅšI$˜0¨?Â…L^ˆw×üK‚¦@jaŽœ[wðÞw�v-Gk^<Í9àˆÄââê{Gdge"z$Zš[`ؘç…÷J¥kC>*�smüä*}Ô\Ú;8A©T"%ñ¬V@Uš÷äbR<®kÌUW¬P jïNì‰Ó;·ZEÜ<}„ë€ «W ÿà‘èÒÍ:: ×z;/é—RpâÈ_B[{Çr=ÈzøõŽùëOðÔÓpquGa�G£ö`OD˜QF¨È áÏ C]#wü¤µGZj26¬^Â=-È—¡°@. ‰•H$5~2öD„ábR<Þyu<^™ ŸÞýñðÿÃ¥…Ÿ‡.ÞZCVÇ<÷²ð=øî‹%ðí3cž{Yøù-,�cÓº•ÂJ¯•ÍKHdlæ-„@LßÜbSf�CNÖMHÛXA")ß?Æ©³C…Çèà ;‡¶8}E÷PTXO7¸¸9ÂÞÁV8HÛhEï÷T/tëáªóØö¶˜ÿéL­!©êöš×Uv1Íz�±Ð€Dò†�/ß®Èɺ‰ çRQTXs stëá i+8»vÔÙVß½“HÓ{O ½÷ö¶ÿÏÞ�‡EUï_Ç”mpE‚@Q‘\.ŠâšK¹µhZJýrIË[XYîe]±LË¥›¨¹e¹Tn©©©¤–+*A` ˆ‚2ƒ2xýý1wg˜˜��3Àûõ<<�™9Ëç{ÆXÞó]ðî¢)HNH‘7+3§C™¼YK4÷ôÂ­Ì l‹ýC^x ��\Ì8’ˆlIìîýˆÝ½¿Âýú†…TKàT\R"aðæ³#q5+©×³¡(Pa~ì&,ßþ|=Ü… ÐdŸLžˆ†eÂþO§ýÞúâ?¾âö‰Ã'1ßÖî˜;ñEƒç;ú•Î)wèt¼¾mÿh6Ü›ºYý^Xêå§úãð¹x( T8›”‚!oÏ6Ú®ñ ´¨›šލ¦Mú×\,™ÿ • ìݱ{wl†PT ½VþA!ˆ4¢R×/žO?7¡ÆÚ”•™�õ+c°sË8:9´iü¤·ô޵³·Â@Û³iÑ{SõB,ÿ ¸·j£7ÔÑc«ŸêˆC$Ýùu×צ[}39!S_ŒÁ#Çâ©ácL^S&“áÝ¿ÀŠ˜9Bø¤{_Ó«†zxzáå)†‹DD!«ë&æì*ÇØWÞV:­âjGìÂÑ»ôÂHgW9f-Z�{%jÌ™¡]�äÝ)càáé…÷?^ 0ì9ü�ü§pÏׯŒ1œŽ�š®÷¸I³=~¶mX­wüƒB�}=Cï^Ž?ÉèürDÕÉÎþQtî\î>ž-„`̘&Í\Ѥ™k…ç1n�É×MÕàã×ð³¼¶òÚeN½•¡«¥¢ûin-朧¢¶8:7¶¨ªû¸IàQ;{¼>û üüýœ:´ —þ8†æž^8bš{´©ðxyÓêù”™ˆj¥êŽ^à&wrÄÚYoá‹í?aûí*œŠΊz¢EvÁËOõ×;N§¡L†O§ý¯fàì_W°óø !d+¶ù¶vÇÛ/Œ2èÙ&¼ÞÊQCšHJAîäˆ�³gâóïwà\rªÐ>ßÖîˆèØÃ{õ€ºäžÔehÒ¬æ-Yƒ¯>_(„âp Ð U™sM·x‚.œ(ÕÕ¦—}ƒ «?B]$@.ùvÀÀ§Ÿ7Ú&] %^õR„½öæì*+ î„—§Dãàîï‘•™!œßÙUŽðȧ„ž†âÀ r²®Wxn™L†©Ñ �žšŒóÄáüqBÛˆmå­ú hÈY¯À—ÿþÀàXÿ ƒ€ª:Èd2ÌúxN= „œº÷5´[/ôöìÿz³¹èqâpUwOÄÿ&Äœ]åxeú,£=/#úEpÇ0!Äôÿñ A·žý¸Š)U»<|ø�³|YA�Þƒñì«ÑèÐ5¢Â}/þ~ß]ùá ®ÙkÑþ¼2sß�Fÿ¾×FT×U7nhã€Ñ¯FWûuì7~ábaÒ¹Q/¢Xg½×ª"\HùàWnï8¢ºävnŽÞb U ~ˆˆˆˆê+nVôæ…\®M[Àµ ó°1H#"ªš·_…É1_æÇn‚£ƒÚºkW"½œvUJ ÓG?-u¹DÕêvn._8�Kçæºrv•cú{K]Q­ÅÀ�ˆˆê�ö�ù oXˆ°zjô—_Ý/jèÀ*«%²uº•"Å^çC«Î7GDDDTß0p³&Q7K{¡)òr„íÌÔ$´2BêÖÕió£^Âø�ý°|ÛO8›”¢÷Zß°Œì^©…ˆj3ÿ Œû*‡’U7+³$hÓh4HM<�ƒ;×áÖõ ½×Ä�Û‘Ý[à¯Ç-8;UÄ·•–½9Yê2ˆ$U™ÕW‰ˆˆ¨ú¤$¥¡kç&U?IŠ�›D4 V}8Í h3æè®Í8ºk3F½­Äq.7"""""¢š‘›“/u TO)ï¢G×0©Ë *j uuÉC ¾v®ýT/l ë…ˆac ÎUR¢†£‹°}M ’/Ÿ1{q""""""ªº¾}zâ·Ã§¥.ƒê�¢Â;GÇÆR—BUÄÀM9×Óqùô1Ú mþ×{1êÕ™éi°ï£vöxã£5ð ÜH¿¢}Á’t�ˆ Ü×h¤.�ê�\¥RêÈŠnçæTý$DT«•¨ÕR—@ЯŠ”w‘•ÉŸT½~;|бC°Ô¥P1p³¢‡>¬øëæ�t€£‹CÇM×{M8—è¹GµGÄPmï·Äó¿iŸó6¢ÊhÙ²9 ñjÅù‰ªêf¾ЬYS©K¡* (·¥.…ˆ$V¤*øúxK] Õ°Ž‚!wsÁÊo€Fó@êr¨Žº�«ÄþGÑ·OO88ØK]U7 ¤\ÒvEê9"«S¨Š0nábÀ £GH]YÁðaƒ±ó§}X4k*>\ö dü¾AT¯h4¬ˆ™ƒB¥ÿ^8KêrHBÝ»vÁÜ÷£±|Õ°|Á:€_�7�¥.�j¡”¤4)ïÐ.Ì1{ÖÛüÛ¤aàfmf$h~ÁaH8} gŽíChÏÁhìäbx¬hû�FƒÛÖ»ÈÑ �Œ]׈ªÀ½e ¬ú"“§Eã­/þÃÐ�¬*õFÞX¶�5Àª/b8ÿF!wuÁ¢ù³0yZ4VÄÌÁÔè ݈ê UaÖ­\Œä„x̘> 탥.‰$Ö¿oúôÇé3çñWÊdddâÁC1µE.^†"ß6{§wêÔ];…b@¿>èØ!˜¿3ÖA ܬH·˜AEšµòÜ)P`Õ©˜4{;¹ÍÛqê—�¸S �xû‰ÎáÌÚˆ¬ }P fLŸ„¥ËWã™÷æãåAýÐ#ø €{S7©Ë£ZF¡*BRú5|wøÎ&¥@îæÂáu�n(Qô{óðÁ/aÀ°çÜ1 ФY ©Ë#"+*Q«qýZÎÿ‡£vV}ð� e2tïÚÝ»v‘º"²Q Ü$Т•7Âú Ãé#»p§@�Oßƒæ­½ÐØ©tòÕí±Ú¡H‰§� Ï5v‘£ÿ¨W¤.Ÿ¨Î5|(üÚù"vý&,ݺK·î”º$ªåän.ˆš0Ç fØVGuïÚ«¾ˆÁŽö`Û†ÕØ¶aµÔ%Q55bžý Ü[2X'""ó1p“H¿Q¯ 7û®&ÅЮ> d¯‹ƒ6@¶�}ãCüC&c7"+jˆeKA¡,€Z­ÆÕôk(*ºSáq‰¥ ðq?©Ë'À?Æê‰öA�hˆ7§½fÑ÷�ò\˼Ž6ž­¥n‰øúxÃËË“ÓNQ¥0p³"KVm “áÅ7?Bæß‰Ø÷í—ÿ ÜŒ{&*OtGƒŠ~Ø3‰#ª4mo$³“O¿X…g†‚·—§Ô¥‘D,ý¾Qžñ¯LÁ²%³g$QÁÀÍš,IÜþÇÓ7¯}° ¼�ƒu1î©ïÂɵ 9ºàQ;{ýó[P U�|…E…EøzÝF|4�+•QÕ(”HMÍÀá_�cÔð¡R—CDDDDVÀÀÍʪt¹41ü„œÁ‘íùa×^À‰SH] ÕI¥ŽÅ�dàFDDDTG4�º"¢Úæû?þ{ï>Ò32¥.‡ˆj¹o¿×.ØrþÂ%«¥.‡ˆˆˆˆ¬€=ܪ�¹½Ò‘rñw\¹|�‘r w ¯€4v4>�Ëð¨™R7‘¨ÞÊW(Q¤º+<æ°R"ªŠâb5Î_¸$<¾pñ2ºwí"uYDDDDTE ܬÈänFžL8s?­�1y®Œÿ­^jÌð‰ ܈¤¢NªsâÔi©K"¢ZìÂÅËz�¿ý~'7"""¢:€CJ­í¡‘¯2nÝH/7l«ìeL}‘õìÙ÷‹ÞãÿÞû/òJ©Ë"¢ZJ7œT‡ÃJ‰ˆˆˆêöp³"s® 'Û¡½‡Á'°ܽüÐØÉÅŒ£¢IE}ïnÝÊ5xþ‡]{õÒX©Ë#¢Z¦ìpR+%"""ªýØÃMw‹ „í¾#_ÁcA]ÌÛˆH:?ïÿÅèóºEˆˆ,Qv8©NÙ^oDDDDTû0p³2K†x†‹Èd µø‹Ýሬfç�{�>_¤ºËa¥Dd±­Û~0ú<‡•Õ~ ܬÉ̬UÛ‹�©ôY…úÞ=¤]Í0ùzÙňˆÊs_£Á¹óM¾nª÷Õ Ü$Ц]0 nÏfÜ+1ü›™‘í15œT‡ÃJ‰È‰IÉå¾þûé³R—HDDDDUÀÀÍŠÌ Àšµò†×ã!€?ïd@FT ˜NªÃa¥Dd‰CGŽ•ûúŽöà¾F#u™DDDDTI Ü$òÜÔèÜ{~Û³±MÁoû¶àÖ�t<(óËõ]U”·sô¾ˆ¨fU4œT‡ÃJ‰È÷5ìøaO…ûUÔ ŽˆˆˆˆlWC© ¨kÌé¡–xú(v¯�çÞÈ@î� ü¶g³Y×xgÿ¨'ªI 'Õù~Ç.D½4Vêr‰ÈÆ™¤:r 탥.—ˆˆˆˆ*�=ܬ‰“ªÕI?ìÚgÖ~Eª"¨ïÝ“º\"²q 'Õá°R"""¢Ú‹=Ü$àäÖ¡½*}<3;¢š•–VñpR�Ÿ÷ÿ‚áÃK]2Ù(s‡“ê$&%³—Q-ÄÀÍŠÌíÀÖÚ7­}ùË3Qmpôø <|h~̽óǽ ܈È$Kçeã°R"""¢Ú‰CJë Ž`%²ž?šßÒ®fpX)™tø×8‹öç°R"""¢Ú‰�›=ððaå¿JÔj(ór ÌË©Òy˜¸YÏ…øËcî" DTÿlß¹Ëâc¸Z)QíÃ!¥ËÍJÇ©ƒß#ù¬þÊÑ_–®Dzòç-ùç`4rr‘º\¢z%=#M›¸áþƒû¯Ý)*Æ£v�â‘GdzÏ7h ³hÎ7"ª?ÊDDü÷ïý×àµ[·òàìâ{;;½çÈ ¨èŽÔ¥‘…¸Y™¹Êh4ضj2ÿНð<çãöáÄÞÍxaF Zqî7¢ãí剷m0úZ�Þƒ1dP?¼õæ©Ë$¢ZBîê‚�æ¾gôµ½cîûÑèß7Bê2‰ˆˆˆÈ ¸Iä÷ƒßé…mM[y¡‰»·AO·»ª*ß.�ÆK³V ™‡·Ôå‘ ʾ™#u 6¡Y³¦h(“UýDDõPq±Ê‚©Ë�œ½½=ä®Y@DDD•ÇÀM¹Yé8¹w3Àóñ }i&9º àvNiàö¿.n�]0eѬûd*Š ¸Mݽ¥nÙˆì›9øùàaìüiùü#YÇ·­&ýß„uéÄð�¨÷5ü¸kŽŸøçÎÅK]ŽM‰š0/Œ{©K!"¤Pàð¯Çq9!ñ“iÕs  G×0À½e ©«‘7+-¨@î�ta{Èø™ppt1Xß@¼íàä‚§£faëÒh¤\ü Ý�‘º©Dd.%$bò´h@ß° ë‚¶î-¥.KR¹J%næ+°éÀaD¿7¡�Cðé¿0t«ã®¦§£­··ÔeÔJ eÆEM…"_O/Œ? Áä.KriW’�pá4b×mFìºÍØóÃöx#"Aöͼ3k>R¯jçí ðƒ«S#©Ë"’ܹäT:¬íDäÛÖ Ë>û¸^ÿüdà&�¬tíjcÝŸköBÍ[ùòndà¿%j»¯Ñàȹx,ßþÆEMÆÆØUõöçg© ¨KšùU\¤öåÒÌÃà5SçjÐðáµ;Ef_‹›‰êžƒ‡Ž"vÝfô aØVŽþa�5t ¶ïÜ�µ¶H]‘M).Vc|ÔTh³­`ØfB“f-ðöÜO¡ÈW`ÑH]Ièà¡£˜<-¡~Ø8{&º2l#*£¡L†þa�±qöL(ò ðƿޫ·??¸IH™›eö¾é�¶9ÖÏt˜ˆ´Ÿ-_õ„øa~ÔK Û*0qÈô AìºÍ(.VK]‘ÍøvÛNÚ°ÍÉ™¿W”§I³ø×œœ;�ÓgÎWý„DT+«1ÿ£at�ÜÉQê’ˆlšÜÉ«¢§!õj.Z"u9’`àfMfv9óyB;7JüoûpWU`´;šn>8Ý×o»× ¯5|ÔÞàõò¾ˆ¨î8}æ<ùˆ2@êRj�ñû.\¼,u)D6#vÝf„vëŰÍL¾~�pv•cëö¥.…ˆ$¢û b^Ô8~àId¦ö�ù jè@:r¼^örcàfeædnNnÍÅ… |óÉT½!¢Æüuö(ònh'äìÐk˜ÔM$" Ý ýáEæñm幋þ8sNêRˆl‚B©�Ú"ˆ‹#X$<ò)œ;ÏÞ²DõÔÅ‹—àÇžmDêÕ1�˜”,u)5Ž�›ZùÂÓ?€6tÛðÉTìûf1’ÎöùëìQü¾ Vð"~Þpp–£ë€ç¥.Ÿˆ$ôg=üAe �ý}qøèq©Ë ² jµ60òi u)µJ‡ÐîeA�Ô¥‘Ξ¿„üÀ“Èb¾­<‡�“º”ÇUJ­È’E †½2k¾‚âBŠ H>wLïu]È&6tâ,88ºp!¢zLYP€¾a!R—QëûøàÐéx©Ë ¢ZÌÞÞAêˆHb­›7•º¢Z©oX”J¥ÔeÔ8nyÄίÎÿ)âpìÇ5(.T˜Ü׿s/ô}n:±³ç²£DD•àܸ‘Ô%Õ_õp‚ynÖöÐü—ÿÑ@ÿÎhŽ"eî•#/;`çÐMZ´AC;{aUÒú÷Ï“ˆˆˆˆˆˆˆ¨öaàfE– )k “Á¹I @So©›ADd ¸¤qÁ>máÞÔMê’ˆˆˆˆˆˆl·:†½àˆÈ”ƒ§KWéìÖÙ¢c•ª;˜» 07êEnDõ\‰Z�Kç¯Ò9|Ú I3펩)‰ÈÏ»hß©+ììíõö¿îÖ´9|ý-ªQ|-"¢únnì7ÂܶÛ?šmöïuÙyùõþBí9¢^´ø÷Isk:ñÕR©oQ…ª"¨KîšÉ]ÐP&«±k<}Nø½Ü’÷�j7+«làõ@£A‘2ÏäëºpDD•¥ûÁ X¸‰© °~eL•Îñò”h!;þËœ=¥]@jÁÒµ�›øuødå89»˜]£øZDDÕMLÀ¨>á˜ñܳ�_»çbwï׆PEY;Œ³ UÖï;ˆíGL¯¶Ù7,ãöVæ¤ú��›5U0¦ô�Fƒ+ñqPßU¡CøP½×Š”yX¿`¢ÉcŒ‹†ç©[HDõ”{S·Zñi#ÕëV.Æôw?’º ""³l?‡i£ž6«Ô}�F/l«i U>ÿ~‚}|0ªw¸Þk®N�17êEÚ)F¬id¯pô’¬ÝŠå9t:‡NÇ#jè@L2Àè>sc¿Ì�z©Rµû´ÞW§ÆRß*7+*/o{ Ñ`ë’i¸���&î^h_&p«¨gÜ��1ðôïGI©I³X±i¯Ñ×Μ<ª×³¬K÷«_?9! ñgÒEê[ADd–Ä«hÿ˜�YûIéLR²0´³làæ`gWm=×Ú?æƒö’¶Ü´K§é…m£ú„ãÉÀÇàÝr'G(TEHJ¿†¿22…°T÷ß²¡[v^¾p+¸¹7u³ù�¤Õ@êê‹]ÿ™ƒÛÙÚož·³3ðßµÉ}Ÿ4ýÇE£ÿ¸hô9IxþøÎ¯¤n‘Eª"Ü×h,>î¾Fƒì¼|©Ë'"ãáégW9`óše(Q««xF"¢ê%wqÄî9`ÖþºýtÇÕ´?%ülÑŽc¥CH}[»cÆs#Ð=8r'G€ÜÉ݃1qÈÌx¾tèpìîý(.)Ñ;×Õì›R7‡j{¸Õ€¬´Dd&Ç �Ÿ4�ØÙ›Üÿñ.‘pv+�gäæÕ$¤œ?†”óÇüÏ!p÷©x¢`""k*o’ܯ͠�³b~ÔKH½‘…]¿ýŽÃçâ¡(P ûU4Ÿ‡nùäT½ãBüÐá1ŒÔ·F'¤%"ÛãÑÚ]zôƪ%óP¨T`×¶o0zÜkR—EDdÒˆž=»{?Î&¥ ¸¤vv&÷-.)ÁÙ¤½ãŒOØ_^O'݇—öv� á�)ºs^Hù TÝŽwuj ;;Ü×h�«(Ð{ÎZLµ©¸¤JÕ¥‹Ü×h�q3RRQxç.Z7oŠ`Ÿ¶öúÒ�ërÚUüy5žÍ›Áϳ<[4/÷þèz¤À¿'¿Rî5FõGÜÅ(T*´õh¥êìì„kÿ‘øW¹ï�©çr•J4su…{S7£÷€É÷G×ïÀé3èG„ú—û{µî\—Ó®€Þý­Îu 7+25¤ôJ|i"6h,º c°ßÃrÎÓû¹éH9L8—{[nDd›.ý�†É1_}m~ì&Þ¹k0<N^NDô—_=îlR Î&¥àè…‹Xöæ” a$¢º-(¤ üƒB�œ�£v¡{Ä´òô6ØÏÕ­©Ô¥aP×.Øyü*Ä]L(÷Ãǽ'O Û½:› Ü>ÿ~‡Y+zê>,Õ}(Zñ9íï_e?lÍUTÛ*¥¦Úw1AoEÎ\¥Òäïš3žaô÷LH½‘…7–­ÖûPW,4ÀŸNû¿ ?ÜÍU*+ ö–½9Ùà9q;tŒ½?âç&==Toñ�¹Q/½©›Á=ÑÕSöýéà�q ëµYw�CüðÉä‰FÃ2S¿ÏË]œ°èÿ^F3W×jûwP×pH©5=4üzp_ƒKÇwÚuê…°þcŒîg4qûß×#�Ú£]§^ôÃ;"’V1‡2鹚•#üpî‚ s¢±*zBü„}–nÝiе>;/_/l‹:Û?š�íÍÆ†9ÑðmíH½ž�q Wjˆ*QmP¨RUý$õÄ„)3…íõ+Ccäû‚Œ=b‰¬*?_!u µÖˆž=›.w¿õ?ÿ@;GX£rFDU‡`ô Ë]œÐ7,}ÃBÐÒM^³7Ì„Ÿ?#ü®)wqÒûÐþžilJ’“—1~AŒ<…ø mÓ9›”‚‰‹>5ø=о:“c¾¨Ô´'-Ýäè¢7TXWC°�ñ¹ýVÿ´Û¢kˆƒÀ—0/v£Ðæ²×>›”‚o9jp޲a[h€¢†„ÜÅ Š&Ç|�—ÿ´¸ýõ{¸YYÙžkª‚z¿—wuS¬Ì�zQh«%t׈:/ô‹z²‰µØÝûõ^€%ßn¶c^݃µ£ëÆê‹ ?BìîýXºu§µßÚ:‹=ܪÙ�‚ÛÂvwïJŸÇ¹IKa»øN�ÔÍ""·rnC¡äÿ�b;ý%R¼ÌûMÑ'ä U‘^×vc˧7”É0¸{˜ðØÜI‡‰j“aƒ!55ÅÅì9k®ðȧàáéضa5T…ü~LTtèÿrø¨Ô¥ÔZîMÝ„û?;atŸ]¿ý@Ûs+°­—Ô%Û¬eoNAÿ°Î¿K;; êZºbõásñzûÍ)lìƒ]¹“#æG½$ô–‹Ý½ß`4E÷à@D (0qÈlÿh¶UÛY×1p«fªü[¶¼…§Éý]šâÅÙkñâìµhìÒÔ`´©¼ea߇~QõY/úÄŒ´ó�ãÛÊ]Ø>q9AØÖMŽ Ê鵿`g'ü¢ª›L˜¨.‰ìÝðí6~jl.™L†—ECK×­\,uIDuZff²oæH]F­õâ€HÀÎã†�Û}�FèA5¢g.e‚okw£슇R–�£Mü{çð^=Lž;¼Cé‡Ã§“ ^Ÿ8db^Õ`ë¡Óñ˜» £Þ_ˆ!3ç`ížV ß&=3¤JÇwôó5ú¼øwnÝ¢�z#[Ø~.²—ÑcÅá1UŒCJ­è!€‡ ŸÓ¹ÿßÿâ‘Æ¿yþ£� ÎòÆpGYÚSî‘G왤Ù€ˆ^ݱ}ç.¸¸8aâø1R—cLu­75‰ø‡üÑ ‘‘cz©ô|U‘ÔÍ#ª6rWDM‹Øu›áìäÄ¡¥fjåé�ˆÃpôÀ.$'Ä#!þ ‚BºTýÄDdÀÙÅ ¯N} ?~ÿ ¡JÐ:Š.ý�¦7=†8à÷Ö"};˜|­oXˆÞ¢:âçÔ%÷�]b< snÜHØ.*.6ºO÷à@tDqI .¤¤âÀé3zçW¨»{¿0ôµª‹}™ ÌÌeê÷òÖÍ�/*týVétXmÝ[”aÿìÆa¥fbàVÍÄÃH‹ïTzîµ¼©Â¶ƒ£‹ÔÍ""½þÙ >‚Øu›ñ¸_;tç/HU’z=[èÆ^‘ì¼ü Wˆ"ªm&Žƒ‹—þÄÒå«ááÞ’ßSÌ4lôK8ÿG • l^³ ó–¬��=çº%²¶™3^Çó>Æ[ïÌÁ§ÿ^ÀÐÍBvvB(tø\¼^àöÝác´=¸Ìùýæ\rj…ûÔE¦FR”ejž<ñŠŸUá`g'„oó£^Bv^>.§]ÅŸW3„žŠºÅ¾~üxn¥ÿ_1¶‚¨¹Ä B˜«¼¾ÅÄá$•��›ÂéàTº¢KvzœÜZXtN�« Ú1ý­ýBع�ȆÌ~ï-(•ˆ~o|}½ðâóÏ¢eËæhÖ´‰Ô¥Õ:}ÃBôæz+�«Sc©Ë%ªŸþ{&¾6­Z¿§hêØJ¿vööûÊXµd • ìÚö F�{M겈êœÇýÛ!æãyˆ~o&¾6 o¿ù:ÚVýÄõÈÈ^ÚE ¶‰Ã´QO “þë¦Ë0waÙa“õ…¹+·ªKîNÚà­2þ¼š�þa�ÍÞß½©Ü›º¡Xg<ÑÖ óc7оOGÎÅ[t.ª[¸U3GÈݽ ÈÎÀùÃßã±áh`aÂ};;×Sâòm,:–ˆªWC™ Ÿþ{“’±äó/1ÿ£˜j¿fe>±²UŽÂv�à þBBõ^C™ k¿úG~�æ­ß×È÷”º (¤ üƒB�œ�£v¡{Ä´òô–º,¢:§{×.˜û~4–¯ZƒÉÓ¢…çûš˜ï©®8ô¿hUØÖ r'( T8�˜ŒîÁ�¸�RÚ[­ªCÅŠKJjü>Ù ]/Aq/7ßÖîØ0{feOi¶þa�±÷äi!D=q9¡R¿ß–�+Žj'n5 Sä³8¼)Šì œØµÿnþ§®ÿ-Qc×W�ï:À°‡»¼Iª¡L†öA�ذf%îk4ÈÍÍ«úIMõÂD©›[eâ^lâù!ÄóFÕg e2ôï�þ}#ªå{J]ø>bÌ„)3ñîí|šëW.Æ»~!uIDu’îûÓ¥„Dܼy &%CYÀU‚ÍÑP&Èž=»{?¾;| ݃…ᤣú„›=„ÐÔ|ebâ �`ö´%Æ(TEÈ̹¥7 ¸<ÓG?�ñ ´˜:�ùQ/Y|MW§š¶éÕ¢¥Yûñwvó1p³¦‡†‹&€oûp$ùý‚¬”x$ÄíBqQ"FO¯p>·ì«‰8¾ãK¨ € ðahÒÒ›‘ k(“Á½e冎›£od/@Uw~© ÝyüÆêkrž‹“—ÑÂÍÕä°DuQu|OÙþíÚ:º99»`ôøIضa5²23wxŸÔ%ÕiíƒÑ>(ýûFH]Jµ³V7@;Yìîý8›”‚ì¼|¡'Ô°vÕÛ/W©4ë|¦æµý#ñ/én˜ ‡“•™xüÂÅBX7ãùÕ;¼ÂcŽ]¸,lG (õ-0›x1…ËiWMÞ+c+í’q ¤. >h “aÈ+ àáH½p ±³FâìÁ-¸rþ(ng§£0?…ù9ÈH:ƒ+ç�â»%SðÓ—ÑPdgì�åè>ô• ¯õÐÈ‘­r°³~Q¨°pý&£K©<}Ñ_~�ñ b°vÏ©Ë&"ù<<½Û6¬–º"ª#Nüº×jçòmåßÖî€W�»8| x3_aòâžHW³ 'º¿¯Ñ“÷WÖÕ¬«µYJ#{•d[5¹ßÚ=0~áb¬Ýs@o8î‹"…í¥[w"õFV¹×ËÎËGìîýÂãòV�µ…a¿âé]ºø Û›Æý2s¾Þ×h°ý׸z;‡`e°‡›•pýC&ÃàW`ïš9Èúß|lgl6ë¼¾{¡Ç3¯á24"²Š¹±ß˜µ_eºÀ[ê…~Øyü*:�C§ãÑ7,ãöCê�lœ¸œ |2à‡ñƒúJyëˆÈ†Éd2¼ÞNuVÿ¸è�ÿÞ¿�¸‹ X¾ý'a®8KéŽK½ž�K§™=ŒRìú­<£ –åêÔ¸J+qš£ýc>ðmíŽÔëÙØ~$RþƤg† ,Ð_X´"îb‚p?Ûz´Ð«)¼C�Þ½|cÙjŒèÙ¡�·C;ÏVp°³ÓNÿ (Àå´«Øtà°p¬±Ug]�„ío9ЉCTkû+"žÞEîä(Ü«ÔëÙøbûOxù©þ�;9âÒßiXòív¤^Ï®ô¿­úˆ�[ jð¿ÐíÔî5HˆÛUáþrw/DŽ�‰&îÞR—NDuLEó~èÔDàæ`g‡�³gb^ìFaX….x“»8á“É+½´:Õ­<½1`ލøw-"") [w �#C;Zt¼8DJ½ž�è/¿6ØgUô4Lޱ|.ËÈÎ!Bï8Ýñ}ÃB,ú�0v÷~½^^¦Ì�zÑ¢®fß´xH(ü{ò+xuñçB�ýå×�»8ÁÍÉQon·Ð?Ì~ùE½cu¿§¾ñùJ¤^φ¢@¥×>Sá“okwü{²áµ'î¯ø<'¾Zjq»¬!W©Ô»§ËÞœ‚q CQ Âö#q=%CüÞ!Hïß/™ÆÀÍÊlèûGº?ýº z Ù©—‘{ý ”·® ¯{„ÁÍÝNr88ºhOÅnmDdUYÝÔÞîQáø–nr½×¢†DFÎÍJh?Q[öædœ¼œˆ¿22‘‘sSèéÖ#8Á>m+õ Õ<·¦ÍÚ­—°m޶í„íG�Ìq«{]¼_y†�~ E…¥ó]š[QMp°³Ch€Î&¥ 4ÀOo5Ms-{sЉù¶vÇÛ/ŒªTÏ4xù©þ¸�òw•¨.EÅÅ•:ν©¶-|ŸlÚ*| «(P A™okwDtì€úEý`Wî䈵³ÞBâÕ >¯B• ÛBü5d€ÉûèoÖ¢5åf¾íË´uãì™øüûz5ê‚¶gzvÇ‘s¥Ïû¶r—º 6í2ᆽ£Ï˜h<Ö)BêR üçíÁ˜û~t½˜Ð”¨¦ôè-ÍÿWs?\ ¨ j¤çY]rðô9Ì�ÝdÕ9XÈvôè=}#{aþ3¥.¥VȾ™ƒQ/LÄ‚¥kѤYõ-òR×ÜÎÍÁœ±ýÛµÕº8‘­Ñ}Ϩïÿö{ôlv�,ÝCh&w1â—”@©ºcrX¥îõòΡ»Žn·Ž~¾zçÒ ë´·{T/ÔS¨Š .¹gòÜ÷5¨î�âv•­[\¯¹Äç×$þ�U|Þò† š:¾¼{æè`/ µÄ}�7µsÜ5}HTö>—ÇÔ¦Þ3±òþmXz|EÃzª"85rлÆÚ=„žy{–,4«Ísc¿;aþœw-º×µ{¸Õ"LF‰ˆˆˆˆˆl[C™¬Âžùvvå½.¾Ž©k™z^îä8•^c!Jyí2§Þò˜ªÉÜóVÔ&sï™9Êd‹\XÊÒ÷ÌÜ{RÕãýÀÕØ¿ƒ‹§Ð§­LïÌú„�›=C1"""""""ª]îk4è5åmáñªèiCc³óò…9—#;‡H]²Ík uT –ù""""""""2¡¡L†¹Q¥‹FLŽù'/'";/ÙyùØþkF½¿Pxýå§úK]²Íc7+ãŒxDDDDDDDTÛôé‚M ‹f[Ю0Ëá¤càFDDDDDDDTÏ5”ɰaöL\ú; K¾Ýn°Zí¨>áöÏ®UžÃ®¾`àfCØ9Žˆˆˆˆˆˆˆ¤Ôþ1l˜ÍÕß«Š�›•14#"""""""ªß¸Õ$¦qDDDDDDDDu7+zø�‹&Õw ¤.€ˆˆˆˆˆˆˆˆ¨.a·ÂŽoDDÒ)¼sWꈈˆˆˆ¨a7+zXΑµ:/u µÎå´4ø¶õ’º "ªÅ”ŠÛR—@DDT+)Uw�üCê2j7k{(Ý×C_DTw èÛ PI]J­r5+m¸\]\—/œ–º”Z%?ï Y³¦R—BD¹~+Oêˆj¥³I)ðòò”ºŒÇÀÍÊ$ÌÛˆ¨xÜpøì©K©5ŠKJ�z=ÁA�R—BdìѹsNüú³Ô¥Ô*§Žÿ¹› e2©K!" Œ1;�Ÿ�º ¢Z§¸¤ÐÚÃCêRj7"¢ZDîêß¶^Xÿó/Â/*ßê÷ì'u)D6cÈÀ~ÈÊÌ@jJ¢Ô¥Ô ·ss�œ�é“_‘º"’HdïžP¨�z#KêRˆj•½'µ=ꃃ¤.¥Æ1p³"){·±çQý1÷ƒ™P¨ð¸¯ÑH]ŽM[»ç¶‰Cß>=áà`/u9D6£Oïptî‚ÏDãvnŽÔåØ´Ô”D,™ÿänr„÷è*u9D$‘v¾>�»¹à�e«9µ‘™²óò±þç_зOO¸·l!u95Ž�›Ô˜¸‘…|}¼±ê‹œMJÁÂõ›ØÓ͈û Þø|bwïGÔËc1{ÖÛR—DdSÊd˜?{&änr,™ÿC7âÏà³Ñ�56Æ®`pOT�98ØãëK¡(Pa^ìF~èIT�K§aÔû Y¼9m’ÔåH¢¡ÔÔ)Õp17#"±öA�ˆš0±ë6ãÐéxD ˆÖ͛·•;ÙÕß?¯fßÄw‡�álR jÂXL?F겈l’ÜÕcW`Èð1˜3c"B»õBPÇ0¸5mWy©Ë“ŒRqÉÆ#îð>*í‚Oÿ½€s·Ü[¶Àª/b0yZ4&.úo¿0 íó‘º,"›’z# Ç.\FìîýíÔóf¿¹«‹ÔeI‚�›±CÕ¤‰ãÇ`PÿH¬þz=bwï—º›!wsAÔ„±Ô?²^v]'²„ÜÕ‡öí@܉߱|Õœ=uLê’lƨÃÙ;�þ ÛˆHÐ>(1Ï☥˜ó@îâ„Îþ¾R—F$¹sÉ©P¨}ûôÄìYo×럡 ܈ˆj1÷–-0ö;˜?û«¡,(�º$É1d#²Œƒƒ=ú÷�@ÿ¾€ì›^Ú¬YÓzý•¯{×.سc .%$âæÍ[8ñûiàÁ©Ë"’Ö?þ�ÈÈÞü°J„�›•±‡IÅÁÁžó Q•1´&"2Oû @´ >° "càfMSJDDDDDDDTï1p³Ì鈈ˆˆˆˆˆˆênVÄnDDDDDDDDÔ@ꈈˆˆˆˆˆˆˆêöp³"«õpc79"""""""¢Z‹�›µ1,#"""""""ª×¸ÕfpDDDDDDDDõ7+c¸FDDDDDDDT¿1p«#ôÙnVôð¡ö‹ˆˆˆˆˆˆˆˆê¯R@DDDDDDDDT—°‡›=‡vÕwìáFDDDµžW›ÖR—@DDDD$`·Z€ó•¯µ‡‡Ô% ¸YM """""""ª÷8¤”ˆˆˆˆˆˆˆˆÈŠØÃÍŠ¸h±‡‘±‡›µU¢‹{ÅÕ ܬŒáQýÆ!¥DDDDDDDDDVÄnVÄEˆH*ÅÅj\¸xEEw¤.…j©à ¸º¸ÀÁÁ^êRj�û “’qóæ-©K!+  €½½=ä®.R—BDDDµ·ÚŠÉ8ùû|·ýœ=wQêR¨Žˆš0Ç fÐPŽì›9غíGlß¹KêR¨šõíÓ “^} î-[H] Õ2 ܬÉH7æbDT]ÖnØ‚Øu›áÛÚ3ž�ÁOÀ½©›ÔeQ-¤P!¿°Ç.\FìºÍØùÓlŒ]ÅÐ͈K ‰˜<-ήr 9þO„ÀÛ×2™LêÒÈJJÔj© pùÂiØõ½0«¾ˆAû @©K#""¢Z„�›=6"ª~÷5,\´‡ŽǨ>á˜6êi4äûTr'GÈ�áÛÊÃ{õÀ¸…‹1.j2~ü~#ÿm‰lÿa7–._ ÿ L˜2NÎ $ë";{{ØÙÛ#¢ÿP„G>…O>˜†ÉÓ¢±ç‡- ¡‰ˆˆÈl Üê†|DõˆÍßáБãˆ:‡ �ºªcäNŽXô/crÌxë�9X¶ä#©K2Ëõ¬¬j=ÿ¥„D!l›½€=Úê ™L†éï}ŒE³¦b\ÔTlÛ´†óíü¹WRÓpø×8N1@6ϧ­|Úzc@¿ÞëÒ‰¨ÖnVÆð‹ˆªSq±±ë6£oXÃ6ª6íóAÌë¯"ú˯‘š–_o©K*—¯¯2®]¯Ök¬Y¿ήr†mõ�“³ Þžû)æÌ˜ˆ½ûÁ¨áC¥.‰ˆ$¦›^œ]åˆ0 Þ¾þR—EdÔ�"®^IBâ•t:2r79ÍŸÅ©j7kcâFDÕèÂÅË€ñûI] Õqý|Ç~;ió�[ǰ}ç.Ì~ï­jùÄV¡,À¹sñ=~özªI³ððôÂñ¿3p#ªçtsèú…`äØWÑÊÓ[ê’ˆ*Ñ_û³+5%k–/âT 5¤�ÔÔ)K×M°¥/"ª;ŠŠî|[yH] Õqvv ðÃΟöH]J…"{‡“’«åüjµÜ1Lꦒ„zô„sçâQ\¬–º"’ÈÚo´a[h·^˜½€aÕ:¾~�˜µhœ]å5 e�Ô%Õi ܈ˆj‘¿Ÿ†ÜÅIê2¨žÜ= Š|ÛÿE,0@;Œ'výfÜ×h¬~þ«éפn"Ù]àª,°ýÿ'ˆÈú²oæ výfD † Sg²Ç3ÕZº©ù ,ýâ+©Ë©Ó¸Ù8öp#¢²:ûûJ]‘Mi(“aÕ18{.o½3Çêç×õ,mÒ¬…ÔM%""‰ü|à0`Øè—¤.…¨Êš4k�Á#Çâð‘cì¹]�¸Y‘äÃA™¸Q=Õ>(3¦OÂÙsñX»a y$""«úõØoíÖ vö\©˜ê†¡ÝWRÓ¤.¥Îâ¢ ÖÆ€‹ˆˆH£†E¡J…Øu›»n3F�†'üáèØm½ÛTú¼<�ºiDD$±´«è>Hê2ˆ¬F7áá_ã¸bi5aàfeÌÛˆ¨®˜û �Žœøj©ÔåÔ ¼§Õoâø1Ô?[·ýˆí;wa»ÔÙ˜3'�býÊÀ‚¥k9L–ˆÈ�9�.Õ-þA!œ›´1p#"ª£²óò1êý…€¹Q/¢Xg©Kªuz¼6£Â}ú†…¼Z´DèãíØÖ 9‘²¤Ü[¶ÀŒi¯aÆ´×h'º®ŠQ/L¬Òñâ�KÌÙU¿€öÂã¶íàéí _?~ÊLDDDÕÏÉÉEêê4nc�8"²UÁ>>R—P+èz¬@ìîý�»8aÖ¸çÑ=Ø04á=•†{˪õâšû~4æS¥sS¨Tàì©cÂcݶ‡§žŸð:ƒ7"""¢ZŒ�›™\£€©ÕB£z‡cTïp©Ë° ¾­Ýñâ€H£¯Þ¹‹]¿�Bêõl€¢@…è/¿FÌ믄n¼§Ú­‚:†é=—›“…œ¬ëHIº„B¥Y™ølA4üƒB05zdì1IDDVt;·´ç·%S ”¨Õ(Ri‡ºº5µÙŸOªÂÜ+Q[Ü>"kcàfM6¸*¨�•CDT+µõhQî�ÜQ½Ã¡Páóïw=ÞmÜŠ?žËᥤ'¨cºt�0úšF£Áù?â°sË*HNˆÇù?âLîODD¶IL–‡SâÀ°~h4gFéT +6í5û¸Kç79hÙšÅ�\jtu×í¿z�[Ò>"kcàfEÀ€‹ˆê…ªê’{÷¦nÂó÷5ä*´¿D6“»�RqI ®dÞÀÍ|ZºÉáÙ¢9äNŽ^§¸¤Yy·‘zCÛC,ا­Þy+’�—�«Ù7QT\ ^[\¿«Sc8ØÙé=/~Îr'G¼ûâóBà¦(P!WQ wïLÝÓâ’(Uw¬vOª"$¥_C 7Wø¶ò¨ð:dd2ºt�À�"¶mX 8uü—r:e~”ŠÛÈÏ»‡F�áÞª�ÅØYÒÓAüG¤±? 4 nfeBq;^>~prv1¸Î£vözÏkSö�k(¾{Ǭ6™êÉ *,@FZ ŠïÞ�‡§7š6kY£ðQý%¦àå)Ñ}x²hÖT*ÂãÚ‰C®ò8»Ê1`ØsèÖ³¿'S�ÇÀ�ˆ¨’ U*©K¨VâÞZâ5sÂb Û?š {»GñÆç+…!•b3žareqI Þ]µg“RŒ¾Þ7,³_~Ñd(”z# ó×n2z]Ýño>;Ò  ×?7êEû´Å«‹?‡¢@%´©2�8ØÙaTŸpl?¸š}S/X3uOã.&`~ì&áúðΪ5FÛVÞ'/'"ú˯ žÕ'ÓF=mpqmd;:wí)nÉ ñF÷Iˆ?ƒÍk–éýA&6zü$DôjÖõ–ÌK8Ïgkv”ûЮmßàè�]´½tûj4¬ˆ™cP¯‡§ž~n‚Bº=*B»õ„©3-n“©?XËödHMIÄšå‹ Îãì*Çëï|ˆVžÞVyŸˆˆÌup÷÷fn©)‰&¿ÖÝB?ƾçú´ ÀËS¢h?t©ŒB¥Û6¬Æ¶ «1xäXDÁà�ê,nÕÈ&z»ÙDDu�¯¯âNüŽQÃÍûƒ¶®Úzø(Ÿ‹Â*ßÖîz!ÑÒ­;áçÙ íÓ_, ;/_/äÒé"R‡NÇãjV–½9Å 4»¯Ñà�e«õŽï‚«Y9Âõuǯ�õV¹=¹>Ùô�AÖâè`ù/�W³obÑÆ­&ïéüØMöik–­Ýs±»÷ �}[»Cî䄳I)Ø~$éÙ9ïT-í$ëjÔ¸ü^Œû~Ø‚½;6 �=<½àÑÚY×Ó‘•™ضa5.�ÿÓßý¨Âë öœð]:ÿ{¹=êta›‡§—Л¬D­ÆWŸ/Ô ÛB»õBJÒ%def`Õ’yø×œò�ضñ+áܦڴ~e .œ6Öé$ÄŸÁª%óh6®…J½7Ë¿Ùe³óQÝ”•™Ua�ÉÞ½bçÿˆ“´Ö„ §M¾Ö¤Y ³†·N~{Ü[µ1x>ûÆ5Ùÿ£ðóbïŽÍ¸pú7¼ûáü¾Lu7kzlÛ°Ÿ-ˆ6yýÛ¹9BØf¬MªÂaxÕÙSÇгß“mZµdœ]å1ætz22™ 72Ó±có×B�œ�ˆj’‡§²23wx/ž>¦Ü}Ë~°¡ûÀ¡&™3,´"î­Ú æš4k� �.¸�›#ô®ÎÊÌ@Òåó éRãm%ªn ¤.€ªæ¡_Dd}‘½{¾Ý¶SêR$·*z& Ô;9bÒ3ƒ…×Ë‹¼ôwšð\Ù°Mwü²7'#4À€6Ô+.)^/.)‚2¹‹žéÙ]ïüíóAÔ�Âã—Ê­?4À‡ €{S7¸7u«ô¼fÅ%%øö—£¥ípqªô�Í s¢Ë½§âPÐIÕ™õ¢Þ¼m¾­<°aöLŒê£?´·²Ãf©ú‰{7tëÙOïµ]ß#l¿þ·½%d2&L) ¸·®û²ÂëÙÙÛ#´[/¥½0Œ9þËa»ÝãÁÂvÜá}¶xUU™L†ˆþCñÙšå^_ܦ·ç~jÐ&'gÌZ´Âì6}¸ìté!ÔÑÊÓƒGŒ^/¯÷‘µõè=€þ÷JS’.Ÿ78Θ3'�âÌÉ£HMI4¹O‰Z-ì'ž«³¼s=¸[xœpá´p|‰Z;Oæí܃ç*£I³�|ªôÚ'~5ºŸF£ABü=¸ëV,¾*j{y÷œãRSM¶SUX€„ø3ضñ+lÛøâÏû˜sÏ+Û&]Mº}4 nd¦ë�gß[Ìz¯©æ°‡›1à"ª?ä®.5bb×mÆã~íнkýýT.°­—ÁsvvzC!³óò…ðéð¹xa¿é£Ÿ6p=ÙKè‘w1Aè¥æ`g§7ÿ™1ž-š Ûç’Sõ^³·{Tï±8œ3E©º‹ì¼|ƒç/§]üy5à [ô/Wúžzµ4üTØÁÎr'¡g_qI‰š‰CÅ.þFÏùòSý j$Û’š’ˆ­ë¾ÔëÑðxPG½}t=œ]å&ç"srv�P’â‘•™�Û¹9êÙoˆpnc½0JÔjáõˆÄùvnçæC6C»õ2:$ÈÎÞƒGŽÕ«£Ñh„󊇩VÔ&SC³üƒBŒÖмe+a;%é’uß8"¢rèz*ö:þé»u´ßg;:™ÜO· Ch·^&ÏW¤*ö{yJt…?Ä‹<ÚŸ7ºïϺ9;Ó®$é­RZ•¹×:„v~.¨T†ô¨ °nåb£s™Š�óJ…ÃQ>òˆ°8€r§Ðh4B¯lgW¹^�èÔ”DƒÛº‰ƒGŽÅ“ÿŒ,÷ž« °üã÷Œö\¬¨MÇÙƒ³§ŽÁÃÓ ï~ø…ÑySí0Ý͉©°w;Õ nDD•4mÊ+Hϸ†è÷æ!æãyõ2t ð3˜µõhatÒeQé|iM›˜J99Qmv5ýÜ[V<é³³·>08ÿGœÉ ävnŽÄtz2ùy·j´Î—§D#7'Kø^Ú­—ð}½² $TV‰Z�w§”þò A·žýàШ1ònÝĉ_FVfŽØ…”Ä‹xÿã•åžO&“!<ò)¡mé©É&ßñô †='lë“Љ0 Þ¾þ8uü$'ÄcïŽÍÈɺn•6e߸frÖ¬Ì ½°mðȱ¸S¤Ò›uÍòEøpÙ7œÏ0p³2³{¸±+Q­×P&çÿ^€‰¯MCô{óàëë…Ÿ¾>ÞhÔÈAêòjÄàîa#‡úN׬c2rn<—�—�Õ?íÖ[(ÁR}ÃB*=„´,¹‹¾žùf•Wþ|ÂŒ°,s}vê’{€“Y‡‘eefT8'Oh·^5½ÜžÞ¾þ0Wö�kfMr­[<¡P©À�Ìt½tGöÿ@Û Mü|VfºY5ØÛÿž(ìÊëÍQöu¥â¶Ð¦f-J‡Pû´ 0û¾‘yt!Û_)Wê凋Ö0xÄX$'Äãè�]&{dýñÛaaÛÛ׿Æ·.Ý#ôæ êV­ó]^<{RØ.ûaÉáŸK§l½¯ˆ[Óæ•:Žˆ*ç¹QÏ ú½y¸”�ˆöA »-%“É„¹,�ìÿÑ pKOM†»‹‡í×VÙ7®Ð.Ž Ñh„éÔêbÜõ½^O0ÿ ½aÿE¢ùÜÄ +”åäì"¬äjîj®ºž†péüï?�ÅÃI{ö"l‹?êÒ£·Ñs‹†–•—[~‰‡©–Õ¤Y az‡³§Ž™ ÜLý,ÿL½z% ý‡šu_¨ú0p³2†dDõ›ƒƒ=*?�lEúFöTÕèÕñ°FW§Æ¯–y!¥4Tš5îyt–ößVÕ'Û�ÄAQ ÂÛÂŒçFXtŽ`Ÿ¶V©¥¢Þƒ äêŽôÔd³ƒ;÷VmÌÚÐ_ˆ÷±†»wø�g}Å!¥DDõÀõ[yfõº²·{r'G«__¼rgûÇ|àÛک׳qèt<®fåàíF¡ýc>Â>Ùyù˜ó 5+}:‡¯E €³I)€Ž�ÀÄ!¥s�(TE˜»©×³…kèÎWÕÕC+Ò=8¡~8›”‚ÔëÙøñøIŒê^õ›!2´£0¯ÝüØMhé&î祿Ó0ë?ëÙ»­ŽöìKÂ'ðKæ¿…Y‹Vè…O�_}¾Pxüü„×-¾†xñ]Pfjñ¼D°"f¦F/€L&C‰Z�Ã?ï^«l›JÔê*·‰ˆ¬£}P ¶»«×|ƒ¥ËWcéòÕR—T«tîÚÛ6¬>`hÒ¬…0lß?(¤Â!‘àèdÞJÅmÉÚéÞª�ÅöSÑ*Û9Y×->§xî·¸Ãû„ÅÄïCÙu*쉉‡ÆššbÁsßk²] Ü$ÄÎgDTSbwïGìîýîgj5ΪR¨Šô‚¼eoNÁ¸…‹¡(P!õz6&Ç|ßÖîèè÷Ÿ‹Â!¹‹6Ξ©·A`[/½ví<~‘�Cp!åo!`[= Í\]1ê}íé£Þ_ˆ¾a!xóÙ‘Õ(êÌ‹‡!ok‚Xºu'z?QíAÈ�5t ðëÂJqè5t 2rn ó牢 Ú£I³BÀU¨TàÝ)cà‚ÇüŸ@NÖuƒ‰¨+³’§±‰ŸËû´?ÂûÐgà3û›˜åæd}^<ßiVfz¹óô‰ÛdNK¶��›=C4""cÔ%÷€Ò‘ �;9bÛÂ÷ñɦ­B”z=[‡í¼dQCd e2¬Šž†Ø=p6)жÑþR©[µT×»«oXˆpþC§ã1éé¡zuX›ÜÉs£^ÄüØM´CK×Îz«FV-�8dœ7zºéî©okwDt쀉C`nì7zµRíôÔð1hÓ¶�`%'Ä (è¼<%ºÒ«¡ú‹'û´_ÌÉÙ³­Àº•‹…:ta[h·^è?ìY½aAÆz ÔD›t²®§WùD¤b*wu�¯�·Ô¥T»þ}#У·u†öø ’âwxüŸPþ$ýå)û}RÌÔP~[çì"¶OÿÅä÷}ñTº¹ñÌÜIØ>ÿGœ^°'~MG¼Ú÷ų'�f�q‡÷½^ó–­ª½Md›¸ÙŠjJêÕ_Íä.ØþÑl‹Ž÷zzóÙ‘Ú€ªœóŠ'î/K||3¹áëvv˜õÞ|v$2snáf¾àÛÊ^-[”RµÌËÞœ …ªg’’áèà€ï6!Òü¨—0ûå‘«(ЫCWE½¼ÌÝO¬Oç“«ŽZóž3ªw8Fõ‡BUuÉ=ƒU`¯fiçÇÒ-ð@5£}§®X°t-ë  é‚åßì‚2?iW’„ç}ÚÀÑÉÅä§ââZÄó¯•Çœ^NÎ.˜þîGÐh4Â$Ï®nM…I§oˆVh3µê\u·I·‘”t�N¡R�5Ë0œ¤(!]/9ÂÐT±„ø3U®3áÂi«|Èa)'g¡—urB‹ö�ºâúµ4l]÷%²23àì*7™"þPèì©cèÙo\åMÊýУ:ˆçö\4k*^çC´ôðæ½ò×e¬_©æëì*G§'-Ÿ3÷ÉF sŒê÷Пj¡P©ÀWŸ/ÄàcѼe+ü•p;·¬A¡R¡„–5xÄXá5cmÏyZÙ6‰9r%S›ÀÀ�ˆˆ¨–K½‘…åÛ~ÂÙ¤„øáÓiÿgÐCðtbé'åO>.uÉdÃÎÿ'ü‘fêÓ~±}?læp36ìS£ÑàÔñ_„Ç ¾ˆ¨¾ë1@òY™Õ¤;=.„ƒ93&=Þ×/£ÇO¶ ««­Mbå¶TsH]@]öÐF¾ˆˆ¨nómå…J»ÐÄÙ¤¼õÅ„Uiïk4XúÝNDù5ípÒ°@Ë牡ºMUX€3'�bÝŠÅÂnþA!0ì¹ �õ"DèÖ¯ŒABü”¨Õ´CI?ù`šð‡Éèñ“¤n*‘äZyz stõú¬ÅÇËd2ÌZ´ž^zÏ{xzaðȱ˜0e¦ÞÜ™–˜þÞÇç•B—îX°t-üƒB ^sv•#bÀ0Ì[²¦Ü*"¾÷½2™ S£`ôøIíÖK¯Ž͉Áˆ1¯T¸2lDÿ¡˜õñŠrÛôá²oªÔ&²-ÿxø�ƒ ­¡GïÁz:îAR—bà—�cîûÑèß×öj#"ËÌýp1 *¨–•D©vK½‘…ñ *^EmûG³Í*{ðô9Ì�Ý„¿î•ºy’:xè(惛êæ}¸�›cð‰¼³«³­(w±±u+ë­&jŒP¦¿û‘ÔÍ­ò}ÚþíZ¸·d/=¢ú¦GïÁ5ÞÓË%j5ŠTxÔÎÞìïÙµ‘ª°÷JÔVÞ*þÙõÙšU>ïу»±mÃjÚyC+깨k“xÎÓš¶nÅb¸6æ0S’ë×uRjm5_2-%""@ÛËíÐòO°úǽª­b£ú„ãùȈ*ÍëGõƒ‡§¦¿÷±E¸M˜:=û æsv•cÀ°çù”ÔM#"ªsªkžP[£ý™d½@ñFfº¶E Vá=Ô›JÅmøúÝçêÿüqv•›5LØÚm"ÛÃÀÍÊ€‘Tìì0㹘ñ܆•–]­”HÌÕ­©°‚gUzHøúâý�W(ýÃàœmDDd[JÔj¬_¹XxÜgà3³dþ¿„”�‹§†�Ñ{=!þŒàUuÁª;¸ÕQìÍFæ0µ²hUÔ—DDT;¨ pî÷ã8ñëÏz=±'¿=ϬŸ�ÏOx]XDbïŽÍ¸S¤‚·¯?<<½qp×÷BØæì*ÇÀ§Ÿ—º¹d#¸YѰ‡‘-ù+á‚0¿šÎà‘cÒŬã}ý1xäXìݱ„UfËzeú¬:=—Y†�›-czGDF\ÍÊ‘º¢zIUXÀ_¢ë1µºXꈈ¨’Üš6‡³«…JüƒBÐgà3f‡m:O ƒðÈÁØÿÓVj§MHIº0ì9tëÙ�½»I7kz«†dÌÛˆ¨¬à'pèð1—”pN.ªv'.'@îÆ€)8(pëæ nõXVf:ÀÕ…ÿˆˆj_¿@|üå¦*ŸÇÉ٣ǽ&us¨–h uuÍC+~•Õ±C0àJæ ©K¡zàjV:‡t�º É5kÖpþ�¸*ž‰j³Üœ,€ƒ{/QŸÕ"¾>Þ�»¹`Ç1þáOÕëÒßiH½ž�ýúH]ŠäÊd5bŽØ�F#u9$�µ{wlFÔËc¥.…ˆˆˆj nVöÀ¿ˆ¨nyùÅpèt<Öî9 u)TG)TE˜õŸõ�»¹ ¬K'©Ë± 숙ÃЭžÑh4øêó…€A"¥.‡ˆˆˆj nÖfÍ1¥›JDFŒ>£F Eìîý8y9Qêr¨Ž¹ôwÆ-\ È`YÌ"4”ɤ.É&øúxcÕ1HNˆÇ†ÕŸJ]ÕUa>xã%$'Ä#æãypoÙBê’ˆˆˆ¨–ࢠDDµÐ´)¯"=#Ñ_~�¾a!?°Üœ�!wr”º4ª…îk4H¼š�Ãçâ±ýHän.Ø» rWN/Ö>(QÆ"vÝfd]OÇÓÏM€{«6hÒŒ!L]s#3ÏžDÜá}(T*°ê‹´ ”º,"""ªE¸Y;“QMi(“áÓ/À†ÍßaçO{phAŒÔ%Q1jÄ0L›ò {¶™0qü´öðÀÆ-ßcÕ’yR—CÕ,´sæ}°‚á3ÕI)I—Ö¹½ÔeÔY Üê0€Du[C™ Ç�Áø±Ï!77—’¤.‰j™?“’OøÃ×Ǿ>ÞR—T+ôï�þ}#�}3WÓ¯¡¨èN•ÏyçÎ]4nÜHê¦Õk׳²�qí:zt CË–ÍàÏà™ˆr79ÒS“Ñ¥{„Ô¥YM¡R�]ä.£ÎbàfEP!S4"*£¡L÷–-8·Y¬ß©K¨Õ¬ùÿÝo¿�OΆƒƒ½ÔÍ"""#"#±}ç.Œó d 㩸�›#u uM°&.€@DDD*.Vãì¹x\¸xYêRˆˆÈ„ÈÞဤËç¥.…È*ŽìÿÞ£«Ô¥ÔY ܪ‰Ô “2£#""ªtAÛ·ß""2!0À>m½°jÉ<¨ ¤.‡¨JâÏàè�]ˆš0–½ë«7+cÈEDDD–غíÀù —P\¬–º""2¢¡L†åŸ} ¹›‹fMeèFµÖ¾¶`Õ’yí‚ñcŸ“ºœ:��[-ÆnDDDµ[q±çÎ_sX)‘í’»ºà럢P©À¢YS±ï‡-¸�›�F#uiDåR !þ –ò>öîØŒQ#†áÓ/àâ@ÕŒ‹&XÓCà!."""2Ó•Ô4½Çû9‚î]»H]™àÞ²¶»«¿þ{wlÆÞ›¥.‰Èl>m½0÷ýh.œUC¸IäБcz�9Ž9³Þæ'ÎDD6̽e ÌŸ=oN{ ™×oàæÍ[R—DT¡.¡!wu‘ºŒz…�›q'™ë¾Fƒ?ì1x>1)탥.�ˆˆ* wu�ÜÕ…ß³‰È(ÎáFDDD$�Ĥd£Ï—íõFDDDDµ7eî‚¡�7®¼/"""²=¦‚µ?ìÁ}NÀMDDDT«1p³²ŠÂ/s¿,J܈ˆˆ¨V15œTÇTï7""""ª¸Õ°ŠµÃ¿ÆI]"U7+²´cZM}‘m9{>¾Ü×·ïÜ%u‰DDDDT ܈ˆˆˆjØ63µÔ´t©Ë$"""¢JbàV]*èvf­¹ÞÌšŽˆˆˆlFjZ: Tîwì·“R—JDDDD•ÄÀÍŠˆƒ.p˜'27H3§Ù&nuÃ="""Ûdn�VX â°R"""¢ZŠ�›•I½@C6"""ÛeîpR+%"""ª�¸ÕUL߈ˆˆlŽ¥ÚŽöH]2U7k’`A“_`ÞFDDdkýzÜ¢ý•ÊdßÌ‘ºl""""²7+cÀEDDDÆ(”ÈHÏ´ø¸§NK]:Y¨¡ÔPå0Ø#""ª]ä®.8ñë^£¯õè=sß�Fÿ¾R—IDDDDVÀÀÍŠ8„“ˆˆˆˆˆˆˆˆ¸Y‘Z™Uþ¤q%Úy_KpGˆˆˆ¨"ÅÅj©K@öÍœ8u?íþiW3¤.‡¬Lî&G§�ö5|ÚJ]Q½ÀÀÍJFކŸìƒG×1R—¢ç¿ÿ-´õn#u)DDDd„² @²kß×h°pѧ8täÀ?(/OyVê[BV–pá4Μ¿„ÃGŽÁ§­–ö1ä®.R—EDDT§1p³’®]:aÇÎ]¸›—ŽFM½¥.G�}ú{€« ©"""¢R÷5¼õΜ=�Á#Ç"rÐØÙÛK]Uƒ.Ý# Ñh�tùƒöÃÞý¿àòŸIÈÍ/ÀÅ_WWûuûôî…ðîÏ¢KhG®ÞR—@õPQÑ©K ""ª“¸Ù€F�ØãŒˆˆˆ¨®à�R""""²9�Êü<À£vöpr®;óÓ–¨Õ(RiçÒsuk ¹"""ªs¸‘YÄAQe5ifÞ|aÊü<Ì™1Ú­&L�)uó­æÒùß±~e `ÁÒµfß"""ª=¸‘YÄAQe­Ø´WêfU;nDDDDds\ÝšbÁÒµ´CJ‰ˆˆˆjnDDDDd–ö�º !XY›c—#9!0ùíypoÕ¦J×’ÉdjIDDDµ7""""2‹�½=ìì�÷6sr*]ÔÀ½U†eDDDT¯1p#"""¢•š’ˆü¼[€.Ý# *,@FZ ònÝDôе—ÎÿpkÚ¾~�çÑí“pá4Tª$'Ä#´[/@Ï~CŒcìú�7³2qñìI\8ýÀ£µ7ºôè� �.&ÛQ¢VãÊ_—‘tù<Š Ð£5:„vGKOÈd2ƒëXBUX€¿. =5)‰~�àíë�ö�ºš >‰ˆˆÈ60p#"""¢uü—=8{ê Ó“áX4k* • ÚI#úE‘ª@X !´[/ƒð¬D­Æ¿^ipnÝyÏž:ÿ L�^™LVîõWÄ̆Ãêdefàì©cÆà:ªÂ½ºuöîØ gW9æ-Y£wK·„ø3ؼf™Á¹³23„í͉1(‘ô¸Ù€«é×àÞ²þ ÃŒ;¼…J<<½àÑÚmÛ˜uÜ–ØåÂvÄ€aðöõ‡[Óæz!WrBk(“aÔˆaØùÓ>©K‘Lä f‡m .¾‹Ñã'!´[/ {ö%ƒ×íìíá"ÂvJÒ%a[UX ônó 1vz2Üâ{‘üg¼°Ý=b€Éý‚;† ÛÇÙcñuˆˆˆ¨úqH)‘ĺt‚¯¯¢ß›‡=?l�ÜÕEê’jLe‚)±Û¹9P*n «�¦§&£¨°Y×ÓÍ:¾Chw£Ï‹C@ñâ÷JÔ¶““é÷©yËV·%'뺰}ñìIdeš×"""²= ܈ˆˆˆ$ÖP&ò%c\ÔTŒ‹šŠ�±+êMèæ*oR©ãnd¦ãË`°’§¥ìí*}l�¨§YYNΥ‡\yÄ!aeç€#"""ÛÀÀ�ˆˆˆÈÈ]]°1v† ƒ!ÃÇ jÂXôúgw4jäP/W/-Ïу»±mÃj᱇§zô„ÆŽN‡F�qíê› ­Ì ‹T…¶¹+›::×�`–ˆˆ¨¶aàFDDDd#ä®.ØþíZü|ð0b×mFì:ÛŒl�xÑ‚͉�¯_ Á>ÅwïT{¹9Y&_+Q«-8“–_@{aõÕQã^Óë%GDDDµ 7""""âÞ²&ŽƒF�€² WÓ¯¡¨ÈzáÑü�b¤nb•ÜÎÍÑ[´ÀXØhçr³ñЧbâ9×ÊÊ˽iñuĽմsÅ1p#""ª­¸Ù {88Ø[}8ipPF½0QêæUZÚ•$a»[Ï~F÷)Q«qôÀ.á±Z]\¥kŠGpuk*lŸ=u ¦Î4zÌų'-¾Ž·¯¿°ýÇo‡ñÔð1F÷Óh4¸{§ˆ=àˆˆˆlX© """"2×ãA…íSÇ1x]£Ñ`Kìr½ç®$]¶Úõe2" 'ÄŸ1¸þ™“G+5\§'Ãáì*ÄÞ‡Û¹9F÷;°ë;¼;e Þ{ýEÜàJ¦DDD6‰�Õ¨ªLôïäì" ñLNˆÇ™“GQ¢V£D­FjJ">ù`Ξ:†—§D Ç\:ÿ;nçæ@£ÑX¥þNO† Û«–ÌÃу»q#3]¸þú•1zÃPu!ZEd2FŒy€v¡…93&bù'ï#5%�72Ó±ï‡-B˜çЭ<½­Ò&"""².)%"""¢%:Y}>ƒä„xÀú•†sÒ�? ]ºG 7' {wlFrB<æÌ˜ˆ—§D£K÷ˆ*×ïëˆÑã' +¥ŠWL´ÛkoÎÆ¿^ @Œ™«Ó“áBÝ€6TÔµUÌ?(ã'½Uå¶Qõ`àFDDDDµJPHÌúx.ž=‰¸ÃûP¨TÀÙUŽðȧàÿDéB ‘ƒFè-làÖ´¹Õjˆè?í‚qñìI\8ýŠT…èôd8‚;¡ÝãÁ°³·¯Ôye2ž>B»ãà®ï…UKm�'¾†L&“è ""¢ŠüãáÇ¥.‚ˆˆˆˆjFöÍŒza",]‹&ͬ» ƒTT…6·€ÀíÜÌ™¡]œbôøIˆè?´Òç*Q«qï^‰UÛ¨«oîûÑèß7BêÛEDDTçp7""""ªÕj:l+Q«q;7gN…ª°Àè>Ù7® Ûí‚«t=;{{› ‰ˆˆ¨|RJDDDDd�KçæŽsv•cÞ’5zCHoçæà§ïÖ �[zxJ]2Õ0nDDDDDèôd8vnYƒB¥…J¾ú|!ºõìz Àä·çq®5""¢zˆ�‘d2Þžû)V6Y™&Wž÷–-¤.‰ˆˆ¨ÎúÇÇJ]Õ¼K ‰˜<-ήrŒó |ÚÀÑÉvÿ[X�j?�FƒôÔdœÿ#çÿˆC¡R�U_Ä }P Ô¥Õi ܈ˆˆˆê±K ‰X³~3Î�‹—ºªf£F ÃË㞇ÜÕEêRˆˆˆê<nDDDD…²ùù ¤¦¥K] YYË–Íàψˆˆj7"""""""""+⢠DDDDDDDDDVÄÀ�ˆˆˆˆˆˆˆˆÈЏY7"""""""""+bàFDDDDDDDDdE ܈ˆˆˆˆˆˆˆˆ¬ˆ�‘1p#""""""""²"nDDDDDDDDDVÄÀ�ˆˆˆˆˆˆˆˆÈЏY7"""""""""+bàFDDDDDDDDdE ܈ˆˆˆˆˆˆˆˆ¬ˆ�‘1p#""""""""²"nDDDDDDDDDVÄÀ�ˆˆˆˆˆˆˆˆÈЏY7"""""""""+bàFDDDDDDDDdE ܈ˆˆˆˆˆˆˆˆ¬¨¡ÔØÍ T÷TÐ<¸/u)D6AÖ !?Ò�È‘¦€€»wµÿ%" AÀÞh(Í�ð‡�;÷€ÿj¤¾D¶£Ñ£€«&"""þjð?%÷K�®¼ŠÂ’B©K!²InnhãâUsÁÛýûÀ͛ڰ�ˆ 5j´h™ ðòªöÞn÷5À_·€ûìhJT¡ÇšŽvRWADDDR«÷s¸Ý¾›Ç°�ÈL÷üÉy¡Zsú¢"†mDæÒh€ŒŒjr]ü_ á&Ã6"s¥çkCj"""ªßêuà¦y Aš"Mê2ˆj•âûŸVp­zNþð!�•%u‰j�ÈÉ©¶ÓgäKÝ@¢Úåþm�P"""ªßêuà–w7Oêˆj¥[wrª§—ÛNET)*Uµôr+*Ô\CˆÈb÷h{‡QýU¯·¢{*©K ªµŠîYÿ¤*þ?ITi%%V?%W"%ª¼"ëÿ/IDDDµH½ÜŠÿ[,u DµÖ= ÿ’ ²)jµÕOyçžÔ�"ª½øÿQýV¿·û ܈*K©VZÿ¤ìáFTyÕ¸q¡""""¢Êi(uuI‰úì앺 “Î�¼Œ�+wf¹¹ã€'pIDAT/}Mš¹J]’Í«Ë÷ìÍç:u Âø©#¥.§^:xúæÇnlÿh6Ü›ºI]’Í«Ë÷¬Çk3}ÃB0?ê%©Ë©%j5ììí¥.ä3'�býÊÀËS¢Ñ¥{„Ô%Ù¼º|ÏÖ­XŒ³§ŽVlÚ+u9DDDTË0p«‚¢Â;¸ðûŸ¸z%çO%Ü=›£CX Ú´õ@`H»*�_ˆãä�–­šÃË·5Ü=›Ãó…Ô·ƒÈf(TE˜»g“R'¾Zj•óêcBüàêÔ=‚ƒàÛʾ­<¤¾ D’Óh48ÿG.œ‚ �Á#Ç"'/'"ú˯küººpïÐéx€ÜÅ #zöÀøA}ÑÐÄù-Ýäè°·³ÝÞ±¶„÷¬ö¸‘™Ž/ÿý • £¯ïݱq‡÷áÃeßTK–•™�¬Ì ½@.bÀ0ŒóŠÉë¹5mŽÐn½„mªï‘q Ü*¡lØ6pdüžh ¹3/¤àä¯ç��y ûwÕ¾n…ÐmÜ”z�ï ×€"å]ìØð3.ŸOÂkÑ㌆n>~màã×FêÛW«ðžÕÅ%%ødÓV!ðªns£^Ô{\xç.výv ©×³ŠbwïÇÅ¿ÓðÉä‰p°³38GûÇ|Ðþ1©o]­Â{V;¨ ôÂ6O/ôè=ÁÃpùÂiœøõgdef P©@Üá}ˆè?´Ê׋AUnÒhàøí0ÎNÝ‚ŒÎÓfgÿ(&Nˬܸv³ÚzI9:7F`H;øû⫘�HIHG‘ò.>™µ3澪7ɉúŠTÚ ÐÕÍYè§Ñ<€2¿P{>§FB8¨ óìÙ¡U›–FCÃÛ¹J¤_Éx·ó4kQ�õ=ÜÎU½ó¼Ûyê]ר=7VŸFó9Y¹Èμ‡FöhѪY…ן+çF. ��‡ÉpÒÔ=+«¨ð Š„6¹{6‡³‹£Éó–צŒÔëPä˜Ý&ñ{U|W»J¡%ÇÖŠä.NXöÆ$ø¶òÀÁÓç$©ÃÁÎ݃è�·¾øÎ&¥@Q Â�·gLò_\R¥ê ™ÜEzz_£A®¢àêÔXè§ óìÑγ•Ñ^sÙyù¸œvìÓÖ¬EtuèŽómå�¦MŒž_|�²õÝ×h�q3©7²Í¾¾¸­W³o¼Û˜ 'Mݳ²ª"ä µø¶r‡›³³Éóšºç•i“îúIé×PT¬] ÛÑÁmÝ[Ö©EÊsþ�8a;rУûôøŒÐûì^‰@Õ7Sììíáëˆ©Ñ °"fŽº}¶ ³>^�VžÞ¾%j5ŠTÚŽN.z <ÜÎÍ—ÎÿnrÅÍ93&B»õ˜¨éøêó…zÃUÀÙU. WMMIÄÖu_"+3Coÿ L˜2Óh€¥Ñhp`×wØ»c³Ñ6ˆÏ_–¸¾ Sgbß[Œž§¼ë›ªYwíÞ3þ[Þ=Óµiç–58z`—É6½þ·zÁ§©6mÛø•ÑóTtOÅï¹%×'"""ªŠU?Eý¢È+¶[´jfr?™¬Ü=µ“ëzÄU7™¬ž;Px¼ÇQh4,:GnN>–ÎÿÙ™·àèÚŽ®�„×RÒqòðY¤¥\ÃÆ•;Q¤¼«÷º®­'Ÿ58oQá,|{™AH¦[�@wþ¹o|Š¢Â;0%#õ:¾ŠÙ(œÇ/È[ïõó§ðË®8ƒã¾ŠÙ(Ô¬;®S· ¡þìÌ[ظr'nç*;WY™9ødÖJ½�¬S· ƒ6}2k%²2sLžçnQ±^ئûw#¾§ñüiôØ +·ë…m�ºéŸ�y +ÿ½%ê{f·«¶šõ’Í„m: e2¼ûâsÂãØÝûq_£±è…wîbÜÂÅH½ž ¹‹ä.NÂkоØþ.ý�†è/¿zù‰÷9t:~>dp^…ªϼ7ß Pê"¯«P™¬/îbÞúâ?ÂyBüô^7uý/¶ÿ„ù±›„°Í·µ»ÞµS¯gc~ì&¤ÞÈ2û^eçåcôì�ôÚÔ7,Äà¼CÞž]îyÿ¼šQ©6À¼Ø�za[ß°ø¶v§^ÏÆËV—{Ok;™L†&ÍZ (¤K¹C6u½¢jº¶×Þœ-<ÎÊÌzQYB¶yxz Ï*X·r1T…X³|²23àì*‡³«\Ø'9!Û7~epN]0T6$ íÖK8¾P©À»SÆ 5%±ÜúÄa›¸¾ò®ôàn|¶ ZÛ<<½Ú­—p|¡R�mVãÌÉ£fß§µ¼ñ’^HæbЦEïM­ð¼û~Ø"œÇÜ6À�]ßé…mþA!ð Ñ{Ͻ77þ×cŽˆˆˆÈZØÃÍB^H¶+®çÞº¹ÉžGÕ¥I3¹Þce~¡Eà ……FF ß°pÚ�kíòï„…íª¨ÃÇ DÈ“OÐöâÓõ;°ëÂû‡é�wçÆýza—¸'ÛsQC…žoEʻعq?ÆOi´>ñpÞÁÏF¢I3W”¨ïéõDÛ¿ã(ú Î_¢¾§f½ýákz½Ånç*±tþ×(RÞŚϾ5xÝq€WvEÚñSGbÿǰÇQ)ïbãÊ�xçãÉFÏ£»§åµé‡-û zß%Æ_ÚÕs@FŒ¤×¦½ßîéÞm‡õ^§šÓL®ßã"WQ`ѰBݹ‹¦�z}:‡Žœ‹z‚í<~Â`µÔÏ¿ß!„]r'½9æÄ½Ä*¼ñùJl˜=Óh}ºÞ{}ÃB0éé¡poê& }Õ­»{¿P; íݶýHœpm]/=…ªã.Ö^{Ùjƒ×MYýÓn½yüĽ `히ݽ0í&½6‰W<ÕÕV¶MâÞu±»÷ÜÓK§ ÷cTŸpÌx®t(ev^>¶>ŠíGâ (Paý¾ƒz¯×GÙ7® ÛŽNÕ3œÔ;{{xxz ÁRÚ•¤r‡5–¥[õT×ÓÍÎÞ72Ó±có×HNˆGrB<Þ�¢�³nðȱˆ4vööHMIÄšå‹P¨Tàì©c5î5½Yçÿˆ‚¡²=ÙÊö|[³|‘ÉÕ]uõyxzáù ¯Ã×/�é©Éå^ÿį? ÛŸ¬Ü¢÷Z‰Z-„ŒëWÆ”;ÄTìðÏ;…¹üüƒB05z�^Í©)‰ølA4`ýÊtz2ܪmº�›£<¾ûáÂùU…ØÿÓV!Ä+ÛÛ‘ˆˆˆ¨ªØÃ­†XÚÓ¬²ìì5è!e©™OÂÀá½ “5€LÖ>~mÐéÉ ½}f/y�» ûtî,ô6+RÞÕë¥v;W©×#­ì°Q;ûG1~êHô  éΟJ(·—ÛÈñƒ0~êH!H´³�»ëµ[7?¤þU:4fès} ´&Í\1qúsèÔ-Ý{wFñ�â ïQZÊ5!LíÔ-ÈèJ´‡÷z»egÞ*·—›©6ézà)ïô¾Û²æGa{ðèHƒ6 ~¶ô¹›7j6ø¥R e2½NwKÔŸcUô4L2@¬Ú?æƒ={¯+ TØ8{&ú‡uFC™ e2ô댾a!ÂëºùÉmø£ë½U6l´óÐÍ�z £úhC÷ÔëÙœmÆD ˆùQ/ A¢n;qÏ0ݼk�xµôÿÉYãž7ÓäNŽXöÆ$ô Á˃úéÕnЏM}ÃB Â6˜8d€^›.ý�¦wÍŠÚÔ?¬³Þ{Y¶®YÿY/lOzf°ÞkîMÝð|d„ðøBÊß–ý#¨c4 ~úN;ÏéËS¢M;­.~�ªtüèñ“0aêL¡îVžÞèÖ³ŸÞ>³>^�§†�öñõ DxäSÂë·nÞл;·¬`|بL&ÃSÃÇàå)ÚpªP©@zj²ÉúüƒBðþÇ+…†2™ ¾~�èôd¸°Ï_ „mUa�@9Ö L³³·Ç„)3Ú­�‹ÂE…÷¨D­Â.gW¹Aئ»'º6úsÿU¦Mi)zÇìúþaûù ¯ë]ßÉ٣ǽ&<ÎÊÌ€ÆÂÈDDDDåaàV��K‡[Š êÖ.Ð[ØÖ- `‰†CeÅsÒ¹{67ºÀAËV¥�WIÉ…mÝ¢ 1°»ÉÞcºÞrð›hXjÙz¾^F�ïV:tIÜnûF¥óOmYó£Ñ0Ïǯ ÆO‰ðþaf­îšòçUaûŸýº˜ÜOüÚ¥³™Ü/°£ŸÑçÅAg�BÿßЇ_FãóMsñù¦¹Fßñ}35ÇÕŒˆŽ¥Üë&ß·D;ÏVϵnÞTØ–»8] À«EKa[ôéG´�—©…†ý³«°ýóïgLÖúx;£ÏwxÌÇè5›¹º Û‹6n5:¼Ò·•‡6ôënV�À—K‡]�ìnr?q›Ÿ‹7¹_¯ŽÆç¿—ºEtö,^€_-ʼn¯–�÷NÜSs¼Õv}‡¬Ì ø…ÌùU¼}ý…íÜó‡-ë´ 0ü÷áÓ.@ïqKOƒ}šµ(�»/?¯ôƒ�›Y™BO°ðȧLö{<¨£°}ü—=&ë+þéw2ÚîG-ý÷ºwÇf£Ãl�œ]0aêL<5|ŒYó�]ùë²°=`Øs&&hß©ôÿÉSÇ1y¾>Ÿ1ú¼ø½Ì»¥ÿÿä„©3±bÓ^¬Ø´×äðfñðRe~^…í""""2·jÔȱQÕOREâ°É~AÞF1qï1q°%&åÄÄÃpÛø˜ž(¼U›ÒpàV–é_zM-Ь…hõÇ»¥á‚�_¡§Y‘ò.V|¼Y™9Uêu(®ÏT»Ë¾fªMŽ®�Lû/ž?Д۹J½¯²sì‘ô,Úß·µ»Ñð&ا­°ù¿a¤e‰C9qÐ÷§¨‡Y[÷–0Å«eéÿk97MîØÖx.¾¾˜{S7½Þwã.Fê�,‹ç·»œVÚ[ÍX@)ÜOÑbÊ"•Yû™j“nÒòdçåë}‰{ÈÕG�ëV,z>M˜2³Šg¬‡F¥¬4jìdññÆÂ4ñ°XO/£SÙPN'K4X›¶Æl@zéæ/Ó ³4F̉¹·*]À)'«t(;{{ 9Vx¼dþ[HMID‰Úò¹:âÕ@ƒ;†™ÜÏÎÞ^˜ÏÍÔÂàåcüƒ)ñ=½ú¿PË£*,ÀíÜወˆˆ¨ºp·j$X�´ÁGZÊ5üö‹ñž"mÛyÌ}VWÓ…m¹³EÇw2þÇ€�}éü~O´5÷t€"Q,©RÛÄ Xb𳑰ÖìÌ[XüÞjm[‚¼1°;|÷2ÚKÌ”ìë¥=Ê›ïMüZ‘‰IÒý|PYE…wpð§ã¸’˜^ãóÖ—þNÃŽcƇ1ûø`Tïp Ïhè¢hèby—1âU¦sæW++rÐ!-T*„¹ÕüƒBоSWtëÙÏ¢¡¿å y-Ë/ }¹beÛ”Î÷wòŸåzDDDDÖÆÀ­†èÂE^�ÁJ�bU Ü4šzÁ‹% &@#ÇŠ{ßXâUf8c‘•WðkÒ̳—¾�3¿]†ÐÕ&^x`ðèH³‚·Ê„[ÖÖyîäeaQ1½UR“Ò„…ȸ›ù ƒ•:Ŭ¸é&Ò Q¨ˆ©^b–}¦‚¦òœKNµJ:îMݰý£Ùøù÷3Øyü„°ØÁÙ¤½…^~ª¿É!¯b彇¦X;;xúœ°¨‚˜8À;—œ*´µ>¹‘™Ž/ÿý •ŠrÃ6@;Ô²¼ðÅ�ÛßÉ¥C�޾ÌádÆâ¡£æ÷6“Š�½=>Y¹ç~?Ž»¾†¸ê‚ضa5üƒB06jºY‹LVnZUaA¥Ãµ²ÄÿîÄüƒB„÷1ëzº0‘51p³PÛvžB`VTx§Üù¾Œ…Fò¦.&{iµm牪ϧ[ÄÀÚ –­|êä-„M3?ž¤×[®&5iæŠ�Ã{¡ß°pd¤^GÊŸWqñt¢ž?p�]¡,wOËW µæûQTxG/l9~ºG†ô¶û÷{«¸U ¥›Üd�¦`ŸÊ÷>Ô/6àÛÚ½R½Á¬­­G !lŠyýU‹{ÝY‹{S7L2ãõEÆÍ»pG/\jÛ~$.�]¡¬¾a!‡nÖÞY\R¢¶E h°Š)Ì�ý¦Rá`m&^‰ÒØJ•e¹5mŽÐn® qO'W7ë„ÚUÑ£tú€Éoϳ8´'gDôŠˆþCq#3W’.ãÒùß…û•œ�ÕŸÍ7k5OÇJ†fÖ Ûè…m†aØè— zémÛø7"""ª Ü,Ô¤¹\ؾuó¶ÉÀM£y „LâùÏ|üÚÀǯz~‘Öhà»ØŸJ¯åï]-×Qä~æïï(ê�bgogq¯;kÓ­¼êãׇ÷Òë)¶ÇQôÔ­Â^nî­K7�æ�Éa¥âyâÍè¥c®ki¥Ã�FŽd²g$‡™V¬ýc>hÿXÕƒ5S¶>*l›3<´&¸:–ÎYÕÖ½¥Y‹T§†2|[yÀ·•&€“—ýå×€ØÝûñB¿‹†——”˜µ[�Š{é˜ëBJiÀ¨¡M†„Öî)hëöý°E¦hNØhW®45Á½µjÒ15×ZM÷ˆ+¾{ǬdÕ­•§7Zyz áÛ¢÷¦Юæy#3½Â…Ä‹T$%é’Uj—·ss„°Í?(DoER±ÊöÄ#"""ªM°�ïã¥s%‰Wª,+'«t•Ì¡Ïõ­‘Ú~Ù'„|Ž®�ÐoXÕ‡ÂYƒ¸ç^Ù•6mAçîÁè9 4°J8_ñ¼3Í=J{Dd¤š $~M|LeˆƒÛ³'Jÿ8éØõ £ûßÎUVßM#³¬ÝsÛ�h燓»8á…~Ÿãú-믚'žó­ìJ›¶ {p ¢†ûËÑ �é\ÚsøJæ “û¥Þ( «ÅÁcUý‘Xº ±©N³óòëÕpÒm¿Ò Û¦¿û‘äáVBü¡&˜ô¯¹ÕrKW>ukÚ¼ÒÇêXÚ+PNU¤•§7&¿=Ox|p×÷#^˜âò…Ó&÷+Q«…`¬ª=ÅÁešhS+œj4«…}DDDDe1p³��ý£ÂÐÀý;Ž¢¨ðŽÁ>Íü¸y¿ðXÒU‡õ=ìÿá˜ÞÜdÃÇ ,w2ÿšر´;ܶu{Mî—–r +?ùqO£D}¯J×Ô…SÍlX±ÿ~ovnüÙäþ!O–†Vw‹*^y°Ë?K{*™Z£ìkíC¶]Ý,›Ð_¸BÞŸïnï÷‡õWõž’ùŠKJ°vÏÄî.ý>0}ÔÓ•Z ¼ÕA+K¼ÂéêMONŸz# ã.Æö_ã °Ò¼Š÷5Ì�ýã.ÆÜØoLîúx; Ϊß&S‹`À± —…mS«»š«¥[i�g—Æ¥áÂ�bã+;®þi·ÞckÝS[t;7Gì8»Ê15z�¤õh4$ÄŸÑ[� bÀ°jëIféœlÞ¾þÂJ�{wl†ÆÄнªÂ,ÿä}ìûaK•W؇SÛ6~…埼�埼oòÚ¦V 5% ¸“°}âןMž÷Òùß…í ŽU_8JGøåÝ2þ}ôüqzó»©Õÿü'"""2—m$2µLÄÀîÂöŠ�7èõ$**¼£×Ó¬S· ‹V¿4E<4Q£y€Û¹J$Æ_ÁÊO¾Á;¯|¬¶ùy£s÷àJ\¥z4iæ*Ì[—�y ÿ~oÒR®éµév®k—‡”„tØu¬²—èÂ)™¬²¯ßBvæ-?pçN^Ö»®î~®]þ�ð¸•wÅóY‰ÛtþTöÿ`XóþŽ óýuêÏÒ?쪆ŠÃ»C»~ÓkS‰úV~ò ΟJЛ7îÆ5ÛëÉd- U²óòõ¾Ä=Ãʾ&žW­²î—ùã1;/'/'â�ÏW¡ïôwõ¶Ð?ô©d¸#î¹e-îMÝ„yëR¯gcüÂÅ8y9Q¯MÙyùxcÙj¤^ÏÆúŸ±ÚµÊdPªî"õz6�ŽÇö_ã îå}�³þ³^xü¸WÅó[ŠÛtèt<Öî9`°ÏÉˉÂûâÛÚ½ÊC‰›¹º Ûƒºv¶wÓo“.d(R í9~Âz†à�W>,_°�ºaĸ�å.öQ}þýŽòW}ßðÿŸ_-­Ò5{MyÛ¬ýæF½ˆþa�%½?Ƽûâ󊙩׳ýå×�»8¡³¿¯ÁJš_Ï|Ó¬•BÍ5}ôÓ¿@ûGöÒ­;±tëN„ø¡Ãc>¸øwšÞª®¡~ 4o.¨7Ÿ)Ô»{?v?�ÈÎ!P©p5+GXŒAîℹ_´êýtoêßÖîB�xèt%ùðÖ²:=ŽSÇArB< • ¬_ƒõ+cÚ­—ÁJšÿšSáj–�Œ¸ÃûP¨Tàè�]8z`üƒBð˜ÿÈɺ®·j¬³«�»ö4뼑ƒFàÂéß�•™�ä„xLiB»õ‚£³ R/êµé•鳬úžÈd2D †£v!+3ÿze$B»õ‚JU üû íÖ ¦ÎÄGïMAVf¶mX�KçÇàc«uA"""ªØÃ­’ï…‘ã �uA’N§nAx-z\� ëìÔ-GFàÕoÛdØŽÎ�1Ù[z+´)ïâü©!˜ò òÆô9¬åÜ(�CÏó>\ù¶ÞµÏŸJÀþGõ¶žÂ,zÏš4sÅ»‹¦½ÈŠ”wqüÀiƒ6Í^òFµ,1nÊ¡Mº{™’�G×FÂB vö�bàȽv—”ü×êµ�¾Ð?D ˆ=KÚdØvvøñã¹Õ§´G‰¢@…C§ã…°-4À«¢§Y}QßVسd¡Þê°g“R»{¿^ØÖ7,ŸNû?³Wv•;9bÛÂ÷à'´gû‘8:/„m¡~Ø8{&|[y˜uÎò\NÓŸÇsîÄõÚ´ýHÎ&¥@îâ„Ï�ÀÄ!à`g§7?ÝÙ¤¨KêÖpokôV³6ÿ D †K×"¢ÿP› Ûm@4ýÝ�0zü$½çÏž:&Sž^=~’Õà 'gÌ[²† ÏézÒ‰Ã6ÿ ÌZ´Âì•Díìíñî‡_è�÷ì©cB¦kÓ‚¥k«%àøôó×Ö…m†aü¤·ÏOx]¯Ýùy\pˆˆˆˆªî>|(uR9sãtÕOípÈô+™´s‡µðhf• ­¢Iïíì±(œ*QßC‘J¹º9 5j4 Ì×.fàèÔÈhï2sö1uþ²Š ï ° H(͹gº{Q^›Å×7U£î\éW2‘‘z]èÍÔÉ¿Êmºuó¶v×ÿµÉÙűÜ÷ÇÒ6™º~‰úRÿÊ@ñ]5üƒ|Lž«¨ðJJþ+œÇœë—ÇÍÁ ¾n�Y|\¹RR*u˜BUdqhQ™©¢¡¨öv�ZÔS©¸¤J•vÈfr!Xº¯Ñ W¡ý·äêÔØèÜoæìcêüÆöËÊ»�ÔÚPÊ·•;¼Z¶(7èÒÝ‹òÚ,¾¾©u纚}$þÏæÍàܸÂ;U©M U2snáf¾v~¦–nrx¶h^îûc­6—”àBJ*ŠŠ‹Ñ%Àßä¹tÿnuí0çúårrÜÝ-?®éù€Ò‘‹�Ê|Ëû¨Ì|jªÂÜ+Q›|ýQ;{³Ã!@;l³H¥ýÿÊÑÉvööÂkº ±¼sV´�øÞ”=¿±:tÿ»5mŽÖm|Lî_ö^˜º—æ^_UX€Œ´\»z�;¡±£|Ú=oy÷¬ì~y¹7‘•™.´ÉUÞ¤Ü÷]ÞV¥M�é©ÉÈÏ»e²â¶èÎcÎ=-�«à-í"ÐDDD$!nDT)¶¸l&p#"-nDDDõ‡”Y7"""""""""+bàFDDDDDDDDdE ܈ˆˆˆˆˆˆˆˆ¬ˆ�‘1p#"úÿöîn7�+ Ãè7ülÀ&Æq|©QÚû¿¥¶gQ«VQժƞ œ5Uc½Ó šµ.`óm¤ð° Hp^d9»Ì/:�¶Þœ/לŒQ·ëÅuëàl-g‹ü¢WW­·çk¹Ì/9k½)8O£nÛå«Ö#ÀÙº˜Ü0“üKúÍYa,V­'Zup»½¼m=œ­õÅ:¿èfÓz[p¾8!ꄼܵï�`ÔFÜæÓ¹Ÿ• ì7Õu]~áÙLtƒ—Øí9áÖuU7­7çg9«ZÖ0j£nUUßí¾Ýà+ܯ¾©ýf?ܼyã^nð56›ªÛáNl¿^WÝ­ZoÎÇzQõáuë)€ÖFܺ®«o_½¯ÙdÞz8yûÍC½Û¾ætÛg]WµßûÇEø/v»ª·o�×Í€nŽøwÛ˪÷»ªéèßa]ß÷}ë!NAß÷õË?׿ýX‡çÇÖãÀɘMæu¿º¯»«»Z ñϤ_Ò÷UŸ>U}üXõôÔúi€Ó1�Vm·UëuÕâÿ»&û¾ê÷¿ª~úµêÏCë'NËÝêÛ„ià3Áí Ÿë¹n=45é&5ŸžÈéÏÃáø‰ƬëŽ÷:<OÏU/“ŒÜ´«š9� üÁ ‚Üa‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ Á ‚7Ü Hp€ ¿@6R2ÞœZ^%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:21+00:00�¶�óóéÌœ.vµ­�i{¦zêèhëØŸJm¥UY\pAQ¥¸@öBÈžçµucIî%Ü×9å&Üûù^óν÷³Ê\.— � Ú ‰Þ„$8 " NBƒH‚“�ð ’à$$<ˆ$8 " NBƒH‚“�ð ’à$$<ˆ¯ÐHHˆ�’ËÍä7àtÂàèîO ëô¾¤+œ„Ämp:]d�®§¶ÑF}“�S—š¸Rkîôþ¤+\°X,�ŸŸÏñãÇ©¨¨ 99™·ß~[hÓ$Ü„Õî¢ÙêhÿÙbsQg°Þ¹ýI‚ë»víâW¿úÕ Û¬V«ÐfI¸‘ï+MXm×òû5A¾$ô ìôþ$Áu€øøx^{í5F�Í Aƒˆ��Ú$ 7RRiâëü÷ $$ЗñCCQúwþIL\5j£F�@¯× mŽ„)«2±3¯ — Ò’C™0TÓ-û•œ&?áJ­™ªÆá„1 ÁÝ&6�'!qU�V>?P…Íî").ˆé©�ôŽÜ¯º¥l��Ï�ƒÖÛÈÛ¥sÝwß}ddd½l‰;ðM~-›PøÉxdJ4Ú> �Û«‡ËÅ�›7c®¨ àž{Ð>ü°ÐILÖ©:ò¾7àë##}²–Ø¥G�ïUÏp?C&#bÞ<äJ%-ßOÓ©SB[$! ‡‹õä}o@.ƒ"=.6ðvÁ¾j5á³gP÷ÝwXëê„6IBN^0�]Ô€LóÆE28ºk��Åë :Õðá¸l6jwíÂåpt}§=†âŒì9ÑúE;kdÃbU‚ÙÒ+>k¾ �½*è5\Ò™È8ÖZÓ6u„†ÔAjAíé5‚»*@.GŸ—‡©¬Lh“$ÜÌåZ3ÛUãt„¡¡Œ*´I½GpÊèhB&L &#‡É$´In¢ºÁ¶UØ.FÆ“–Ü}5m]¡W  Ï¤I(ccq�ÔíÙ#´9n ®ÉÊ–ÜÖ2›ÄX3GuoM[Wèu‚C&#|î\dþþ4—”H¡/ÃÐlgkŽ“ÅÉàè¼×=e6�¥÷ ðÓhŸ5 �BÞD³ÅΖ\“ƒ Œ�D.‘Ú襂>Ub¢*ð,6'ŸçTQßdC«ñçáIZ|}Å÷ñŸE$|Ö,|CB°èt4H¡‚‹Íáâ‹:ªôV4A¾üjr Š z¹àä áóæ�LFc^f)TÐãp8]l?TÅåZ ê@I‹F¥oL¯@@¿~í¡‚ê¯¾Âiî|ßx ÏârÁ®#5\Òµ¨�“>E‹:P¼bIp„Nš„"&GS5_-´9wÉ7ù5œ»ÜŒÒ¯UlaÁþB›tG¼»<§Ø¨\¿—ÕJøÜ¹�!´I·a_AGK[ËlO‰¢_x€ÛŽeµZÙ¶mÇ�'??ŸË—/#“É8þ|‡÷% î:š ©ÍÈ@æçGÌã�ãÖù9`åǤªªŠºº:jkk©¯¯Ç`0 V«ñiëÉâëëKDDáááDEE¡Õj ìbQmO$·°žƒg‘Ëá—µÄkÝ'6€êêj¢¢¢€ÖFS&“ ³ÙŒÓéìð¾$Áý„š;0ž=‹T1�=†LÞ½wÝ äååQTTĹsç(,,äܹs(•J¢££ kÿ£V«1 8ÚB6›�ÚÚZjjj¨ªªB§ÓɰaÃHJJbêÔ©<ðÀBŸB·r¢Ô@fA2<4>’¡ý:Ÿù?oÞ<ÊËË9}úômßg2™øúë¯=z4qqq¤¤¤pæÌ™N NÜO˜6{6æ+W°VU¡ÏÍE“–Ö¥ýÙívŽ9Bff&™™™3nÜ8’’’7nO<ñ‰‰‰h4Ïõs:�”••Q\\LQQ555BŸ>·RTf$³ 5Iaöèð.‰­#²páÂnÙ—$¸Ÿp5T Û´ ýáà €2.®Cûp¹\deeñé§Ÿ’‘‘A||<3gÎä•W^aâĉøûwÏý\.'>>žøøx|ðA¡O�[)­4‘q¼õ eZІ”�ÁB›Ô)$ÁÝ„€~ý?ýáÃTõý–-C®¼s9~ee%6l`ýúõ¨T*–-[Æ[o½Edd¤ÐKêÑ”U›øŸ¼j\.˜<\ø{B…6©ÓHa�[2yòµPÁ7ßÜö½ÅÅŤ§§3bÄ*++Ù²e §N�â¿þë¿$±u‘ë-üû`5§‹Qƒƒ™˜*´I]BºÂݹ\Näüù\þôSLçÎÑTXHpRÒ ï)))áÏþ3{÷îeÅŠ¬_¿¾Wz ÝEµÞ–\6»‹á‚˜Ñ…ÑQ‹-"??ÿ†m:�»ÝΠAƒnØ®Õj9xð [Ö$ î6ø††>}:5»wS·gʾ}ñÓh¨¬¬ä…^`Ïž=<ûì³|ôÑG m®WÑ`´±5· ‹ÕÉ=1<0&¬Ke67›qàÀL&£G�¾a{˜ÃARXà.hhµ|i4òç?ÿ™ßýîw¬X±‚ààžùð.fšZlÚ}³�¸H%¿šäži6wø)RXÀÍô™5‹‚cÇXµz5¾j5YYY$&& m–WÒ::ªUlÑ}<<1Êm££„@Üp:�¼òƬýÛßxvêT3†h•pmÖ¼‹ÝÉÖ\u;!~¤OÖâ/Ò2›Î" î6Ô××óè£�b2™8SXˆ¢¤„Ƽ\hs{<»�Örº¼‰9K§Å®öÌè(!Ï5[$¼óÎ;¬^½š¬¬¬Ÿ‰ ZCa¿øµß|ƒ­¡Ah“{4{O¶ŠÍßWÆ¢)Z¯H‚»�×_��?þ˜ììl† vË÷§¤8t(.›�ê;puÂ=,Y…õ;ß„¯�Œ_NÒ­ñÜœ6¡�Gk²ñŠ+ظq#ûöí#66öŽ¿>{6¾j5V�Ž7e%x3Ǿ7�w¶¹ AFG �$8àø‡âÀ�wýí£TqµÑÁƒ˜øAèeôN_2²÷Tk™Íƒc#Hˆé=a–^/¸5kÖ°ÿ~vïÞMhhh‡~WKè¸qTïÚ%5 º J*M|�ßZf3=5ŒÄ½+%®W î‹/¾àý÷ßï”Ø®2e ŠèhMMÔ~û­ÐK5eU&væUárÁÔd c„%½Vp¹¹¹<ýôÓdddÜÕ3Û­�ËåDÌŸß:« ¨ˆ¦¢"¡—&J®ÔšÛÊl`LB0㇆ m’ ôJÁ•——³hÑ"6oÞLJJJ—÷ç§Ñ´‡ ê23¥PÁO¨j´òyÛè¨ä8Ó»PfÓÓéu‚s:�<þøã<ÿüóLŸ>½Ûöœ’‚jèP\ 5­é4m|žÓ::jH_sÇôî‚Ü^'¸—_~ž{î¹nßwØìÙø¨ÕX*+Ñ:$ôR§ÉdgK¶Žf³ƒQJæ�×è(!èU‚;pàŸ|ò 6l@ÞÍíïàÆPAÃ�X._zÉ‚ÑZf££Ñd'&LÁ î©iëiôÁ }ôQþñ�Üu¬­3ÄÆ¢7\.ª32pZ,B/ÝãXlN>Ï­¢®ÉFDˆ‹&iñ÷“ĽHp/¿ü23fÌ`Μ9n?–¦-T`×ë©ËÌzéÅîp±í@º š _Ò'G‹ªÌFhzEµÀÙ³g™:u*………DDDxä˜×Ï*ˆ˜?Ÿ ^P!îtºØv°š‹:Á>7×ëB‡ÎêÉûÞ€\ÿkB±½¤Ì¦³xµàÞxã V®\)´ÄÆrï½^*8yÁ@Na2ÌÉ h÷Îió¼Vp{öìÁjµ2wî\¡M@“–†¿VÛ*ð‚ª‚âŒì9ÑZÓ6kdÃb{OM[WðZÁ½þúë¬\¹™Hr‰dr9‘=„ÌÏca!Æâb¡Mê4篘È8ÚZÓ6u„†ÔA½¯Ì¦³x¥àJJJ())!==]hSnàgU��B›ÔaÊ«[øòp5NÜ—Êø!¡B›Ô£ðJÁmÞ¼™Gy__ñµÝ NME5t(N³¹Ç… ªô¾<Ô::jd|0S†w|jkoÇ+·eË–,Y"´·$|öl|‚ƒ±\¾Œ¾‡„ ꚬlm+³IŒU1sTï­ië ^'¸#GŽ —Ë5j”ЦܹRIä¼y4äæb¾rEh“n‹¡ÙÎÖ&‹“Á1�,šE ÂGh³¼¯\vvv�€zäHD*p¹`ב.éZTÈIŸ¢E­_x¥§âU‚ËÊÊê‘‚ƒ¶ª• ËåË4äå fÇ7ù5œ»ÜŒÒ¯UlaÁR™Mwâ5‚Óét477sÏ=÷mJ§ð l­*ô99X*+=nþ‚:N]2¶M³‰$*T*³én¼Fpßÿ=C† ÚŒ.‡º­ªÀÓ¡‚ÜÂzŽ–�Ëááû¢è.eþ»¯\ii) B›Ñeú¤¥á…­±‘º}û}„6£[ Ÿ;·=TÐxäH·í·²ÞÒ6:ÊŨAj&z¸Ì¦¸¸¹\αcǸ"òÄíîÆkg4Q©¼«ÌÿúPA}vv·„ j­|ž«Ãfw‘Ô?ˆ™£Â<¾®¢¢"är92™Œ�?þØãǯ\ss3AAÞ7¾6 .Žà±c[íÚÕ¥PAƒÑÆ–«“{b˜;Öób8}ú4‡›ÍÆ|€ÃáÄ!ð Á9�N¬V+ …wjæNÅ?*ªµQ'C†[sZGGÅE*yh|”`e6ÇŽk÷PšÍf¾úê+Aì¯\ss3���¢iÔÝÈ||ˆœ7¯=T`ì`¨Àdq°5ç úf;Ñ}<<1JÐÑQçÎ�»f›ÉÄ›o¾)˜-žÆ+'“ɼ>¦ã~­ª ¡‹ÍÉÖ\u;!~¤OÖâ/`™MSS ×�dv¹\äååQZZ*˜MžÄ+„ÅbÁn· mŠ[Q�E@[¨ànª ìÿ>XEUƒ•Ð _Ò§hUTTD@À�™,r¹œ¿ÿýï‚Úå)¼BpjµšFÔ’¹›ˆ¶P�¹¢ýmBN§‹/WñC�™ 9‹'k R _fSTTô³[‹ÅÂ'Ÿ|‚E¤m&º¯\HHH¯œO` á>@CN–¼éû¾Î¯áÂ�-øËY<%†Ð qŒŽ:}ú4ÍÍÍøùù¡T¶Î"p:�lÛ¶MhóÜŽ×.44´×$ÄHð˜1àtR½cN«õ†×÷ž¬åLY3þ¾2Ò§h W‹ClÇ�Çår!—˹ÿþû™1c���477÷ ç‰×N£ÑP__/´#lÚ4ü##[]*È:ÝÀ±óm££&iÑjÄ*9wî>>>Èår>ùävìØÁ‹/¾ˆ¯¯/œ9sFhÝŠ×.!!�’’¡Íð×W4P´þ_äþÏaòJôm££"é/²ÑQ���Ô×׌R©$66™LÆK/½ÄÎ�;Q©T¬[·Nh3ÝŠ×nذaœus)‹Øð '`ô½V•]’ËØÚ|Á è@¡ÍûEEEøùùñÖ[oý¬XxΜ9púôiŒF£Ð¦º ¯\bbb¯œÕî¤ü‡k·Ñ>.'-U$gŠ[QQï½÷J¥ò¦¥Tƒ&33“šš¡MuÂû‰»‰ÄÄDŠŠŠ„6Ã#\®5sºÌÈÙ #q¶@‘!£5&甋÷¿tìØ±¤¦¦²zõê[öž òʜثˆ÷§ƒÄÄÄ`±X¨««#,L˜¤\wb¶:9w¹™ç T7^óJ6ÅÃÜx–[ Ái¿ÚÔ[’šš ÀÁƒyþùç…6G¼FpÐú zèÐ!浕´ôt\.(¯6QpÑÈ÷Wšq:[·«”> �U‘Dd¨‚Š2%ö†.]„"*Jh³o‹ÕjåèÑ£Lœ8QhSÁ«7cÆ ¾ýöÛ/¸&“�¢òfN^4Ðhº–®©$u�š{b‘Ë[³5f3ö†d¾¾øEDmú9räÆ C­î�SS\SS'Ožäøñã”––ât:Yµjìô>g̘ÁâÅ‹…ZR—p8\”þh¢à‚�²jsûvM�/‰±*RâÕ¨þßem«˜ö×j{ÄT›žÚ»»Lp©©©\¼xñ†mO>ùd——’’Bcc#ååå 0@¨¥uˆZƒ�Âr§.i±¶Þ3úÈe$Ä’D\ÔíÝûæ¶Ô.ELŒÐK¹+²²²xî¹ç„6C0ÜÂ… éÛ·/£G�æ£�>âŸÿüg—÷)“ɘ>}:ß~û-¿þõ¯…Zڱ؜œ­hæLY•u×vµI‚Ht×Yý–¶+œ":ZèeÝ‘ššNœ8!]á„`Íš5íÿÞ¸qc·í÷�à³Ï>¥àt  .6QTnÄæhuã+ýä �U‘:H�6´ã}ü¯&/÷ÁmÙ²…yóæ(¾ ¼§ð*§ À‚ xæ™g¨¨¨ 66Vhs0¶Ø),k¦ Ì€ÞxÍÒ7LAr\0Ãá×Éêk›^�ÓdB€_h¨ÐK½#›6mâ/ù‹ÐfŠ× N©T²hÑ">ûì3^zé%Al¸Þ�_RÙÜ^' 'i@©ñ!„vÃ(kz~»páeeeL›6MhSÅëðÄO°xñb^|ñE�ö9©k²r¦¬‰Ó—Œ˜,­¹âµ$ÇsOL@·z{’ÃdãÆ�<òÈ#øúzåGî®ñÊÕ�3†   rrrHKKsë±ìv'çu-?sç‡û‘< ˜ñAn›Úî0¹àÌf3ü1ß}÷�ЦŽÛ÷Øc�qàÀ�¶íÞ½Ûc#¥–/_ÎÛo¿í6Á]u€ÿ`Äjo½gô÷•‘ÐWEòÕÝù]ÆåÂZU úì’üãŒ?žÄÄD¡M· näÈ‘íåóWñdRê²eËxõÕW9vìcÇŽí–}Þ*ŸQ«Q�Lb•Ç:bYª«qÙløj4øˆØëçp8xç�wºÕÝ“q›àþøÇ? º0…BÁÊ•+ùë_ÿÊŽ;:½Ÿ«�3åÍ”\nÆÞæÎ¿šÏ˜:0˜ˆÏ�åí)“-[¶Ð¿&L˜ ´)¢À+Ÿá®ò›ßü†5kÖ�ŸŸÏèÑ£;ô»Ég‚žà0±Ûí¼ú꫼õÖ[B›"ÜöíÛ9zô(КР°nÝ:¾üòKþó?ÿ“þýûwé …‚U«V±zõj222îøþ«ùŒgÊš¸¨kiwç_ÍgLH 8ò\ì¡Ôj…6å–üío#::šY³f mŠh�¹jY¼|ùr>ùä“[¾~øðaÆ�ßåãX­VFŒÁš5k˜?þMßÓÕ|FOã´Z)ç�Ɉ{þyd>îñ‚v…šš’’’Ø¿¿ä,¹ÁçIrrrX²d EEE„„„·Îg Sû’Ü_íVw~Wi)/G÷¯á¯ÕÒ÷ñÇ…6ç¦,_¾œàà`évò'xõ3ÜU¦L™ÂìÙ³ùïÿþo^økn�Ï80mqµ•»bw˜äçç“‘‘ÑëzÌÜ ½BpÆ;‹–ý‰_=0»v±ƒS€îÉg³ˆ–[ZZxì±ÇxóÍ7Ûï&$®áµ‚»¡=Ae3NÌýß/±íÃÿÆ/¾cBrßnÉg1g˜<ÿü󤦦²dÉ¡M%=ówn•Ï8HÀ‚ËPO³á�ÿËœ­[…6µSØ�FMMÈ•JüE6Ó|÷îÝdffrâÄ ¡M-^!¸[å3ö öcÄ€`’ãU¨­K]·n“&MâÝwß<8ßÚ¯nZ-ˆheee%Ë–-cûöí½¶_ÉÝУ§k°p¦ÜHa¹K›;ÿNùŒ …‚/¾ø‚ñãÇ3vìØ×=Ê* o“ÉÄÂ… ùÃþ e”Ü�'8³ÕÁ¹Ë&N^0P¥ï\>c\\ëׯ'==�ÜÜÜ.õQñøúu:}û m К+¹dɆÊÊ•+…6GôôÁÝ*ŸQá/gX?#«‰ê`>ãœ9søË_þÂŒ3ÈÉÉ!F„ˆ›amœ¿H2Lž{î9Ùºu«×ÎXïND-8C‹ƒâ2#— è›»?Ÿñ‰'ž ººš™3g’��-úŽÍ¶º:œf3¾j5¾"hþæ›o’••Enn. …øã—b@t‚»U>cp€Ã¨9HÝ­ùŒ+W®¤±±‘9sæðÝw߉ú�ßÜ–?)†pÀÚµkY·nõ9¢\�ÁÆ™r§.i±\Íg„„¾*·ç3¾òÊ+ f̘Á®]»ˆŒŒútܔ뛾 É_ÿúW6nÜHvv6}Eò,ÙSTpbÊgüàƒxýõ×™0a‚G+Ó;t¾Úžß”~ÈW¯^ͶmÛØ¿�yî‚îfý~2†Å šÏ¸råJÂÃÙ6mÛ·oï–j…îÂi·c©®™L�– 6›�ßÿþ÷œ:uŠÜÜ\úˆ,èÞSð˜àŒf;ç*L\4Pk°µo[>ã²eËèÛ·/=ôk×®ͬ›NN'þ‘‘Èü=[a~åÊ-ZDXXß~û-ÁÁÁBŸŽ‹[w³|F€ ¥Iq*RªÑ‰£ ózfϞ͞={HOOgïÞ½¬]»VðnÁf�ò'³³³Y²d O?ý4/¼ð‚äúï"n\]“•âr#gÊ�L 5 éš;¿{û3ºƒÔÔTòóóùýïϘ1cø×¿þEJJŠ`ö´—äxÈaât:yûí·yë­·øì³Ï˜1c†`k÷&ºMpÉgì)±aÃ6oÞÌÌ™3YµjÏ<óŒ ÍL=9´£¸¸˜ßüæ7ÈårŽ9ÒåV×èrÅ÷Íò}}d Žg{‚ÎrñâEžzê)t:ï¿ÿ¾ÛÌ^�Ól¦üÝw‘ùùÑÿÙgÝvw`±XxõÕWùðÃyùå—ùío+ú;‘žÆ]U›,öœ¬Ãl±3H«ÂßO~Ë|ÆaýU(<ÔŸÑSÄÇÇ“™™ÉöíÛyüñÇ?~�©S§’––†¶±4cq15;w˜�@ÔÂ…wõ;¥¥¥dff’™™Ivv6C‡å±Çã‘G!´LJõf$Áy€‚‚²²²Ø¿?¹¹¹hµZ&OžLrr2 $$$0`À|nÒA¹vï^šŽC3e ¡÷ÝwÃkv»�óçÏSTTÄÙ³g),,äèÑ£Øl6fΜÉÌ™3ùÅ/~Axx¸Ð§@¢ IpÆétrêÔ)8ÀÙ³g)--¥´´”ªª*Htt4J¥•JEHHÎòrd--ØûöÅätÒÐЀÁ`@¯×SQQA¿~ý>|8Æ #))‰ÔÔT©µ¸ˆ‘'Ìf3çÏŸ§ªª ³ÙŒÉdB¯×S¹{76«•¸$4<�FCHHjµš¸¸8©Òº‡! NÄXt:®lØ€_Ÿ>ô[¾\hs$ºÉ,b,"Ÿ! Ñq$Á‰¡Jr$܇$8ãÉ  Ï N¤8-ìuuàヿH›ItIp"¥}$UT”('œJtIp"Å"âp�GœH¹*8ÉaâUH‚)W›¾*%Áy’àDˆ½© ‡Ñˆ\¡ÀO£Ú‰nDœóHa‰®! N„\õPúK¯Cœ¹ê0r†€„{èY�"{.W{ÓW!§äX,JJJ°Ùl 2„ Ì£ó¤+œÈ°ÔÔà²Zñ ÅW¥òøñ_|ñEF�Epp0)))Œ3†‚‚¡O‹× NdXÜpu+++ã»ï¾Ãn·ßñ½ÿþ÷¿ihh`þüùŒ5JèÓáuH‚îHXÞºu+3fÌÀh4Þñ½ÇŽãÒ¥KlÛ¶MT㺼Ip"Ãzµ%ž@i|°{‘'"\v;Öš�ÉPJ^‰$8ap袄g�Â"ÂÜ6´£+ïÊÊJtm·¥×oƒÖv}?�^š””$5"ò ’àD„µJrÞÿ}^ýõ›¾6mÚ´Ÿm»xñ"zé½Ip"ÂÒ 3–.]ÊèÑ£oضcÇ6mÚÄúõëQý$¶)=+zIp"Áa2a×ë‘ùû£èB§äääd’““oØvñâE,X µ:Éi"nx~“†lx-ÒN$ˆ¥¥Bmm-ƒ ýï+W®´_%cbbP*•‚ÚØ“‘'Ú+¼ÜêÕ«ùðÃoØ–žžÞþ&Ož,¨�=Ip"À|å -€{7uêT^{í5îøÞ‡zˆþýûßòuÉ£Ù5¤Ùcºt‰Ú;p˜Í„L˜@Ÿ´4¡Í’p’ÓD` ùùíbh¹tIh“$܈$8�ñëÓ篤\Jéòj¤g8�ÑL™‚M¯Ç^[‹O@ásç m’„‘žá$$<ˆtK)!áA$ÁIHxIpDœ„„‘'!áA$ÁIHxIpDœ„„‘'!áAþ?ü¼~ˆ‹cZ>%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--r7cetx2y1t.png000066400000000000000000000027621524103652300220120ustar00rootroot00000000000000‰PNG  IHDR쓺y2 cHRMz&€„ú€èu0ê`:˜pœºQ<,PLTEÿÿÿ‡ªÞÕåÿ¾Óõ’²âž»èÉÜú�»ç“³ãÀÔöÐâý«Æíްá³ËñÔäþ¸Ðó¤ÀêÏàüÆÙø™·å—¶åÄÙøÍàü¦Âë�°â�¯á©ÄìÑâýÀÕö”´ãœºçÉÛúÊÝú¡½é’²ã¾ÔõÒãþ®Çî�®àÓäþ‘±âÎßüÆÚù™¸æ—¶äÄØ÷ÐáýÔäÿ¶ÍòÂ×÷•´ä›¹çÇÚùÌßü�±â±ÉðËÝûÎàüÅØø˜·åÅÙøÒâþ»ÒôÁÖ÷ÍßûËÞûœ»ç•µäÂÖ÷š¹æ�°á“´ãÅÙùÃØøœ¹çÈÛù‘²ã‘²â–µäŽ¯á˜¶å›¹æÇÛùÍßü¿Ôö–¶åÏáýÁÖöÌÞûÊÝû�¯á˜·æÄØøÈÛúÃ×÷š¸æ—·åÀÖö”´äËÝú}æŽVbKGDˆHtIMEé œïYŸIDATxÚíÝi[Q€aƒ S–IqC5еÔR3+±²\ÒJ«ÿÿ*»PÙæpλqÞ/Âlpž fìé±cÇŽ;vìØ±£<÷„N}¬OÞøïº|ÐûÐ×ؾþP8âël4ä<ªþíìÀ`lèï#ñØá‘ÑèõcáØHx,>þÿ™llb"™ªy*;95ýøÆ¹Øtf&3{s‘X¬ÿ‰3w{™Pl67¿pw©Hìb|,œ¯³\ 6²Š÷Õ]#»¼òôYƒUÒ°«ÎZ´áJYØôúX&Ýxµ(¬ÛçÏ›­„uû<Ñ| 1Ø}ÞX·Ï_´ÜHvc3Vhc3 ØÚ>Ž�„gjú\661Ñüt#;¸Õçr±[wû\,v»NŸ Åfs±�»pÅ6ês�ØÆ}.[lÜçÒ°¥f}. Û¢ÏEaÝ>©¼3/lp§¼ÛÁÕ>÷|ºá‰Í·Õç2°›¯”N7 ±ÃΞâé†ÖCŸ³Ç&^·ßç̱“�^}ÎëµÏ9c=÷9_ì~.öFçñc•úœ'V±ÏYb‹+oßi?(MlÉ9Ø6pXŠØêϵTûœÖ_é Ïyaƒ;‡Ë¦ŽM »¯ùtC«¡ÏÙ`7>|<2út°Ÿœ6¿?ç�ÕÕç°Úúœ>ÖíóϯC»• ­kësâØí5�}N»Ÿ;ÖÚ焱'ñ½%s˜Ha«—S-ÂQQ±§e}N[r¦Mô9E¬±>'ˆuûü œŠƒ &Íõ91¬Ù>'…Í__ÞØBÌpŸÓÁô9¬û�©ßxŸÁú_P©pX¨>'€…ës|lô¬Ï±±…‹ã¯ØL ,pŸcbÁû{ZN~ÃaÏú ‹Óç8Xe £Ï1°©äáwl±Ï¡±ùèùZŸcwË—GØ* ,vŸbgÑû믠÷96H¡Ïa°Dúëö9ÍÓ�~láâŠHŸÇžÄGÉô¹a,­>7‹ýñ“TŸ›Äþšòr»ìé›Öy9q,Å>7„Í^Îìs#Xý—S‘ÅÒísýØâ æ÷ç ØUåÛ�`�g,ñ>׊uûà÷í$°þ]ßñ‚Ï´¾)éñ€eÑçz°ƒWCØo;×îíHIO[XF}Þ1Öíó”âáiMk,¯>ïË­Ï;Á²ësu,Ã>WŲìs5lµÏO°ß–kŸ«`Ùö¹ VèôرcÇŽ;vìØQžßÖ ä£>%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--se7sz45xy.png000066400000000000000000000312261524103652300216600ustar00rootroot00000000000000‰PNG  IHDR«ç üyÎ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïY1vIDATxÚíÝyT›÷�ïñ�$ÐÎB¼‚m Ç oñ¾ÇvÇ6v’Ó´�It»§žw2�ž&M§�¦�lMÓ¹mÓp/u›&Ž÷x¼cÆ 6Æ$„ö$tÿ�ŸÇàxa‘ô<’¾¯srNÀHúŠÄ~û÷{~¿ßï!„ÂcB® „B…bE!„÷(V„Bx�bE!„÷(V„Bx�bE!„÷(V„Bx�bE!„÷(V„Bx/n _¸fÍ®g%„éR)–�‹Ç¿ý-h4š Ýoss3¾ó�ïpýôáŒ\*EÕÇèk+Xð�wðdYÆdʸ~Ž„„E�Å‚ÛÛ*Оš§ÓôûWg�ÄäU[0£P …4žë§KHXÄëoA|h'^9p`À·Ô6`I¾ {jôhÑÿ7-!|Óc± ½¢Ýù3`ÒŒ ÉcÈ%q˜S�„šz-2!!§¿ñá]ÈX»vP·T¬R¥˜–¯Â_kº(X$ª1¡òL(�wâ´�>Ö䱉x¼0 'êÛawR°HôŠÓß‚äÐNd¬Yùèуºí XP°H´óZ­�På‡>TŒÉc1¿(Õ í°Q°HènAr(°¢l¨€!žLM”búDvUw¡¹ƒ‚E¢‡×jÅím�På‡'TŒÉc± 8Õ�,U„º6ÈïDÆÚÁ¯¨Øûꃧ$H1£@…=µ]¸Úîàú{AȰq*Fñè,{Œ‚E¢‡°³ ’Ã;�9ŒPÃ|�UJ‚%™ø´Ö@Á"�¡bL¡ÄÒÇRQ]ß›³›ëo !CÕN¨×®�lÌð) ûEÁ© Ì(ÊÄ?Np­�¶IäñZ­¸ýçmpçOçT á»@¨v@õäê ‡ Ñ»®'+ŘQ¨Æ?ÎP°¿ô •7BBŘ8B‰eÓÒPK×°Ï0[ª'ƒ¿¢b#TÃ')Ä(-ëòm:tA¸çµZÑ¡¡bäç(°t:­°õ·!=ðd¬Z²P!þyVL°öžé¢`N1¡rO˜±¡bLÌQbé´ÔÀ ‹Žµ±¡Z³ŠÜÜÐ>V¨ŸL’"p kï™.\i£`‘ð몉%\�s”X>= Õ;`¶{¸‡Ä p† ÓO f‚õùY  ¯h cBŽ+§§£¶A ‹„Q¸C„ñÇÚ÷ VS›=\Kb{<= CÅ`‚UCÁ"a8õ÷IXC„1V@ X3 ÔØ{ƈÆV  �~‡)¢4TŒ 9 ¬ž‘�ÚF-Ì6  &Tª'V…5T@˜c‰ 1J ÕØwΈ†V[¸žÄvë/orĦ¨¼,9ž(ÉÀÉK,ƒÒC;§þòòÂþøa�p'XEjì;k¢`‘ òÚlwCU4“ëqÂ*/KŽU%é,tƒ²#}ÕJ(Æ�ãdNb‰r1fMÒàÀyhK��×fCûŸ·Åd¨ã²,TƒÒý�P)9XQ18‹(åñ(+ÒàÀy#êoÒ ‹ *W ‡Š1.K�Õ¥´%H†�YQ©V­à4TDZ¥ìN°.˜)XdHú†Êã¡bäªål°L,2ÌŠ*cå ζþúâFæŠåPNàÿŠŠ�›ëC!�ÇÌ" N\²àÌ5 ×ã�bBå]/­¨BjD† ÏÌÊÄy VÔuïÛÕòåPŒ�Œ;;× –\‡²B ª›¬¬(E¡ ¿R<=+uW;a0»¸‡„³õ§^µ"âBD`¬€;Á*ÒàD“g®Ñ–`4¡Pq',Î^ÑÃh¡`E“ÀñôíP-_ÊÛ×Q=ò9p=ÀPÉ%q�-Á& +JP¨¸—“.Å3³U8{Y�.«“ëqH°×¨–/ƒr®Çúóàz€á`‚UÝdÁé«´%ɼ:*+áE¡âZNºOÏVáÜå.m¬H&2j!Û¿ªåË �àP+àn°~óî[ø·ŸüF£‘ë‘Èܸqï¿ÿ>€@¨´p�,DO1…ŠrÒ¥xfVÎ6éa±¶ÿôþð¸i{0´·Ý@åÛ¯á‹ßDúŠåñ:ªG‰øX€L‡ÕkŸÅ…SÇðOÿü~ö³Ÿ¡¹¹™ë±ÈCìØ±—.]‚U¯„jD…ŠgrÒexz– §/w¢½å Z¯_ÆáÏ?áz,ò7®6 òw?Ã{o|� uXÿ Q*ˆãz€`—_ˆQyh¹Z�ãÇ�ãüùóÈÏÏÇš5k0eÊ®Ç#}èõz\¼x&“ ?ùþlZ³âɳ¹‹ÜGNº %Ù.ü÷ÛïÀn5áòÅSX¼º"QÔüÑÎ×Á…Ó‡Ñ|¹O`õ;wêTdN�ÊõhA++Æœ…O°¿‰\.zzzÐÖÖÆõXäUUU0™L€&Cþkw%>ßõ×c‘ûøéOŠw~ùØ ­€ö¶Tþ;×c‘>z}>è;oÃnµ°¡JT*ñüË/s=ZPEU¬Š¦Îˆ1ã! WŠÕÏÿ_¬^½šë±HN§µÕÕ€8‘yùÅX¸j#–®}ŽëÑÈ}|ÿûßǺuë0aÂ…"ÀñƒŸÁï÷s=¹C(aÉêMø_ÿô=LLMLš<jµšëÑ‚*êÖò“g<—ÓŽ¯¿ü]Ô6éá÷ûQ–ŸÂõXäŽm}»Ã�qÙ#1÷™¯c|aôlSD#‘H„'Ÿ|k׮ʼn'°c÷_Ñ|õ Žüó-ãz¾@à”àÌIjT_ÔÂïfN¤`qÅëp £¢«–?‹:LÑÏ-EQÑcøøK-üyPS°8#4uB¶ÿc¤-„ V®\ÉõX¡y®\jRqfMÒàì ªÍ\�“˜P¹sò)TQB�"Áú¹j\¼¦‡ÖH/æ‚ÀØ é¾*¤-^Ć*šE}¬@"aV¡u-vœ `…•Ïé„¶²*ªÇæp= "uª(Xœ¬¨ª�¾dqL„ ˆ‘X�`•jp¡ÅŽc &®Ç‰ >§3ð^Ù(TQJ�*Á†y V M��îßS¡b(VÀÝ`ÕßtàX#+”˜P¹)TQO�,fƒÕa `…’ÐÔ É¾*¤ÇÈÖ_¿çÎõávw…EÁ 6T걪Á«¾™‚*B‹âAFŒ­¨ØçÏõ\�ˆE˜Y¨Á…N­7s=NTéªi ¸‡„‘:YŒ�óÔ¬Z �쯂jÑ‚˜ £±îº˜¤ÆÅ›¥VPøœNtl«€‹B³2“%¬ Z ï«BÆÂØ ñq| Xõ7�¬abBåÔäÂK¡Ši}ƒÕnpp=ND£UŸï×pM/ÂÌÂ@°¾¤S‚CB¡"÷ÊL– üq5›»p[oçzœˆ$´ ù¢ æÇ|¨Š€»Ájh¥` –ÏéÄíŠJ ù UŠWãÒ Ú:)Xƒ!´ ÙW…ŒE  ,,äz^ XÝ!Ž¡ìN°^ Ÿ6<½n7:ª>†'s …ŠÜ—*E‚ ó5¸Ôb Ö±¡Z8ŸBÕŪÉ�`]¾í¢`=B¯Û�öŠ*¸2F¢gúB®Ç!<–™$Æs ²ÐtÓˆ6 ÖC -H÷U"}Á< Õ=(V÷`‚u…‚õ@½n7Ú·Q¨ÈÀ¥%ÆcÓ< .S°ˆYQ¥-˜�„¢"®ÇáŠÕ}HâE˜Y¤ÁµÛn Ö=ØP©(TdpÁR£é¦‰®aÝ#°¢ªBú‚yª X=@|œ¥Ej\»íÆ� ®Çá ®´D16ÏËDS+‹!°!Ý_…4 ÕCQ¬‚ VómÖÅv°zÝn´WVR¨È°õ Ö­–Àj„toRÐÖߣP¬!>NˆÒIj\k�Ý`ù˜P¥�¢P‘ HKcóüL\Žá` ¬FÈöV mÑ$ÒaŠG¢X @¼èN°:<8P[×°|n7:*+á¤P‘ KKëÊÍØ ªÔó(TD± xÑ�kXZ7öŸ��–ÏíFGE%\i#á¥P‘HKcÓ‚L\¹eB«.6‚Õ/T“&q=NÄ X B¼Hˆ²B5šuž¨ªô‘è)YÄõ8$Š¥%ˆ±i^&®¶™p+ʃÅnýQ¨�b5H}ƒµï\tËçv££j;…Š„ ¬[&´Fé–`ßP%P¨�b5ñ"!Ê Ô¸ÞéÁ¾³Ñ,6T©9*V�kXj\½iÂ�×ãsê�B5t«!Š� ë†>z‚8õWOú áDJB<ž[ ÆõvsÔK`5BƼà—B5d«aˆ�¢ôN°>?ÓÅõ8Ī;c$<Óè0áNJB<ž›VK»•ëq†E`5BöE%ÒæÍ¥P Åj˜˜`µºñé)=×ã …ŠðMJB<žŸ¯Æ ­-‘, UpQ¬‚ >NˆÒ‰jÜ6õà§#+Xl¨ÒGP¨¯$+ã±yž7:"/XýBU\Ìõ8Q�b$l°Œ‘,ŸÛ�öªí�PM§kT„’•ñxn�-í–ˆ û^ª ¢XQàÐ…&/þqª ~?×=X¯ÇUZ…ŠðZ’<›ªÑÒnÁMžK`3A¶¯ésçP¨‚Œbd"‘3&ªÑaîÁg§ù¬^�·+«(T$b0ÁºÑnáí¡ �ÍéÞ ¤?N+ªP X…@ß`ñm…Å„ÊC¡"&I�çjТ³¢¥ÃÂõ8ýl&ÈönCúœYPR¨B‚b"L°´þ«o¨º)T$%ÊãðÜ|5Z´6ÜÔò#XL¨ÒæÌF”)\�µ(V!ÄKgîÁggôœ‹BE¢¬6Üàx…%°™ û¢‚B«‰()TCkôâ§¹ …ŠD&X­Z+Z8Za1רRgÏ¢P…Å* DÂ@°t¦ð‹BE¢U¢<›çip³ÝöÖÝ­¿YH¤P…Å*LúëÓSá ª”l ‰J‰Š8lž¯Ak‡7n›Ãò˜› ò/*�:g6…*Œ(VaÄ«Óìŧ'C{è¢_¨f,æú©2l°tvÜh7…ô±v ä¶#e6­¨Â�bfl°,=Ø]Ó’`±¡J̤P‘˜�¨ˆÃs Ô¸¥s„,X»òý•H)+¥Pq€bÅ&X&»»«uèíí Ú}³ïL‘˜‰î™Ë¹~ª„„M‚<Ï-T£]ï@K�ƒ%´[ ÝWA¡âÅŠ#"¡%j˜½øk�>(ÁêõxÐ^±ž<*ƒ”Ò8”ÏW£­Ë�ÖvsPîS`·@º¿i3Ë(T¢Xq¨o°öÔ/Xl¨’(T$¶)¥qØ4O�[z;Z;†·ÂØ-�í¯DJé Ç(V ˜Q¨†Ù‰!‹BEHJiÊçipKoG›vhÁꪤ©S¹~J1�bÅB�Ó'ª`qbÐ[‚þîn´oÿ„BEÈ=”2ÊÏÂÍN;ÚtæAÝV`³@¶¯‚BÅ#+ž ˜6Q«kàÁòwwãvÕ_àQ¦Q¨¹&X­:n p…8ž8õG¡âŠ�ô Vu×CƒE¡"d`”26>®Æ­N'Ú,�Í Å�J$ÓŠŠw(V<ÃËí`°üÝݸýñ'*BH)¡|~&Z:hï¼°â�ÈT!i…Š�(V®Ç"$bÙ]½ðt÷¿ìH¸‹<Ŋ甲ø~K{=�ÆÑ6B†*Ai¼ ßç}6®Ç"�@êñ˜Ïç‡~$ÊE�IP§ˆ±BxÒ£»� ¾ù-!±Äêê�H @‚<R±9)bÌ1ž„ùØ1®G#A,xªÇÛ‹ÚKZ䤯cåô,öó~ŸÚ]» 8òW¸ç­„ô÷ BÊâìAåa-Šs“�šœ札7o=lû«Ésæp=&¹ú“އ˜Pe§ÄcåôŒ~¿&‰ ~ê)ÈÄ>H�ü•VX„ �ÙUþ¨D¤ô x% 8—ÃÖt™VX-}@·aƒ%ê¥`r&[¶Ò"d2²U‰º�ÿN°¬,^¡Xñ@�·5�ZŒQI°djÚ n+‰ ~úIÈD^ !}˜l=ØvD‹Â±ÉÈÊHÔmýR9‹Ëan `ñÅŠc=¾@¨Æª$X2ep¡bD"hž~š‚EÈ[7*ŽhQ8:™iƒ Ã/•õ¤æúK, Xq¨Ç׋š-r3‡*,¡Òc,» ¶nTÑ!dÊ�CÅðKåp-ÝK}#‹c+ް¡RI±ø±á…Š!‰ yæ)H>H(X$lݨüR‡q#’¡ÉPå>ýR9œK7Ãt±&:%ÈŠz|½¨­×"O-Åâ)©A½o&X2¡—‚EbŠÁÖ�ªÃ:L™ŒÕðVT÷òKåp/Û Sý% G(VaÖãíEíE-ò4,šÜP1în R°Hl`B5~L24éÁ Ã/•ól3Ì —`¢-Á°£X…Q�7°¢—-ÁÂÉÁÙú{�~Á¢C$Š¬Ý¨8¤ÅøÑÉÈæ5ªGñKåp/Ý s}#+Ì(Va„*7[‚Å¡ ƒN ’hg°Nýå�IAvˆVT÷òKåp/ÙS}#ŒÇ(XáB± O�ÕõÈË–bQ˜BÅ `‘he°v£òˆG…/T ¿LÏ’M°4R°Â…bbžj굟-ÃÂâÐ\£z&Xr]Ã"ÑÁ`íAÅ‘Œ•:èü‹_¦€{ñ&˜ë/Q°Â€bBžj´˜�Ã]¨‘êuOC ‰l�Pµ#Tr‚t<}¨ü2T ‰t�&¶êÀÄÑiÈæ8T ¿L÷’rXê)X¡D± �()ÇÂOª~Á:¾‡‚E"F§ÉƒÊc:ä�MEV:?BÅ`ƒu±Æã'¸'*Q¬‚¬o¨/Lázœûbƒåï¡`‘ˆÐiò ê¨#S‘óP1ü2ÜwÞšÉx‚‚l« bBU4Š¿¡bD"¨Ÿy rŸ‹‚ExMgö`ûQŠÆ¦#[ÅÏP1ú­°(XAE± O·'.jQ4R�¹üCõ³Ï‚uŒ‚Eø‡ UÁ˜t¨Óä\�3 l°.4Ж`Q¬‚ÀÓíCu½“F)0·0™ëq… Vï�`ùý\�D€;¡úR‡ÂÑéФGF¨ì–à…z˜NTs=NT X “§Û‡ê†�‘cnQ2×ã I¿`ý+‹pNk¼à·`lä…Šá—)à^¶溋¬  X ƒ§Û‡Ú†�R`N„lý=ÈÝ-A7‹pJkîÆö#(ÎÍ@V„lý=H¿`US°†ƒb5DL¨ŠF)0‡ç‡)*¬g(X„3Z£Û�t`R^FÄ\£z6Xç)XÃA±O·':PT ¿"®å›a:WóéÓ\�Ãk«`WTã1c|"×ãð,©›‚E†¦­Ë�Ç;1u|ḞŠáW$½¤æšS°P°ˆbuL¨Ê&$P¨î!ˆ�GÖz ¼¶.vïÄcã3�‘,ãz^aWX'OS°€bu�¾¡š>.¶·þ„‚E+*=…ê!üŠD¸–n‚‘‚u_«>œ/NÔw lB"…ê˜`É(Xä򼆿Ëq=›@¡z¿"`¬¥`Ý‹bu‡ÓãEu}få'aú8ÚúA|<4,òì5ª ÈH¢P „_‘÷²M0Öž‚õÌ®Çá Šú†*Óò(TƒÁKê²BRý9‹°+ªNLO¡¬@°6Ã@ÁbÅ|¬œn/jØPÑÖßPâ㑵a$N‹né+ªiã3�N[CÂn Öœ‚…‚Û±rº½¨ièÀL Õ° âã‘MÁ"„jçñNL¯¢P “_‘xáp ­°b6VwO`ëob…*Hb1+ÆÝÒ»°£Z‡)THO–r=NTð+á\¶ Æ“'c:X1+‡»5õZÌ.HÆÔ\ºFLl°Ü¬XsKïÂÎ�˜6!“Bd~E"\K6ÃÃ+¬˜‹•Ã݃˜P%p=NTˆÅÈ~–‚KZïlýMÍÏDZ"…*˜S‚±¬˜Š•ÝXQ-œœB¡ 16X. V´kѹ°ó„S(T!w÷XûIXÏžåzœ°Š™XÙ]=¨mÐâñI)˜4ZÉõ81A #{ý�`Õì¥`E¡Z'vUßÙúK¢P…Cà�.6ÃXSSÁЉXõ Õd UX±ÁrÁ"Qã†Ö‰¿ÖêQ’Ÿ‰4 UX±ÁªŽ�VÔÇÊæð ¦A‹ùÅÉ*Žô Võçìç{{{¹� ‚¿ÏÊøºÖ…¿�ìBi�©*N]”Ã\S Ó©S\�rQ+›Å„ªÿ÷+¼÷ó­XPœŒI£è—Ø`Ù l°¶}ð&̦.®G#pêÔ)üþ÷¿ÕßOêQ2!IJ ×£Å4B\K6à‡¿þ5Þ{ýu¸Ýn®G ™¨‹•^wŸ|ô6þëGÿçkbÞ¼¹*žˆÅÈÞø,$v,{«p»µ?ÝÎõXd>ûì3\¸p�-&|z²Ó'f")‘BÅ>e*FMÃçµµxéßÀ/ùKèõz®Ç º8®–WpâÐßqýòE8ìV@¦f^,_Ãõh¤�XŒî²Tüô§0 ¸vé<Ü.'¤2úA||uõêU\ºt ‡?{ó |ó•ï#™VT¼²tý?£¾þ,LV >ŒóçÏ£°°›7oFNN×ãEÔ¬¬Ün' §§›ýÜò¥ !¸�ôñë_ÿÿöÿ�›Àإá|ÌõXä!víÚ‡Ã0µ_Æoö}Ù»“ë±HR™'—²ûº»!•Jár¹¸-h¢&V'•`íóßÅÈÉË/cĈX»v-×c‘{|ë[ß·¿ým”””@,Îû¼ß_2èt:Ôž< �É(˜\‚g^xó–=ÍõhäóW¬GRr ’ñ\A¾6w.Æ�ÇõXA5Û€vgj:ð�Öc{w rss5O/ª””” ¤¤���øKUÎ×Õ¡ú÷?Çãÿ¼•ëÑÈ=>øð�ðùüWX‚UÏl‚:;—ë‘Ȥ¤©0j\ä2F¯}æ}Hœ2…ëÑ‚"*þ4·:»QsQ‹%SSP8R‰•+W¢¸¸˜ë±È#àßüc\¿r‡~ÿ{Hª?‡gær®Ç"w\ëpBï‘ão}9Ùj®Ç!°`ù³ðû{áW&Á¹d°¿¢"X¿ hut£¶ž UàÔ_YYärº`)ÆŽ�ô#ˆ­:ˆû¼‹p§¹Ý�¿ŸêBùóÿD¡Š šœÑÈ1ÁZ¼ †êZX¢à…Ã+«£µ Z,™’ʆŠD&¡D‚ìò��XuŸÜÏõ81­¹Ý�¿�6`F~&’èÔ_$ó+“à^RcÍIØ"?eDi½3E´ñ'¤À½|3ŒÇª#v…q±êªñ9t]*Q°Âïr›Ÿ�6`…*jùRàZ¾ ]Ç«a9yÁЍX1¡Z6�Bí(XáÓÔæÀgg (›¤¦w¦ˆrþ„”ÀÏÃ:~æ³ç¹gP"&VG7jï„jB6…*P°BïR›{OPV¨F¢\Ìõ8$ în ‡%‚‚±bBµrZ…*ÆP°B§©Í�/NQZ¤F¢‚BKü )ð,ßãñã0Ÿ=Çõ8ÂûX™íÝ8ÙÕøl×ãô –„‚Mmì=c PÅ0vKðD5¬u¹ç‘x+³=p�jE …*Ö1ÁS°†íÒ-{ T…ªXçOH�gi9º¾< ëy~‹·±2Û=wC•E¡"�`emÜ@Á†K·ìøâ¬‘BEX�`mD×Q~‹—± „J‡U%é*Ò�H* «ë$gr=ND¹tË�½giEE¾ÊŸ˜Êû`ñ.V}C•—E‡)ÈW‰¤Rd•o„XßJÁ ÆVöžíÂÌ" …ŠÜW¿`ñð¯be´yp²^‡•%i*òP¬�kluà‹s�P%Ðñtòl°¾ä_°x+“ÍXQ•¦amý‘`‚%麅øSt ë~î†*‹BE„¯ÁâE¬L67N6vbMi:…Š ŠH*…fãÈŒm¬{4´Ú°� U<×ã�r7X_Âz‘Áâb*ÜKË¡?t¶‹ aü°ÆÊp'TOÍLÇh­¨Hè޵—CÁ:ßlÃÑz3fR¨Hh1×° ‡‡=Xa‹•ÁêÆ™K*>B&X�­Q¬óÍ6|Ùh¬B ä2  =b*\Ëî«!|Á K¬ –@¨žœ¥¢P‘°J¥ÈÚ¼1*ƒu¶ÙJ¡"œl n„áÀ!Xì�ÇÊ` ¦„J–'EH_Ѭ³ÍVk4cVQ…Šp¢7) î¥å0†)X!�ª§feP¨§Ø`é#?Xg¯õ •4ŽëqH cƒuð0ì!VÈb¥7»pêr T£Ttê�pO(•"kS Xqgq=Î�œ½fñK*½Iip/Ù}ˆƒ’XéÍ.œ¹¢ÇºY* á¡T ÍÆõ�w4G\°¡2a&…ŠðLoR«æ²§¯Ú1s’2±ˆëo !ÃÖ›¢B÷’õ0 3XCŠª sÔÐP¨HaƒÕÖö`Õ\6ãì5 ‰>¾äL8m€~ßþ!kбҙœ*ÕDr94L°êއå1k.YpúªeE*�ü©ªÀ ‡‡¬Amˆwšœ¨»¦Ç†Ù™*Õâ h6•££¢2ð YBȫ撧›m˜5I)…ŠD±ÞUà­™öoôm«S 7ñôL$^Øív®Ÿ7!!—¸v zwïFŠ4 È™ôû·9=8yY‡i2á÷ºàòrýŒ 1‰˜ÿn}¾kP7p¬RÒ3qfÇ�qv'×Ï”�ðRÆÇcnvr—Íîý*•pÚí¨Þþï8á@ ¸ûk~€^ðCÐ÷‰~¿ø¡JMðm~¿ßÏõà„BÈÄíÇÚB!CE±"„Â{+B!¼G±"„Â{+BHTÑétØ»w/œNgHîÿ‹/¾@ss3×O3æÐ»d�ÛíÆ+¯¼Òïs2™ ÙÙÙXµjŠŠŠ¸‘�¨ôñÇcß¾}ìÇ2™ � .Dii)àÆ�x÷Ýw1yòdÈåò ÏðÁ`Æ ÈÍÍåúÛShe5½½½ÐétÈÎÎÆºuë°nÝ:Ìž=·nÝÂøCÔÕÕq="!QÉn·C§ÓaíÚµX·næÌ™ƒ[·náõ×_ÇÁƒ#GŽÄ /¼€ÄÄD®Ç%AD+«aÈÍÍŲeËØ�W¯^�^xÀäÉ“¿òõƒ.— *• b±8(3èõzˆD"¤>äÅuN§F£ …ÉÉÉ÷}‘©Ùl†ÝnGjjjHþ6JH0-]º”ý=ôÄOॗ^Âßÿþw,\¸YYYX·nÝok·Ûa·Û¡R© ÞÿïëÌ_HÒÓÓwÿ?*m6233éÅÛ!F± "¹\©TŠžžž~ŸonnÆÛo¿�ëׯÄb1V¯^�矞ýͲ}ûvìܹÛ·÷Ϭ÷ß.\Àû￸xñ"¶nÝŠ-[¶`ÇŽ¸ví //ÿú¯ÿ •JÅÞÖl6ãƒ>@uu5z{{xíµ×0jÔ(ÀÍ›7ñÞ{ïáÒ¥K¡PˆE‹áå—_F||<×ßRBI.—#77MMM€šš¼ñÆøío µZ xî¹ç°xñb8ìÛ·½½½P(xõÕW1sæLö¾ü~?vìØ��;w²o)'‘Hð /`õêÕì×ù|>üêW¿Â¡C‡à÷û‘��€ï~÷»˜6m×ߎ¨E±�ÇÃþmµZ±wï^Øl6Ì›7�ý³ÙŒ×^{ )))øÏÿüO¤§§ãàÁƒØ¶mâââ°yóæ!=ö‡~ˆòòrlÙ²øÅ/~�ÿùŸÿÁ~ð€×ëÅk¯½£Ñˆï|ç;(**Bww7êêêØ@šL&lݺ#FŒÀ/~ñ ¨T*444à�wÞ�X,ÆK/½Äõ·˜�Gòù|¸}û6ÒÒÒúu{÷îEYYÞ~ûmüæ7¿Á¯~õ+!!!ðFÅؾ};žzê),]ºr¹ÍÍÍ_9¬±gÏÌ›7ï¾û.|>Þ{ï=¼õÖ[øÝï~©”~bz(P¬†aÏž=سgû±H$‹/¾ˆ²²2ösû÷ï‡ÍfÃo¼Á®fÖ¯_�––ìÙ³7n„H4øwÚ^±b»™™™‰+V`÷îÝì¯;v ---غu+{á4 ûï»wï†×ëÅÖ­[¡T*³gφ^¯ÇG}„¯ýë´º"¼ÔÜÜŒøøxX,ìß¿:�6lxèm222ðꫯ²Ûußüæ7ñꫯâòå˘>}:œN'víÚ…ùóçãÅ_do7}úWßÀxäÈ‘xùå—Ù�¿öµ¯aË–-¸ví° ŠÕ0,Z´«V­8Ô××ãø¼^/»gÞÚÚ µZ͆Š1cÆ ;v :�YYYƒ~ìÂÂÂ~k4v¥§T*ÑÐбXŒ3f<ð>�’’‚ãÇûÿÌ&£Ñ¯× ­V‹#Fpým&ä+¶lÙÂþ{zz:6lØ€�7>ô6ý®+1q3 €+W® »»sæÌyäãôûøÞû"ÁG±†ÔÔTäåå±Ož<]]]¨¨¨ÀŠ+ P(`6›ï{*‰ùœÙlR¬d2Y¿�™­=ŸÏ Ϥ¤¤‡^ôµÙlp¹\8zôèW~­¸¸˜½/BøæøÄb1ûÏ@Üû{†ÙÑ`þ?w¹\€äää!ßsm˜Å*È233áõz¡×ë¡P(�‘‘�sçÎ}å뺺º€Ýg�‹‹COOOà­óûÆl6iŽääd˜L&ø|¾n3&''#!!?ùÉO¸þ¶2(J¥2h'jL¤ôz=Æ�ÏõS$÷ ×Y‘ßïǹsç  ÙSHyyyèêêB}}}¿¯;|ø0’““ÙÓ{ðz½hkkc¿ŽÙZŠéÓ§Ãëõö{å½JJJpíÚ5\½z•ëo!œËÍÍEBB>ûì3ÐONâZY Ã… ðÇ?þ@àdà… ÐÚÚŠgžy†=´páBìÙ³o¾ù&žþy¤¥¥áàÁƒ¨¯¯Ç+¯¼Â®¢¦OŸ…B�·Þz ëÖ­Cww7vïÞ=äן�}· ¥R‰‰'âå—_îwH"‘àõ×_ÇG}„?ýéOp:�ÈÉÉÁ÷¾÷½~GÜår9^{í5|øá‡øå/‰ŒŒ ¬_¿ƒ¡ßÊG&“!//‰¤ßL ÈËËc·ü¶lÙ‚O>ù‡ÂîÝ»‘��€ &°×ˤR)Þ|óMTUUáóÏ?‡^¯Gbb"4 üq®¿Í„|EZZòòòøb^ ð{1//¯ßIÖÑ£G#==½ß× äåå!))‰ýÜ‚  T*ñÉ'Ÿà­·Þ‚H$BNNž}öYökÆŽ‹”””~÷%‰�——Ç�'ÁG?)˜BïÑ5+B!¼G±"„Â{+B!¼G±"„Â{+B!¼G±"„Â{+B!¼G±"„Â{+B!¼÷ÿ66ÃSÞ½¨•%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--um6vt6k57ob.png000066400000000000000000000345161524103652300220770ustar00rootroot00000000000000‰PNG  IHDRàà-já cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïY8.IDATxÚí½é“ç}çùɺ«ªïF£»q÷E¢@I¤(Z¶$ËÖlxìÙñ(Ö;ûjc÷OÙ�ØÞ™Y{w<3;3Öȶ$"E‚HÜ7h ï£î»²ªòÜͦ( ººëÈò¡à¡+³*¿ù<Ïïøþ]×uLLLº‚¥Û`bò,c ÐĤ‹˜41é"¦MLºˆ)@“.b ÐĤ‹˜41é"¦MLºˆ)@“.bëö˜lP©©k ¥ªBQ”k*•†FMÖ¨Õê’Ž¦ëÔe tPu UÝø·V+X à²[—Ó‚ÇiÅã°àvXð¹­=v^A· ŸÛÚí[6³­³E™tA&]l°–—È•e »ÕŠÇmÅã°ãrØp:­8lV6 »»ÍŠ 8l›‹ `µ ¨ê†8dECÓudEE’5$ECRT’J½¡ J2QAS5‚~;ý>;}Núƒvb!A�½Û_Ñ3…)À6"É:kùk™:‹©:‰\«M àuà÷lü/àqàqÙ°Y;{PT�j]¡\•(×$Ê¢DI”PT�¡°“±¨‹á~'CöÏ…nÒzL¶]‡Õl�‡ë5$Dò%‰pÀIÐë¢/à"ìwâ´{ë'É*¹rƒl©N±R§Pnñ;Ø=èazÐÍ`Ä…`ê±e˜Ü! YãÁªÈ½5‘Åd �ËJÈK,ä&pbéñ§UÕt •©œHºXCl(LÄ]ìö05äÅi3ãx;Áà6�” ÑÝ^©²”ª ¸ˆE<ÄÂ\_ávJ]RIæEÒ9‘t©Îh¿‹ƒ»¼L xqØ{ûeÓ L6ÁBªÎÕ¹2së"ý~ý^"ì>¿YÕHdEÙ*™b�©A7G'ýŒÇÜݾ´žÁà¨ÔTn-–¹ú°‚E€áx€Ñ¨»¹õúdEc9Ua%UtŽìöqhÜo¦;ž€)ÀÇ�,J|6SdvMd8âat @Øçìöeõùrƒ¥T‰µŒÈža/ì  :º}Y†ÄàWXÉÔùèv‘D±Á®˜Ÿ‰¡ ¹ÚmYÑXJVXH z¬œÙbjÈÓíË2¦?gv­Ê¹›yM`b0ÈpÔÛóL£ é:«é*skEœ68{(ÌÔ )D0ÈJ¦Î»7rTk:{ÆB E¼Ý¾¤§št¡ÆÝÅN‡À7ÍñÙàz¾Á¯¯æ¨ÖT¦Ç¦ð:ˆ®ÃZ¶Êƒ¥<~¯…W�õ3z6ψϜ+5…÷ox�Ù;f,ê7+;º„®ÃRªÌýÅ<ÓÃÎ ?sQÓgF€ª¦sá~�OgÊŒÇüL�;^iòhdEcv¥ÀrªÂ‹ûœžb±<oÅgB€+Ù¿º�Âít°oW¯ËìÂ2"ÕºÌ�ù²¬ð§ûî{úÓ>OµeUçÃ;ynÌW80ÞÇHÔ×íK2ÙÉœÈ͹,SC.^9yªëMŸZ.$E~y!C$äfÿxÄÌåõ²¢q{!C¡\çû§b승º}Imá© ªê¼+ÏíÅ*G¦ú‰†ÌºÄ^&�¯qýAšƒã^^>܇õ);>UÌ–d~þi»ÍÎá©èÝã&½�$«Üx˜¦ÑPùã3ѧª¬í©àµùïÝ(°w,Ì®¸¿Û—cÒeî-åyõX˜CãOÇoÜóTU�·®f˜O58µ7ŽÏmzš<Í”E™K÷’L¸øî±HÏoI{Z€¥šÊß’À‚•£{bÏl_Þ³†¢j\�FR~ò�XOIõ¬W² þþ£ƒ!¦F‚ݾ“.0»R`1YâO¿ïÙœaO pf¥Ê—²›Ž ›QÎg™d^äúl†ïŸìgÏHïv÷œ/Ü/ñéL‘“ûâ„|OO4Ìdû”D‰‹w“™ðrö`_·/§)zF€ºo_É2—ªóüþ8.‡YNfò[j …Ïî&™tòÚ±þn_Ζé ê:üâbšTQáÔ¾¸YDmòHdUãÒ�$±°•?:ë‰.à PÕt~~>EQÔ8µ çÃÎ&íEÕt.ÝKâsÀŸœ‰aßoT -@EÑøÙù4 Ží�™&[BÓu.Ï$qÛáOÎݸ"ʰW¦j:?û$…¤ÂqS|&M`Nî‹ÓÐ~v>�¦v�1¦uþá³5ŽMÇLñ™4‰ ŸŽÓ�ágçShšÖíKz$†à//¦)VuNì‹›â3Ù6‚°qt©Ôu~q1‹[†à[—³$ '÷ÅÍm§Éޱ'öÆI~}=ÛíËùýëëö|™OgŠÌ§êœÚ7£�&-Ãj8¹?ÎÃõ:ŸÝ+vûr~Ãpf¥Ê…ûE3Ï·t]§!©”E™²(Ó�T Ì6v«…Óûøì~‰™•J·/ç QN²ž­óÖå,§ àvâ’ …¢j¤ 52…ÅjƒRUÆn·àrl¼¨ê’†,k¼v‚^'ý!Ñ�Ë|‘}·ÃÊɽqÞ¸œÀç¶3é~w×ó€eQáßýz•#S1³°ú+”E™ùõ"kÙ*C}N¦= Gœô¿76ZVt2%‰•lƒë"ë¹Ã/ƒA|=ܮӒy‘›ó~úÊ0þ.û�vU€š¦óÿ¾¿N(àezÈl)ÚD’Uî.æHjœšpdÂ�×Õ܃R­«\Ÿ+sq¶D<ìaïxØðã±;Éìr�\¥Ê¿üöPWã ]à¯.¥IUNíèÚ`4’y‘2žðqf§}gÛȆ¬ññÝ·æ+šê'î½–�vqi&IÅîá»ݾUC «ÝXãåƒ!ŽwÇ3¶+O~¦$óÞ�'̈ç,&J,§Jüå+ƒ-ÀH¿‹ÿþ•!%ånß®!°[-œÜãÝ«9²e©+×Ðñ§_Uu~~>ɾñ°i ô9™b�ÙÕvv€€§}Qà ÇÆ?y€ÙÕ<ÙR½Û·müS£a~þi µ 5£àû7óØí6ÆcO‡­ÜNÙ4úÁ©(!oûS0!¯�?:åÚƒ4ªjæ&ýX-6ÎÝÌwü³;*À…¤È�å*G¦b¿Q£2¿^b,êbb s)˜ÝnF"Næƪ é&G§¢ÜZ¬°�êìΠcYñË O>]ŽÕ¥ªD±*Q%dUCQ5ìV 6›ŸÛA$àÂó˜iLº®³�(ñ/¾=Øñëþæsaþî½u&‡B�í¯Ör¥:•š„¢hȪ†ÍjÁn³àó8z¼O‡/�Ãnåðd”_]LñW¯�â°w&5Ñ1¾w#O$ä~*f5”E‰¥T™õŒˆÍ&0Üçd¸ÏŽÇiÇa· ÉÕ†J"/2³”Ãe·20óýNÎ)S¬ò؈ø;îØ xmdK5úƒ¿ýMTMg%Ua)Y¢!«ŒF] …x¿tobC%Q¨ñp%�ªÁ@ÄÃX,€¿Çþ±°›õ¬‹s·r|·C©‰Žp5×àþJ•—�Žtä¦ÚE±*q9O©Úàèn?¯ ï âÑuXÎÔùô^‘s׋šˆ|ñÊ—ëÝz~•Ýq7¹Rã ¦ 5nÎeˆ‡üÁÉ£ý®'úªäÊ2·—*|vw�€×ɾÑpO¯ŠvõsîÚ ûÇ|)Uk{PÕtþÍÛ«L ‡ìÑ9쪦so1ÇZ¶ÊKBÙíßVõÄ|²Æ/.dØ5`r8ÈÕû)Žíöp`¬;9¨;K®Î×86åÁj‘ÅD‰œîgW¼ù—‚ªé\�+óñ�Ã/{Ç{w’ÑZ¦ÊüZ�ÿᵡ¶Oêmûaì½n»½gÅW©É|xc‡Uã_¿>Âñ©À¶¬‰¸›Ÿ¾:Äz¶ÌÃÕ"’ªávv¯<Ìå°¢(*V $²~úêжÄŸ·üLøŸ^ÁaÕøðÆ*պܵ{Û Cý^ìvî—ÚþYm`¥¦rþ~™ý½e–ºI¶XçüíuÎìòâ_tìŸÛÊŸ¿<ÈB¢D©"u%÷´‰ªéªKÉ2þ­|-(Lv9,üð…(göùäÖ:¹Í7œèãÓ™"•ºÒÖÏi«ß»™eWÌ�×Õ{‡ó\©Îåû)þø…(G'Z›³ô¹­üàt?5I¥,¶÷þ:Ê¢B­¡òƒÓýøš,ö~G'üüèù(—î¥È—{O„—�Ѹ�nÚú9m`¢ 1·Vgr¸÷ºĺò…øÆcí ’ìŠ»™ò°žëN Àz^bϰ·­÷ø£ç£\šI!¶y%iÓ#!$ò�¶}FÛøö•,{w…{n6»¦o»¾t ´íóÐV9³/Ä|RìŠY�®oF¼¸¯½/ȉ7gö‡¸r?Ùs]û6«…=#aÞ½Þ¾ ™¶¨c>!R­©ŒF{¯Ülv¥HÄoãÄTû;†"N‹ÀìšØñû¼¿VE° v`¬×©=B^V{¯òf<î§XQÚV!Óž»Y`z,ÜÞü_¦&©,¬yýDçúÃFû]œŸéüƒy~¦Èhë».Çë'"Ì­©ËjÇïu'L�†x¯M«`Ë8»V¥.ë öõ^Úááj�#»ýøÝ�󥋺XÏÕy¸Þ¹UðÁšH"×`<Ö9<6ïòópµÐ±ÏlCý>²Æ\¢Öò¿Ýr~x;Ïž\ýTMg%]áôžÎ�‚N»•7.g©Ëíwo®Ko\Îâ´[ tðEpzo€•T¥«©—í 05âý[¹–ÿí– p.QCRúzÏö ™ês¶<ÿ$\ ^—�XØÃ›—2mÿ¼7.eˆxðº¬-Ék6ƒßmc ì$•ëü™w§ E¼ÔëÕL­¤¥¿À§3&{Ô\)[¬15Øù‡ÃfAÑ4Ží“È”e~s£õoÙMÞ½–#[Q9¸Û…¬ê]éJ™ò�éÑäüäp åƾ-ûÒE‰LIf°¿÷Î~…jƒ‘þÎûD6d ‡MÇí*ò�Óî¯Vøèv¡åŸóáí<³ëU¾sªŒß¿ŒÝ’Òù�%Ã'ÅJûòjm½ö˜�DA"Õ¼`ËøÉÝ"ãÁž�çP­+½�¯Ø*®Ï›v�WN׸³RæŸ>K·ä¬¤j:ÿøYš™Õ ¯>/âplˆÎíÐ�`Øk£Ò£5¢A`w<À…û­óÔi‰+5•¹u‘]ƒ½—÷ÛDV4\;´Ü%QÅåü­Ü.�×^)7êüí»ë$ Û¯”Iä%þöÝ5*�¯½PÅåü­ ÝN�RÊà\+rVÞV1>àÞZ•j£5ß]Kž¸[‹eú=ØM‡³¦YË5~77f³êœ=Qe÷hƒÿôÁ:ï\ÏQ­o=V­«¼s5Ëÿ÷a‚Ý#*gOT°~%¶Ȭå:¿Ôu�ÞÜ%Øm†"nnÎU[ò÷Z¢˜«sÆã½í5érXÛ^ùþ(Ös ¢áG‹kj´Á~³F¹^æ¯ß\áW—2,¥ë�,]Ót�¥t�7.eøë7W(ËUþè›"Sc�Ž8FûÖ²�`¥®ârô¶C÷X<ÀµùÖlCwœÚ(Ñùº?èb'<ÒE¹£Iø¢¨P©+„ý�_Ý\8u°Æá=0»¤ðÖÕÕšN�“uÜ®­m Ç,Ü^®òâÞÎ¥Žæ5úü�«Ài£~®Ì•v,ÀmA%Ecn]d4ÚK…V2Ôïåöbçª4t®/T˜n~èvé E5öŽ«ìWŠjM‰o“Éa‘óåŽuc¨šÎ�¥*Ã=šªú2£ý^¬Ö�wè­º#>Xé¸z®åèQøÜvÂ^'WtƶýöR‡M'Ö×½âäXDÃnÓ¹³Ô™�•—fK„ýN<=Ø ýUv+‘€“«; ÆìH9·—ª=éõ"+ÙR�µl•ÕL•T¾Fµ®°w¼��ï(TÛŒ‘�nå9º¿û!GöÖ9w+�¬´w,TÎÏÙ7Þ‡XWHçk¬e«¬e«äJõžLM ô{¹³¼³²ºmŸ²ÆrªÎžñh·¿‡-!«ËÉ2ëÙ*eQ¦Ïo'à±!PkhdÊèAàgŸ$ù‹o îx4Øãxër–XX'î~kN¼O%ÖyëJ†?:Ýžß²!küýÇIAàÓÛ túýŽ/jQWD…\YÆïÙ0ï�û{"¥5ñòÎ|ކ¬mûYÙ¶-áí… —V9¹?ÞíïákÑt�‡«E®™ôptÂÇh¿ë‘vsÙ²ÌÍ… W”ˆìü³—âxZìZöéL‘ë E¾w¦†ÍjŒ®Exóc7Çvy¾Å±¡òŸ?L’/Ë›pxÜ÷H/UMÓYÎÔ¹6WáaBdr8Èä�ñ+«.ÞIrjÚË�mŽ7Û¶ÿÛùn·›1Y©Ôd.ßK ÚøîÑÁ-?©KïÞȱ˜¬ñÚ±SC;/ÒÖu8w;ÏÝ寜®á1X P¬Ã»Ÿy80æçìs­i'›]ùõÕ,»ân¾s¸oËÝ…ªÂ¯¯fÉ–Žï‰zŠÖb¢Œ$ÕùÑ ÛÛ=lK€ºÿûÏ9{lİIÕt±ÆÕûi¾s$Ìá]Û{I\Ÿ/óÖå,n¾u(L4¸=Ççõ\ƒ7¯dA�9{üÉ9ºnQ—à£+nÐí¼~"Â@x{¹ÝtQâ½›y5¾w"‘mºÊ]Ÿ/óÞ�<Ç÷DÇ>ßHÔ%…s×Öø_4¶­—Ö¶¸’©ó‹KÎ6¦Õ|ºPãêlšŸ|#ÆÈmf×D~þi M‡xÀÁÑI?cQ×-éó™…d�ëóeÊu…#Ó»GzÃìá²�ë³v‚G&ü슻Ÿ8:-W–YLÕ¹6_&U”°ðãb;Þ=,§ëüý')ŽMG ;Wäƒë+üèùè¶üu¶%Às7ód*°<Üí{ÿ=Ê¢ÄùÛ‰–ˆo“[‹ÎÝ*°w,L*/’/Õ�d�hÈ�Ç¹ÑØºÌ©ÖU²e«ba˜n0U{Î!@×a5eeaÍE*¯£k Øñ¸¬¸t}c«.6TÒ ‡] /è òso1Ï·‡x®E–û+™ ¾x`ŸÀÜYÌXøæs¡¦ÿí¶øo½Êž‘‘ ±2ª¦óá�UÎ>×ú™ßo\Ê�u^<"a·•©KP¬X¨K IºN§ŽÓAŸŽÛiŒK«ë¥*4$ iæÁáÐq9 èÓ¾h©úàr˜>¯•×Oô·ôóo.TøèN‘—næD¦XãájžŸ¾:Ôô¿m: !É:ù²L8`¼ÚÏûËyÃŽ–‹à»Ç"üŸo¬P(ªD#5š®¾ÞË]m�Kÿf×Dî/çÙ?n¬Qa¿‹l©�¬êحͽšN^¬åk„}Ã…‡ÅºÂrªÂ÷Ž·ÇRÐf8{0ĵû�52ê%®Î8xùP[“áVùÞñËɲá\¶­� ×A"×|aEÓ\ÍH„ XL;»’çäT åy»/shÜOC†tÞøIâN“ÌÚPUZvî{^—•Sf hmò¹YÉ4_×Ûô“´˜®6˜%E#‘99ÝÞžDA€#>æWŒ·ýî6s+NŽìö·=ØtjO�D¶JÃ`¿}K�`¢ öë\IU˜ôtÄfïà¸�¥„ŽöìÿžˆªÂjJå¹ÑöwŸ¦=¬¦[Ó‘Þ*úüNÖ3mÞ‚*2V,8íÆJ¾§ "ûG;SîwÛxd‹Æ:w“\I äs´d¾àVØ7ê%]4–·¨ÓaÅb(5YÈß”S%‰ ßXeªª“/5oó$£/3q’1Ï�_�ÊÙîÀ<õMvÅÜäŠ Ã9l<R¥æL´šzŠ2…�Šu#Q%Â>{Óáß�0Øç$W6Ö‹¨›äK6†:(@»M èµQ®vo¶â£ðydŠÍ�›àz¡�ßm¬¯$JÄB�½&¿ÛJ½nnA7©7|®Î¦gâa%ÑXô{¬çڸ͖c °!©½�=“zœV½é-Û2xœ�Ý’Ü6’±"¡~·ƒl¹�+`©"áéð›îIÈêö›!·‹ Е©¶†E×:\˜árlÌÔ0^·�b»‚0•šŠÍfÅf°Ne�΋¡&i8Œuî*v›@½Ã«‘_€v«Á²Ñ„¼U¶¬¦RUÆÛ¡0s3X-ÂŽ�©š¥RSp9 øt ·S§\ë¬U3\9$€Ïm£Ø„åÿ–X¨)¸�Æ{í»Í/û;e)Ý ?l¬zÄn Ë,¥;k0•¯*¸ vp;M=�[_E—Óx7ìóØI; Ó4�ë"ƒý¦7ŠªÌ®‰hÌËeJ2~ZU¸6 •­Gè¶,Àª¨® äs’-ÉÛ†Þ^ªâ÷@ÈonA7 ùuün¸³Ü™ò0IÑÈ•d‚‡àpX›û¶eвŠÃf<Z-}'×Û_šT—6ü<N÷æ€ÉvòÜž:ÜÊÓèÀœû‡ë5"A§!Ï€N›Qjƒk Gæçm…¡¨�ksíw´þÕ¥ CQˆ÷™Ûϯ2Ч2пñµ›kse†ú�9Áa·RkbvàÖ· u»W@€á~/é¢Ìzçݽs-G®ÒàÄcUá‰û«dÊ ~s½}sî×s 2%™!ƒÎ—pØ,ˆõ­O¶,À†¬ã0è ‹ 0=â­+Y´'ˆ4]çí+YæSU¾ó¼ˆÅ˜_�!°Zá•Ó"~}5Ûò\�¦ë¼y%ËôhÈ�ÛO‡ÍŠØDNtË�“¤êm³hcq?º`áÜ­|Ëþf¥®òwï'H«¼ò¼ˆÃf^ž„îóÊó5Ö Uþîýõ¦&û>‰÷oæ‹¡Í ­V¡©.�- PUuþu696åî’Èù™âŽþŽ®ÃÕ‡eþÝÛ«DBß>eНv�ïœ ‡ëüÛ·W¹6·óhŸÜ-0³"rt:ÖíÛûZ,‚€¦n=³åÄž¦é³ƒû*»•žàÂÝ$™’Äw�Ep58Òt�û+"ß-`±h|ûT�pÀXõ†½‚ À‘écoÕ‡%Îì±gØÓÔ‹¼.küúJ–µœÄó { ÚÄbh&D·uêÆ,ýù*.‡�3¹»˜ç¯ßXáÔt�Ã>¼®G�tùÖk\Ÿ/ãqÁ�©£q3ÒÙ Â~�×^YJØùd&Ï;×r�ð39èf ì|¬‡Lµ®rc¾Ì…Ùƒ/ga5ðh‹E@k"³eª=!@›Õ¡ÝÆü̯9o… ÛF4äÀﱂåšJYTI¸œ6ba/kÐ2…ׯdÆd2'sË·–ªÔ Ñ ¿ÇŠßm��ߤ Q¬) õyy~ÿ¯±Zྋ Ð̨Ec¯ç;åó/BÐA°X,¿ó @6\­5ÍŽ"ûAï�—L¯¢it}ã;Gøò"°ñ –�ßLC‡§üçØò hµlœ‘¬=° ÊŠÆÝÅ©‚Èéé ?z¾ï±~¡›[Їë5>»%ávúÙ·Kbl¨ûÓkŸ&×íÌÌ»¨KGvÙùƾñÐã· bCåú|… wÄû<ìï3\+Ü£Ðt[Ù²-‚eC€%Õ î&‹:ùñë#OlÖ„ �—Á>'g¹¿*nDÜ­œz®favH¾háâm7`å¥Aö y·äêqZyq_�ã“~Þ¹šã“›ëœ>Çå0^CÀ—Ñ4K�¿­ Ð" k:³IVùìN‚ã“~^Ø×ü¤W‹ °oÄËÞa/×çËüæ¢ÎÔ¨ÎáéZÏM7ê6º×gÝ<\xù`ˆ#Û3íuÚ-üáé~ÎÏùôv‚3q°)`MÓ›’È–¥jµ -¯2i5WgÓìónK|_Fàèn?õÚ0ù‚ƒß\ô"ɦ·Š$ ¼{ÁK±èà¯^æh ³_Üdÿ˜‡«Òݾ½¯EÓu¬Ml•·üÿtX”wž7ÃRª h¼|0Ô²¿éuYù‹o 2òðÎgS„[@’ÞùÔÍHÄËŸ¿<øØôÏvxù`tíóßÚ˜¨ªÞÔø´- Ðå�c¹Pm¢é:³Ë^?iyªD6F“M xy÷‚Õ˜_�!PÕ�9óÓC>^=Ò×òm»Exýx„Ùå‚awc EÅÝÄØö- Ðí²!u ×k;¬fªDƒöm�Þ*ß9ÒG¿ßÉ廯¬Â7—îz‰]|ûpûæ÷ ö9éÚY3ØlˆM$YÃëlà è¶[ht\KW8º»ýºp²Ÿõ4¤rÆ t‹DÖF2¯ŸhÏ|Æ/stÂÏZ¶Òí[~$’¢ânbDÞ–èw[ ¹ªšN®Ô`rÐÓöÏrÙ-¼|(ÌÍûÆÏfnÍ:yù`¸#­“ƒn²œ  Ë^W‚0n§ É€+`¡Ü èÜlˆ£^Ê5(”Í€Ì&ù²@µûÇ:³=wØ,„vŠãYƒ4ä6�ƒõ&Zí;E¥& v®VÐb˜ô°ž1·¡›$ÒV¦†šërØ)Ñ€�JÍxó …�oënm[`Àk£fÀ�uI!èíluÄXÔI&o¸]àÈ>3úù8ŽîoðÁ­|Û¬KÞ¸œa,Àc°Q骦S¬È 4€�&\ѾøV�ˆßN¾Ü ?h¬¾¸=£a>º±ÆÍ… ‡vµöŒðÖ•,‘€“hhcõ¯5 e�FÃFC± ë:N»ŽË¡ð©xÝÆzAí”jM \hÈj AÀaÓq8túü*.—F4¬8ùõÕ,p²¿¥Ÿ}¾L¦¤ðÒaã gÉ•ëôœØ¶±-ÞÖ«drÈMºX3œ­�{büæÆ:aŸm[[‚Gqs¡ÂBªÎžÑ0\ÒÉ•¨Ä\. .ûÆY.©ˆu�lYA'Ø=Ò`(ª²vñëÐtXK[™_u’Îë  ôû¸]Ü+š®S�5ĺJ¦(aµZè 8‰…½Ü_Êsk±ÂÁñÖ¼—3uÞ¿™çÅç 9!•«19´½gm[Ü=àåÎršýcánßûïáóØ9:å¿~œâOÏÄÝa›ÌìšÈ›W2謥KÝíc<Ú÷Äž¯bUa>Yãú\… ·$OËLŽ«Žöq<\vp}ÖJÐãàÈ„�ïw?±Â?_‘YLÕ¹6_¤ZWxãr§ÝÂôÐÎÒKé:?û$ű=Q|ncÖÿ¥ 5^Ú·=+A×›�[é:üoÿ¸ÄÙ#ÃMuÿv’L±Î•û)¾u8ÌщíùÅ\›/óÖå “ƒ¾}¨�H`{@"ßàÍËYd^:^Ãe¬Ž/hHðÁ‚nãõÂÛ3¹Ê”$Þ»‘g>Qã{'"Ùæ÷u®Ì¹›yŽï‰n·µI]RøàÆ*ÿËÆ·µËÙ–þÛ'IÜncqãN+­Ôd.ßK ØxíX„Ð+Õk’Æo®çXLÕxíx„©øÍè:|p;Ï�¥ß9]7ܱ* ü梇c>Î>nÉ–ùÁšÈÛW³ŒÇݼr¸—ckg¤BEæí«9r…{cx]Æ\ùeR�?~a{gÓm ðöR™Ë³"'÷Ç»ý|-š®3·Väáj‘ÝŽìö1ÖïÂòˆ2¦tQâÖb…«Ëôüä¥XS½][á³{E®Îyý5lVcˆPQÞüØÍ±É ÏïÝ™«øW*ÿå£$ْ̱)?‡Æýô?b'¡i:K™:׿*Ì'D&GBL xæû2î&9½ÇË�Ñí�w·-À†¢ñüÓ2¯žÅn°¤è£�U�åd™õ\•rU&ä·tÛ¨542e «  êàw[ù‹o ´ÍáëÒÔT‘w®~õëøøš�ÝÅNGÛò÷²Æ¿o�j]C@×u"n‡]‡bM¡P–ñ{í öù�ùzã™R4Þ¹´ÌÿüÃÑml[€ÿõ£~߯ÖKȪFE”¨II{»Õ‚ÏmGQ5ÎßNðÓï5e+Ðôç+:ÿ×[+¼p¨F,Òݤ~"kãÂ-ÿãkÃØ›™«Õ$…ªÂß¼³Æ™ƒƒX-•šŒü¹»‚ÛaÅçq®ÁöI,&ˈ5‘?=³ý]àŽîøÀ¸�DÖ˜Å_‡Ýj!ìw1ñ2ñ ¹q;mÌ,åyé¹P[Å`· œ=æê}w·¿ ®ßsñòÁP[ÅòÚ8³?ÄÝÅn§�hÈýÅ÷ö»zN|ëÙ*ÏíЊqGw=5è!S¬#+½_šU©É* ŽuÀaà¹1²,�Êw/мžq ªlûüÒ,'¦ü* ªõÞ¯&jÈ*ÅrƒÉÁ. Ða³09äf)mL›ðfXËT98îëX�™ À‘]~æWšõ‹u�Õ”…{‹Vî-ZYMZëÍ_÷ª“Cۜ۷¬�£^Ö2½·kú*+é “Cž;òíxÝ?¶ÛÏJҸ㢶J¾\c"ÞÙ-ásã^–“:ú6u nÜwñÆGÞøÈÍÜRµÞ‡Rïcn%À¯>róÆG>nÜ÷PßBÏ´®ÁJZå¹ÑΛÙ=à&W2^1³,'+ŸÜùniLJ�ñ˜‹®“¯4ûÚ7�¨Ý”D™h°³ù¦€Ç†Ïe#_è{Lƒo½!pý¾—ńʾ/¯÷1Òïú½UK×7J¶n/Vø§s:ãƒO‹�õ®É—ü.+�6Ÿw¿J4è ,öö4Wªcô–”:¶äÛ?2éc>Y"ìkO»Ô%Ÿ«óUöƒ}N2…}Áß/S»¿èåæ�ƒã^=øµÃ.Æ¢.Æ¢.Î óé½"¿üHçÈ´ÆÔØï¯8éœ�¡Hç_˜>—•ºd,G…fYN•8Ú‚ÕZ°88îg-#>Á˜N3q’+þîÊ«(Î]ò³°j域à•#}MMšõº¬¼r¤�?;;ÀÜŠ�/{PÔß]2³%+Cmœ§ø8A@ÇÛAV4Ö²5·¨Û¦%ô¹­ìö°�hoGz;±Û,Ô»0~Íï¶R—~+ŽjÍÎ[ç=Üþò•Á¦}&¿L<äà/_ÂçtóöyµÚoîzÃÒñí'lì4z!Éþ8%ö�xZV!Õ²oâù=ÖJ†kÔÝ*^—�B¥óg�ÓúÅœ‰ZÃÁ»óñƒÓÑ–Dd­�<åÀˆŸw.xEèuÉ‚ÇÙy!ä« >×v~š®3Ÿ(qzo e³e¿@,ä$vôlˆ9äu²ÚAk½Mœv ’"P£¼ÉÉþQg„Zþ9/=bï°‡®Zɧ‘½+¾*«™:¡ Ö-§* „D­»þ–þgö™[+vü‹i‘�›ëbÇ?WR4l ×ïm4ø~ûPûz,7æÜ[¹»�Çnµ uáÌ>»^#bÐÖ¢¯C×a~­È‹ûZ[¬ÞRqÚ6Jtz�xØÃZ®Ñ1oËMj’F¥®�*ˆ™¯þú‰~’9‘j]éøP›’¨�Ì7ˆ…�åé¹Ö³U—Г«àÔpˆësåŽ>˜‹©:C»:W…39èa°ÏÉbºs)%QáæB™ÝíÝÂu‚ÕtŸË®xëWî¶¼r¿y0ÄÌržt:u—ÃÊÄ`�7Ûdmø(V²u^hqìVxq_ˆåLçøÆå,“CÁŽòÜ)º³+^nÓÙ¼-Ü÷òXXJõ^‘öôH�|YáR›]¶Ö² tMß±qѶîsȃ®é¬w`ªÑ…û% U•É\ý’eB~kËÏ~›´íÐñÝcî-æ¿hºìAàøÞ8ß-0ŸhoÇú'3&âž®X ÂÆ‹ò“™öžyç5>½[àÄÞ˜áí%¾Š¬jÌ®äyõhû‚cm`<ädjØÃƒå|Û.¾]x]6Nî�ñŸ¥Û6öl!YãÁšÈ`_÷,ÒÃfW«,¤Ús�óÉÿøYšûâ†s³Þ ³‹9ö {ˆ79ó¯ÚvûöáË©*•ZïU¿‡ý®/Dxu®µíVåšÊ?]HãvZñw¡l¿Ç†ÛiåŸ>Ë´<ýru®Ì?~–æÔ¾aï%Þ+5™åŒÈÙƒíõ¾m«½N/ì pw!×Ö›h}gr~¦È?~š¦Ö‚¼Y¹¦òέ³k0HÐëèjHÞjyŒøçÖ)·@„5Iã>MóéL‘3 û{/épg!Ë™¡–»â}•¶'žNï  (JÏ–¨y]v¾yxY³ò×o®pqvûõ®s‰óÎ*Cý~&‡‚Ø­j�îµæÔ$›ÍÊÔP�ÁˆŸ¿yg•¹mž{UMçâl‰¿~sY³òÒáaCûy~«é ²¢rjªýö$mßÿX,¾ªŸÿüa’þ  G�…¡ac¥Ø¿«�á˜�;KyÎÏ82áçà˜ï‰nÙºKéŸÞ+‘)ÊžŠ nDÔ¼n;éR÷¶çé¢ü…H&‡ƒ¼~u9K4`ç…½AÆ¢®'ˆ2%™ÛK®Ï• úœ<`€€Ç Öß[@R4n/äø³³ñGzǶšÙ6ï¯fI—TŽNoºM³TD™¥T™D¶ŠÅ²ÑT9ð8­¸ê’†ØPI$–Ru\+cñ#±ßõœIj̯æùWßêÊ}üßï¬19Ü÷;¶ïª¦³’ª°”,Q—TÆb®ÇÞÛZ®�®A<âe<î7ìì†f¸ú Å`ÐÆwŽôuäó:&@IÑø7o­ðÜ®(Ñp÷íøZEY”)V”ë2²¬¢(v»›ÕŠßm§/àÂó˜N{]×yçÒ2ÿâÛƒÛž;±]2%‰¿{/Á«'ǻʉu…l©N¥&£¨*²¼qov›ŸËNÈçÄçé}Ñm’Ì‹ÜYÈð¯_ݱÙÒV阖Ó5~öqš³G‡qt¨K§™]- «2üBgí<~v>…Íædª“ãí !«|x}•¾cW¬s�£Ž6„�FÝÚåãÆÃL'?ÖÐL XI×·üØs‰«Ùƒ­k,íun>Ìpd·¿£âƒ à[‡Ã¨ºÂB¢÷­ [�ÍjáÈt”_\LS¨¶¿¼PUøÅÅ4G&[Óqÿ40·^BQ^jC#ô“è¸-��Žro)OYÜ‚�å3@$àbz8Ä<— ØÆNŒbUá?žK°g$lØy{�¦$J.ÝKõ\­h»0ðÿ¼»ÆJº–3uþö7kŒÇ†žéØIdEãÒLŠW�õöw'˜ÔÑ ÌWyër–DAæÔþ�n]‚áHæEn<ÈppÜÇKÏ…vܤ[—5>ºSàöb…#“QbOQz'è:\˜I0¶óÝãíw"x] ¦éüû÷}n¦GB]ûŒFCV™Yʓ̉œšpd·_¾ •šÊµ¹2—”èó°o¼¯+&LFåÞJ�rYä/¾=ØÕ³pWPª©üÍ;«ÚÝO¼½BÚIE”™[/²–­2r25äf$â¢?hÿ=1IŠFº(³š­ó`µF¢Ø`¸ßËÄ`ð©H�·’DNäö\–Ÿ¾6Ø7ô/Óu¬çü§’<¿?Þ³–uíDUuÒÅéB�b¥AI”°[-¸>÷õ¬74dU#àqò9鹉†Üf”ó* .ÞIòÏ^Š1Ô‚Ù;Åx°&ò«KYÎìÉÞ±N¢ë +*ÒçNÞŽÏ«Sz¬ßµãˆu…�o®ñúÉ~öc·e|6Sàê\• öäÄTã"«ßXãô?'§�Sýc¨§üù}!v:¹t7Ù³÷&ÆCUu.ÜM²wÈc(ñ�ÁðÚ±~Bv.͘"4Ù9š®sù~’��•ïíL‡C3N€ß?ÕOÈ#på^²ç¬ MŒƒ®ÃÕû)ün�?<ÙoÈ3²!(ð£b¸WfS¦MšF×u®Ì&qØáÇ/İX ù¨S€°Q3ú'/FqZáò½š)B“-¢j:g’8­ð“célß.†Š‚> MÓøÅÅ,é’©}qlftÔäkP5�K3IB�½`lñA6öò¿¼˜&YP8¹?n¦(L‰¬j|v'ÉHŸ�?0è™ï«ô„7yûj†‡‰§÷Åq›Éz“/!Ö.Ì$Ø;èá•cÆ‹v>Žž À¥û%>™)pj_œ Y¶fÊ .ÝOò�}AN,Ï÷$zN€÷WD~y)ÃÑi³€ûY'‘¹þ Ã�êgÚ åeÍГXÏ5ø/Ÿ$‹Øc¶2=slŽ [N–ùÉ7c †{s7Ô³„ ›÷Ÿ}’DÓ-ß3ƒ3ϲ¢qýA �?}1†ÏÝ»ñ€ž l„�ß¾šc.QãäÞþve6y2%QâÒLŠ=#n^=Ügø4Óèynrk±ÂÛ×rì 31hzž<�̯—˜].ðÚñ>Œùº}9-á© @¶,ñçÓ`±pl*fšÿ>%4d•ëÒhºÊ�Ÿ�uÍ@©µ�U�oç¹9_aßx£±§ãÜð´³–­róa†}Ã^9yªÝÜžjn²žkðË lvÏMôõìàȧ�JMæöBMQøÃÓQz4·× Ï„aÃô½ŸÝ+2ó256ó†AV5f—ò¬¦«¼°?È©i¿aû÷ZÍ3#ÀMª …s7 Ì®‰L�†�û{¢jþiD×ufWòìqóòÁ¾¶Ïd7Ïœ7I¼s-O±¢0=b¨ßg ±Cè:¬e*Ì,èó[yõh„xðÙ, xf¸ÉJ¦Îû7s”ë*»‡ÂŒ˜Bl+ɜȽå<.»ÀˇÂLÄŸÎèæVyæ¸É\¢Æ¹[yêu�‰‘#QS‰-AÓuVÒæV‹x¾u8Ì®g\x›˜ü +™:ŸÜ)°V��ú™>Õaðv"+KÉ óëB^gö‡˜ê½–¡vb ð1¤ .Ü+so­ÊP¿‡±˜Ÿ°¿û³z�\©ÎRºÄz¦Æ¾Ïï Ñ0S?�Âà¨6n.T¸>WFÓFbF£^ög+Z÷$²ÊJªÂrºŒ82éçð.ß3ÕlS€M°œ®såa™k"‘€“�~/ƒ}Þg¶ÌMV4Ö³UÖ³U å“CŽOú1ÀÔ¡^Áà6�U�«U,$kôû]Ä"âa7.Gï6‡n…ZC!•¯‘Ì‹d‹u&â.Œû˜ô`³šA«f1¸C$EãÁªÈìz�¹D ·ÃB4ä&öö»z~FŸªéäÊuÒ…É\ EVÙw±gÄËä Û PíS€-D×!‘oð QcnµFº\'èsö¹ û]ôù�†ïQlH*¹r�|¹A¾\£X•è÷»˜r19àf ÏeæI[ˆ)À6¢¨:ë¹:+™K™+Ù:v‹@ÀãÀëqð:xx\¶Ž×¥ÊªFµ¦P%JU‰JM¢(J ê F\ŒG� ÷»ìsš[Ë6b °Ã”ª ©’D¦Ø`½ �-6(Š >· �ÓŽËnÃá´â°YpØ?ÿ¯ÍŠÅ"`³ ‚€ ð…M¿¢jèúFÂ[Uu4MGRT$EC’7þ[—U¤†‚(ITj º¯�hÀÉ@ØN4è$´ã÷<ÝgX£a Ð ˆ •bE¦XS)Š2•šŠØÐ©5j QR?–Ž.èhŠŽòùüD›EÀbt‡MÀfp9¬¸�— ·Ý‚Ïc!è±ôÚzlfzÀ ˜41é"fËĤ‹˜41é"¦MLºˆ)@“.b ÐĤ‹˜41é"¦MLºˆ)@“.b ÐĤ‹üÿã:‘ÀzËèó%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--uu69fkh3cks.png000066400000000000000000000514461524103652300221460ustar00rootroot00000000000000‰PNG  IHDRs­_� cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïYRIDATxÚíÝçç}ïýÏÌö^Ð+ ÁNŠElj–É%±ì܉�äØqKìäÑýÇܯ×9ñIrŽ[b'î–»¬F±J”Ø+@‚DÇb±}vfwgæ~�¢$RDÙÝÙ]\ï'¶`÷7 à‹ß^sÉ4MA¡®ÉV ‚ ¬�sA„ Â\¡ˆ0Ah"ÌA€sA„ Â\¡ˆ0Ah"ÌA€Ýê„Ú g³Ìýâèé4r$Bû / »ÝV—%Â2‰Î\ öË_¢Ž�SL¥ÐÆÆ˜ûÍo¬.I„�ÄÞ,�E7LÒJ‰T®H&£¢Æ“èé$¤3�Ï"i hy¥"Ž¢Šd8Œ"£€tßã˜@Ñæ¢dwb Sr81\pº‘¼^$_[0„'&Ð%tâvÚ¬¾|AX·D˜×©L^'–*0—*OÐæãHñ®\œæBŠ –Ài)z‚� ’?€#Æá÷àòù�ý^ìn7N§ œnÿù=ŠÉä½Ç·G›ÿÕ(ªÌR 5­ eйÅL#›ÅžK!+išBÞæ!퉠ú£˜Ñfœmí4µEi9h:‘eiõ+Â#‰0¯™¼Îd\e2®KjÌ%5BZ’^=N‹2‡'5ƒìrálëÀÓц«µW[ö`pÙÏ¡ŒŒ0ÿë_£çóØ}>š?÷9<ÝÝËûbÓ¤°°@nz–Üä …¹9ŒØ%IfÁÛ”½‰bk�Öf:š\t5»i 9‘D¾ BÙˆ0¯A±´ÆDLc"®29¯¡ z¢vúõ8áø]¤‰[ؼ<½½xz{qõô`÷û×ü¼z&ƒ:=�«« »Ï·æÇ+Äã¨ãã¨ãänÝB·»H6õ2ælg\ŠÐuÑÕ䢧ÅCw³»M¤» ¬–ó • ÆfUnÏ(ŒÎä1Mh‹¸‰�l·Å�o]CÁÕÖ†gãF|›6a‡­.{å×9=MîæMò££”2ô�a¦šS½Ì% t7»ØØáe ÝKÄï°º\A¨+"Ì-’ÎëܘÈq}"Çlª@sÐIsÄKsÈK@.á¼ùö‘óØÝn;vàÛº›×kuÙeSˆÇÉ^¼Höòeì>î�{õõs;¦1³ àtØìp3Üí£»Ùcu¹‚PóD˜WQV-q}BáÊ�ói�îÍQÍ!6YBÎ$q^{iäþ-Ã÷îÅÕÚjuÙ•ešäïÜ!yæ …™YJÃ{)l~ŒTIf>‘cb>GI7ÙÒícK——Îf1÷]D„y…•J×§rœ¿�cfA¥»ÙKkÔOsăüî@)ŸÃ}ñÒ­ë„öì"°o_YÆÀë�‹‘9s†ìÈÅ-(mÙ‡iw�UŠÌ&²LÎe1 غÁÏ®~?a1#÷ˆ0¯�XZãü­ —ï*„zZƒ´F¼÷½„ãÒ)ìWÏÚ½“ð¡CbÕ%PL$Xxõu”‰ »Ÿ@Üyïc¥ÀT,ÃÝ™,ma'»ƒ uz±‰©�Â:'¼Œ ÃäÚDŽ·FÒ¤r%6´ùél âu}x×ynω_ãno§éÙgV4�p½Ð¦§™ÿÝ(Ø]¨�?�ßû˜n˜Ì-dŸÍ�Ê—ØÙ`ï`� G,\Ö'æe  ÎÝÎðÖ�4>��Þ¶mQïƒçQ:žw^E»JËŸý¾M›¬.¿¶™&ÉÓ§Iž:MqÏS7íþЧäÔ"ã3iÆf2 uù8°9D[Èiuå‚PU"Ì× �+ñÖÍïdi‹zémö?�áÖLж�ƒÇ7‡ék3a„õA„ù*dò:'¯%¸<–¥¯3Ho[�ë£7 ”fq¿òcÂ{v>rÄêK¨KF¡Àܯ�º�Ayö¯Àõà 6L“Ùù,£“)Ü.™'·…ékkœi�‚ð "ÌW@ÑtÎÜHòöH†žV?ƒÝ\ËØ\JŽÏà~ù¿iþ³Oà¶ú2êÞÂk¯‘¾1Jþã_ÄttHO/d¹9–Àë±ñäö0}­"Ô…Æ$Â|´’ÁÉ+)ÎÝJÑÝ` 3¼ìå…Y\/ýˆ¶O}ïÐ�Õ—Ò0Ž#yùÚ'¿„éüèá*Ó„©ù 7ÆSDývžÙ¥=,ÆÔ…Æ"Âü#˜&\¸�æµË Ú£^6vE9œò>Zï¯ÿ-Ï~ ŸèÈËnáå—IO΢<ûE–³k—i˜LIJ\»›`S‡‡'¶Gñ‹Ù/BƒaþÓ ¿{ž’!±eC‘ ke`šx_ú!Á �DŸzÊêËiL¦ÉÌ�~D6ÐNá±§—ýeºnrg*ÉÈTнƒA ‡±ÛÅ9-B}aþÙ¼ÎKçãLÄ4¶ôEèh^ÝJLÇÕ³xgnÐõ7Ëë…Õ1T•»ÿû_QŸþKŒæŽ}mN-rãNœt®Äó{£ô·‹ñt¡~‰0¿Ïù± ¯žOÐ×` +¼êU…’–ÇýË¥ëo¾ˆ³¥ÅêËjx™‹‰Ÿ:‹òé¿_ÕÎx2ÏÅ[óô6»ùØî(^—zê�s ‘+ò»³qRŠÎÎ�Í„ý+Rù×Ù?r›4üãV_Úº1ùÝï‘ÚO©ou÷&tÃdt"ÁÝ™,O{ `õ% Ьû�Â37S|ç¥)‚>OììZs�cèØF/Ú»×êK[WBûöâºynÕ_o“%6õFÙ·µ�Ó×Rü×±Y²ù’Õ—%˶nÃ<“×ùÏ×f¸tGáè®.ú;CeÚvܽ�³¥G$bõ%®+¾Í›!1‡”I®éqÂ~Gwuáq9ø?œäÆTÎêK„eYÁ<»Æq}Rá÷gçénõ³s0‚TÆ÷ä™;ø7‹ùäÕ&ÙlxúûÐfïRºoC®U=–,±±'JsÄÇKïĸ>¡ðÜcM8ÅŒ¡†­«ŸÎBÑä·oÅxéÜ{7·1¼!ZÖ Ç4áîMmmV_êºdóùpÞ½^¶Ç ù]ÙÙI¾`òÿ8ÉÌ‚fõ% ÂC­›0OdŠ|÷•)Ò*<±«såóÆ—C’Àã'?3kõå®KÚä$zÛ†²>¦Ã.³}c+C½~ôÆ,çng¬¾LAx uæ£Ó ßešŽf?;6¶`·UŸ#}ꦮ[}ÙëŠrû6EUCÛº¿"�ßõsx{§®¥øÕ™9JúºŸ&Ô˜†óSWSüöì<{6·Ñߪøó-�”üQÒ/Y}éëJòÄ Š;ŽTt�–ÏãàðŽNÒ |÷•)’Ù¢Õ—-÷4l˜k%ƒ›åêdŽ#;ºˆVbXå!J�=IòÄqÑ�WI~lŒB*CaÖŠ?—Ý&³gs+mQßeŠñ˜jõå РažQJ|ÿåid»�[;–µMm9-]èþ(ÙË—­~)Ö…Äñã{²ªÛ&ôw„Ù¹©…Ÿœ˜ãÊ�¬Õ/� 4^˜ÇR¾óÊ4Í!/Ûúš‘,Ú¥°û ŽŸÀ0 «_’†–¿}›B*C±§ú»R6½ÞÞÎ+—»´`õK!¬s æc³yþãÕ¶ôDêµvÑŽÑÒ…é ’»xÑê—¥¡%Nœ ¸ç �­ùQö{�ÚÞÉÕ •_¿9�aˆ£‚5&Ì/ÝÉð‹S1öni££Ågu9¨»Ÿ$yâ¤èÎ+D£�ÎPì­üXùGq;mÜÞN"Wâ''ÄLÁ æïÜÊðò…·· TïF磭ݔ|”KbfK%$Oœ ¸û¨e]ùýì6™=›Ú1M™›F+Š?àBuYÿ[°FoßLsòJ’ÃÛ;xkï(0m×Sbì¼òwîPL¥)önµº”{$ ¶¶àq9ùÁ+3(š˜Í$TO]‡ù©«)NßHqpG^·ÃêrÈhíÆðÉ]¹bu) %ùÆw©‰®üƒ¶ô5 ºøÁË3bçE¡jjï7a™^¿¼À…± ·wâvÖö~aêŽ#$޽!ºó2ÉOLPHf(ôm³º”‡Ú´¡‰öf/?|mVtèBUÔe˜Ÿ¹™âò�û-˜C¾FÇLoåêU«Ki‰×^§¸ëpMvå÷ÛØ¡9ê凯M£Är¡²jû·áÞ¾™æÍßÖYA¾DÝ~„ıc¢;_#ub‚b:M¡»Õ¥,˦ž‘�—›¦Pß{¡rê*Ì/ÜÎrâZŠ[Ûq×Q�è�}èîʵkV—R×’o¼AqGíwå÷ÛÜÅïqò“7æ(‰@*¤n~#®OäxíÒ�ooÇç®í1ò‡Qw&ñÚë‹ûž +¦NL Åúkw¬üa¶ôµ ÙlüâtL|û…Ѝ‹0ŸNhüîlœ}ÃíøjtÖÊr�ý^?Y1v¾*ÉcÇÞ+¯¯we°8mqÇ@39ÍäwgcV—#4 šóD®È��Ͱk¨™�¿ö摯T~Ûa޽!ºóÒ&&P㉺+I–Ø5ÔÊxLãÌÍ”Õå ¦¦Ã\-ü×k³lê‰ÐñZ]NY]˜./91v¾"ñ7ŽSÚq¨.»òû9ì2û¶vðæõ4×'ÄaÑBùÔl˜ë†É�OÌÐõÒÓ´ºœ²Êï<Ì¢;_.ujŠÂ|œÂàN«K) ·ÓÆžáV~w6Ît\ì‡.”G͆ùKïÄÁ´±©7ju)egt `:»‡šøÉÉ9M¬Ö®&ÃüòX–[3yv ¶Tó¼�ªÊï8DBtç�¤ÍÌ Æâh;¬.¥ìZ">zZüüüdL¬?Ö¬æÂ|.¡ñÒùnÃa¯¹òÊFï܈aw’»~ÝêRjZâõ×b¬üa{"è†Äk—’V—"Ô¹šJKµ`ð“S1vlŒÖäˆå¦½»g‹èÎL›™A�›o˜±ò‘$Ø5ÔÊ•ñWïŠãç„Õ«©0ÿåéM^Ú›üV—R¥®AtÙAVtç”8vŒÒŽƒ Û•/qØeönnã÷ï,�È­.G¨S5ægGÒ¤•ƒÝÖ÷VmÚŽ#$Ewþ!ÚÌ ù™Y ·+¿_ÐçdKo˜ŸŸŽ‰£ç„U©‰0�§‹»œ`çP+r£Þñ|ˆRÏ †Í�rã†Õ¥Ô”äo ï8 ¶úܺa5zÚƒ8í6Ž]NZ]ŠP‡,s]7ùÅ©Y¶nˆà÷ÔïRýµPwaáuÑ�/)ÌÌ LÏ4ôXùÃlhæüí csbþ¹°2–‡ùkp»t·5Ö •(ubØmänÞ´º”š°pü8úŽCëª+_âtØØ9ØÄoÞœC-ˆC-„å³4Ì'æU.ßͱu Åê×ÁrêöËóÎ×¹ÂÌ ù©i ƒ»¬.Å2­m/¯\X°º¡ŽXæºaòÛ³q¶õGq6ð|òå*uoÂ@"·ÎÇÎŽ§´ýñuÙ•ßo¨7Êè´Êجbu)B�°,EO\IàqÚho^Ó—#¿í0‰ãÇ­.Ã2Úì,ù©iŠC{¬.Årv›Ìö�Íüîì%]ÜKÍ’0�§ ¼}+ËÖ�f«¯¿¦è½›1LPFF¬.Å ÇŽcì8¸î»ò%­aŸ“cW’V—"Ô�ª‡¹i‹oÎ3ÜÁí¿´¤n[ŸcçÚÜêô…�ëw¬üA6÷5qáV†Ù¤fu)B�«z˜_¼“¡¤Kô´¬¾öšTêÝL©¨£ŒŽZ]JU%�§´õqLûúœžú0.§�-}þð¶¸*|´ª†y¡dðÚ…¶ô5Þ¶¶åTÜu”ä±cV—Q5Z,†25IiÓn«K©I]-Ô¢ÉÕqq˜…ðpU óãWS´F=„.«¯»¦z6S,êëfì ót^çÖ´B÷Jg°˜0Äfüdº< I”v®ë=[ЉêØ] ›öZ]JMRŒiJæò÷_q:lô´ø9w+muéB ¨È{ö³7SôuqØý·B.Nã,^DVÇÁH€dCöí$ç<ˆ)‹!šû©½Û±Ÿ?IþÎ<6X]Ί%ÞxƒÒ¶}˜N·Õ¥Ô”’™aÁ8ÉBñ6dÉEÐ>HXz —üÑ{þ÷¶‡8uyŠC!ìâÄ®u­ìa^ÔM.ÜÎpdW×G~ž­p—ò2¡¦Ý¸;>�ÃÝŠi¨¤æNc,|<ÃäÝO`Êâ4"$ }ça¯¿ŽçK_²ºš)&(££?÷ «K©º©�ÐϰP:G_p�· �ÝO¦çNö ·Ò?Â)Gi³?‹KzðÔÍ€×ASÀÉ•q…�ýâ÷d=“LÓ,ë6lÆ2\¸¥ðØ–¶~\Ö“¸sD2“´t>ƒ78øÀÏÓK ©¹Ó¤æÏ#ù6“wÅ”ÅGLÿ/¿Më§>‰»·×êj–-ö⋤´�G¬.År ñÍ¡CxìbÃ0Ë�çRâ ÒZìO#? ÿšK(ŒO§øÒ³V_š`¡²¿/;7š¡ã!cå²6‚+ù]"áz7ý¡A`³{‰v>CïÖ$èqãŽÿ^å·HFÆê×ÌZ’Di硺:�¨˜H�½9Jax}�•ë¦Â|éUFµoôy®çìnúă@–e{x®ëë¸\ w ߣh~x|¼%ì!©‰¥ÅiDëYY;óxºÀ^™æÙý½š[îPNáÔÞ¢}à ¸|Ý+~l½¤�޽Mzá,¦{ÓúîÔMÿ¯þ7-Ÿú$žž««y¤Ø‹/’q†QwµºK,·”É3\Iž¡Çñ—xä÷wá# ø�&Û%¶˜^¯ÊÚ™ŸM³¡#ð¡ wå�ã*\¢{èïWä°Ø©G:ŽÒ½ù yx“ÿŽ/÷»õÙ©K…mIÕAw^J&ÉÞEÛ¼ÏêRªN7â¥W-,¯”MáhyŽñâ�QÍÙ÷}¬£9È¥±º8¼bÝ*[˜ëºÉå» ]-Á÷ý»K9�C½Bçб9ÖÞIÛìž{¡ôùñ$þ OöEd=YõÏJ…�¨‰ùñq«KùHÉ'0·í]W3XtS!®/§¼%žë^[ˆß¯Ó7ÄþÖç¹[øo4sþÞ¿ûÜvÂA7¦ÄÔÞõªla>:«ô:ðºß»A#«7phgéú"ö2ü ßo)Ô{†¿I8Æ“úÞÜ‹Hë%Ôß;¯åJ‘½qcÝtåK�øÍâ·ñºÕ5wâÓåbwó3Œ‚�úÞ¿7¸|·¾7aV¯la~u\¡£å½yá’¾€+û;Zû>W–Žüalv‘ö£ôlþGBþ0žäÿÅ›û’ž¨ì+W ý;Ð’)ÔíΓ'N`niü®ü}!îÑød÷×ÙÛü|ÙCü~}þmôø72Yú9&‹C+-Q/wgUÔ‚aõKÒP ñ8¥dÒê2©,a^*ÜžÉÑ] soúg4w=…Û[�éRò»¡Þ;üMBþÞÔ÷?Ôe™Âöƒ$Nœ°º’)¥Ód¯_GÞou)óзUçÆü®ÈǰÛK¤Œ3Àâ~-íÍnnLŠ¡–r™ùéO™ùÞ÷˜üÎw˜ÿõ¯­.ç#•eÑÐÈŒB$àÆéX<ßÓ�?ŽÓ$ÝUõ Z õPË>R±·�âßÃtõ/Î~±Eª^O¥vR¸xubw÷ên.WBòÄ ~¬!»rÝTH꧉çÙàæ“‘¯W-Àï'Ë2�7†—&¿ƒ×¹ §¡-âçúDV, Z!EÓIçuòj‰|Ñ P4anšàí1¤ââ¾ñÉë#ŒwO Cx2n§Œ×-ò8q:¬ßƒª,a~mB¡³Ù €¬Ï!+ïкù«–^˜ls¿êûÉÄ߆¹ï"»6’ói¬P—e´m‡Xxã8�_ü‚ÕÕ‹]yæÊUòŸÿ–Õ¥”÷ºL…”~†˜~Ž ~ëBü~~G˜mÑ#Œ&K¯ãoi�z¹psEÓñºÄáédšïžI¼P`&©1—ÔHæJØe‰ ×ŽÇeÃí”q;d|šAÀ0YŠi “d¦€ZTÉtÔ‚‰¢$sEœv‰ˆßA[ØEg““®&wÕ·&^s˜ëºÉ­i…�í]œßêÉþ�HÇÓØÁ5>ryÈ6¡ÖCš÷’™?‹1÷$×ÏS˜¶¨Õå•Eip'ÅË'ÉOLà©�îõÝÃ_¬Ûñ †Q 3–ÄÜi$×òž§0 Ôí7Θ¹NǬíÎKé4ãÿúoä?÷Mp{­~YÖv-ñ­‘#5â÷‹åÇ9û5ýŽ`z>O&§ð¹ƒëû(>­hpæz’ó·³D¶mð³±ÝKÀ³²w,'Ž]Çév²oÿоn6©12©pñN·Sfÿ¦ [{TjWð5wæ£3yÚB0M\ÊkD{ž¥Vƒ@–�ïëÔ͹ï"»úPì…K8>¼��µ>dU,…zïÖ&jÓúþìÏ�õ¸Õ¥­ö‚Ðv$ñ†u3[Jé4Ù+WQ·§s%~ðê£Ó9þæév>µ¯yMA``b[C;-I°±Ã×>ÖÁá-a~ófŒ—ÏÇÑ�ò®Ö]S˜§s%òƒ�ω3ÿ‘öCe-®–B½gË?ŽtãMýågØôùµ?x••6îD›ŸG›ž¶äù“'ObïÆ¬³®üý!^ý)†år¶õ´“1.Ññ0:�·º¤ªšˆk|çå©{ÝxK°<ãÔ†IÙ†F6wûøÚ'ºHåt~ðÊtY׬)ÌG§:¢^ìÅ[Ø%o`ecJµD–�›÷ӽ囄BݸÓ?$˜û1riö!_Qƒ{`È6´­�“8~¼êO]ÊfÉ\½ŠVG]yÉTˆë¯0RX ñ¯Õeˆßosp? Æ"A·gÖO˜�Í©üôø ŸÞßÂÁÍå=’Ð0ͲnbåvÊ|îp+½­.~ðê9­T–Ç]S�wb*Ѱ—ú&¡¶ƒe¼\ë,…zïð7 †7àMÿÁÜ�± Ô]‰ïµwöbiÓ.ÔéÔ*wçÉãÇ17íª‹®¼d*Ìë¯.†¸[ã“=K!^3°Ö¢ÕÛ‡C²ã MÏ×ÅjÐxºÈ/OÍò¹C­ ´W`•)Uä¦åÓ;šìðñ“7æÊ²AÚšÂ|"®ÒêבK3øÃ[ʵ’dÁæýôlùÁðÜéÿ"�ýoÆ,’‘C6â¸2/Z]æ‡É6ŠÛ«»ßy)›%{íZmwå¦AÑL’0_a´ð/øÜjC…øý6÷ K—芸˜ˆ«kÀ¦• ~rb–§w4ÑÓR™©°†’­2“:žÚ!à±ñ‡wÖ>¬»êÙ,‰\Lèõ\Aw #I�¹@a)ÔÑÝdÎaÎþ.É�®kHÊ5\öšçI«Ë|Ÿâ¦Ýh—N¢NOãî¨üv ©'0†vÖLW^0“䌻”ÌEÒäôiJä‘$‰ ¾­<ßöõ† ðûõú·r1ñ­™ˆ« vÔÆ÷¥^¿” §ÙUѯ:&r'è}ê@ ÿþ‡)ÆfúÚVÿ½Zug>Óènv“K^ÂÝY¹+­K¡j9€^ZÜ™N’LäÜÚE«Ë{¿w»ódÆÎKÙ,é+WÐ6ׯ,qýMî¿ËTñ7Ì•Þ$QºNÁLpDød÷7²ÿ ‡ì¢Ý³wè“ó�{úÐ|ºÈÕ»YžÚQÙ)ņɚf³<ŠË.óñ]Qþx.ޱ†.«óñ…<"‹GXUk3-«µ4e·¯‡+‚„ F Gê·ØÕÚ ôâÐâØy¥g¶¤NžÄÚ‰é­�½@šlûi“?†MZ|ÓibÒíæÏº¾Öð!~¿^ßvi„™„Vö)pµâµ‹ Ù©ø¶†iV|åÌP—¿ÇÎÅ5la¼ê0Ÿœ×hrÝÅÜTáˬW”Ö¾ÏÓ±ñoéþ&Ý[þ‘æîçpûºqfþ€7óßÈÅ«Ë\d³SÜþ8‰“'+ö¥l–ôÅKh[X}µ‹õ˜yæKǘ1þ„ǶøÇ¥ÃÓÏã-auiU׿ UŒ Ì$o¾yJ)21¯²³¿ 3� © k¯n ñöÍôª¿~U%êºI"[B.ÜÂ\ÍC4»3L i탈ÿ/MMC¸3?ÆŸþ!rÑš¹Þ÷+íA�œB›©Ì˜äéÓ°i¦ÇÚ®¼dæ‰ëǸ]ü|žÏu•�¡Ç;Û8Øúº\i“l´ºzij›e6Ñx7Aß¹™fgG…nLÞoq˜¥ò?Cýí^JºÉÄüê¾_«ª0–.ÐÐÐK .ŸuKÇk‰$Ù4ífÃÖ"Ò<Œ;óS|‹CÝf§°õÉ tçz6KæÂEÔ­ÖMI½?ĽîŸèúú½1ñWû›?�Cn¼-x—«Ó·›wœ¹Tãuæ×&¶o¨Na˜&HÕªÚÞçãÚÄê†ZV泩}‘9¼þjy+¼êß"Ú4Œ7ûSü™"—¬ õÒæÇÈON¡ÍÍ•õq“gÎ`m·¤+Xˆ{íï½åޏ:»Ö÷FSmž�hÒ$±tÑêRÊj.©a˜ÐrVåù l•œÎrŸÁ#S«[쵪0ŸO‰ºfpzªr�õh)Ô{¶|‹HÓ0ÞÌR¨OU·›}ë>ReœÙ¢g³¤Ï_¨ú¼ò¥1ñÛ…‡‡¸ð�Ý�Ëî%©Æ¬.¥¬nÍäì¬Þöʦa"Wp6ËýZBN ♕¿›ZÕ<óXR£?:‹Û÷ñª\`=[ ut¹äUä™_ ËaòÞ§0ì�U©AÛ´ÛÏߢ0;‹³­mÍ�w¯+÷V'DKfž¤þ ý,Ýþaö…¿.|™Z=½ÌçHf‹„«|XB¥Ì$ lê¬ÞÜyÓ,ãæ,ËÐÙäb&^ )°²w«êÌsʲlâp5Љ=&I6ü‘ít “¦Öø³¿ÀŸú¶âÝÊ?¹ÍNiËÞ²œª+ ™ ÕéÊïïÄ}žŸè�øJµº»ñ…âÌ7ÐPËLR£-R�!Ý„*Üg½§=äb6µòõ+î̵’�_ŽáõY¢M=’$d;¾ðVrÉ+$gƒ�oq?u熊=oqÓ^ò?ýŸb1œ--«~œÔéÓ˜·V´+/™yRÆ[,”D'¾VMînl®WYÈ5F˜k%ƒ\^'ºÂ®u-Ì íÍò0m§®¯|Ü|ÅažÎ•h÷§qzÖÇB¡Jù`¨Ë³¿ÅÈW.ÔM»}ûã$Oœ õ³Ÿ]ÕcèŠBúüyÔ?ÿzE^“ûC¼Ã·‘�·Ÿ=\‘çZ/üަ\ ™ÍåÝMÐ i¥HÐg«j¸ê¦Qµ a¿ƒÔ*þø®8̹"aw—w[Õ.®‘U3Ô ›CYCwžÕŠÂ<_ÐqÛ5dG}þuoLÞà ÞàF”ô( S¯c¨ÇÈ»¢»>ú�muÓ>ä�;OŸ>�Ù;ôÈ®\'OÊ|‹ùâÛtzEˆ×"›éF)®n7¾ZѺáô’‚$Û�eWÅŸO’௟ìàýæ.Ÿ;ÜF[¸ò«Nm’ƒ§;þŽùO?ÖC›ùÃH+s—½ˆÝ^½Ë„åz¨'¦ßÀPO’÷¢ä|H¨;]°u/©“'iùÌgÞ÷!CÓHŸ;Gþ#ºò{!^x{±o!^«ì²US¬.cÍlöê7’v›\Ñ¡•ÑT/NûÊFÁWôÙÅ¢‰KÖ�eæµk)ÔQÒ#ï†ú ò®Ã”Щ+›÷úóäGtå:*)ãMæKïvâ"ÄkžKr‘7ë»3·ŠM®v”ƒ¢–ð¹W6óhÙ£ëzQA�û)6©ÀôèwP²cU¾± n=òúð¾ún¨¿J.}†³GPŠ�èzŽÝþÌÎÐáíçÙð—Dˆ×©°³·Ý�ª¿÷.Ú+¶OXYz÷´¡*™Ij«š9³ìa–ö /€³S’°;›híù,v{õóÊÇè£sÓW¸ž;ŠR”Ylß$2¦“ñ ;ϊᔺç²y9ÔúN|˜¦D»w#GÚ*» ¾ÑȲ„^Å0ŸMh´EW>õrÙansx)úž¥ ûèÙòx•;G¨.Yþðt/¯#‚ß¶º4¡ šÝÝt8aæx¢í¯pÙÄ:‘‘L0«³m¢a˜L.èjª`˜Ãâ>»2õ»¿ƒð~F)Obæ ]?Ç-YºeïqI8šNñûÉåNæfÕ'f å¶xZN}n²e5›ºQ�çº;Ÿ§ÉïÀçªà˜9€„¨ÒU c”ò¤æÏ’Ž¿�é àý+¶ÝÍÐýÙ&¦.+D=N\ο£(ÝæZú5®¥N1:Ho`Rµ7vÊÂ0‹H8¬.£.I’„aV'÷F§U;W·ŽgEa.ÛíÈ"Ìë–^Ê“Ž�%½pœQB_Æ´…QßœgÃî›lˆ¸9óÝ)ZC8\ýôÈýhŒq=õ×Ó§Ù|\„zÒ ©ªçå4›DUæ™—t“Ëw2|éc�«úú…¹Ýî@—Å0K½¹?ÄM×FÔÐßcØÂ‹St2·²ìø‡n¼M½n¥qmYü}tÛúÈ3Ƶī\KŸb8(:õz¢›:²$†YVc±3¯|š_º›¥³ÉMÄ¿ºwP+úSm“l˜æâFñBíÓKyÓo0qýÛ¤•,Jøk(¾ÏÜ ríJ‚®Ý\¾÷þ® “¼�Æ,¼ÿ]˜‡>z_¡™�s5ù¿Ÿü71¦^'ЦŠLå7§jD’,aVø¨n˜œ¾–dßÐêw¤]QgîpHhº SW@TÔ*½¤�š;Mzá’{ Jøk˜ò‡ÏlÕ�Ìè{]ù_ÄAóF7…›)\Û><-Ñ#÷Ñ+…œ1ÆÕÔk\K�f[äݾa«/]xˆ‚‘ÇnŠ)¦«!CÅÇÌß¼ž¦9褯սêÇXQ˜{œ64ÝE©¨ŠÓ†jÐRˆ§æÏcz‡Ñ"ßx`ˆ/Q/'èÞ|_W¾dàh„3ß™¦eSÙñà7p>¹}äôÛ\Š¿Æ•äq¶†E¨×"ÃTñÚWë™\á½Yâ™§o&ùò*ÇÊ—¬8Ì º]lÔSSîq¼Ã¨M_ÿȇŮ[?>[?Yc1Ô/%Þ`{ä¨õRDÁc÷Y]F]’m‹ÇÆUB¡dð³1žÚ]õXù’•MM” `8Qµ\�>ÕXî…xü>KÈgçù½-eẏ¹.…ÐÔÔJ¿L(ƒR1Mrö Ùäe ÷V´ð70m+ï¶Ô+Iºvq=Umàh˜7¿?MóPpYÝùýD¨×¥”Â,xñ7UþسF´x´|q>1¯òâ™C]>>¶3ŠT¦‰2+sI &Êva£}8Ä¿¾ª‡Å®šÁ³ÉÚÝø‚òAyˆ´>ÂÙØoy3ökÂÎVº}[hóôáwD‘¥õµ/‰nêÌ©wX˜ÝÅÞÝb’Âz°êé �QÉb®Ìu‚ë,Ì&ÿ„’@Sf˜¼ù]üM�£5ýE³6~qòW’´oñã Wî-öÀ‘(oÿ×4î�Õ;˜ m�€íŸѾͼ6ɼ6‰„„ÇÀis±-ü$�¾!«Ë¬Š9uŒ ½™Ñ´LGDtæëÁªÛ•î7wmhÊ ¥utòPröéøYÞÛàØ†,»ÉdS5äfÁ {3ÆÇW8ìrÛ�„;]¨#i«/ù }οÇ#/®h31Éë"ÎÎuäw2—ñšƒ´‡]UYJ.XoÕaÞÓìán¼„'8D6qÙê먊\ê&éØI0%$GEÿ3hM_%ýgÔàg¬.ïår’¶Í^¼‘Êßø8!}!iéØù9$/�öÏày÷Ðñ€½›m–?¬“¥ECc& 5ÙKWKí.rÊkÕÃ,aŸ�=[È.¼L¸å€Õ×R15FjîJú6ºïšk/¦T›3–ºòm_^Ûá°Ëlwìp“MãÝTÙw+á–;ˆØžD3OD:ŒßÖOž›\\xƒ«‰ãliàãìîf¯ÒâÞÀøm™}›kãÝ¢PykZØÓìb<¥©TDS¦qy;¬¾ž²*¨1³ÇQ³w(y§}¾fC|‰r5Ië¦êtåK†žóÎOfñ ‘jè-}Ķ͈á”Wðybƒ}ˆœ9ÂÅøë\Iœ`k¤ñæ©ßÎ^ la2©ñB“óõbMaÞÛêæætžp÷^Òsghéû¬Õ×Sun1Ä3㔼Ð"Ÿ©ú» ­”QxwµçßWfËÃÛ]Zœ(#|Ïlù vÇ3ú7Ÿ4ˆÏ1HÎáBƒ…zLG-åÉ+�Dü 9A¨MkúN÷·{™žÏ“wì&›£THZ}=kRP瘽ó3¦GH¦ÔA.úÏhžƒuäêµ$mC><áê×;ødåbÓ¨�±óGñɃô9¾Fˆ'9?’—¦¾Ë”2buYkr#y†ˆý‰ŒÊÆv�ÕåU´¦0�ø¸œ2) Ï.±7­¾žU)ä?⑦ୟ‡Å®<}-ÆCÖŒ[Û]ø[äG­YºÛ }ίà7q>~Œ?M|§.C=Sˆ3§N–¶3›PØØ.¶½]OÖül¨ÝÍ|B¡àÞG6q…R¡v¦©=ÊRˆÏŒþ7Y³§.C|‰v=Eë _ÇÊ?hð‰¹:ëΗHHå!zí_! æ�Øëuê¯Ób;@¡(“UŠtFÅL–õdÍaÞßác>¡`Úüèž=,̳úš©�ŸenìçLßú1Y£‡lÓ7Ñ\ûê2Äa±+O]M3p0li¡N7�&jvçK$$üò}ίâ“óÎü±º~YÐ&‰©SDì{YH)ô·y‘kèf´PykN¯Þf‰\‘bÉ÷ãäߦÐ2‹ÓÝfõµ}ˆ–›$9{-?GÑ{-ú™r¼–So¤hÝèÅÛdýJ¿�OF8÷³¹ÅU¡u&K�z@$«�p>vŒ+öÅ¥�ÞÚÛ)ôÜü+´ØžDÂÁ\2ÁÖ.1‹e½Ysgn·Ëôµ»™ŽgAvQðanü÷Ü·DÒrZn’Ù[?ffì—d¤>²ÑDsÜ(d¯¤é³h¬üƒB�nüQ'Ú­úíÎï'!° Ñëü ~ñÎüë¼4Y[�ú­Ì;¨†NȶÝ0™™Ï3ÔU¾ƒÀ…úP–yK[{|Ì-,.é×½�Q4œ$kàf¨ú�ÏEÿ‘Bƒ„ø½k¼‘¢yÀ‹¿ºò%ƒODÈ\¨Ï±ó‡YêÔû_Åo¾;ü2ù=ËC=¯§¹˜8F‡üi$$f:›]x]µu>¥Pye óÁv/ói�BQ@õ=Orö5nÉE©¹ foý7³ ñÆú7‹Ù«ú×FW¾$ÔíÂq¢6Hw~? ‰ m�>Çâì+CÝÄäôܯ‰HûqÉÍÌ-dÙÒ#ºòõ¨,an·Ë ¶û˜‰/vç¦-LÑ÷3c?Å0´ª]ÌRˆÏ�ý’´4D.ò͆ ñ%ùë)šúÝ5Õ•/|2LöB ¨;¿ßC}ªº¡~iá54šm�PÒ fT6uŠ0_�ʶ–kŸùÁö¾ î�õ;°–P/ï̜̿6I—í/qJïÿÝ1Mxùíq¾p¤•ÖH}üLåWö0?+ÍÅq…Ç6µ?ðãNåMìùã„Zj9ð‘]ºš› 1ý:ZA¡à=Hɹ�÷µüëPáJ[¦ÀŽZ­.eÙâc*—~3OËg×gw~¿¥P�•Žáq¸Ù9ô‘¡>–½Ì…ùWñÛúiµ}Yúð=’¹…»3 ¾ülu·>jKÙüP4ùÿ~}‡§vwãq=8¨%=…;÷'äÒ4Á¦Ý›v`s¼7þ›ÏŒŸ~�b©@ÁsÝ%B»òØÏÆÙ÷7íø[j÷Æçƒœùþ4ö�îþõÛ�ßï^¨ëï†zø½PÏëîf.3’>�$¹i“?�G~øÉQg¯Î²³Ïî�Ú¾‡"TVÙÃàåsqRlîmúÈÏ“K³¸ ç wÙÄån¦��S2 Þ£èîÍ€ñ%ÚÕ$¶T��Ÿ«Ÿ®|IüvžK¿�‹îüLLRúâúqLJH˜èf� }Ai^ù£�ÿËæ‹œ¾4Å?}º»M¼®ëYEÂ<£”ø×ßOð±}½8ìËÛ6 äÒrqSv£»·#Büý–ºò½_h'ÐV_]ù’·¾?�4À#ºó11‰ë§ðKC¸ååßļ2£#bçȶå߃SEî"¼v:}LÄ–¹`D’1피ûÑÝ;Aþaú힨oSýî+3p4Dö\Ó„âB=§[]RÍ��h¶ZQ�Š:wçsìÃ+B…ÂàЦ ·&S µÙ’UdÃ$öV5QĶœw:5*ÚçŰ¡ŒdÈœš#gýÌ?¯„»3i¶mð‹Mµ ‚aÞq 8˜Š‹_Ø51Lþ0�Q0qÔñ/­^4ÉÌiøZldN/��!S´º¬º¥ë&·¦Óª­MÖëT´Í;¼%Ì͉å•_Œ‚Aú•Yr3‹›•…:ês¬ ¨œÿyŒ©s9tÝ ¤V—U·îÎ&hóñ[wL P[*æýmÂ^™ÉùÆÞl©Š ˜"3‘¿w Á¨ßñrwÀÆÁ¯tѲÙ{ïØ#W°º¬ºTÒ F¦2Ù*ºrá=€}r{”›w“¢=_£`ÜèC²KØÞÝ/ÐYß«ûìN‰ÝŸkcÃþ ¡Æ‹˜%ñs±RwgRll÷ЬßwjBùU<Ì»›ÝDŽåÏlpµ»Áf£©ßÖç¢8|6ÂÝ�q®ãæg£tíöcêPJTo¿ûFP,ŒNf8²%lu)B�©ÊÔˆ§¶…½“Ýù ˜†IòB’�‡Ctl Ðw „Ë[¿7@?hëóÍøš3ŠÕ¥Ô•;³I6uzÄX¹ð!U óÎf7mQcSi«¯·nG3„:\;»ñ¾Ço|tè™(ʘ"n�/S^+q{*Ë‘­b��ðaU›´üñ=ÍŒL&Q b¡È£˜†Iê|Š�#�à÷kôbwJ”&rk°uàÆÝö úê÷F¸P9U ó°Ïήþ#ã V_sÍ+Œfu8îuå�làH˜Ì; Ñ�?B"­±�ÑļrᡪºœððÖ0³ …TFÜôzÓ0I_JÑwd}¼•nòasËhãbìüaL®Þ�óÌöN‡ØêBx°ª†¹Ë.óÄö(WîÄ­¾îš¥�d6; wÔ÷4Ä•Øx$Lþ’xÇö0“ó\²ÄÖ bƒ2á᪾ÑÇ®¾vÙd|NLUüÃ$s)Eÿa«+©ªÖA/v»èÎD+ê\½�à�E­.E¨qUsI‚OíkáÊíòâfèû(#üMŽuÕ•/é?&{^tçt}l��ý~ÚÅqpÂ#X²_KÈÉcƒ®ß™·úúk‡a¢\J±ñèú¼ÁÕ:äÅi—)Lˆî|I,‘g!“çÈ–õqÿDXËöS=º%‚¢™Mˆiiù[ü-vÂÝ«K±Lÿá0™s¢;Ð “K·b|ro³¸é),‹ean³I<··™K# Kë|÷<Ã${1ÉÀáõÝ�µnöb·I¨b윛ãq6´yèo÷Z]ŠP',=é §ÅÍ–^—ÇbV¿–RF²ø£Î†Ù{e-6 £\\ßÝy,™gz>ÏÇw5­ýÁ„uÃòckžÙÑ„¢™Z¯³[ “ÜåGÂVWRZ7û°#¡M®Ïî¼PÔ9?ãÓšp;-ÿõêˆå?-6›ÄgoáÒí²ùõwòŒr+‹?ì$Ò#ºò%}GÂdÏ'­.×nÅØÑ ¯U ¯+cy˜´]Ýáü͹õuf¨a’»˜``�Í+”öa6ÓD�Ì[]JU�Ï¥)tžÜ¶º¡ÕD˜ì òØ™LX]JÕäF³xÃÑ•?ÀÆ£a”sëçg!�+pu,Égµ`“Åìaåj&Ìþâ`+Óó9fÿhÓårŠ�¢+ ¶a’i¢M5~w^,œ½>ËÇwGh ˆÓƒ„Õ©©0w;e>w¸• 7Èä{ü\ÍâÙˆö¬ßyå�²ñh˜\ƒ¯ 5M¸psŽáNÛ7¬.G¨c5æmaÏî‰ðöõ™†�nš�½”¤ÿèúžWþ(‹Ý9 =v~{"�i˜<-¦! kTsa°cC€þv—Gsþy~4‹7$ícåE’`àP¨aç�Ï'rŒÍeùüQ1N.¬]M†9À'v7¡ë7Çë&˜iBîR’�ëd¿òµjßâGÖMÔ;Oç ¼}#Î ‡Zñ»ÅÉAÂÚÕl˜Ûly´•Ù…³�sv¨v+‹Û/Ý ÆÊ—C’`àp˜Ü…Æù£®tÞ¼6ËŸ=¥»Iì†(”G͆9€×e㯟hçúD‚xªþ;3Ó„ÌÅ$ƒbËŠ´mñ#�†èÎKºÁÙk3ì °µW6!”OM‡9,žú¹ƒmœ½6G&W°ºœ5QogñxešúÄ꾕�$8B¹˜´º”51M¸0£;êäàæ°Õå ¦æÃ »ÙÍs{›yëÚ,9µdu9«ro¬üI1V¾í[HšŽ6]ŸÝ¹iÂåÑ.;<·WÌ\ʯ.Â`K��£ÛüyyE«¿@×ngqy$šúÅXùjHô‘»�´º”U¹z'Žª•øìã­ÈrÝüÚ u¤®~ªvõØ¿)ÄéKÓhutäœiBîJŠÁ'Å9Žkѱ=šŽ6­Z]ʊܸ»@6§ñ…§ÛÄABÅÔU˜ìßd÷@€Ó—§)ÔÉ¢"õn—šúDW¾Kcç¹Kõ3³et"I<•篟hÃe¯»_7¡ŽÔåOב­a†»<¼ye†B±¶;tÓåB‚�bµgYtl `*:ÚLíwç·&“LÇ3|á‰v¼.›Õå ®.Ãàé]MìèõqòÒùrQÇr8œ2MýbK9Hl<B©ñî|t<Áô|–¿yª¿G¹Pyuæ·„ØÓääÅ)”�å’»”`èɰÕe4”ŽÌ\‰Â\mvç7îĉ%þî™"È…*©ë0‡Å@?²%Ä©‹ÓäÔÚÚiQ½“Ãa—h]y9Iô ‘«±yç¦ —Fcdóþî™1´"TU݇9Àž�AžØæÔÅi’YÍêrîÉ^H0ø”˜ÁR �;ƒ˜¹bÍtçºaòÎ�L£ÄžlÇåhˆ_-¡Ž4ÌOÜ®þŸ>ЛWf™ž·þp‹üX‡C¢e£˜ÁR ’}Ã5Ñ�Jo]™!ì³ñÿmÇaÓ…êk˜0h÷ðŧ۹z7ÁÍ ko�)— ‰ÕžÕµÃ�‘)R˜µ®;WòEN^œd°ÃÅgö‹­lë4T˜´…œ|é™væ®�Å1-8Z»›Ãa‡æ�b¬¼’$YZÜïürÒ’ç_H«¿8ÍÑmažØ.†Ók5\˜„¼¾ôL;…B�³×«?=+æ•WMçÎz¦úcçw¦Ó¼}}–µ°C÷&Ô€† s·ÓÆžì ¿ÅÉç§HfªscT›Èa³CË�Ïê—`]�d‰þƒa”*íÙ¢&—F昊§ùÒ³�lh÷D„Úаa‹7ÉžØåù½M¼um–‰¹Êr¡\L1(Nªª®�~JUèγù"Ç/NâqÁ—?ÖEÄç°úÒឆó%ƒ�^þîévÆfR\¾C×+3�ž»‘ÆÔuZ7‰®¼š$YZœwþö•ùÞÎųœ¼8Íã›Büù�V1cE¨9ë"Ìš‚N¾òl^§Éñ‹¤+0½�(⋈nÍ m[|¨1­ìY^Ò .ßšçÚx’¿>ÚÊž1>.Ô¦uæN»Ì§÷·òôŽg®Ì22ž(ëlÿ�Ÿ|º6·htÙ¹"žVr;æTVã� S¸_ûD'Mn«/Sj] >Üí§3âæWgb¼yyšmC-ø\k)ìa'ù´A>UÄz5ÍßÊa/ÓÍHÓ4¹5•äÖt†çöDîgu µo]uæ÷ úìüíÓ ÷z9q~Š»Óé5wé’,áï÷1yÞú¨ë‰¡›L]Ìá\{覲N\œDQT¾öl§r¡n¬Û0‡ÅÙ.7‡øò³$Ó '.N�Zã¡ÑîMÆÏg(êãàŒF0s9‹-ìÀXý»!Ý0�HpæÊ û‡B|áÉÞuùÆU¨S’iZ±F²6�MóÚ¥$ýú»Â«^š�:£©ÅΦ§ÄÅJ+iÇÿu‚Ðm8[\«zŒùDž‹·ãt7»øøîHY†Ü¡ÚD˜@6_â¥s LÆU¶lˆÒÞ¼ò·Ùº¢q’ýÿ£_“;¯¤kœ'‘…ÐÁæ­¢–¸q'N*§ñ‰ÇšìÛ/õK„ùCÜ�©¼ôö<²Mfó†fB~犾>?’E½–äÀ—;q¸ÖõhVÅÌ\Ëqý¥8MŸéF^Ák¬ë&cS F&Óì rh8Œ]œÏ)Ô9æÁ4áüí ¯_\ ³ÅÇ@W·sùdNÇqê%v¾ I¬1)«l¬À[?˜&ò‰Ñåý¡5M˜œOsíN’�6O툊“€„†!Â|´¢Á‰«IÎÝJ³¡=À@g§ãÑ!`&É?Í ÛØþç­"ÐË$3§qöG³ö5áé{ôj[Ó„™x†ëã)B™�팊9ãBÃa¾ЦsæF’wF3ô´ùÙØÁõˆNÝÔM’¯ÌðËìøl+’ØïzMÒ3Îþ× ¡M¸7<:ÈçnN,àtHŽ0Ø)ÆÅ…Æ$Â|Ò¹ǯ&¸6©Ðß ·=ô‘Ã/¦n’|}»n°ûs­¸üb¶ÄjÌ^Írõ÷q‚‡[p÷<<”MÓdj>ÇØt§]æèÖ;Äî†Bca¾Él‘7GÒ\ËÐÕ쥷=LÐ÷ðñÛÜŹv¿ÐJ¸[¼Í_.Ó0¹ùJ‚©ëY"O·ãˆ<ø5.é³F§Ò4íØ3T„uC„y¨ƒwn¥xófš�ÏI_{˜æ°ç�cäùq…ô©yº¶ùÙøT›] »|”ôŒÆÅßÌ#¹í�´ ;?<ëDÑJL̤›ÍÐ׿åàæí‘ÕÍ9„z%¼ŒtÝäÒx–wn¦ÈLz[tµð|`ÆÐt2o. ÇU¶üY3MbàƒJšÁè‰$S³÷Eñô¿¾¿ašÌ.(LÌ¥If‹lßàgïÆa¿˜×/¬O"Ì+dfAãÜX–«w3´„=t·h yÞw4?®�{+Ž;ì`øcQ‚í+›ËÞˆLÃdâ\†‘ãIÜ�E‘ï›>˜UŠLÆÒŒÏfi;ÙÝ`S§WÌÖ=æVÔM®ÞÍqáv†Xª@w«�æ¨�Ö�I’À0QnfÉ^Lév±á@˜p×ú"Ћ&S—2Ü>•ÂtàßÅþîØxN-2Ï19—¥P2ØÞ`w¿ŸˆèÂáæU”QJ\�ÌqåNŽd®HW‹—Ö°Ÿ¦°I‡ühåJoÐFïþ-CÞ†ŸÊ˜Ï”˜z;Ãø;<í.\Ã!œmn²ù"±¤ÂT,‹ª–ØÜëck�Ÿ®&·˜¯/ ÂÜ")¥ÈÕñ7§òÄRÚÂnš#š^Z•¹ó”x�¶m>:w¶6N·®—Lb7rL^È’™ÑhöSèó×uæ“ ó‰<‹ÇýméöÒÛâ.� ¼¨ƒÛ3 ·gTFgs¸2=Ín:B]õ×��بÂühžøXž@‡ç7)�ÉDBez¡H{““�^6¶{iŠ!AX æ5h6©qwNcbAer>�dJôº„sF¬„©”ˆnðÝà!ÜãÁß\žàÓÒ:©•P§—m{–” ©I•ä]�øÝ<ÙX{‹-lcʦ3¯•h»èjqÑÝ䦷كÓQg¡¡†ˆ0¯Él‘É•‰¸Æ\¢@j¾@P•ˆÁ™Ù0ñ5Û ´»iîöhuâ‰Ø�ååÏðˆ�ä¹üë9Šy§Wf×çÛ–½°©¨êdbRÓÓ*ÙÙjª„á—ÉzLæí&¶fÍa'�Q'=Q7íQrƒß„ja^§’Ù"óé"±d�ùù¹X3Y¡‚W3±�„Ígðá Úqûí¸½2þ�—GÆå±#ÙÁã´qêÿN’O¾wµ'jg×ÛÑUE)¡eurY5WDËh©"FÖ@Ïë˜%Ð\&y'˜A®ˆ�P§‹–°“Ö�ƒ–�[ZáÃD˜7˜’n’Ì•Hf4RóE²ÉŤNAÑ1ó:†fBÑÄV4Áyñ°ë|$Ý&Q’›‰á’‘í²SÆ�qùm¸ÃvQá&'!�¿ØNV,#Â\àìL±pW»÷ß-›|ìþ|«Õe ‚°L"Ì´\‰ ?ŸCM–ð6ÙÙùB·è´¡^ˆ0AhbC A„ Â\¡ˆ0Ah"ÌA€sA„ Â\¡ˆ0Ah"ÌA€sA„ðÿ÷–扌^‘%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--wikitbj9nkr.png000066400000000000000000000152561524103652300223270ustar00rootroot00000000000000‰PNG  IHDR½’-ËÓ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïYŽIDATxÚí�és[WšŸ,\@bH‚ îµP”(Ú–É[·íØ]éîñÌô|˜t¥’tR3•ÿ&•ÊTM%==Oe¦Æéθ»Ý–ݶ,Û-YÖFJ¢D‰¤¸€$ö}»Øn>HT˲p/ˆû|¤È«÷^üpîù�÷=ïQ‰¢(¢ ÐB¨¥@A¡Ñ(¢Wh9Ñ+´ŠèZEô -‡"z…–C½BË¡ˆ^¡åPD¯Ðr(¢¯3…B‰S—ƒDS©CQ¸‡"ú:£Õª¡û¡‡ß] ‘Ì¥©åQDߎŽQ«!–�¿ý�‡Ós„|Iê°ZEô  ÇÔŽÍÐN¯YÇËGØŠø›ßx8{#F¡¨Ôû5•ReÙæV\YJ3³¿€d&ÏÂj˜H*ljƒ&¦†ô¨ÕÊÔÑ7ˆBQä¿}°ÎÉ)'ºíýŸG k²…¯NZ˜puKê®G}ùèbˆtAÃ>·ù;ÿˆf¸±¡C+râ …1g—ÔáîZÑ7�P<Ï{Ÿ{y}Ú�JõèßÙ ¥XX‹ ×©yý°—½Sê°w»f)ŠðÁù‘d^êP‹Í؆±Sƒ?š~ìï8mݼrÄÅ€ÝÄ/ÏøÇÓ^|±œÔ¡ï*vÍHÿùµ×V“”J"úRý–©Cz$s+ ./¥yæž¡}%QdÍ—ä–' ½ƒW¦¬XºÛ¤¾…¦gWŒôk�,³w¼pÐÉ¡a;ÿçŒ�Å­ôÎ/\¸õ„áéZµJÅ�ÃÀkG]hÚ:ù»S›|x!HªŒ¿Ux‰´P`ÑÁNóì>ÏŒ›Ðhª¸P‹ÒÔÃÄÙ1â™Ò#GÌ®Î6^˜ìçúZ†S—BÈé«m3¶aÔiŸhhŸDW‡–ã=›+ò¿>Þ`bÐŽÃúô$NI¹rÛ�X*ñç'úd1ÞÎО˜zò—¶î&¸Ât´Ãk“V{uRߦ,iJÑ¿ÿ¥Q¥åÀ°­¢¿»±"Ëò““}»k#´�p×ÐjØç¶ìüb÷EØ §˜_‰`7hxíˆ ‡¹]ê[•Òyrq1N(Qdb¨rsºȆ³ÇÀ/>Ý" ƒ„Ï̘‰u²¦sq•ên‚ëõé,F=ÿtÆËû_ùd�´k4M%ú@,Ç™ëQŽìíA]Ͳ0ì4²×má½Ï·ð³’ÞÏ}C©}NA¥R1è0ðÚQ7Zm'÷ñ&¿ý&H2£¬ñ7Íô&—ùù'F, Øõ;¾^ –áòB€·fl’¿k« .-þ±ä¸^äòE7¢¬û“Œ÷w35¢ÇÝÓšu=M#úÎHåàðHOÍ®M |3ïãÄA3ÓãFIîëq%ÇõBÈñ“¬ù’¨U%&õ2ÈÂã4ЦýìJœ/¯'89åD£®í’c*[àü /ûÝ]¼vXš$Ö©ËAR¹ÚÚrˆ&6 6i¬-‡‡ ÔÓ&“eÝz!{ÑGyþþÓ-ŽìÇÐUŸb«\¡Ä7ó^ú­m¼=ckø¦P<Ï{§½¼~¬º íN)‰"ÞpšM’`"Ë„«‹ÃC†][Ö,kÑ %~ñû-úLìéÝù<þI‹"|tu¨øñ ½ íþþ÷[¸ûLô•‘w¨'™\�/Éz0�VSC&‡õèuIãª%²ýo/'KLï­¯ÉÛFE®.Éæòüù‰>º:÷A_[Mpñvšg4æ^Ë!šXóÇñøS8­L�ÙëìB]ã)f£‘­èozR|r%‰ÃNÚ´��n,¬Gð‡“üÅËLušR=L=2´µ¢XñEÒ¬ùÄû\]L�é3ËsÏÂÓ�¥è£©?ÿx“ç80ë¥É&.oÆYÞŠò“} ûp¥2´•� løS¬âthàð°�ÃÆ†¾wŠìD_*‰üïÏ6±› ;¥YFÜÆN3»äGÇí ;ê?×þ£¡u¡’ÂÑV€(B0–ÁãOà‹dìédjÄÀˆ£Sö­Ld'úO®„ðó<{À!u(„âY.ÜðóÖŒ•ýîúši€_Ü3´åÒÉ…|±Äf ÅF(I&›çàP7G‡�XôòÜÚ(+Ñ/meøÍ… '§hoð<þI$Ò9Îßðñ̸�ãæºþ_×V\\,o­I¦óxqV}I º6Ž�8°§›}ž²}H*ú´Pä_Ϙ롣]þ뼑„À€­1[ð¦Ç \ZLì:Ño£V©pÚºqÚºï—>üêë`CJ$ý¯¿àìÕßïW#w¢É cŽÆ$ªötóÉåi¡ÐÔ†¶tíÆÝ&ÆÝ&¢I�Uœ¯n®×­ôA2#{îf„këYž?Ð/ûiÍ6gf=üèx޵ C[O±oS·§W(”ø¿gì´¢oÐæêz�+”ÈæJô¥íü«Ñ¨8èÖïZC›HçYÞˆà‹e86bäÝíuk©^7ÑŸš £k×Ö½_M½‰$²ô[:d‘9žÝ}Ú‡Åþ'/ÔOìÛÔEô7=bàO^p7ì°Œš‹>š*pêB˜g:Ðjd±GeGÄSŽ›¥ã>Ính¥û65}©$ò«³~öî1cê–Çè¸DBñN«|öìÞ7´Ù]M”óHg ,oDØe86¦—DìÛÔô©ý~6ŒF£aÐ!m¿šZOç0èÚèl—ÏK£Qqh�žµ@sÚ‡ÅþÃã.ÉÏüªÙÿ¾¸•fÁ“æðhãSõõ"œÈâ¶Éï�utÄÀú–¼÷Ц²®.øjn‡EÃ_¿ãâä!«ä‚‡�ô‰t�ßœ03Ñ×ð¾“õ$–8è’_¿F›±‹Q‹7œ¡ß&¯¹}*[`y3‚7˜az\Ï�d0²?ÌŽE/ŠðÁy?ÃfYö«Ù áX׳Ôa<’cc¾¹—�è·Å¾HsdTÏŸ S¦ûžw,ú3×Âä jÆœònßQ)¹|‘\±„ÕP}b-’Ê×­·ËÄ€ž�¯„%7´él�¥o‰Ý%[±o³£÷Ϊ?Õå$Sc»g¿M(.àÜaRêWð“Šu‰oÛЮú’<Ÿt¶ÀÕå_ÌnÐkTóWï¸xõ°Mö‚‡ˆ>%ø_9²·9ÚwTJ4™eÏNß‹$óø¢9NÏEêãÑQ�ÆÚt¶ÀìbsŠ}›ªÞ‹¢œ ²§×@�©9ÚwTJ4‘ez¤ú%Á§MÇ­­43�Þ:tP°îî¡m„¡M n¯Gð†ÒL�êùñq·¬–r+¡ª¨ÏÝŒ�̉Œ»ÌRÇ_DQ$’Ìá´V/Ôeo‡UϸËÂG—Ãu‹ufÌÀº/^·ë§…×W‚œ™Ý Ï¬æ¯ÞqóÚa[Ó ªýVXàüb‚£ã½²(ª±TKw[ÕKm¢kþ,v‹Ž¡>él‰Oª.±N 艦ÒÙÚî¡M æï‰Ý¦Wñ×o7¿Ø·©hz“Í•øåY“ÃvtM4‡«”pBÀi«~>ï� è:Ôt¶Ý}Fû‡m|:ëgÔ¡C[ã<†F£bÒm`Õ—`ÿàÎ3´¡À�­(ë¾S£~0Ó¼Ó˜ÇQÑÝüú¼Ÿ>Kóµï¨”H2»£ÊÊUo»ñ�^ÇnêD¯ëàÂb¬.ñÓïØÐf¶Gö+XõÛÓë®W7ÑÔÓ íƒb·è[KìÛTô{þ€™7ŽZ9?ïÅNK{]ˆ$ܽ;˜Úx3Ø��ö· m._d~%Äç—±?LÕÝ ÓðÓWûÑwÀÙë[¹úV5’hBÀjl«ºÏʪ/ƒÝ¤{j§‹¡‹¾�¯oÕ~ óØ˜‘ë+A>»äÁÚ­â?¿­ˆýavô$´Z5?~¾—³óQ¾˜Ûdf¢³^~;�Ê%’ØYgâ[™µH†lœžÝdjX�±«v‚Üçê&�È13n¤{7…Ú 5YŒÝ-7šÈîèt»eoºìó³:Ûµ õøl¶¶u9�Š—YÁ?�še vƒÁ�$…ªMl$™§X½®üõýq·™Õ €'˜•úÖ[Šš¦Ýæv~úZ?áDŠÙE?%o\~˜`, *0UÙ‚pÅ›¡ÇTÙ[B£V±ÏÝ%Ì&zTMOÍs͆.-ÿîÕÚÕ"g¯{òò6¸Å’ÈüJˆË·|¼9m¯ú:Ëþ,6så5I=zŠ¢†ëkµ_ÂTx4u)°hoSñîK}réørn“XJžÜp<Ë糨)ò³·\쨮�î~)q•çá²òÙl!¿»K<äB]ÝÎóÌX müÃcvÙTgK"·ÖÃlS¼9mcï@÷Ž®÷p)q¥˜õXM�œ»ãåIù7pjvê^J'7ƒˆd8}ÙC»ºÄÏÞtíXðpw>oßá¶É‰A—–D“y©Ñ®§a'†Ç3EþåK/mmmëiø! ùb‰›+!Bñ oÏØê«Ý[ç?õÒßg¤Ï²³kÞ^�R(¼ûb_CŸM«Ñ°¢i£NÃ_¾â¤K+rnÞÛÐ ®/’æÌ• :øOoºj*øÇ•WÃÈ€‰ÍH޵€²„YOºS`ÛàNôwòE n._äÊm?7WÃüðxoÏôÐ^ãízëÁìcK‰+å�/…”%Ì:"Éö˜“Þ8jåëëõËàn†RœžÝÀaÑò³7œ;êaó$îø²�-%®§½ÔjæV¤iâÔ H–«žpwcèÖòþW>b ûj°© ›/r})HV(ð“{éßÁïrXöe˜¬~}ÿQì´ñÉ¥Mn¬¥sêîÓa36ï¹]r£aFöqÔÒà®û“Ü\ 39ÚÍË­u7Ëi¡Èß|¸Î›Ï Öü ¨\¡D0–!IŒg‹%\=:F:F: 5,Rk5$=@./òÁ×~Âé3{{+n˜Ê¸ºD,xç¹^æÆTzÞXOqáv’cõ_mIg ¢BÑ4�x†ö65#}] ;î¾ äÖ[ÎÈBôÛ|q5Âå;IžÙßWöñ=+Þ ëŽï5q|ÂÔÐT^RRµ3Üߨ“WDb)�@,K(–!Ë`Öw0æìd¨·“==�¨ÕÊ—àqÈJôóëI>ºfê)ÜT6ÏÜR�6µÈ;ÏÚ±_Çÿß½Æ3ûû+ª¬¬Å’H8ž%ÏŒeÈdЏ{:í×1Ø×Y·váÍŠì&†ÜzÌ:-ÿòÿ# ®(Š,yâ,mF9¾ÏÌñý�Ý·©¦”¸^hÔ*z̺ûµüB®H(‘åæfš3W£h40tÏ õêvuO›r�ÝH¿M>¿!œÈñßrÊbƒ³(º?ÃË6©C©µJ…ݤ»W g!W(qaÁG Ñ:…nÒ+è)¨TðÊay•ÛzÃY:;5»â–\®H2�ãÄ�^©Ci­íhªdÅŸÝq)±\˜_ ñÒ3]Íÿ.EôU°ä-¿Õ‡œñ…Ó¹<Ó£­1—ßF}… %üÑÚ”KII¹¾æûGm¨¼·AjÑWÈz0‹¹F¥ÄRrg+N�^ˈC[8Isr°ìÏb14·P„|‘¥õß›Þýl< EôrÇ›¡×ÒÜóù›«a&‡ô’”nÈEô°Ý•¸™ûuÆS9ü‘4/4IŠd(¢¯€U–ž2ºË™ùÕ0'Yšê„ïZ£ˆ¾–¼¬M¼T¹LQȘn®Ò‰Z£ˆ¾V}åw%–%QäæZ„7¦m-_kßÚw_‘dž¢¨’E)q5l…ÒXô†úšóK[KÑ—I5]‰åD,)0âPŠèËfÙ×Üõ6±d–~kõ§¬ì&Ñ—Áv)q³Š^E"‰‹"zPD_Í^JKå1ui•Ž ÷PžB¬4ñ(Œep+ö>ŠèË`É+`75o½M$‘eXý}Ñ?…íRb«±9çâ(Šepïà¨Ð݆"ú§à g)•Dn{bÄezŒÐ“ˆ$Ìú¶–Úõ4dÝ A.x£9n¬%˜_O¡BE¿MÏ@�¾)U7VÃØõ*åXŸPD_!a�kIæ×St´ipö°wW}ÞT½ù좇wO4®¿g3 ˆ¾JD6BYæ×SÜXMÑÝÝÆ€M�ÓÞM[�~¨–x*Ç…/ÿõ{¤EV(¢¯Å¢È_†k«)–¼iìÆNzõ8¬]¨%,C¾å‰¢o/ò½#Íן§ž(¢¯1Ù\‰›žWW¢yúm]¸ûŒX �_=ùüò?xÖ†»N§°4+²oöÔlt¶«92bàȈ�xªÀüz’Ùe?%`ÀnÄÝ£oHf7–))‚ÊHß <Á s+IÖÓXM�¸{ ôYê· ëêr€=V-ÏPVmF}ƒ)J,z3\\Là�8ìÝ ;ŒË<„¢„|‘O/yø/o¹Ðë乪$%Šè%$”È1w'ÉÕÕ$º î^#ýÖ�¯þ,¬Fèh+ðöŒüÛˆK�"z а¸•bîNŠU§­‹¡~SU£._ä³Ëüûï÷+'�<Eô2#%˜[Jpa1Iw§–A‡‡­«ì¹ÿìb€^£†×�´f#§rPD/SJ¥ ž4çãÄ“EF†ú Ol'è §¹¹ä?¼áRj矀"ú&À8·eÅ'0â41ÜoüΑ9ѤÀ77|¼ûR.›RQù$Ñ7�¸À×b¬³Œô›p÷êQ«U¬z,oÄø·Çí-Ù�µRÑ7!þ¨ÀÙ…Ë b‰Ñþn^ž4·loÊJQD¯Ðr(nG¡åPD¯Ðr(¢Wh9Ñ+´ŠèZEô -‡"z…–C½BË¡ˆ^¡åøÿêêÛ|Ë\²%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--xkf0e7kq4ae.png000066400000000000000000000261751524103652300221140ustar00rootroot00000000000000‰PNG  IHDRN–±IaŸ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïY+]IDATxÚíÝ÷{›çyèñIÜCÔ ö¢¶dk˲d'q’¶qÓ¦q›:NÛs®«˹ιÎmF�4Mš´'òc[ö¬=(JEj�'@ì=Þ÷=?@Ö°$  ŸÏO6E/o<ã~î[RUUEAÈ™¦Ô ‚PiDàAÈ“œ‚ y�S!O"p ‚ äINA„<‰À)‚�'8Aò$§ Bžt¥¾az)™ßŸuŒ¦±›tüùË ˜ ÚR_– ÌjbÄYáŽvùœHˆÈÜŸLòñ_©/If=8+\4!?ñÿþHªÔ—$³žœnU› ­”ýo­¾`š�.MKÊÓ»cAžKÎ gµh0št´Ô©wù_Ÿ‡V+ñ“�‡¹ØBÔ¾„Â�³‚©*»êãàúþl{=¾H£^ÃþNono¤ç~„w��0æK–úRaV�³‚]½Ælв¤ÙŠÕ¨£Ê¬cÜ— ±ÆÈ[{›Ù´ØÁŸžàÐy�˜¾ B�ˆÀY¡’…Ó7üì][óðg Í xâOüÞªv;ïhÁdÐðc1}„‚�DøÊt¼ÛO"™áµ�uÖ;åT·—Ýk\,i±>u›‰@’#W¼d2 ¯¬¯£Õe,õÓ„Š$g DÒüüØ(o¿Ú‚Íœ=Ã�HÉüò“1&ÃitZ-+Ú,¼¾©ö™·¿>æø5?óÌì]ëÄjç !bª^�N\÷³i‰ãaÐè¹a2œ #Ë zâ(ŠòÌÛ¯j·óÛ¨¶hùéÇ#bú.y�³ÂŒN&™L°iIõ?·™uèµ�ÞN­VƒFóü·× —رª†ïíiâöXŒw�Ž0<G„�³Â»æc÷'ú/²ÞXÜdeQ³«IB«�M‹9ÝŸËnà»;Ù±ÒÉ{ç&9tÞC$.vß᫈ÀYAz†"ȲŠ6ûSÿ&Ið­­õ¼ýj:�ÄòVk^÷ÝÑlᇯ¶RmÑò³#ÙÝ÷çMõa®�³Bd2 '»ýìë¬E’žÿ{£––Z#÷=‰¼ã‹éû÷÷4sg<ÆO�20+õS„²#vÕ+Äç7LS|{ký ÷ì­‘x†W:ks¸çç»=ãð/uUz¬«Åa»ï‚bÄY¢É ú‚ì^åÌé÷ç×›tç?âü²Žf ïl¥±ÚÀO�Žðéu²"¾gAŒ8+À‡<˜ v¯uåôûÓ)~yb˜¦j#ë;XÓnÏév_ÅIsäŠ$Åþuµ,l4—úe„’#Î2çö'¹=gÛŠÜF›Š¢ðáE7¨cþ'¯ùñGÓÓ¾§MÏ›;Ø·ÖÅáË“ü×gãcÓ¿_A¨D"p–¹cÝ>¶/¯Æ¨Ïí­J¤U’éG»áÑ„Ìè6Šž§£ÙÂd§ï?;2š�¾ËbÒ"Ì-bµ¿ŒÝ�‰É¬]hËù6£»UKäAex‡EG{ƒ¥ ×¥Ófwß×.ppò†ŸŸf_§‹Ž¦Â>ŽPÞ’i_(E(.“’2i•dZ%)˵Zôz �N¨Ó`5jpÚ ØÌÙ~X�h†O®úˆ$3l]ZõÌÚ åL¬q–)EQøÙ‘1ö®u²°1¿€MÈ»ê¥o4ÆÁMµ¬jË=ðNÅÀDŒ#W|TÛtìïtQmÓ—ò¥Š –”òÄò$ðSL†3¤3 5vU:�„^&½ƒNK2£’N+d•TZ!’Èà §Q§]O0"Oe¿ÜuZxûÕVœô¹�³L]è qg,Êww5Mù>>ºì¡Öndcާˆ¦CQT.ß sú¦Ÿõ íl[V�N'V‚*‰ªÂ{ç&èŽá°èÙ½ªš1’�‰¡X†–Z#íu&ê�\6vKþÖD*;JýåÉ1¾8_!íu&6.©ba£�FÊû~gšœe(‘Rø×�îóÝ��ÔWO½ô[ßH”«wC¼¹cêÁ7_¡¸ÌÉnÓI^ét²¸¹²¦`sÙ��>(; ÓiضÄÁü& MÕú¯¬}�¯?]œ¤w(Š‚ŠN«á¥eúFcøÂi–ϳ±ªÝF“³|ËŠÀY†ŽuùHË*×ç–~ô<ÉŒÂÿ=4Ä?¿ÑŽN;³ßâîG¯ø±™4ì_çÂå0Ìèã ùqû“|pi’‰@š/JeÕÚuüð`[QOUáæýÑ„Âò6ëõO4MÏ`”îÁlwƒ——WÓÑ\~kç"p–™@4ÃÏ�Žðö«­?LÓñ‹OFYÜlaC‡à O�¿˜¾Öãge»�]«œ3~ ÂWñ%9Óãg<�dÝ;—ïFHedT¾±¥�¥-¥ Zª ·F"œ½@Q%¶-«bù¼â®ÕçCÎ2ó»Óã4ךغ´zÚ÷uk$ÆŸ.¸I¦UœVoîhÄiŸùøp\æD·�!wœ]«�¬*@B¾0=‘¸Ìñn÷=q¶-­fÍ;Z­D*­2êKPmÓS]&GlïŒÅ9Ýã ^]_Kcuég/"p–‘!O‚?]ððÎ�V´˜ZÿÇñ1îO>Êá\Ùnã›ë¦q�Ó~‡/Ob5éØ¿ÎE­£rvQg U…CÙËÚ¬ì\åÄX!³€Ç;ì[[ƒÅ8ýÙT‰ÀY&TÞ=6¶eÕ,˳$ÜóüêäCîò œ�M³º|'òpú^I¸•.Kódzôxu}® üâJ¤Ž_órw<Î×7×Ñ^_š£¿"p–‰®�0]wüµ·¹`÷9èNðá%ÁX‹AÇßìiÂi+�éW$žáx·ŸAwŒÝ«kÄô½Èn�ÆøÓEëÚÙ¾²æ+KV‚w‚λY3ßV’ç#gÈÈ*ÿúÑ}¾½­�¦šÂ¦`$R2çûCøB)¾µ­¡ÔOõ)÷= _™ÄlÐòJgÍ´Ò¯„§©*|rÍGßp”7¶ÕÓRàÏW)Eâ�s#Iol­ŸÑ©»œeàÔ Áh†ol~q­Í©ÅeÞ=2Ì?¿Ñ^ê§úLO­»­tæ|6_x¾LFá½snRr¶;€É0û^SUÍ6/ì‰òæö†;µ–ó+é§ùõÉQ~vd˜×|%{¡f›P\æÊí0»VÕí1f-&ƒO0Uê§ûL’”í¼ùö«-üøãû\ —ú²*Z"%ó›O'Ðê´¼¹½aVMÈ~vö¬v²q‘ƒ_že"�œ™ÇÍuÄùïÇÆñe7tZ‰××ײb~ùäUUªCç=TYuì\™[Ù¸©:|e’*«Ž-_êŽYŽÆüI_ö¢ÓH¼²ÞECUéÓO*I,)óŸ'Çi¯3²oÝôºT’›CŽ\õò/5Ð\k*êcåü5K?ª½˜‘U†|3Ùg³ñ@Š�‰8[–TÍÈã�¹äƒ “¤2åÝ„­Éi䭽ͬ]hã·§Æ9rÕûD©<áùR…ß~:ÎÂfóœ šËçÙøúæ:þëó Nuž,\9Å/Ë9pºìF$ NU˜W;{™KåØ/;Wæ^ksªîŽÇ¹>%‘Rèsè¼§ÔOý…¾˜¾¿s €ùð>ûCˆùçS•ß}î¦Ñidw—~ÊY•UG:£pæ–Ÿ_�+Ú’OαßÞZÏÒ6£†—VTs¢ÛG8–)õëT±z‡£$Ó k¿rÑ­ûaR��ؼáÊyßL û;]¼¹½‘žûÞ=6˜˜í<Ó{çÜtp`ýÜi>îÖp EUQUPd8+X”ÇÉ9pjµ� ìÔUعÊIçB¿?ã½·§@VTNvûØ»Ö9#ùg-LúGd7V^_cMvú¾i±ƒÿ>=Á¡óbI¹Ô—U6Îõ ÆdÞØ\_ñ9šÓQmÑ¡‘²aM’ –*ÎeÊsÄ—–Wc2h9Ó*Í+TÁ.ô©u˜_àÊìϳ¸ÙÆÖeNj«tôÞØVœ´§™��¾·`2høñÇÃs~ú®( ÷= ÎõxckÝœ¯�º|ž��‹ØÍ6š±5œë üq¦uŒäµ�µüÛ‘aæ7šgUbm1%R çû‚|oÏÌÕÈغ¬ŠÍKìüï÷*û�Ëdв¿ÓÅšù6_ör} Ä«ëj‹¾“Zn®Üs´kE�Õóí8­•w„²Ð$ v¯­a÷Úìo(šáÝc#´Ô˜h-àçcZAv³–W××òÁyѰ+''»}¬l³â²Ï|Š�F£¡¥ÖÈ ;^ê—¡ ª�|o3—Tñÿθ9tÞC4Y9ë·Ó‘HɹâAV@ºÃ"óàV¯m¨ãÐùɇš aÚC�e­Vê«ô\(Ò"ìlâ ¥è‰æÜê·4X¸ç.^šF)¬j·ó£ƒ­ØÍ~úñÈœ˜¾+*ðØÌA¤3³üIOÑâ MNgz»Ï‚ÌÙv­©á|�H\,Ö•c]~^^î,i9¬ù fîŽÇfÝÆŠQ¯a÷jßÛÓDÿX”w�Ž5�¯ÔŒz z½„h4°j¡­ …¯g«W:k¸|7Œ7\˜Ós œN«ž•íVÎÜ ”òµ)kîÞpšu‹J[èòí á˜ÌO?áÈeo©_–‚sÙ üÕÎ&v¬tòÞ9‡Î{fåú…¾ m.#ÿøµVÞ9ØÊkëK[.°ÜÙÌ:¶.«âØÕÂ|æ ¶KðÒr'=Cü‘ôôïl–QU8vÕǾN'Úvð Å2ô�ÄPU•hRææp”`lv¾_Í~øj+Õ-?;’Ý}Ÿ-©sɴ¹[Aöuº¨²èŦPŽ6u8ðG2Ü÷L�¿`�ÓbÔ²n‘ƒóýb­óË®ÞË6žZRâŽ�iY!­c'¯ÕeĨ“žŒÓVWšFJåâÄu?;ØÌåÑççqóëÍ\è °uùìü#Á˜¿rÞ«/zèŽã&é�ó/ñ¿þ8Ä‘+^2ªÊž55,j¶ ×e§à­µfæÕ= š‰”Ìé?¯t–>Ó!W£¾$v‹NälÐÒV+w¦˜QQ´Å·ÅÍú‡cs®jR&£p¢ÛÏ76וu]ÄÇ›ZE“2]wB4m,�Ó'Áhš3·‚h%‰—WT?<¢Šf¸ç‰3àNÀƒnªªb6èxç`3ÆÇJªýE­9ûe ¨4Ö˜žx/>ï °¤ÕRQ©Xƒî êÄÚf!µÕ™¸Øä¥åùß¶h�³½ÁÈg7@ùì(Ï„óý!š\FÚÊüCn6è€/vœ%b)ù‰Í’RI¤²�ÆüÑìµÝ�±´ÕÂÀD’P,ͼ:3M5†&’¤e½^bU»ã‰ ù…¦g¤€¢º#¼} ¥´O4Oƒî8[—ÍÎ�¼R™Wgâ½³n2²Š.Ï%µ¢Î—wÀM&£Ì™âªÑd† }AÞª€u¨¯mªãý nb)™:‡‘xJæ—ÇÇøúæÚ¢ŸH‰$2L†2´¸ŒO¬«*\º&}´>ŒÉ J|mSí#ÄË·CÜŸLÐÑhaeÝV�wùز¤›©ü2ž'“Q÷'i»éeÐi¨«22ìM2¿>¿×¶hŸ½V¢Æ¡gÌŸ*ûÑW¡œºægíB[E…«¶éø›=Oø‹ý!~ñÉ(»VÕй°8ë³×î…ùô†�P\ÁåÐóúÆ:¼á÷Æb º˜�Z´:È< ;,Z^ZîÄ rD°¾ÃÁúŽüNÏ O&˜$ùÆæÊêÉ㤨±ëŸ9ª¦§Íe`Ì/ŸÀ 0¯Öİ7>'§ÛŸäöxœl-õ¥LÙÆÅÚŒ¼n’¾‘¯ot<õbˆp\A|¡4¿>1Î’V ­¼²Î…ͤãb�ëƒQ4‰í+OÍ©:zÕË®Õ57šŒ¤©-Aáë¹ÀYeà¾'ÿÃE œ�N#}£s#ŸóX·�íË‹ßê·ØêFþv_3§{üüÛÑQlpå\œDUá£K†=It: »ÖTÑ^kaÄ—dp"Æ 'Áä—Nœ­šgáµMOnJm\\UðÓ1×Ãh$‰åm¥-´2Þp—½üg1•ÈeÓÓu'ÿÂE œN«Ž@� ‡–³Û£1"1™µ s_k+gM¶ªÐ‚&+ïŸwsk8Æ�õ. /©u†¸>FV²#Ä?|6 •º*í f¶¯¬!“9uÓG*%ã°ص¦ø)AYåÔu?ol)�¬�|ùÃIVÌ›Ÿ­rSë0à ç_Z±¨�³ÆaÀ™Ý=`%›~´¯³�¦²G›_Öê2òƒý-ïòñ³Ã#¼²®–¾á(Ѥ̚V–¶dÿ˜½áƒã Îß< šƒÄ�Î{jª½¨ÕL<©Pm�™ š³·‚´Ôši­­Ì#À¾p¦$=ªæ“AÄ’r^�ŠúÉ5ê5è´‘D¦¢v1óqév‡EÃÂÆ™iõ;ÓŒ: 7Ôrw<ÆŸCy‡<1n4D˜ð§É(*mµ&ÖίâÒ�l �&{¬óYë“F�fÆ6:Âq™KýAþnùg:ÏÂå;aê톼҄ŠåÔu/�‹ìTY*w�0•V ¶A&<ͨג̳fCÎ_ûWn‡øð’‡Q_‚_|2J*ÇV›£–xrv6>}3ÀÒ+õS8ëZiôZ óc£“AÃŽ•ΧR¯ª­zö®©aÕ[É“é'IîŽ'غ´º´2MiY­ˆêM•Ê “H§ó+1—ó»qén˜XRUbÜ—ä|_nåçM‰xžU ü‘4×¼\ÂV¿3mÓ’*Œz‰yõö¬u•}y³ã]>v¬rVl¦C,)sø’$uÎÖ}(6YVIË*�ü6±sž??^˜XR9mM: ‰YØJãx——-˪ʾ%«ÛŸÄͰ°Á2íé^×½0×ײ¼vxo�Ĉ&eÖÎ/ßB+/òÞY7ƒ“qTEâ7'Çxç@+ŽÚP› 2…ŸÁN3áOOÉìX™[–GÎ_Å«Ûm˜|s×Wغ$·<;£QGr–õðò$pÓlê(ï³ÃǯùøÕÉqþpÆÍÏ� MN=ÃáîxŒDJeY[ùMYQ9qÍËÞ55%_.˜ŽoõÁfœ$Á¨¿2ªÔWŠO‚pTAEBQáü­PηÍ9pn]VÅ+ëjh¨1ð·ûšsÞ�ÒIò,꣡ªp¬ËËî55hË´Öæ×Ù3y8Ú÷†3\ìËýƒñeŸß °}euE¢‹·ƒ¸ìzTx¦C{½ íƒ\A¢ÅU™éTåÊfÔòø�Îd*Ò®ºÍ¤Ã¤×ä0dUESÂ^â…vm0ŒV#±¬µ´'PRi•?œuã §ÑëàÀúz ÷ÆcÜ›ˆ3èI<ÕúwªÎ;cq)•¥-åê&‘R8×ä¯vW~¦Ã7¶Ôs¡?ÄÙÞßy¹{™/ UšÆ#ÛWØ9u=ˆÕ¨á››s? Qô“Œ¢ Ÿ%;‚iYåô ?ßÞ6õîx…òY��»ã�޳þúä(&ƒ†ù f:š-ìë¬åÎh”³}2°[´Ü��LËìïtes~,?ÛWVUÄhóÔu?ËZm³¢ ¤Q¯aûŠjn †q”aߪÙà¥å5\¹á­½ÍØ-¹¿ÆE74•›B÷„3½~ÚêL4Í@qfo8Åñ.EeC‡ƒÅÍVEeÄ›àž;Áµ�È¿ï0kù‡×ÛžøYç"«çÛIf²É½iYåt��Ÿ¾Ï+�.–µ¾x½òöXŒtF}xJ¨œyÃ)nGxç@åZy‡U‡?šÁ)Ϋ\FV‰§”¼‹Ù=p¦e‡¶ò§¡¸Ì•Ûa~°¿øpeEåwŸOà eçÖ£¾mµa†½IœV=óŒì\áä\€`Tƨ—Xùœ&^Z­„åÁë¯×Jì^í¢£Éʇ'éˆppCÝWN?ëñ³£BÖ6�wùغ¬*¯ •Àe×ã ¥YØ(Ö8 ÍISmÕåýù.zàŒÄ3Ì›eåNvûX×áÀ‘Çpþ«x‚ÙÑц'ÏP‡ã27#£�$Si…j«ž7¶Ô?‘“ØÑbáÆP„6—‰Ö<^ãÖZ?x¥™3½þíÈ0;ŸSóÎXŒLFeI¬m¸³•—Êa¥Ð\v“ÁÙ_,§üáô”*O=p†b U¾>3H10çG¯f Ø3áh×$±¤Ê¥ÛV·[Ði%&’ciÚëLõZ2rvÏÏaÖ²uÙÓ%ëÛ¦Ø~X§Ó°cU KÚl|xÁí‘(7¸ž8šøi�Ÿ«Ê?¥GUáD×${ÖºÊ:Óaª\v}s¼Ýv±øÂ)œŽ2 œÁX‡­²ç±+^v®væU˜"ö wõËÓFU… ýAbÉìŽw2%sý^”­+ªxm£ëa«Ro$ÅÉ.Š [–VmGµ¡ÊÀ[{›¸|'»GGé\à`Ø'Ë�Ψ,n.ÿéa×@½^ËÒ–ÊN?zžúj#þdYô„šmF})Vµç¿~_Ôˆ–‘³EA¬ÆÊ œ½ÃQ’i…5í¹Ÿ@9tÞÍ ;‰„BG‹�——U1àŽqg<ÁÀD Uy2M¨µÎôÔyj—ÍÀŸ½<3)5�†�‹,h4ñïÇÆæ~j$‰3=^^Y¾ÇJS…Ïnøøóz­JÁbÔb·h$ŸÙ€N˜U…aO‚×7æßJ¥¨ÍíORë¨Ü:‚²¢r²ÛÇ�õ®œ¿éG¼IúGb¤2ÙàxåN€›aæ7™YÐhfïš4•ßî&—±›uÜè*õS²ki5v£¾ìzš¢ªL„Ê{míLo€ æYPæÕ›t'fýóœI£þ$‹nJ›‰E œÃÞÍ®Ê œú‚Ô: Ìox4L¤Þ¿à!ÏÐXmàà†:TUeÔ—`È“àæð£  `ÐiùÛ}M8¿TˆöË�ÒÊE[�…‰@ Y½Ö”ñYïp,Õ;aþþ•Êjõ;íu&®Ü ³uiyó­$÷ÝqÚ¦¶•sàô‡Óïöã §8Ñíc÷ê†õ¥XR¡ëN‰”Âù¾ ßÛÓôÄÏÿxÎý‰çî@šAw‚xJ¦Æn`^½™Ý«ª9Ýd—B«……�–§‚f9۳ƉäáÒ½ Õ:šÊ÷ýû¤ÛÏÆÅUs¢ðż:º0I2­Tlµ§rÓ?ã¥åS[†Êù÷þùI&üÙÒV—úBÔÛ ¬xA¡Úo‚Ý3ÐS¦�¼¡4çú‚¸})–µZ¶,ðGÒ ŒÇ{¬¼—ªªXŒ~°¿å‰óÂF+#Þ8:�–ÆêÊ š_ذ¤Šz§�ãÝþR_Ês�ù’ {â¼¶¾²ZýN•É e^½‘Þ‘hEW|*�H$Í‚†©¥Jæ8céG �ÒŠÊ�/ù•�ÓL¡‘¤ë+S�hšß|:F(–ÝO«*]šd`"NZ懨uèñʨjöHÜæ¥O§ IÛßæ Í.ÞPŠDJÉëxæL9Öåe×j眪Œ¾²ÝÁåþ€œÐ=fÅ<ë”ëhäÕ\v#�p ‹QÃêŒ6oÜ�°¬ê6>®ënøaÐFÓ¬�ocÓÇѧªÂ¹[AÆýIVµÛèh.ß©ìth5Ùj^é,ÿÄüBÓj$V̳Ñu'2ý;›Ã&âè´�ÓÈPÈ9pjµ;Ô8 ̯ÿê€1æK¢‘¤‡ÉÜ•¢£Ù†EœÚj�|m ù]³…?’áʽ0Cž¿þt‚sýS¯åYHn…h¨2ÒVWÙK!SµeI]÷B$R³¯«ÂL9Ý`ë²ée'佩ª/þš?×díÂÊœFí^SÃîR_D8×ë'Ï.[$R ½ƒ!¶,v”ôšbI™sýÞ*ÓT®™à°èèh6sùNpÊ;ÂsÙðd‚P\fù4ëéæµê/i$”TsŸ ¥rÇYW¡�SÈ29)XSú ¢S7|¬žg›óåÕ¶.«æb(çN³Â#Ÿõxiyši~žóºµFâ…�ó³?›—TaÈã\·P~¶-¯¦¥Öˆ^F�Äö�n¼¡4}Ã1^šC]EŸÇe7° ÑÌç½�R_JE¹7ÃÉLélú—å7┤l‹Ëç÷'¹ïI°~‘8ÝPé : ßßÓÌ›/7¡ÕkXÔTÚ5Å#W½¼¼ÂY–©Q¥°gM ]wÃxËüHl¹�•#W}¼ÒéD[€V>yÎç�8EáË“ì]]3§rëf»¶zzIÂ.Ýè�±8¡XF,ÿ<ÆfÒ±my5G®xK})áÜ­µ‹› “Z—׿�FRŸ»9tꆛYËÊù••»)¼X{ƒ™¡‰ÄiY3EUáø5/ûÖÖ̪¦…°q‘�ë÷"üᬛ`,C{�‘�+�Ó^¿›-n�Äð‡S4Õ¹ÐâïönS1¿À‰õ#ξ‘(=CQþn[˜‹ÚkMô�ÇX×1ó»êWt,*ã3ó¥¢ÑhXØháì­ž@ £N˶åÕ¥¾´’;uÃÏù[A2•�««Ÿ(Ò=]ù}5IêSSõáÉ]šäÏ^j˜u½^„,U’è¿å?>eØŸ±ÇMf>ï ²·³²ê̤H2ƒDv$ž‘³Íüè¾"#«ddIæ×ÎsW]Bylª>àNð»Ï'xcKÝ´²ð…òKÊœºáCî{“|p~YV§}¿¹ø¼'@G³…†ªÊ+”2SV¶YÑH* i`EvŒgW•ááÉ2 uŽNEQèŠM¦ñStÝ óÞÙ ¾½­þ‰z•Âìâ §‰Ä5Ž‹%d|Ñâoù£i®Ý ³}Eu©_‚²¶ ÑÂww5²qIV£ŽDBävlê¨F#�êgÿzWÁ‹îä†�÷Ð;EU%~~l ›YÃ÷ö4•dÃ@˜9õUFª,:ü‘lð´™tÔX‹ÿžŸ¼ægó⪼û]ÏEmufÚêÌlêpðËc˜�–WX��BòGÒ|xÑÃ7·Ö­@MÎ#Î _êáŽzFV˜_oAs0è%¾µ­žE�&$ |sk]Ñ;I{“ŒxlÕÎóâ°êø‹—ë9rÕû°Øö\ŽËüæÔ8;VVµªWÎ�Óh|ô«Z «çö±·¹¤¡ÚÈwv4Ñê2MÊÓ¿Ã8zu’=«kÐÏÂV¿ÅV_mäÛÛê9tÞÃÝñ™ÛÈ+�Hš_�¥s‘�µ ‹›’sà<°¾–F§�»žUíV:•¶àƒ0ó6š¸7QÜ?Æ$$±É1 muf¾³½‘.xèº[U­ŠÍJò'Æè\dªcl1HªªÎÌ©PñÆ)�›à�mE¹ÿŒ¬ò¯ óÆ–:Zk§ÖÒ@xd2”æ·ŸŽ±±ÃÁæ&¥2èŽódzn^]_˲iV=Ê•8b 䬱Ú@<)s{4F1¾nÏõh®1ˆ Y µ=³»™îÁï�uÏÊjJgoøãY7olm˜±  bÄ)äáb�ÝPUê«õüå®&Œª‚‰Ëüôð0oíkÆiëç…”É(¿îçÞxœom©£~ä\Ç’2\ðMÈ|s[ýŒ·#N!g]wÃdd…Œ¢2êKq©€UáOÝð³v�CÍ"Ðé4ìït±}E5¿þtœó·(JåŽ>o�Åx÷èµoím.Iÿ%‘$'äîK›Ü/ªÍš+·?É�±?:ØZêg8«­˜g£©ÆÈÇ—½tF8P„Äðb Å2½:‰'˜æõ�µ%=x#¦êBÎ.ÜpöfˆhB¦Æ¦ã­}-©�ùëSc,oµÑ)ÊÆÍ˜Þá(Ç®z™ß`bûJgA `Z2£p©?Ä…¾ ›–T±eIUÑs‰_DN!/ÁXšÝ\vÛ P�½$Ɖë^ÞÞß"ʡͰTFáÌÍ Wï†XÜdeËrGYjI¤.ô¸|7ÌÂF3;V8©.“¥8…¼Ý�q¦7È_ïnšÖý(ŠÊ�?fÿºZ6VΔq¶I¤d.ß q±?ļ:3kØ‘…÷/d ºì\Y]´t&U…#W¼Ü‰ÑäÔóú¦:"± Ýaº‡¢,m¶°uyuÙ­}‹À)ä-“Qø?ïñ?¿>oZ½¥.ö‡¸;çÍ ¥~JÙèõÁ0×"Ù#Ö~®‘Tþñõy8,…ßé óñ%o¶ü`Ôi04¬œo£s¾‡µ<·aÄÜHÈ›N§¡Éiä¾'9åûH¤>¿égÏÚêR?áƒNÃúEUüõ®&x¬|¤¢J|xÉËÕ;!ü‘tA+–”éŽr±?ô°L¡ XÍþékmì\é,Û  bW]˜"�VâðåIV´[Ù¹²æaíÃ\�¾áci›•:GåçÎ6�†u mt F�$¨­Ò³¢Í€;Áé›’i§]O�Ý@­M‡ÝªÃ Ó`ÒK´4: ¨*‰”L*£’–Â1™@4ƒ7”ÆN¡(ÐZkdA�‰É@�FEV©˜.¦bª.äí\_€Ï®HË*�ʦÅNö¬Éýï�¤ùűQÞ~µ›Yt (Wc¾$iY¥­ÖôÄc2­à ¥ð…3LFRDâÒJYQ‘$)Huz½«Q‹Ón Æ¦ÃåÐc3=³¢î�Åhtiª�ä|1âò68‘ýƒPéA;�Üç']>¶,­A³Ì5Õ<;ˆõš\&š\…yœj«®$ý¬¦C¬q ykpx˜9$�#�8èŽã ¦Ø´XÔÚ*—q yÛ¹ÒI<)so,Ž*Ákêsº]¶Õ¯ŸÝkœ%O`„é#N!o’7Ôò×{Qƒ>· xí^�–µŠZ›Be�S˜²*‹�NÂzqŠJ*£ði�ŸýkE«_¡ò‰À)LËüSN-ÎÞ Ò^o¡É%jm •ONaZÔ[¸3#óErCq™+·CìZU9z‚ð""p Órm(ÂàDœŸáÊ�g×ç<Ùíe]‡½(Gö¡Dà¦ìîxœÁ‰*Ù$æó}AåÉóã� ¶Ìâž7ÂÜ#§0e‰¤Œ"?š¢ËröØÜãŽ^™dçjgÁZlB9ŸfaÊ·Z©«2€”ýµÖšŸè…Þ;%�QYÓ.  ³‹œÂ”éµßÛÝ̾5U´^]ÿè ž¬¨œèö±g�3ï ‚PîDà¦Å —Ø´¤šÖ:÷=‰‡?¿Ð¤Þ¡/i_A(8…‚ho0sϲµÏÝ ²k�Hvf'8…‚XØ`a`";âüôºŸUíö²ê_#…$§PUV=áxšß~:AÏp”mËDõ#aö�S(ˆß>N: wÇcHˆÚØÂì&§0m©´Êd0 vÏ)¸=+õe BшÀ)L›^'¡7<Ê92êÁi/¯v®‚PH"p Ó&Iðê: ÕF\kÚí´ÕŠ*HÂì%šµ ‚ äIŒ8Aò$§ BžDàAÈ“œ‚ y�S!O"p ‚ äINA„<‰À)‚�'8AòôÿÍD�¤V-,Ë%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--xwh5jadmcnm.png000066400000000000000000000754711524103652300223120ustar00rootroot00000000000000‰PNG  IHDR§¥^'9“ cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïYzIDATxÚíÝg@SWà7D¶ âDq·Õâjë`$„@X‚€LE±n­[¬{àਠD\¨6«�®¶Žjë¬(ù~´—O[mIÎMržhrï{Âxsoî9—£P( (Š¢(Ñ#€¢(Š¢þŽ–EQÅ:´œ(Š¢(Ö¡åDQE±-'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëÐr¢(Š¢X§Am|óæM„……‘ÎLýE¡P€Ãá�ŽAý¥¢¢‚tŠb­5kÖàƒ>¨ñãkUN …–––X³f éqRvìØ�.]ºÀÑÑ‘t €��```@:ŠÎËÎÎÆÏ?ÿŒéÓ§“ŽBu:¨©U91è/;4hÐ\.—~?(ŠÒ:ô3'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëÐr¢(Š¢X‡–EQÅ:´œ(Š¢(Ö¡åDQE±-'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëÐr¢(Š¢X‡–EQÅ:´œ(Š¢(Ö¡åDQE±-'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëÐr¢(Š¢X‡–EQÅ:´œ(Š¢(Ö¡åDQE±-'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëÐr¢(Š¢X‡–EQÅ:´œ(Š¢(Ö¡åDQE±-'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëÐr¢(Š¢X‡–EQÅ:´œ(Š¢(Ö¡åDQE±-'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëÐr¢(Š¢X§éê´gÏ\¼xúúú˜8q"ºvíJ:’NS(زe nܸSSSL›6 mÚ´!K'edd 55ÎÎÎpqq!Iç%$$ //zzzð÷÷ÇgŸ}F:’ZéÌ‘ÓÙ³g‘žžŽ;wîàæÍ›Øºu+éH:ïäÉ“ÈËËÃÝ»wqõêUlÞ¼™t$�TXXˆ¸¸8œ?·oßF||<ž?N:–N»uëNœ8�Û·oã÷ßÇÞ½{Q^^N:–ZéL9]¿~2™¬úë²²2( Ò±tÚ�7PQQQýõ«W¯HGÒI÷ïßGff&îß¿(..ƳgÏHÇÒiwïÞEqqqõ×¥¥¥o}­ t¦œzõêU]N …oýa¤ÔÏÊÊê­ïÉ‹/HGÒ9r¹Ë–-CÆ Ñ»wo–“±±1éh:­C‡o½™~úô)ŒŒŒHÇR+�(§{÷îÁÏÏ|>@ƒ àéé‰×¯_“ާ“Ο?�©S§ÂÇÇöööƯ¿þŠ3f�ަ3är9FމW¯^áÛo¿ÅСCáéé �[[[ܺu‹tD�TPPwww 0"‘¾¾¾°²²‚“““N=iý�?†P(Ä„ 0gΜê÷óóèQ£àéé‰'NÐwŠjôã�?ÂÍÍ »w»{õ¿;;;C(bæÌ™Ø´ié˜ZM¡P`âĉxüø1RRR`dd„Ï?ÿ¼úÿ›6m >Ÿ�ììltîÜ™t\�QPP>Ÿ,\¸°ú߃ƒƒ1uêT8;;###�5"Uå´úȉùF‡„„¼ULÀår 8;;ÓÏ;Ôä}ÅMš4AVV¾þúkÌœ9“tT­6{ölüüóÏ8yòä;OMœ8_~ù%póæMÒquó÷ÊÏÏï­b‡ƒ­[·¢OŸ>pvvÆË—/IÇU9­-§'OžTŸÂ›7oÞ;Ãårƒ.]º@$éÔ!3 ÿVLŒ&Mš 33gΜÁ¬Y³HGÖJ_~ù%¤R)RSSѰaÃ÷>nܸqX´hìììðË/¿�Ž­Õ ààà???,Z´è��a ªoß¾‰DZ_PZYNEEE‰D6lØ?Þ�üãÐÓCtt4¬­­Áçóé%´*R“bb4mÚYYYÈÏÏÇìÙ³IG×*K—.Ejj*Äb1ÌÌÌþóñcÆŒÁ†   ñÓO?‘ޝ•˜bòõõ}o118¶lÙ‚¾}ûjý”Ö•Ó‹/  agg‡eË–Õè9Ì7|ðàÁptt¤—Ñ*YmЉÁTnn.-(%‰ŒŒÄáÇ‘••…æÍ›×øyˆˆˆ€@ À?ü@zZåÍbZ¼xq�žÃü½êß¿¿V”V•SII ÜÝÝ1hÐ lܸ±VÏåp8ˆŒŒ„H$‚@ ÀÓ§OIG+Ô¥˜M›6…X,Fnnî?>3¤jgÏž=ˆŒŒDVV,,,jýüáÇcÏž=pssÃwß}Gz8Z�ùè¡6ÅÄàp8ؼy3ú÷ï>Ÿ�ÂÂBÒÃQ:­)§ÒÒR¸ºº¢{÷ˆ¨óvÂÃÃááá[[[<|ø�ô°4Z}ЉÁÔéÓ§iAÕÑþýû±|ùrH¥RXZZÖy;nnnˆ‰‰�‡‡Î�;GzX�)&ŸZƒ)(æŒ�¶”V”SYYÜÜÜ`ee…]»v�ÃáÔk{Ë–-CHHø|>}ú(}ûvvvHHH@PP²²²HW#0Å$‰°fÍ¥n›)¨!C†hMAil9UTT`øðá000ÀáÇѠ�j»˜5kÂÂÂÀçóñÛo¿‘6«©²˜fffHOOGzzú{ç¯éº³gÏ"(( èß¿¿Êö3dÈ$''#$$§N�"=lV{³˜Ö®]«’}p8DDDÀÆÆF+ J#ˉYL&“!..NeÅĘ0a,X[[[\¹r…ôðYIÅÄhÙ²%rrr�––VãéºâÛo¿…——Ž9•ïoÀ€HIIÁĉqüøqÒÃg¥ÂÂBˆD"•ƒ9‚ …_P·¶ž\.ǨQ£ðüùsœ:u †††jÙïØ±cajj ¡PˆŒŒ |ôÑG¤_ ÖPg11˜‚rpp¥�¿×d—/_†§§'öìÙ�§¶ýöë×iii‰D(--Epp0é—‚5 áèè>Ÿ¯òbzÓêÕ«ŽŽŽ‹Åh֬闢Ö4ªœ˜Å*=z„¤¤$µ/!===899!==½úºŒD11˜‚âóùàp8u¾$Wüúë¯pqqAdd$ÜÜÜÔ¾kkkH$…BTUUaäÈ‘¤_âÞ,¦uëÖ©}ÿLA dggk\AiL9) Lž<W®\AFF±UÄýýýÁåráè舔” 0€ôKC ÉbbüýJ ê·ß~ƒ@ ÀÚµkáççG,GÏž=!‹! !—Ë1zôhÒ/ 1EEE …àñxDЉ±zõjp8ˆÅâZ­ BšF”“B¡ÀÔ©SqñâEdffþëb•êàëë ccc¸»»ãÔ©SøôÓOI¿Dj÷ã�?ÂÕÕQQQÄŠ‰ann^]Pç?×'Ó&÷ï߇P(Ä‚ D:zôè�ììl”””`Ê”)¤#©]QQaoo�õë×“ŽƒU«Vøÿ)>M)(�¸ âË/¿Ä¹sç�ššÊšû˜¸¹¹aïÞ½:t¨ÎÍ–gŠ)::šx11˜‚:zô(V¬XA:ŽZÀÑÑ'NÄøñãIǩ֭[7äçç#22›7o&G­˜b²³³cE11V­Z‘H¤Qk‡²¾œ,X€ÌÌ̯¢¬N"‘ûöíÓ©Ùòo‰Ï6þ�¹¹9$ Ž=ŠððpÒqTêéÓ§àóù1b+Ƶ´´„D"Á¶m۪߹k»7‹iÆ ¤ãüÃÊ•+«×Õ„‚bu9-Y²)))¬þ0ÏÉÉ ‰‰‰@vv6é8*Åæbb0uøða¬\¹’t•xñâD"¼¼¼0þ|ÒqÞ«C‡ÈÏÏÇ¡C‡°|ùrÒqTŠùŒ‰­ÅÄX¹r%\\\4¢ X[N7nÄÑ£G‘™™Éús¤¶¶¶HHH@pp°ÖΖ?wîD"«‹‰ÁT\\œÖTiiiõÊûšpúÒ‰ǎÓÚIÓL1ÙØØ°º˜+W®„««+ë Š•å‰]»vA"‘Ôiy† ‚””­œ-îÜ9 :111¬/&F«V­ª J[N+1 wéÒ‘‘‘¤ãÔX«V­�““ƒôôt­[vêÍbªímzH g}A±®œ¶nÝŠÈÈHˆÅb´iÓ†tœZéß¿¿ÖÍ–×Äbb0uèÐ!�/(™L___´k×ÑÑÑõ^y_ÝÌÍÍqúôiœ>}³fÍ‚B¡ ©Þ^¼x''' 2D£Š‰777ÖÞ¿ŽUåƒ�7Öû¾3$1³å'Mš„C‡‘ŽS/š\L ¦ ˜?pà€ÒoW *Ìr]>Të:’ªÖ°aC¤¤¤à·ß~È#PYYI:R�½YLõ¹ã6Û¬X±¬*(â唘˜ˆéÓ§#++K©7Dcf¶ü’%KðÕW_‘ŽS#ÚXL deeaÏž=j]„³®æÌ™ƒŸ~ú §N�Rû:’ªfjjŠääd>FFF6lÊÊÊHGªöòåK8;;ÃÚÚw ]-[¶ ¾¾¾àóùÄ JíåtæÌ#>>Ÿ|ò ‘A“Ò¾}{äçç#>>ž5³åÏ�;�*&Fûöí!•J±eËlݺ•tÄÄÄ ""b±­[·&G­ôõõqôèQ´hÑ...xõêéHxùò%œœœÐ»woìØ±CgЉ±lÙ2 ><�HA©µœÎž= ooo=z¶¶¶j,0³åÓÒÒˆSL±±±:WL ¦ 6oÞL´ 8€¥K—B"‘hì¿úâr¹Ø»w/:vìËòf1íܹS犉±téRøùù)(µ•Ó7ß|///>|öööj$Û˜››#77‰sæÌ!’áÍbruu%ý’ÅœâÛ¼y3¶mÛ¦öý?~aaaÈÌÌ„••é—ƒ(.—‹˜˜ôêÕ "‘/_¾T{†’’¸»»ë|11–.]ŠQ£F�ÇãááÇjÛ¯ZÊéÂ… ðôôDLL ø|¾ÚÇffffÈÊÊB~~>&Nœ¨Öå\h1ýó™`DD„Z *33“&MBjjªÖM¥¨+‡ƒmÛ¶¡_¿~àóùxþü¹Úö]RRtïÞ�ÓÂÂÂ0jÔ(ðù|µ”ÊËéÒ¥KpqqÁîÝ»é¿iÚ´)233qéÒ%µÍ–§Åô~:t€T*EDD„Zæ¥åää`äÈ‘HNNÖú+Vk‹Ãá 22¶¶¶j›ZRRWWWtïÞ»ví¢Åô7ê.(•–Óµk×àââ‚ÈÈHxxx¨|0š¨I“&‹Å¸qãÆ�§Ò‚¢Åôߘ‚Ú´i¶oß®²ýœ;w���8vì @zجÄáp°iÓ&¸¹¹ÁÎÎN¥Ÿy0ÅÔ­[7ZLÿ‚)(uœâSY9ýúë¯pttÄúõëáçç§ÒAh:SSS¤¤¤àÎ�;*›-O‹©æ˜S|7nTIA]¸p^^^Ø·oŸÎ^TË—/ÇÈ‘#ÁãñðàÁ¥o¿¤¤nnnèÚµ+=•Waaa UyA©¤œnÞ¼ �@€U«V!00Peᵉ‰‰ ’’’ðìÙ3)u¶üÙ³gi1Õs›ñ 6(µ ~úé'¸¸¸ ** ÎÎΤ‡©1Þ<¥ôÇ(m»L1uéÒ»víÒØßÕmîܹÕ¥Š7 € ÊéîÝ» …X°`FŒ¡òI›#99åååðööFyyy½·yöìY :”SXZZB*•bÆ رcG½·wãÆ ˆD"DDDÀÝÝ�ôð4NXX>ÿüsØØØàÖ­[õÞSL�;w¦ÅTsçÎŘ1cÀçóURPJýnÜ»w<³gÏÆøñãÕö"if¶|ƒ 0lذz-çB‹©þ˜‚Z¿~}½ ŠyÓ¶lÙ2øûû“–Æš={6æÎ� >Ÿ�ß~û­ÎÛ)--­.¦Ý»wÓbª£9s樬 ”öyüø1„B!&L˜€I“&©ýEÒ&8vìÌÌÌàååU§å\h1)sŠoýúõعsg­Ÿÿþ}ðx<„……a̘1¤‡£ñ&L˜€ùóçÃÁÁ7nܨõói1)SPÊ>ŧ”ïJAAø|>BBBˆM*Õ6\.ûö탹¹9D"Q­–s¡Å¤|;vDVVV®\Y«‚*((¨~Ó6aÂÒÃÐcÇŽÅ¢E‹`oo�_~ù¥ÆÏcŠ©S§N´˜”hΜ9;v¬R ªÞß™'OžÀÁÁÄ—ãÑ6Ìly++«/çB‹Iuºté‰D‚•+Wb×®]ÿùø¢¢"8;;#((ˆ¾iS�1cÆ`ãÆ� …øé§ŸþóñoSTT-&%›={¶R ª^ßæ—oذaX¸p!é×F+q¹\ìÙ³½{÷þÏå\h1©^×®]« jß¾}ï}ÜË—/áèè�‡ �Ž­µüýý�@€ï¿ÿþ½�+--…»»;-&›={6Æ��Wï«*ëübnWloo�eË–‘~M´‡ÃÁÖ­[ÿu9ZLêÓµkWäää`Ñ¢Eï,(æáÀ�±qãFÒqµÞðáñgϸ»»ãÛo¿ýÇÿ3ßKKKZLj0kÖ,Œ7®Þ—ý×é»Ä¬Ø;hÐ ú˧&_ÎåÉ“'hf\®ü%-&ºvíŠììl,Z´û÷ï¯þ÷²²2¸¹¹ÁÊÊ ›7o&³Öä¯^áõÇPÈ夣Ԋ››öîÝ‹¡C‡âܹsàp8àVU½ULÑÑÑ´˜Ôä­‚ºw­4§¤¤VÛà(j±âè¥Ó ¨¸ú+J*Ë‘ô{6lÚNgS°bùR85á Y…!ª¸À%Ѥ��¿þú+¶­�³g�ðB^‰ÃßÝÄþý‡ÀårIÇ«•âŸ~Âó¼<(ÊÊÐÀÌ ­ýüÀÕ°[Ägffb_x8æ¹¹AÀÕ‡‘þò%-&B¶mØ€�£Sóæà¡ÙÀ�húé§5zn�ËéÉ�Ë(<žý¿æ…¾jª‡ë-t{yRšÉ ÐéöKà¯ï\¹±WÛu�\Aß(� +~„¾…/a(ÓƒÀÓ&rìÿE}·P–àV­ÐJ_¿úëß|¯ÆÕò•A€ ²ÍþGEU㉉ éh:©CQÚ¾ñ9¹Aóæh;vl�žÛ ¦;y~å" ÞX°À ¼ ÅÅ/Ð?ˆêÖØ@Þ~å_¿@¥B³Þ©k‹.ÜRÊþ|WÎÐH¦‡ÂÂB•쫸¸�5Rɶ+›7Þ(§W¯^ᾊơ*zÕ_ëëéA¿¢B­·¤¡þ¯ xûoU-δոœÌz~Œ—W€+ûóë× ª0zt(é±ë$¹¼×÷o…ÁsªôÐëÖ#D!¤cé$¹\ޝVÍBãVЫüó¯ªpèÐ!•ìÏÃÃTúét…B�ÈiÓ`  ‘¡!—” åÎìŒ�Eƒ5þ3Á ORRðâçŸÁ ß¢lÁ¥GNDlX³¥Ož c‹Ð71A£~ýjüÜŸ„5ïø1^õ²Ä³&U(ko‚Å)™X±bé±ë$.·z„L÷M�p»[Wt£ÅD„\.ÇÈ‘#‘~ö:d¶Á Ó*¼l®‡Å©iˆ��'¯VfÍš…S—/ÃÀÝ_]¹‚þ àIq1•º±:´tsÃ�††È~þ­ƒƒi1²víZìÙ·½fÌÀ©—/!³³CãZÜ·¬VŸšvì�¸OñAЈÚw GŽÁêÕ«I¿:IOOE¯ ŠkJ:ŠN’Ëå1b qâÄ ô…`±øÚx`Éš¯0mÚ4¤¦¦’ŽY#áááÈÎÎÆ‰' ß°!î¼zc;v •••ðòòª×�$<ÒÓÃ/^€kdD:ŠNZ¼x1öïß©TжíÚáyUµÚF�/_177‡D"Áþýû±nÝ:Ò¯E© SLEEE8~ü8Œþö°wïÞ8yò$BCCqúôiÒqÿÕþýû‹ÌÌL˜™™½õo®ñèééY§5)ݳ`Á¤¤¤ 77o|þW[õº¶²U«V‹Åؽ{·ZnkMQ¤ýW11>ýôS?~~~~8sæ éØï”””„yóæ!55­[·~çc¸\.bccѺuk8;;×h -J7) LŸ>‹ÅhÑ¢E½¶Wï ÿÛµkW}×к¬ØLQšâÍb:qâÄ{‹‰1xð`|8<ˆ¾}ûÖè9ÌZýû÷ŸÏdzgÏHƒb …B�)S¦àÂ… ÈÉÉA³fÍ”²]¥M™fVl^¾|¹Ê.£¥(˜bzñâE­Š‰áéé‰uëÖÁÙÙ¿ÿþ;ѱüþûï‰Dضmkõ\f -ggçê%´(Ý&—ËŠŸ~ú iiihܸ±Ò¶­Ô Ìzcàr¹ôŽŸ”Æ«¨¨€ŸŸÊËËëTLŒàà`TTT€Ïç#77–––jË“'Oàââ‚°°0øúúÖy;áááhÔ¨lmm‘““ƒ6mÚ¨},yL1ݹsiiih¨ä¥®”>»®{÷îHKKƒ““LLLàáá¡¶‹¢”éÍb:~üx�‹‰1zôhÃÑѹ¹¹hÕª8ŽÊ×§”Ëå())©¾·ÔÔ©Së½Í°°0�ÇCNNÚµk§Ò1Pì"—Ë‚gÏž!==ÆÆÆJ߇J¦~÷îÝééé‰DÐÓÓƒ›››Ê_,ŠR&eã‹/¾@aaaõíO5j???ØÛÛ+} ?ÿü3vî܉’’äççC `Ñ¢EJÛ~XX6l[[[ˆÅbtîÜYéc ØG&“! ¯_¿®Ñ…Au¥²ez­­­qòäIŒ=ééé*{¡(JÙTUL ¡PˆF�!55wîÜÁÑ£GQUU¥ôqÄÄÄàÎ�;ÈÌÌDYY™J pòäÉ ƒƒƒnܸ¡ôíSì"“Éàçç™Lö¯S)”A¥kÈúé§HJJ¨Q£ •JU¹+ŠRŠŠŠ >¼ú—OÙÅ�=B«V­P\\Œ¢¢"Èd2•,T^^޲²2<{ö *»€aüøñX´hìííñóÏ?«dyåååðõõ…¾¾¾Ê~7Þ¤òœ 8‰‰‰ð÷÷G^^žªwGQuÆSEEUöË×°aC|÷ÝwèÛ·/,,,Э[7•ìËÚÚM›6ÅàÁƒqõêUÈUxÁ1cÆ`ãÆ�prrÂ¥K—T¶Š æ¦�ÆÆÆˆ‹‹ƒþ«×«ŠZ–2d:___$''ã“O>QÇn)ªÆÔUL¹¹¹1b> ¹\Ž-ZÀÎÎN%û;v,úôéƒ_ý+W®„ŸŸš4i‚Ñ£G«dþþþàr¹ …HJJ§5¼©Ån¥¥¥ððð€¹¹9öï߯¶UêÕ¶¾@ À�àáá�””ôïß_]»¦¨ÅœGWu1edd`Ĉ8zô(ø|¾ZÆÖ¿ÿêßµììl”””`Ê”)*ÙŸ¯¯/LLL0tèPœ8qTË8)Õ())�»»;¬¬¬°{÷nµÞMX­÷- …Ø»w/ÜÜÜpþüyuމ)&==½zÍcú/)))5j’’’ÔVL×­[7äçç#22›7oVÙ~\]]±oß>xxx@"‘+U/^¼€££#ºté¢öbÔ\N ‰°}ûv¸¹¹á—_~Q÷î)ªÚ›ÅtäÈ•�G���ǘ1c�””DüHÂÒÒ‰Û¶mêU«T¶'''$&&"00YYYDÇLÕ^QQœœœðñÇc×®]j/&€@9À°aðyóf…B\½z•DJÇÉd2 >\åŇ™3g";;›5ŸµvèÐùùù8tè–/_®²ýØÚÚ"11ÁÁÁ8uêéaS5TXX¡PˆÁƒcÇŽ*Ÿ$þ>Äî¿ìëë‹ÒÒR899A*•Ò |”Ú0ÅÄårUZL»wïÆ²eË ‹ñÁ�ö[,,, ‘H PZZŠ5kÖ¨d?ƒFzz:ÜÝÝQYY oooÒC§þÅ“'Oàèè¡PHü>}ÄÊ BBB —ËÁçóqúôitêÔ‰è‹Ai?¦˜4h€Ã‡«¬˜¶oߎõë×#//�µo¼Zµj…œœ8::B¡P`íÚµ*ÙO¿~ý�––‘H„’’Œ9’ôЩw(((€@ €‹‹‹ÊÞ¬ÔÑr€ÐÐPTUU�ÏçC*•¢cÇŽ¤#QZJ]Å´víZÄÄÄ //íÛ·WÚvï_½Š>-Z øéS4nÙR)Û477ÇéÓ§áää„Ù³gcìˆèذ!à(ñõ±¶¶†T*…P(Dee%úôé.—‹^½z;mDýßãÇ�áàà___,Y²„t,('øüóÏQRR¡PˆÓ§OÓUŽ)¥“ÉdÕ³ÛUQLå�c|Ïžx�oÅbH¥R¥þƒ& ¤kWÜØ¹mкK¥lÛÌÌ YYYX2f JO�¤>À±±°ðöF%Ý›zôè�ÌÌL|òÉ'èܹ3¬¬¬Ð§O¥®÷GÕÞ½{÷ààà€‘#GbáÂ…¤ãTcE9À´iÓ —ËÁãñê}ïyŠz“ª‹IQY‰'IIøÀÌ îæ†oòóQ©Ä#‚öwïÂô¯uÌšéëãüÁƒ(QòçX¡ƒ£±L¨xö ÏòòÐÊÓS©ûàp8èÚµ+._¾Œ-ZàÊ•+¸ÿ>]Õœ�»wïÂÁÁ“&MÂŒ3HÇy kÊ fΜ‰ââb…BH$’z߃ž¢˜b200PÙ²+OŸ¢ò�[—UU¡Aq1Š•¸/Ùß–’UT ¬¬L©ãPümñY=œnËÈÈÀ•+Wðé§ŸÂÄÄúúú*_£�z·;wîÀÁÁS§NÅ´iÓHÇùV•,Y²�H$J»å/¥{ÔQL ß¬¸ ¢²°ð¨¸}ýýÑNIø\»v wíÂL �Œð ¨gÏ"qút´TÒgOEEEXŠPkk4lÐ&-[ÂŒÇSêë´yóflÙ²³f̓Àáp0hÐ ¥��ª¹Û·oƒÏçcæÌ™*[-¤¾ˆÌsú/ááá‰D(ü랢jC]Ř{xàjQä-[âjãÆ°upÀo¿ýVïmÿøã�àñxp;ý.ÄÆË—á¸nøNN4hnÞ¼Yï}€ÇãA¯m[4ôò¶_~A»ÐP4PÒ-·år9&OžŒ={ö //+W®Ä–-[°yóf|þùçJÙUsׯ_‡�� fÏžÍÚbXxäÄX½z5är9\\\�••…F�‘ŽDiˆ7‹éðáÃjY¨Ò°ukì¼rëF�˜= kÒvvvÈÌÌć~X§mæææÂ××;wîİaÃ…ååÐÓÓÃÒ¥KÑ¢E ØÛÛ#99}úô©Ó>=zGGG¸ººbÍš5¸víî•”€Ãå*åu)--…¿¿?JKKqæÌ4þ«ðèï3×®]ƒP(Dxx8BBBHÇùW¬ú©ÉÑÍW_}…°°0dgg×ø~Hvvv�H$ ÃúõëÿóñW®\�@ À²eËðÅ_(}Ìßÿ=ŒiÓ¦aóæÍt’-açÏŸ‡H$ÂŽ;D:N�±¾œ@OO±±±hÑ¢¼¼¼P^^N:Å"oS\\kЉÁãñ���€àà`?~ü½�[»v-¶mÛ†³gÏâ£�>ªÕ>>üðCœ;wÄ´iÓPõ·ËÂ?þø#6mÚ¤’›feeÁÃûvíÂĉUûÂRÿé‡~€««+vîÜ ///ÒqjE#Ê ¸\.8€&Mš ¤#Q, “ÉàííÍÚbb 2˜Ä Aƒpÿþ}èëëÃÆÆFé p¹\ 0æææ¸{÷.>ùä¼|c‰%exõꆊ»wï"''‡ dffÂÇÇGŽÑèb4´œÀØØÉÉɸ}û6Æ�…BA:¥åååðññÑØbþ¼¿‘¹¹9† kkk4oÞF-êªLÍš5C÷îÝ1hÐ XXXÔøê¿šxôèììì`aa�””:©–ÒÓÓ‚¤¤$ØÛÛ“ŽSo[N`bb‚””üú믘>}:é8”ŠiC1€••BCCamm�O>ùsæÌQÉ~ÂÂÂ0pà@ôìÙ¾¾¾…B´iÓ†t,µÒ‰r€7nÀÀÀPUU…Û·oC¡Pлt”‘‘�¢¢"üþûïàp88p ÆÓæÍ›ahh¨Ò}Ìœ9S©kI6W(àߪUõ×-�Œ°{Ý:TÖóö$]¹rr¹œtŒ:;þ|u1ÀóçÏñôéS´lÙ’t4µÑ™rúû%—ÆÆÆ´˜ëر#¸\.ÌÌÌpëÖ-¼xñ‚t¤zkÞ¼¹JË©qãÆÐ××Wê6¹••xUY‰¦½y{òê,>ü�5x•ñ °°�tŒ:ëØ±#5j„ââb@ii)š6mJ:–ZéD9) ìß¿•••°²²‚±±1ÆŒC:–Îcn·póæMXYY!##§OŸÖè•§L™ Ò1jíÛÇQpã îòe|“•…ÌÌL4oÞœt´:¹rå ŠŠŠHǨ3KKK 6 ¹¹¹ÐÓÓÃ?ü€… bíÚµ¤£©�Ö—“B¡À”)SðË/¿ ## 6$‰ú —Ë}k5ù¼¼<øúúâèÑ£]PšèÓ€qTüñœ­­! ‹éä[B¼½½áíí xòä @g Jë'0„……áüùóHOO§ÅÄr¶¶¶8vìüüüpúôiÒqtZxx8† [[Û·>û ÈhÙ²%rrr�žžŽ°°0ÒqÔB«ËéË/¿Dvv6ÒÒÒèÍÐ4-(öXºt)BBBÀãñðÇ�Ž£ót­ ´¶œ.\ˆôôtˆÅb˜™™‘ŽCÕ-(ö Ø1c`ccƒ[·n‘Ž£ót© ´²œ–/_ŽÄÄD�þ@W×Ñ‚b�9sæ`Μ9àóùøí·ßHÇÑyoÔ¼yóHÇQ­+§M›6áСC�H$hõÆÜ JóЂb�‰'âË/¿„ƒƒnüuUESPiiiZ[PZUN›7oÆÎ�;!•JѺukÒq(% ÅãÆ�ÃÊ•+ÁãñðóÏ?“Ž£ó´½ ´¦œ¢££�¬¬,�[æCÛÑ‚b�   lذNNN¸|ù2é8:O› J+ÊiïÞ½X±b¤R):vìH:¥¶¶¶8xð |}}‘››K:ŽNó÷÷Gdd$ñý÷ߓޣóÞ,¨eË–‘Ž£4_Nû÷ïÇ‚ �™™©÷8ÑeŽŽŽˆ‹‹ƒ��-(Â|}}www|óÍ7¤ãè<¦ µ¦ 4ºœªç2õèуtJ hA±‡««+bccáîî©TJ:ŽÎÓ¶‚ÒØr:~ü8¾øâ dffâƒ> ‡R#ZPìáì쌄„ ''‡t�ÇTBB‚Æ”F–SFF&Mš„ääd|ôÑG¤ãPЂb;;;;v AAAÈÊÊ"GçiKAi\9eeeaÔ¨QHNNF¿~ýHÇ¡¢Å666HNNFHHN�:E:ŽÎ377¯.¨åË—“ŽS'UN999 ±cÇ0`ÀÒq(x³ òòòHÇÑi @jj*&NœˆãÇ�“Ž£ó˜‚:vì˜F”Æ”Ó×_�ÀÀ@$$$ÀÆÆ†tŠE˜‚òöö¦EXß¾}‘––†É“'ãàÁƒ¤ãèé8‹ …BZP,ѳgOdggcñâÅØ¾};é8:O ŠÕåtéÒ%¸¸¸ ** ...¤ãP€{tïÞyyyظq#¶lÙB:ŽÎc *>>+V¬ ç?±¶œ~úé'899aóæÍpww'‡Ò LA >œ®^@XÇŽ!•J±uëVDDD�Ž£óÌÍÍ!‘HpôèQÖ+Ëé×_…H$BDD†N:¥�„B!öïßOOO­)¨ÊÊJ’ŽQk:t@^^¢££±|ùrTTTàùóç¤cé,M)¨¤üÝ�7ààà€5kÖ €tJƒ½YP'OžÄgŸ}F:R�]¸pQQQxõêZ·n�%K–ÀÄÄ„t¬kݺ5$  „'Nàã�?FëÖ­±téR’ާs˜‚b>Ç_´héHÿÀª#§»wïB(bÑ¢E&‡ÒÚruàÀüöÛoøá‡põêUÄÅÅ‘ŽTk­Zµ‚½½=~þùg\¼xW®\Abb"éX:‹íGP¬)§{÷î�ÇãaΜ97né8”ц‚ª¨¨ÀåË—qûöm\ºt ¯^½"©Öär9¾þúk4iÒmÚ´�B¡ÐÈqh“7 *<<œtœ·°¢œþøãðxÿüsÌž=›tJ‹ …BìÛ·O£>ƒªªªÂèÑ£add„Ó§OãÁƒèÙ³'1vìXDEEAO�ï1ßK.—cäÈ‘xþü9¾ýö[üñǸÿ>  QŸ›i³V­Z!''€… ’ŽDöÈéÉ“'àóù Ôº[ SìäääT]Pl?‚R(˜8q"nß¾�'N [·n°··G«V­�œœŒ»wï"((•••¤£¾WEE†Ž¢¢"œ8qFFFèܹ3ìììh1± SP‡fűr***‚³³3|||°`ÁÒ¯¥CÞ,¨o¿ý–tœwR(˜|8ÊËËqüøq‘ŽDý‡V­ZA"‘°¢ ˆ”Ó‹/  aoo�¥K—}(ÝÄÔСCYWP …S§NÅ¥K—�––†† ¾óqÆÆÆHNNFii)QQQA:z5™L___4hÐ'Nœ —‹k�7 jåÊ•Är¨½œ^¾| ''' 47n$6pŠbkA………áÇDFF5jô¯�544DBBd2XQPåååðññ�¡¡!âââ ¯¯O:UKLAÅÅÅ+(µ–Sii)<<<ЫW/º” Å l+¨yóæ!''iiiÿYL ÄÇÇC.—ÃËË åååÄò—••ÁÝÝ&&&´˜4é‚R[9•••ÁÍÍ VVVصk8ŽÚKQï–‚š?>233!‹affV«ç2ehh///¼~ýZíù™7ŸÍ›7ÇÁƒÑ ñ‹�©z"YPj)'™L´oßÑÑѬ¿ô•Ò=NNNˆ��%VP‹-BZZ²³³Ñ¬Y³:mC__ñññhÖ¬¼¼¼PVV¦¶ü¥¥¥pww‡¹¹9-&-Cª TÞ2™ ÞÞÞ011Áž={h1Q¬åììL¤ –.]ŠS§N!;;Í›7¯×¶¸\.öíÛ‡–-[ÂÓÓS-URR777têÔ —ËU×KG©É›µjÕ*µìS¥MÁÌq000ÀáÇé»)ŠõÔ]P6lÀ‘#G�••…-Z(e›\.{÷îEëÖ­áìì¬Ò%‚˜bêÒ¥ vïÞMß|j1¦ :¤–‚RÙO’\.GHHÊËËG‹‰Òê*¨M›6!** R©JÝ6—ËELL :wî +=ÿ‹/ Э[7ìܹ““PgA©ä§©ªª £F�³gÏèJ#½YPß}÷�Ò·‰�;wB*•¢uëÖ*ƒžžöìÙƒ^½zA$áåË—JÛvQQœœœ`mmM‹IÇ0uðàA•”Ò¢˜%W=z„“'OÒYá”Æb ÊÃÃC©µeËDFFB,£M›6*‡ÃÁ¶mÛЧO¥SLƒÆŽ;è•·:H¥Ôrb–\ùå—_pâÄ «å…¢(UQvAEGGcÓ¦M�J¥°´´TË8¶lÙ‚þýûƒÏç×ë.´………ptt„­­-�D¯ã,,,ª jõêÕJß¾RËiîܹ¸xñ"ÒÓÓß»ä EieTLL V¬X‰D‚N�:©u ‘‘‘°±±�££#ž={VëmŸ�üãÿ™b Ä¢E‹HÇ¥4€……²²²Sï£ì:ÏŒeæiœ>}Zé)ŠíÞ,¨¤¤$|òÉ'oýÿ‰'0uêTdffâ£�>"÷½ÂÂÂÀápÀãñ ‘Hª/ ¿wïø|>BCCñå—_’ŽIi�víÚA*•‚Çã@�ïr^ãr*{Uˆ×ߦ!°k ˆnÂæÍ[qúôi•ÏÓ Þíõýûè[V£Û·!/-WCoy}7ó^ß¿®Y3tró‡ž�éH5ö÷‚úЪJŠî!ýÂLœ8©©©èÕ«é˜ÿiîܹÐÓÓƒ£ƒŽ­^ ç&M09 S¦LÁ´iÓHÇ«5…L†nhÓ¼9ä¯^�K¯V»7 ª�F�`ðÝw�wìXã¿U…B¡¨É¯ìÝãÇ2@¥¾²ÏzáÃÁn¤_�TYXˆ?DUI ÀÀÂmG�"«Öîä&AþýUp*ÿü”wj†.~ãHǪµŒŒ44ºöZUzÀµÊB´âù`À€¤£ÕŠdÝ:´«¬„¾žÊ9t ‚Q»v¤cÕÚû÷£üÁp4k†Ö!!У«Ôqï̼”H`ò×›NCKK´ ¨Ñsk\N×¾ZÃâªê¯o6,ÖÌó¤Ç®“xmÛ«cÇê¯_ÈdX}áJ++IG«•/�?AëâÿߌîEC9e~C:V­ ú¨-†›u„Þ_¿å† ¬»x O KIG«•0kk´yã]í…gÏ{ý:éXµÒÔÀ³?þ�þºÉ¡Àþë×q¾óº¨ú îÒÌÍ«¿ÖoÑí>ÿ¼FÏ­q9]Ý £ÇÞÀ¬R_Ùà�ѱ—é±ëœÊÊJ,Ÿ9£;v„é_¿€2Ú††’ŽVk÷Ï'£å¯/ W (8À =´u$«ÖŠ^…�ôÇêrª0у±‡ Mš�ŽV+e©©¨zü ÐÓƒa¿~Ð×€Ó’o’ŠÅhóÓOh×´) ¤¢�BCa¬¢õ ©wï›oðB,F£¿Ž\M¬¬Ðjøð=·ÆåTVZˆ'öCö²÷¹ÀâmG ‘HèUzj$—Ë1bÄáÐòåø99 LL°A,†UŸ>5kÿúõë¹:cÏÚÉhôLE3cŒ[�±c&cÒ¤I¤ãÕÚ/û# ÿ¤z@Þ¥º{ÔìÝ!›TâIj*ä¯_ÃÀ­\] Z7/!!“'O†8&†7oâuYòïÞEî“'ô–ñÜ¿<á¡¡h]Y‰ÖVVèìãSóS¬ŠZøõ×_3fÌP( Å‚ ü±âÙ³gµÙUG2™L1lØ0…‹‹‹âõë× …B¡7nœ"""BñüùsEß¾}sçÎ%³F®_¿®h×®�âÀ� …B¡ U<~üXqëÖ-…•••bëÖ­¤#ÖÚãÇ�3&‡(ž>ü�t�¯hݺµâÒ¥K …B¡‹ÅŠˆˆEyy¹ÂÃÃCáãã£�Éd¤cêŒ{÷î)ºté¢X½zµB¡P(æÎ�«øå—_jµ�:Ïs ‡H$‚@ @aa!é’ÖjðóóCyy9Ž?þ�[�˜™™!##éééX¾|9é¸ÿêÆ�pppÀªU«üÖÿuìØ‰‘‘‘زe 騵vóîs4jÖ–t ��éÓ§#33½{÷~ëÿ pìØ1Èd2¢¢¢‚t\­Ç1�3¦Î—‘õœ„»zõj888¨ìffÔŸ·¹>|8d2ß{o¬–-["''ñññ'û�˜b Lj#ÞùKKKH$lݺ‘‘‘¤#S,wôèQ̘1™™™ï½lŸ)¨ŠŠ ЂR!e „å‹Ö­[‡¾}ûB$©ôvкˆ)&.—[£›6¶lÙ‰‡VËm”kãæÍ›àóùX°`BBBþõ±:t€D"ÁW_}…•+W’ŽN±Ô‘#G0sæLdeeýçDgÄÇÇ£²²’”Š(³˜%”s3³?üžžž(++#ýi™L___èëëãðáÃ5þ0×Üܼú+lY¤óÎ�; …X°`Æ�_£ç´oßùùùˆ‹‹ÃŠ+H�b™½{÷bÖ¬Y‹ÅøðÃkôœ7 Êßߟ”)»˜%­JÎáp°cÇ´nÝC‡Åëׯ‰¾PšŽ)&ƒ:]eÄÜ¥rß¾}X·nѱܽ{<sæÌÁ„ jõ\f!É£G�bÙ²eDÇA±GLL .\±X\ë5 ™‚ªªª¢¥$ª(&@‰÷sÒÓÓCll,Z´h///”——y¡4�L&ƒ�� kuÄôw‹Åؽ{7¶nÝJd,L1Íž='N¬Ó6˜¢MLLTê>¥™¢££±lÙ2äææÖy1]=zUUUôoU=1ŪôßO¥Þ —ËåâÀ�hܸ1=¯[åååðöö†±±1âââРA�×åðÿõ­"##ñÕW_©u,÷îÝ�ÇÃÌ™3ë=oÉÜÜ999HOOGXX˜ZÇA±GTTÂÃÃ!‘HÐ¥K—zm‹9‚Ò×ׇ··7-¨:x³˜T±8°RË øAUVV"00•¶¤)eeepww‡©©):Tïbb´oßR©›6mÂŽ;Ô2¦˜¦OŸŽÉ“'+e›-[¶ÄéÓ§!‘H0gεŒƒb�Ý»wcåÊ•ÈÉÉQÚ õõõiAÕ‘ª‹ PA9¾+IHH@YY‚‚‚ —ËUúBiº²²2xxx yóæ8xð ÒЉÁ\ý¶~ýzìܹS¥ca~hÇ�‡©S§*uÛfff‹ÅÈÍÍŬY³T:Š=vî܉իWC"‘(ýNÂLAЂª!u ¢rþ?·àéÓ§øüóÏQUUUÿ�j¡ÒÒRxxx E‹8pà€Ò‹‰aii‰¬¬,¬\¹»wïVÉ>˜Ú±cÇbîܹ*ÙGÓ¦M‘••…¯¿þ'N„¢f«oQ*""k×®…D"�•••Jö¡¯¯�£G�ÂÀÀÆ £õ/ÔUL€ Ë Œ��‘œœŒÛ·ocܸqôÉß0ÅÔ¾}{¥žÊ{Ÿ.]º@"‘`ÅŠ8pà€R·ýøñc…BŒ3FåŸ 5mÚ™™™¸xñ"-(-¶iÓ&lݺR©�:uR龘‚222¢õê,&@Åå&&&HIIÁ¯¿þŠéÓ§«|@𢴴îîî°´´Dtt4ôôTþ­tíÚ999˜?><¨”m>~ü|>ÁÁÁj»¢®I“&‹Å¸víÆ�O�̵̆ °k×.äçç£ã·‡Q%æ_ãÆ�éU|£îbÔPN`jjŠäädœ;w3gÎTËÀج¤¤nnnèØ±#¢¢¢ÔVLŒnݺ!;;óæÍC\\\½¶UPP>Ÿ�ÀÀ@ÌŸ?_­ãhذ!RSSqóæMŒ7Ž”–X¿~=¢¢¢ ‘Hж­z×*är¹8xð š6mJ ê/$Š PS9¾ÓÍÊÊB^^žN_mÅ“••‘bbtïÞÙÙÙ˜;w.Ž9R§m0Å€ ‡©©)RRRpëÖ-Œ1‚^|£áÖ®]‹={ö@*•ª½˜ÌÇLAéò¢�=‚P(T{1j,'àÏÏ 222�‘‘ÁÚÅIU‰)¦.]º`÷îÝÄŠ‰Ñ£G¤¥¥aæÌ™8yòd­žûäÉ888ÀÏÏ .$:$''£  ÁÁÁtú‚†Z»v-bcc!‘HЦM¢Y˜‚233ðaÃt² =z>Ÿ�#F¨½˜5—´hÑ9998|ø0V¯^­ö“RRRWWWtíÚ»ví"^LŒÞ½{#=='NDRRR�žÃ“��-ZDzþ,¨¤¤$<{ö AAA´ 4ÌÒ¥KYSL .—‹ýû÷ÃÌÌL玠H@ œ€ÿ/Nºÿ~âk¿©Ã‹/ н{wVãã�?Fzz:Æ��äää}laa!œ��!‰°dÉÒÑßÂ\ZVVFïÝ£A–,Y‚øøxH¥R´fÙíÔ™‚jÖ¬™ÎŠ TNÀŸk¦1k¿mß¾�Ø  j/^¼€³³3>þøcìܹ–ÞöÚÚÚ©©©7nRRRÞù˜¢¢"8::ÂÁÁk×®%ù� ‘��™LF—ÐÒ‹-©S§�—— ÒqÞ‰)¨æÍ›k}A±¥˜‚åü¹ö›D"Á† T¾r /^¼€““¬­­±cÇÖ£oß¾8qâF��´´´·þ�)&{{{Öí2ë¦ÉårzÅ‹-\¸)))ÈÎÎF‹-HÇùW\.ûöíÓê‚bS1„Ë øsifå‚èèhÒq”¦¨¨B¡ÄöíÛY_LŒÏ>û III=z4öîÝ‹ 6àÔ©S …°µµÅ† HG¬¦  áåå…¸¸8lÞ¼·nÝ"�0þ|¤¥¥iD11Þ,(OOO­*(¶À‚rþ\¹@,cÉ’%u¾¬™M !0dÈDDDhL11ˆÕ«WãØ±cÈËËCtt4zôè��7’ŽV+̤J###>|999X±bîß¿O:šÎR(Õ·UÏÎÎFóæÍIGª¦ Z¶l©5ÅÆbXRNÀŸ—5gffbæÌ™HLL$§Îž?�@�§qÌßôðáÃêå”8ŽÆ¼»ý;===´hÑ¢ú ÂÓ§OÿqÊ’R…B�éÓ§#??b±Íš5#©N¸\.bccµ¢ ØZL‹Ê >úè#ddd`Ê”)5¾¬™M áää>Ÿ�õëדŽS/mÛ¶}눯qãÆ¤#Õ ‡Ãyë²rtïÞ�t,�£P(0mÚ4œ={V£‹‰ñfA :eee¤#Õ›‹ `Y9ÿŸw3~üø÷^5ÆF……… …àñx_LˆÁƒ£C‡øðÕ~û uINNFnn.Z·n�öíÛC(ÂÎÎŽt,�¢P(0uêTüøã�ÈÉÉ�™™éHJÁ”¹¹9<==5ª Ø^L Úe°ëÈÚÚ'Nœ€»»;öïß‘HD:Ò¿*,,dý%Öµe`` ²Û^¨Ë‘#G0kÖ,¤¦¦ÂÚÚšt�¤P(0eÊ\ºt hÔ¨éHJÅÔèÑ£áé鉓'OÂØØ˜t¬¥ ŰðȉñÙgŸáÔ©S5j¤R)é8ïõäÉØÙÙA hM1iƒƒböìÙÈÈÈ ÅDˆB¡ÀäÉ“qùòe¤§§k]11¸\.öîÝ‹V­Z±þJSŠ `q9À Aƒ�˜˜äå呎óppp€‹‹ Ö¬YC:õ—�;wbáÂ…�J¥èÕ«é8:©ªª ¡¡¡øù矵º˜o[?ƒÒ¤bX^N0dÈlll0bÄÌŸ?Ÿô°)•••5j=z¤•;5…L&ÃðáÃ!“Épüøq’ŽÄJo”ªOñiK1\NŠY³f�ÇãáÎ�;Jßþ½{÷Àãñ0fÌ�ÿFk æbaa!Nœ8¡óŸm�Â|¸\.Nœ8A‹é?èééaïÞ½øàƒTVPÚTL€†—L�:Ó§O‡££#S¦LÁ¼yóH“PZZ èëëÓSHÉd2øúúB__‡†¾¾>éH�Ãá`ÇŽøðÕ^PÚVL€”LŸ>ãÇ�ŸÏÇ£G�ê½½»wï‚ÇãaêÔ©˜6méáQJJJàáá�æÍ›ãСCô"!åååðöö†¡¡!-¦:àp8ؾ}»R J‹ Ð’r€Y³fÁÏÏB¡Ïž=«óvîÞ½ >Ÿ�iÓ¦á‹/¾ =, Þî^(ÂÊÊ ¨¾Ï¥^åååðññ�‰‰ âââè÷¡ŽÞ,(‘HT¯‚ÒÖb´¨œ`Ù²epww‡@ ÀóçÏkýü;wî€Çãaúôé{‹mÃÜŠÄÚÚ»v킞žVýÈjŒÒÒR¸¹¹¡aÆ8tè-¦zb ªW¯^‰D(..®õ6´¹˜-+'X¹r%œœœ PXXXãçݹs|>3gÎÄ”)SHƒÂŸËDÙÛÛƒÇã᫯¾Ò¸ÛÝk æ³¾–-[Ò#W%âp8øê«¯Ð«W/¸¸¸Ôª ˜b ÖÊb´°œ`õêÕ4h\]]kô ¿}û6x<fÍš…É“'“ŽOáÿ¿|"‘ˆ.¬KPii)ÜÝÝaii‰ƒÒbR2¦ z÷î]ã#¨7‹I›§·he9q8lݺÖÖÖÿyN÷öíÛàóù˜={6&MšD::…??÷³±±ÁèÑ£i1TRR777têÔ QQQô”ªŠp8lÛ¶ üñ”® ¥åüÿÉ|//¯w._ãÆ ØÚÚbΜ9´˜XâÖ­[ÕWJΚ5‹t�ÅSçÎ�±{÷nZL*V“‚Ò¥b´¸œ€ÿÏ+°°°€§§'^¿~]ý¿þú+ø|>æÏŸ�‰'’ŽJ¸víììì°`Áz¥$A/_¾„££#ºvíJ/BQ£+(]+&ÐúÈ\.±±±†··7:vì…B‰D‚ððp„„„�ލ³ªªª�¿a>oÛ¿îØ�ù'O"<<#GŽ$M礧§#==r¹W¯^EïÞ½±cÇzŠš15uêTxyy¡k×®àp8øþûïuª˜('àÏ‚š0a6n܈{÷î  ÅTRR‚Û·o“ŽQ'¿ž:«ÊJpMLáè`k«‘ã©Í•¡lSXXˆ£G�VO¿hÒ¤ V®\I‹‰‡ƒY³faúôéøã�?;vÔ¹ÓÜ:QNðûï¿¿õµ‘‘ …ÆÿþüóÏØ°aéuâ`b7P(4v,r¹œt„:{üø1^¾|Yýµžžž?ŽæÍ›“ަ³îÞ½ …BQýµ±±1Š‹‹uj C�)'‘H„üü|<}úzzzèØ±£Æ|ú駘>}:éuòë7ßà•XŒ†úú¨T(ðGy9¶mÛF:V�àóÏ?'£NºvíŠ:T¿�{ñâÅ[)õ0`Ú¶m[}äÔºuk�»_™Î”“……–,Y‚“'O¢mÛ¶ðôô$Içuûì3\—ËñãÉ“hÜ©Ö?ŽŸ—,Á²eËHGÓ)\.áááˆ��‡ÃAqq1„B!²²²Ð­[7Òñt’‰‰ ÂÃј˜ˆ† bذa¤#©�ΔXZZÒ…\Y¦ûàÁXƒÕsæ Õ×|>ô¦ŽjÖ°aC„††Vݼysðù|¤¥¥¡wïÞ¤ãé¤æÍ›cܸq¤c£SåD±[Ë–-‘““�‡  ,,Œt$�}}}8::")) Ÿ~ú)éH”Ž¡åD±Š¹¹9²²²`gg.—‹Ù³g“ޤ³†SSS¸¹¹!>><�t$J‡ÐÙuë´mÛR©;vìÀŽ;HÇÑi®®®8vì ‹IÇ¡t-'Š•Ú·o‰D‚uëÖ!**Št�foo�„„áäÉ“¤ãP:‚žÖ£XËÒÒYYYàóù011APPéH:kÈ�!HOO‡««+^½z…àà`Ò‘(-Gˉbµ®]»";;àr¹ð÷÷'Igõë׉ÎÎÎ�Édo]ÝGQÊFˉb½îÝ»#-- NNN011�‡‡éH:ëƒ>€X,†P(Dqq1�šA© -'J#ôîÝééé‰Dàr¹puu%IguïÞyyyxùò%-ZD:¥…è”ư¶¶Æ‰' ‰DB:ŽN³´´D~~>âãã1oÞ<Òq(-DˉÒ(Ÿ}öNœ8�€€œ>}št�faa�œœdffbêÔ©t=>J©h9QgРAHHH€ŸŸòóóIÇÑiæææ�J¥øñÇ1qâDTUU‘ŽDi ZN”F²±±ÁÁƒáëë‹ï¿ÿžt�Ö´iSˆÅbܼy#FŒ@ee%éH” åDi,GGGÄÆÆÂÝÝçÏŸ'G§™šš")) Ïž=ƒ··7ÊËËIG¢4-'J£9;;cÇŽpssÃ/¿üB:ŽN311ARR4h€aÆ¡¬¬Œt$JƒÑr¢4ž——¶lÙ¡Pˆ«W¯’Ž£Ó �-Z@$¡¸¸˜t$JCÑr¢´‚��V­Z'''üöÛo¤ãè4.—‹˜˜téÒxþü9éH”¢åDi���,]º¸uëé8:�Ëå"** ƒ†££#ž>}J:¥ah9QZ%44³gÏ�ÇÃ�;wHÇÑipww‡­­-Äb1ºtéB:År´œ¨wºuëV­Z…Ç�£iÓ¦†P($«VfÍš…?þø3fÌ€¾¾>š7oŽÐÐPØØØ�ަ“&Mš}}}ØÙÙ!##½zõ"‰b1ú™õNGŽÁãÇ�EEEÈÊÊ"©Nš6m }}}À³gÏ�’’B:’N;v,6nÜ�@@Wö þ=r¢ÞÉØØø­¯5uÍ4¦˜Þ÷5¥~þþþ055…»»;Nœ8��’ŽD±=r¢þ¡¢¢gΜ�B¡@“&M`llŒ¬¬,�»<»¼¼çÎ�4iÒíÛ·ÇçŸN:ÀÝݱ±±ððð@vv6é8 Ñ#'ê-2™ ~~~¨¨¨@bb"Š‹‹aff†Ý»wƒÏç#;;�;w&ó?•––bèСhÑ¢öïß�¢¢"4kÖ \.—t4ê/ÎÎÎHLL„��¢££éŽ©·Ðr¢ª•——cøðá044D||<ôõõahh˜8q"4hˆÅbtíÚ•tÜ÷*))�»»;¬¬¬°{÷nèéé¡eË–¤cQï`kk‹´´4xxx ¢¢ÞÞÞ¤#Q,Aˉð瑆§§'š7oŽ AƒþhŒ;&&&àñxÈÈÈÀG}D:ö?¼xñ"‘½zõÂŽ; §GÏ\³]ÿþý‘––‘H„W¯^!$$„t$Šh9Q())�‡‡,,,°oß¾w#((\.NNNHKKÃÇL:~µÂÂB8;;£ÿþضm8éHT Y[[C*•B(¢¸¸S¦L!‰"Œ–“Ž{õêÜÝÝѵkWìܹ³FGþþþhР„B!’““ñÉ'Ÿ�  ! ±nÝ:Òq¨:èÑ£òòò  “É0sæLÒ‘(‚è9VTTGGGôèÑ£ÆÅÄðññALL <<<ª¯ˆ#åñãÇppp€³³3-& ×±cGH¥RìÚµ óæÍ#‡"ˆ–“Ž*,,„““ŒíÛ·×é³WW×êË�% ‘q<|ø|>¾¾¾X³f ‘ ”rµoßyyyHOO§¥Ãh9é ‚‚ØÛÛÃÞÞ6l¨×g3ÌåÀ���‹ÅjÇÝ»wakk‹1cÆ`ñâÅjÝ7¥Z­ZµÂéÓ§qúôiLš4Ic'�SuGËIÇ0§ÀD"Ö®]«”mÚÚÚ"!!AAAHJJRË8nß¾ �‡©S§ÒÏ&´”™™233qùòe„„„ ²²’t$J�h9é�G�©ìØ�!C�žžŽñãÇãĉ*Çõë×akk‹™3gâ‹/¾Pé¾(²š4i‚¬¬,<~üÁÁÁ¨¨¨ ‰RZN:âîÝ»°±±APP�ÊN�õë×iii˜8q":¤’}\½zŽŽŽX¾|9&Ož¬Ê—Œb $''£¼¼Æ ÃëׯIG¢Ô€–“¸sçø|>¦L™‚ùóç«t_}úô�T*żyó°oß>¥nûâÅ‹àóùX¹r%F�¥ÒqPì¬Zbll ¼zõŠt$JÅh9i¹7nÀÆÆÓ§OÇ´iÓԲϞ={";;‹-BLLŒR¶yþüy¸¸¸à«¯¾Âˆ#Ô2Š]ôõõqøðatêÔ ...xùò%éH” ÑrÒbׯ_‡ƒƒ–-[¦ö÷Ý»wGnn.V®\‰­[·Ök[?üð\]]±cÇ 6L­ã Ø…Ëå"::}ûöŸÏdzgÏHG¢T„–“–ºzõ*ÂÃÃ1zôh":uê‰D‚-[¶ ""¢NÛÈÏχ››öíÛ‡¡C‡Å.‘‘‘pqq�­­->|H:¥tù"-tñâEˆD"¬_¿ÁÁÁD³XZZB"‘ÀÁÁ¯^½Â¢E‹jüÜÜÜ\øùùáСCppp :Š}–/_SSSðù|ˆÅb´k׎t$J‰h9i™óçÏÃÍÍ _}õkN�µoßùùù())©Ñeì1bâããÁãñH�b©°°0˜ššÂÖÖb±X#î5FÕ -'-òÃ?ÀÝÝ;wîdÝ)°V­Z!''ŽŽŽP(ÿ:855cÆŒArr2>ûì3ÒÑ)–›2e ôõõagg‡ÌÌL|øá‡¤#QJ@?sÒgΜaýg3æææÕKÒLž< …â�9vìBCC‘””D‹‰ª±ñãÇcݺu …¸téé8”ÐrÒ`- `¬P //>>>8xð „B!éXÿÊÌÌ YYY¸pá&L˜€ªª*˜èé Ž9‚éÓ§C,³â6”f ÄŽ;àíá�†—.ÁV&ÓŒ º.Ÿ†¢§õ4�B.ÇãG1¢ukT–•áð¦M8|ø°Æ|6Ó¤IˆÅbø{yáìòåÛ±#ïß�¨C‡�™™ÉÊ;ìRšÁÃÖ÷ï£ñ_s ^]¼ˆÆÆ0³³#�ª%Žâ]çVÞãÆ�X¿~=éÜ:­Å«WèTPPýu±\ŽäÊJhÚ²˜¹\t}ã®»TT GCßåVTTàòåËðóó—Ë%G§}øàÊdÕ_?76Æ�V­HÇÒiR©Ó¦MÃ|PãçÔéÈ©¬¬ŒôXuZ¹L…BQ}« …B�—/_¢¢æï3X�Ó¤ ðF9éxñâéXõBWÎ&ï^q1ºêë£�ž*9<36†\.'‹ª¥Z—SÆ B:·NSÈåx‡’û÷Q¡P íçŸ1jÉôìÙ“t´Z)ÿã<>u ò—/Á52ÂGNNÔ§éXuæáá�€€�Ž¢³¢¢¢°pï^Ć…AÿåKôrvF×�?&Kç]¾|¹ÖÏ¡Dh —‹6ÁÁøÖÔ?üNN¸rå éhµbض-ÚŒ�æNN0 Bc .&м]»vaÕªUÈÎÉAE×®øÎÐ�h1i,zA„¦âpð‚ËE CCŒ=FFF …ÈÊʪÕy]Ò4jDK‰ª·íÛ·cÆ ÈÉÉ�••nݺE:UO´œ´D@@8!‹5ª (ª>Ö¯_�èèhäååÑ%Œ´-'-âïïpttDVV�)Oi½µk×bïÞ½�H$hÛ¶-é8”ÑrÒ2þþþàp8Õ§øhAQÚjíÚµˆ��…D"A›6mHÇ¡”Œ–“òóó…B:©•ÒJ‹/FRRòòòвeKÒq( å¤¥üüüÀápàääD ŠÒ* ,@zz:²³³Ñ¢E Òq(¡å¤Å†prrBFFzõêE:EÕ™B¡ÀŒ3pæÌdgg£Y³f¤#Q*DËIË >ÎÎδ (�¥P(ðÅ_àüùó�H$hܸ1éH”ŠÑrÒ¾¾¾´ (�¥P(0eÊ\¾|hÔ¨éH”ÐrÒ>>>þНwïÞ¤#QÔ’Ëå3f nݺ…ôôt4lØ�t$JMh9馠‘––†~ýú‘ŽDQï%—Ë1zôh<~ü066&‰R#ZN:ÆÇÇ...HMMEÿþýIG¢¨¨¬¬DHH qêÔ)‘ŽD©-'äíí ‡WWWZPëÈd2øûûC&“áøñã´˜t-'5lØ0ÂÍÍ )))´ (V�Édðõõ…��Nœ8}}}Ò‘(Bè-3t˜««+öìÙ777|ÿý÷¤ãP:®¼¼ÞÞÞ022B\\-&GËIǹºº"&&îîî´ (bJKKáææ†† âСC´˜(ZNàââR]Pß}÷é8”Ž)))�»»;:tè€C‡¡AúiEˉú‹‹‹ öîÝ ZP”Ú¼xñB¡�;wFTTôôèŸ$êOô'�ª&‰ª êÛo¿%‡ÒrEEEpvvFïÞ½±k×.ZLÔ[èOõ‘H„ØØX :”¥2EEEprr Aƒ°}ûvp8Ò‘(–¡åDýƒ³³suA}óÍ7¤ãPZæÉ“'°··‡��6nÜH‹‰z'ZNÔ;9;;cß¾}ðôô¤E)MAAàììŒuëÖ‘ŽC±-'꽜œœhAQJóøñcðù|x{{cÍš5¤ãP,GˉúWNNNØ¿?ÜÝÝ‘››K:¥¡îÝ»øûûcÉ’%¤ãP€–õŸ„B!:ZPT­Ý½{|>'NÄÂ… IÇ¡4-'ªF„B!âââàããƒÓ§O“ŽCiˆ;wî€ÏçcÊ”)˜1cé8”¡åDÕ˜££#áççG ŠúO7nÜ€�� ¦OŸŽiÓ¦‘ŽCiZNT­ØÚÚâØ±cðóóƒT*%‡b©ëׯÃÁÁK—.Å”)SHÇ¡4-'ªÖ˜‚ò÷÷§Eýõk× °bÅ „††’ŽCi(ZNT�ØÚÚ"!!þþþ�H$¤ãP,qéÒ%ðx<¬^½!!!¤ãPŒ–Ug666HHH@@@-( .\€H$¶mÛL:¥áh9QõbccƒÄÄDÒ‚Òa?þø#\\\ðÕW_ÁÛÛ›tJ Ðr¢êmÈ�!HHH@`` rrrHÇ¡ÔììÙ³‰Dصk¼¼¼HÇ¡´-'J)† ‚ÄÄD!;;›tJMΜ9ƒaÆáàÁƒððð ‡Ò"´œ(¥ �@@:¥…h9QJ7hÐ ?~���HMM%‡R²ôôtŒ9IIIàñx¤ãPZŠ–¥ƒ ©S§0zôh¤¤¤�ŽC)Ijj*F��“'ObàÀ�¤ãPZŒ–¥2LA…††"99™tªžФ¤$|öÙg¤ãPZŽ–¥RDzz:Æ�G JƒÅÇÇcÚ´iÈÊÊÂ'Ÿ|B:¥h9Q*ׯ_?¤¤¤Ð‚ÒPGŽÁŒ3�‘‘��?þ˜tJGÐr¢Ô¢_¿~HMMŸqã�””D:UC111˜5k²²²Ð«W/Òq(Ò€tJwôíÛ©©©puu:i“墢¢ŽÓ§O£k×®¤ãP:†–¥Vo”B¡ÀСCIG¢Þa×®]X½z5$ :wîL:¥ƒtªœnß¾�ãÇ�ÃÂÂ~~~àr¹¤#餾}û"-- ...xô芋‹Ñ¥K :‡t<�ôüùs>|UUUxõêvïÞ ‰D+++ÒÑtÖ£G�päÈaäÈ‘011!I­t¦œv(//GóæÍIÇR+�('…B�}ûöA.—£}ûö°´´Ä7ß|ƒ}ûö‘ަ³JJJ°sçNÂÒÒ={ö¤§ôiÚ´)Fމ.]ºÀÊÊ ÏŸ?ÇܹsQUUE:šNR(ˆˆˆÀ³gÏ`ii KKK\¿~6l M­´þ3'…B�É“'ãÊ•+ÈÈÈ@Æ ׯ_‡££#ªªª0zôhÒ1uÊË—/áììŒ�>ú;wžN¼Gb5{{{ØÛÛøó�ƒ››Æ��]»vÑï�š}ùå—8sæ ²³³aff¸ÿ~õ"»óæÍ#Q-´ú§N¡Pà‹/¾ÀÅ‹‘žž^]Lн{wäää`É’%øê«¯HGÕ/^¼€““z÷îMÿ𱔩©)RRRðûï¿cĈ�Ëå¤#éŒ/¿üb±b±¸º˜€?O�K¥RìÙ³kÖ¬!S-´ú/×_~‰¯¿þ©©©hÔ¨Ñ?þ¿k×®ÈÏÏGDD¶lÙB:®Ö+**‚““¬­­±cÇú™‹™šš"99Fee%éHZïË/¿Dff&Äb1š5kö�ÿ×µ‚ÒÚrZ°`233ß:4~KKKH$lݺ¤ck-¦˜L‹IC˜˜˜ %%¯^½BPP***HGÒZóçϯþ{õ®bbèRAie9-]ºÉÉÉÿù�ftèЉ;vì@xx8éøZ§°°ŽŽŽ°µµÅÆ�IÇ¡jÁÐЉ‰‰xýú5iA©Àüùó‘‘‘Qã¿WºRPZWN7nÄ‘#G�••U«K/Û·o�¼¼<9rË–-#= ­ñäÉØÛÛƒÏçcýúõ¤ãPu```€cÇŽ¡²²^^^(//'Ik,X°éééï=•÷>ºPPZUN‘‘‘صk$ ,,,jý| H$$&&êÌ1ªTPPˆD"¬]»–tª ###xyyÑIºJ°páB¤¥¥!;;»Ns˜´½ ´¦œ¶mÛ†ÈÈHˆÅb´iÓ¦ÎÛ177GNN2220wî\ÒÃÒXL1¹¸¸hå/Ž.Ò××ÇÑ£GѼysxzz¢¬¬Œt$�µpáB¤¦¦Ö¹˜Ú\PZQN111ذa¤R),--ë½½–-[B*•"77³fÍ¢ËÕÒãÇ�Áçóáëë«u¿0ºŽËå"66­Zµ‚H$«W¯HGÒ8‹-BJJJ½‹‰¡­¥ñå´oß>,[¶ 999èÔ©“Ò¶kff†ÌÌLœ={“&M¢UC�=ŸÏ‡¿¿?/^L:¥\.111°²²‚‹‹ Š‹‹IGÒ‹/®¾XK™ËicAit9;v¬úJUÜs¦iÓ¦ÈÈÈÀ¥K—0~üxºœË¸wïlll„… ’ŽC©—ËÅž={ЫW/ˆD"¼|ù’t$Ö[¼x1N�:…ììl´hÑBéÛ×¶‚ÒØr:~ü8¦M›†¬¬,ôìÙSeûiÒ¤ Äb1nÞ¼‰±cÇÒ‚z�»wï‚Ïçcòäɘ?>é8”p8lÛ¶ }ûö…ƒƒž?N:k-Y²§N�BNNŽJЉ¡M¥‘åtòäIL˜0)))øðÃU¾?f9—»wïÒÙòïÀÓ”)S0}útÒq(5âp8ؼy3† GGG<{öŒt$ÖYºt)Ž;†ÌÌL•C[ JãÊ)++ &L@ZZúöí«¶ýš˜˜ )) Ïž=CPP-¨¿Ü¹s<Ó¦MôiÓHÇ¡àp8ˆˆˆ€³³3ž>}J:k,]ºG�­óô–ºÒ†‚Ò¨rÊÎÎÆˆ#�””„þýû«}ÿÆÆÆHNNÆëׯ ó³åoß¾ �‡™3gÒÛ]PX¹r%ÜÝÝagg‡G�‘ŽCÜÚµkqôèQH¥RµCÓ JcÊéÌ™3 ±cÇðÉ'ŸËÁÌ–—Ëå:=ñÆ�°µµÅìÙ³1yòdÒq(–X¾|9FŽ �‡�ŽC̺uë«ö#¦¿Óä‚Òˆr:wî¼½½qäÈØÚÚ’Ž=zFFF6l˜ÎÔõë×áàà€åË—cÒ¤I¤ãP,†Q£F�Ïçã�?þ GíÖ¯_�˜˜H$VÜQXS Šõåtþüyxyy!66¶úf[lðælù¡C‡êÌlùëׯC `ÅŠ5jé8K………a̘1àóù¸ÿ>é8j³~ýzìÙ³R©”ÅÄÐÄ‚bu9]¼x®®®ˆŽŽ†H$"ç˜Ùò­[·†³³³ÖÏ–¿víV­Z…��Òq(–›3gÆ�ܺu‹t•Û°aöìÙÚ#¦¿Ó´‚bm9]¾|"‘»ví‚››é8ïÅÌ–ïÒ¥ D"‘ÖΖ¿zõ*V¯^�#F�ŽCiˆ™3g",, |>¿ýöé8*³qãFDEEA"‘ÔkmOUÓ¤‚be9]¿~...ˆˆˆ€‡‡é8ÿIOOÑÑѰ¶¶†³³³ÖÍ–¿xñ"ø|>Ö­[‡àà`Òq( 3aÂÌŸ?¸yó&é8J·qãFìÞ½R©”ÕÅÄД‚b]9ݸq�k×®…¿¿?é85Æáp°eË 0|>_kfË_¸p...øê«¯H:¥¡ÆŽ‹E‹ÁÎÎW®\!Gi6mÚ¤QÅÄЄ‚bU9ݹsB¡‹/FPPé8µÆLF´µµÕŠÉˆçÏŸ‡‹‹ ¶oߎaÆ‘ŽCi¸1cÆ`Æ pttÄÏ?ÿL:N½EDDTß?N“ЉÁTtt4+ï·Æšrºwïø|>ÂÂÂ0vìXÒqêŒÃá`Ó¦Mpuu…@ À“'OHGª“ü®®®Ø¹s'<==IÇ¡´D@@6mÚ'''üôÓO¤ãÔYDDvìØ‰D‚¶mÛ’ŽSgLAEEE±® �÷ï߯^i`„ ¤ã(ÅŠ+Àåragg‡œœV^½ó>?üðÜÝݱ{÷n¸»»“ŽCi???èééA  55•Èj/õ‰;v@*•jt11Ú·o©TZ=U',,Œt$,(§Ç�C(bìØ±Z·ÒÀÒ¥Kall �‡œœ�øAþúë¯áåå…˜˜V_%Ii6___ÃÍÍ IIIDW}©�ÈÈHlÞ¼YkЉÁÆ‚"zZïÉ“'ppp@pp0+^ UФɈgΜ�··7âââh1Q*çææ†˜˜xxxà›o¾!ç?mÞ¼¹º˜:vìH:ŽÒ1Å–S|ÄÊ©°°ÎÎÎ>|¸ÖßÿçÍɈ¿ÿþ;é8Ÿ:t�€tJG¸¸¸ 66žžž8{ö,é8ïµk×.DFFjm11ØTPDÊéÅ‹ …àñx:s+ï™3gbÞ¼y¬œŒ˜——___ÄÅÅÁÁÁ�tJÇ8;;cÿþý:t(¤R)é8ÿ°{÷n¬Y³‰D«‹‰Á–‚R{9½|ùB¡C† Á† ˆ œ„ñãÇcÁ‚àóù¸qãé8þ¼?³¨.ŸÏ'‡ÒQB¡‰‰‰@NNé8ÕvïÞ�Õ«WC"‘ S§N¤ã¨  J­D”””ÀÝÝŸ~ú)"""ˆ ˜´±cÇ‚ËåÂÞÞYYYj¹“ïûdff"88 °³³#ýÒP:ÎÖÖ ðññÁ�àèèH4OTT”NƒôEj;r*--…››ºté‚Í›7«u�lŠ�7B(›ë‘‘‘���$''Ób¢XcÈ�!8~ü8‚‚‚�””D,GTTV®\©³ÅÄ y¥–#§òòrøøøÀÒÒQQQàp8j$ùûûCOOÎÎÎHKKÃǬ¶}§¥¥!44§N�§Ÿ~Jú¥ ¨· 4ééépssCUU•Ú'�GGGÓbz©#(•—“L&ƒ��6lˆ={ö@O�5‹R7|øpèééA("99Y-s=RSS1fÌ�š[Béž~ýú!-- ®®®¨ªªRÛòYÑÑчD"�••é—�5H”JË©¢¢¾¾¾044D\\¸\®Ê¤i|||`ll œŒŒŒ0mÚ4¥lW)å4þ|dee!''�7&úBi“¿ÏõðööþÏç03Ûé9tJ›uèСº JJJ°páÂ=ïÈ‘#X°`²³³i1)Qûöí!‘Hª×çTFAÕ»œ/^ŒÔÔTH$4kÖŒôk¤uúôéƒôôôê¹ÁÁÁï}ì®]»ªWO¦ó4(m×¾}ûêÏ är9–,Yò¯�?zô(fÍš±XŒ>ø€t|­£ì‚ªW9mذñññ8}ú4š7oNúµÑZü1¤R)«/Óÿ»�;wbíÚµtÉJ§´jÕ ‰�eeeX³fÍ;wôèQÌœ9““Š)³ ê\N‘‘‘ˆŠŠÂéÓ§aaaAú5ÑzÌ¥´LA…††VÿߦM›°uëV­¿E½‹¹¹9rrr  P(þñÁ|||›Æ�‡Ùë×°èÐVÇC¯†SŒj\N¹�£ ì ôU9ú4¢w'å/³Cý·ß¯]ý½{ÑÁÌ U ¸­[££’gÍS5÷,+ //\ @O�û÷GszãF"ŠŠŠpnåJtoÑ…w Ñ2 Z[“ަ“î~ý5^æäÀÔÀ`Ø¡ÚÖè¹5.§ô»;ñJ^Týõoß<ÁwÇn‘»Nв%ü:uóÞ¼¸¢~ú ¯*+IGÓI{ô@—7®R½þâv\¹B:–Njj`€Y½{£Ñ_K¦)ì»~Ÿ?'M'uîŒææÕ_ë·h�vŸ^£çÖ¸œ¤ãiùŸGN ô ñ‰™;Ì�-I�]'½~ðÏQ%“¸M›¢UHôèâºDæä ä§Ÿ¹� €™½=éX:©ª¢bc!/,è¡U@ Z¶$M'•ܸ�gééP¼~ 0±²B«áÃkôÜ—“¬ê5Î?ËDyeÚ™ö@çÆÖ¤Ç­Ó ¥R”üö8zzh:x0L»w'IgUUU¡P*…ìñcè[X �G?s"¨äÚ5�= EUöè�¦C†�ޤÓ^^¼ˆ’ë×ÑÀÔÍ¡WÃõVk\NEQ¥.ô¶´EQëÐr¢(Š¢X‡–EQÅ:´œ(Š¢(Ö¡åDQE±-'Š¢(Šuh9QEQ¬Cˉ¢(ŠbZNEQëü-½¿� Ùù%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--y1ce3rajhma.png000066400000000000000000000112221524103652300221540ustar00rootroot00000000000000‰PNG  IHDRË‚è¬<— cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïYrIDATxÚíÝÙs[çyÇñ/bß;Å]¢(Q$¥Xr$Y‹)K'ž¤©3I›N&ͤÿRÓtÒö&™N{ÑéE"É’—Œe‘¢Dj1iî»°N/@ÚR¢H yHby>wQÔ!ˆÎyÎyŸ÷Ñ(Š¢ „x%íA€åBÂ"D‘$,BIÂ"D‘$,BIÂ"D‘$,BIÂ"D‘$,B©¦Ø/š=èCbot‹û:9³Q$ ‹E’°Q$ ‹E’°Q$ ‹E’°Q$ ‹E*ú¡d1éu–ÒVn»ñ 6Q…²y«(y¿Ç‚¾F½ó�jaYL¬20ü”Ö ™¡Ñ$™õ<�A A:­æ@^8Q=’Ëë O'XŒ­Rï3¡AÃèl’ó'BhTzû©–ɹov¹9vÈÀBb�[C ®6EkÄICÀŽF­£bÓÊj–Ç“ ¢K«¼~ÔÅÏÕbØ<›üúÚ4ñt�JW9ª…%‘Îöz¾ü³Ïeàg}Ì'ÖùýÌ%éhôRç6ïóË)*Qv#ÏðT‚É…4g;øá¹Zô5ÏG¼&–J-,Š¢°²žÃeýóoçwøñÅ#³+ôöG�ÓÓÑèÁfÖïÃK**�¢ÀÄBŠ'qZƒ~ñÍ0V“î…_ëuè]̪ö«–�œ‚^÷òK¬– …&¿™;#)>¾?KØg£­Þ…^'7äDq¢É5†¾ˆb5iùÑ…~—á¥_oÐkÈåÕÛO¥°ä‹ºë Õj8ÝæàDƒ�[ƒq®6E[ÄEcСZ&*ÏÚú�ÇãD“k\êts¼ÁVÔ¿3è´läòª‡*aÉ+ʶîx™ Z®ôx9Ùê ·/ÊÍþB=ã“zF<#—W›I22³Ä©;P£+þ}¦ÓiÈ—Ú™EQØÑ™Ák×ó£ †gV¸Öe|Vϱf/“ª�DšyºÌÃña�‘Ÿ] á´lÿ=¡öÅJI¼+[Cšf>Nq{`†p�•ÃõnU(‰ò�Hg�¡Õ(|ÿõ:"µ¦�3  âNÞª…e·)Öj5¼vØÁÑCV®ĸÙ7Å‘CêýÅ]ŸŠò¶¶žãÑxŒèÒ—O_—¼ŒÊYQ), ª�ól&ß=]Çl,õ¾ãóI:š¼ªÝ+¥%—W�^bd6ÉÉ;ïœ�üÙó’RQ—a/ôùé[ÁB=Ó·€Ãj¤½ÑƒÅX²‡,¶i>¶ÂàhŸÓÀϾzásºRRÚGG¡žið›¹ó$Éí{3Ôûm´E\ÔÈ󙲕^É28e=»Á_}­–¦@yÜ-ù°èu¾~ÔÉñFÛf=3ÍáCnê}RÏ”“ìFž'“q¦—9ßáâTky=_+‹°l±›u¼}¦Pϼ×ebs½™Û!õL)Sò  i>ŸŒs´ÞÊÛ߉`Ô—ß•AY…eKÐcä§o†Kqóþ<>·…ö7½n÷ß\¨j>¶ÂÐXŒZ‡žŸ\â±—ïšÀ² ‚v5Ùi�Xùða‚}Ó´„�4…hËéÜ^¡Ò«Y†F£d²|û”—æ2©K^¦lòŨ×òæ =Ív®ĹÙ7Í‘CnBµÖƒ>´ª”ÍåÙ\:ºÍÉé#•ÓüWöaÙâ¶éùë³>ÆVéí‹11Ÿ¢£ÑƒÃjØý7¯¤(0µ˜æáXŒ–€™_|3ŒÅXY—Å–- >3?¿æÁDšë÷æðy,9äÆ(õÌžyšXch,ŠÝ¬åo/ð9+óªâÂ…z¦³ÁF[ÐÂÇ�|Ð?MSÐIsXê5­f6x2±ý¥óåª"òÅdÐrù„‡ÎF;½}Qnõ§éhòPç*ÿbó mäò|>µÄä|Š3‡�üð|mÅÔ%/SÑaÙRëÐóã‹…V€Þþ(V“ž£M¬¦ò½�y¦Ò<žˆÑxyKo%ªŠ°lù²`$Ň³Ò ° ‰T†¡±(:-üàœŸ°·úWUX`³ ÍÁñ·ã\¿;EkÄE“´6¿ÐêzŽÇ*/�/WU–-æÍÖæMv®õE™^HÑÑäÅëÜE³QÉåFg’|1³DW³�¿9þr?®jUµaÙâwøûË[­‹XM:š½X«¸µyké¼s鼳ėÎïy6µ†,4úÍ|òh‰Û34ì´F\Uq—gK"½ÎÃÑ(�Â÷vÛÒ[�$,ϨÑi8ÌEW³�ë÷âܸ;E{ƒ›p]e_§gÖs<žˆ³�XáÒq7��v©ß^@Âòvs o¿þUkóèl’cMÜöÊú¤Uò cs)žL%8Þ`åû¯—çÒùý"ay‰­ÖæGSËü¾§ÍÈÑFæ hm^L¬24Åk×ó³·‚¸lòÌéUÊÿ·¾Ú#VZ‚>y¸µtÆAK™Ö3éÕ,Çb¬e²|óde,�ß/–"éuÞ8ÙÎ�û…z¦œZ›·Zzg—9ÛáâT«OÖÉm“„e›–Þ>SÇøÂ½ýQ¦ ëÍ–Ò\i«(…ºdx*AG½•ï~;‚É uÉNHXv¨ÁgâçWÂÜMñÁƒ9ü^ GêK«µy«.qÙjøÉ¥ ^‡Ô%»!aÙ�º›í´×[ùøa‚›%Ò °¼–åñxœÔÊ:—O¸i�Hר$,*0é ­Ý›­ÍôMs´ÑƒßcÙ×ãÈåF¦ŒÎ&ùZ«ƒ³uey¢TIXT´ÕÚ<6¿JoŒ±Ù$Mì{\Ïlµô>‹Ñ0ó�ߊTÕÒùý"aÙ�~3?¿âÞhš[ ­Íí‡ö¦žI¤2 ŽEÑká�7ü„<Õ·t~¿HXöˆV£¡§ÙN{ØÂÍqnöOs¸ÞÍ!¿:KIV2<�±”ÎðV—Gê’} aÙcf£Žo�ªådë:½}QÆç“kÜy+@.¯0<•`l.Åé6gÎ×mk–Ø9 Ë>ñ9 üÝ¥ç[¶;ålæé2�Æc„xPØE³­ÞE¨ÖÊÀÈSâÉ A¯…æ°“á© ñUÞ8梫I–Î$ ˲™t|çkµÌÅ ­F£är…Án#3)FçRô´ØùÞ™°,�/ò(·‘wÎùx~¢R�Þí• ”ù-”ˆÔj”篱´ läÔ!*vCÂrÀÖÖóôöEùíÍ9üvŒ:­³±‡ÝÀ/7ŃñôA¦@j–“W”Í'üq| —zÂô:Ž·xŸûºD*ÃÇ�£Üù<ÉÕ“^yB€$,`kíX�NÇ™c�—®sÙ�œ=bj1ÍÝš§9`æÍ.�¬ý:–}Og¹>g.¾¾­UÉ Ôûl„¼VF¦üêÝ©ÍUÅåÙÚ\®$,û`-›çö`‚ãiZ#..vסÙÁ›\§Ópø�›°ÏÆÐXŒÁ÷¦ùF·‡Öàþ¶T+ ËR6;)ãø½_Õ%»e5éy­ÝÏbb•Þ¾(Ÿ~žäj·W:!÷˜„e�L,®q­/ŠF£åtG`OÆõÕ¹Ì\è31Ÿæ77fi Y¸Øé®¸ñt¥B¢²äÊ7îÇ_XÛ—Ý_4 ;¡Z+O&ãü˻ӛ»·Øe÷•IXT’Í)|ò0Á�á$MA—NFöµøÖ×h9Öä¥!à`h,ÆÝá$Wzd_05IXTðhj™ßߋᴹÐ>Ð+mf=¯-Ô3ïÝ-ì8yµÇ#;Nª@² 3Ñ ïõEÉ塧͇Ë^: ë\fÞèóÅL’ÿý,]Í6ÎuUýŒ•Ý�°ì@j5Çõ�ã kip)Ñ]öµ ­a'õu6MÄùå隸Ô馳A–úï„„ery…»Ã)>|˜ ÞoãbO˜]éR :ºZkI¤×ùôIaéÌ•/õÒD¶-–"Ú�£XMÎ�•åd0—ÍÀ×;ƒÌÇVøŸOñ; \=é•É^E’Wéæë\닲²–§³¥®"fNú=j]fFg’üÛû3RÏIÂò¬®ç¹=gpb™Öˆ‹“G*kš±N«¡5â$ì³ñx<Æ?ÿnºê§¿Š„åOäò Ÿ>IòÉã%ê}6.ŸŒ¼t3‰rg6èèn«#žZã£G1¸Úã!à.�;{¥BÂòŒá™zûcXÍzÎ�b5Uϳ ·ÝĹÎS iþóÖ<Í —O¸¥à –ÊÒÛãi2KÇlè]*4¨÷ÛÕ>ß ðõ£.ÙÈ�*ËÚzž�%KÓtr±E¦aÁW­õ~;Ožy>SíõLU†EQàÁDšë÷bø<.t‡1–ТRa6ÖÐÕVÇÓÄ·‡¢ÜMq¥Ç‹ÏYšSÎöZÕ…e|a•Þ¾Z�nÏ–ÎWšZ—‰7ºÂL-¦ùí�9ZfÞêöT]+@Õ„%žÎò~Œ…¥,G=ª´.Ù©­Öæ€Ç“É8¿zwšsUÖ PñaÉdó|ô0Á½Ñ4-a'›¥.Ù�/[üÇ¢Ü)ti6UA+@E‡åÁxš? Ĩu𹨯h¨®Ë†½d³è9Ý`1±Ê»wc8­:®öx¨uTîemE†e6VX:¿¾§ûq;äÛ^©s™¹Ðbb!ÍonÌÑQoåÂqwEn9[Qayvéü~´ôŠ�öùÖæú¿)Îw¸8ÕZYK„*",ÙœÂ�'Iþød©¬–ÎWšgë™ûcQ>«°z¦ìÃ24‘æq;�ÆcÜwŠ7»<´G¬}h/¤NX4äQíÿÓ(ŠRÔ}¬¡Ù—ÿýz6ǧ牥28­^+ ~»ïbß,&V™^L3]AQàð!-aç+ÿ]G°¸ï¯ZX„(WņEÖ¸ Q$ ‹E’°Q$ ‹E’°Q$ ‹E’°Q¤¢Ÿ³QíäÌ"D‘$,BIÂ"D‘$,BIÂ"D‘$,BIÂ"D‘$,BIÂ"D‘þÉêö÷QÕ˜´%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/images/s2shapeindexva--zvfp9yhjq3.png000066400000000000000000000636541524103652300221220ustar00rootroot00000000000000‰PNG  IHDR¤¤~LQ5 cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“tIMEé œïYfŒIDATxÚíÝyœ\e™ÿýÏ9§ö¥÷½;I'é,�„l��° TPÇ]ÜAGGýÍã‚(Û(3ósÔñ™udfDQT !„$dO§ÓI§÷¥ª»öåœóüQ��@¶N/§–ëýzñº««®S„úö}îû¾nÅ4M!„ÂbªÕ!„ �$„"KH !„È HB!²‚’Bˆ¬ �$„"+H !„È HB!²‚’Bˆ¬`;Û^ýõV×j©™+ª(©õ°í�í¤ºÕåä §·„D$huB =ñÄgõ¸³¤£¼>ï±6MEÓEÓ0@eÒ/úd]�UÍø–Ç‚ª(#…�\ ðÆ#M”‘¤ËggÙ{¦cs© ì�1p8:é×–‹ìÞ2š.¹…`Ç:·=…aV—$„UUÀsä“ñè§¢yìCÀ0ÍÌç鈣ÿ …Fõz£ $ŸßÇ¿üä[V¿G“JSl´…_çHd/Ó}‹ø»ï~Ýê’rB4¡óßÏu§YyñÛ˜÷‘÷[]’bi*Üù•E(�j©û°$:8Ù‹Cus^Ù¥V—“ÒºÉ#ëz„ÓÔW¸ižVauIBˆI¦`£ËŒQ’2ùwá,e˜:‡_`IùU85�Õ%e=Ó„'7öÑ9� ¢ØÎ¢¦*”Bûƒ#„8'£\eWX,í‘ÝÄ�0ÕîF¦úæY]NNxv[?{;"x]KgÕ`Ód!§âìŒêÓÂ0 gR:š¢+vM±±´|�Õåä„Mû‡xe‡Meys .ç¨×Ì! ØènÙY]í$119Ú†išÌ/½Ÿ½Ôê’²ÞþÎÏoDQá‚9•ø=«KBä˜ÑÝO)�DꎵN Rl¯dVÑr«ËÉz]qžØÐ‡iÂ’™T”È\›bôdéM’FœÃáÝœ_¹U‘9�Ó DR<¼®‡”nrÞôªüV—$„ÈQrËîMZCÛ0Ì4Mþ¥”;¬.'«E:¯í!š0˜^ëgz�ÜÚBœ;ùõÿ8ƒ‰N‰.\š—ù¥—X]NVK§ ]×Ã`(EM™‹ùÓË­.I‘ãF·1–üÝ«›)†3{Ž––¯Á¡¹¬.)«=ýJ? J¼–Ì®>¡mˆBœ ™Cq(¼‹¤£Ö=“zïl«ËÉjÏodW{�KeYs5vÙk$„Ò©§ôÄbSl,­¸Æêr²ÚÖÖ÷aSU–Ï­Å-{�„ã¤à7Æš¦Ikh+ç•^ŽÇ&«ÄN¥¥+Ê3[ú3{�š«(òÊ^#!Äø)ø[v�Ñ"é!J5Ì,^ju9Y«;�àñ ½˜&,œ^AU‰Ûê’„y¦ oÙ%ô(G"{@Q¸ òKÎpÊÁpЇ_ê!•6™3µ˜i52ŠBŒ¿Q?au¹ãë@è5 tfûWP⨱ºœ¬”H<úr‘¸Î”*s¦”Y]’"Oìò¨¾x;CÉ>ÜZóÊ.´ºœ¬¤&�½ÜCßPŠŠb‹šä\#!ÄÄ)È[vi3EÛ±=GWaWdrþdž~¥Ÿ¶Þ8EËæÊ^#!ÄÄ*ÈR[xi#ÉT_3uÞYV—“•^Ø`ç¡0.‡ÆòyµØmùGE1‰ îSf85@_ì6ÅÁ²+¬.'+m;bÃÞ 6Uaż<²×H1 *�LÓ ux+‹Ë¯À­Éj±7kíŽò§WûX:§ŠbÙk$„˜$µéHt/1=D…³�éþÅV—“uú†’Çí5*§¦LÎ5BLž‚!Åô0‘ý(hœ_)í�Þl8¦óÛµÝ$R&³Ši¬+²º$!D�)˜coÃÄ`nñJŠì²|ùx‰”ÁÃk»Åt¦Tz˜;Uö !&ßè)G7ÆöÄÚJõá·•1·d•ÕådÃ0ùÝúãöͪʛåýBˆÜ’÷#¤”‘àpx'K˯Ʀʊ±ã=ýj?‡zâ¹í²×Ha©¼ŸC:ÚNÚL1Ý·ˆ*O£Õåd•w²£-ŒË®±l^µì5BX*¯?�‚É85ç•]ju9Ye[[ˆ—w aSaYs5^—Ýê’„.oÉ0uZCÛX\v5NM–0u¨7Æ3¯ö£(°dv5¥~§Õ% !DþR{d =Bµ»‘©¾yV—“5ú†<ör/†çM/§¶\‚Z‘ò2�¢é!ºb-¨ŠÆÒò5V—“5B1�‡×öO̪/¢±Vö !²GÞ’‰Ikh¦i2¯ôb|öR«KÊ ‰´Á#/u3Õ©+÷0wZ¹Õ% !Ä Fw@ŸaX]ïuÇZ ¥)¶W2§h¹ÕådÃ0yìå^z‚IJ}N–Ì–½FBˆì“W#¤¤§=¼€ó+× *yuyçìÏ[ië‰áõØY1¯M•4BdŸ¼úÄn mC7Ó4ù—Rîl°ºœ¬°ng€­†qØUVÌ­Æa׬.I!N*oi0ÑI Ñ…Kó2¿ô«ËÉ »ÚìÝĦŠæj|nÙk$„È^yHº™â`8³çhiÅÕ84—Õ%Y®½/Æ6õ¡(°xv¥~yO„Ù-/épxI=N­{&õž9V—c¹þá�®ëE7`þôrêʽV—$„g”ó�NèŽĦØYZ!ç…ci~»¶›xÊ`F­�²×H‘#r:�LÓ¤5´€óJ/Ãc+ì#ÉSºÉ£/÷2MS[îaþôJ«KBˆ³–Ó�Ôm!’¢ÔQÃÌâ¥V—c)Ó„'6ôÒ5˜ Äçd©œk$„È19H =Ê‘È.¨¼%kGÞÚÏþÎ(~—�ÍÕhZa¿BˆÜ“³�t ´�ÙÅË)qÔX]Ž¥6ì òZK§MeÙ¼œÙk$„È=9H}ñv†’½xlEÌ+Ymu9–Ú}8Ì ¯Ž�k${�„¹*ç)m¦h ¿À’²«°©«K²L{_œ§6÷°¨©’²"Ùk$„È]9Hmá¤�$S}ÍÔygY]Žeá¿[߃n˜Ìo,¥¾ÒguIB1&£ $Eµ6¿†SôÅaS,,»ÂÒZ¬Mèüfm7±„Áô3ëK¬.I!Æ,gFH¦iÐ:¼€ÅåWàÖ sÏQZ7yd]ÁpšÚr7 fTX]’BŒ‹œ ¤#ѽÄôΦû[]Ž%LžØØCç@‚R¿ƒ%³ªPd³‘"OŒ.�LÓ’"cz˜ÎÈ~4ί,Üö@Ý6À¾Ž>·Æò¹5Ø´œù}B!Î('>ÑoÃÀ`nñJŠì…y‹jã¾!^Ý?Œ]S¹`®ì5B䟬¤žXC©>|¶Ræ–¬²ºK´tFyaû Š 4WQä)Ü¥îBˆü•Õ�”2´Gvp~ùlªÍê’&]×@œßoèÅ4aIS%•Ån«KBˆ ‘Õ�t0´�”‘dº!UžF«Ë™tÁHš‡×õ�ÖML+¡Aö !òXÖR0ÙË@¢‡êæ¼Òˬ.gÒE:¿y±‹hÂ`z�Ÿ ¥V—$„*+É0u†¶°¤ü*œšÇê’&UZ7yt]/�pšš2 f”[]’BL¸¬ ¤öÈâz„Jç4¦úæY]Τ2Mxrc/qJýv–Ì®–½FBˆ‚�u�MÑ;€¦Ø¸ ÷=·}�½Q¼.• æÔ`—½FBˆ‘UŸv&&­¡m¦AséEøì…5oòZkˆÍû†ph*ËæÖâvÞªB!Dáʪ@ꎵJ Rl¯dNÑr«Ë™Tº¢üyKf¯ÑÜ*м²×HQX²&�’Fœ#‘=,­XƒªdMi®+�à÷ë�î5ª ¢Dö ! OÖ|ê m#m¤hò/¥ÂÕ`u9“&IñðÚnRºÉ¼ÆR* ³‹¹BŒ*�&ªµê`¢“ÁD.ÍËüÒK¬~O&MLŠ]1žymÓ„¥³+)‘½FBqŒ%�”УtD÷  pAå5(ã9ôÊR݃ ~¿¡'F³Ê©.+¬†±Bq&£ ¤ñŠ�ƒámè¦Îìâå”8j¬~&\(šæÑ—{H¥Mš§3¥º0nO !ÄhLú©?ÞN уÇVļ’ÕV_ÿ„K¤ ~ûR7¡˜Î´*³ʬ.I!²Ò¤RÚLq0¼€%eWaSó{Å0L{¹‡¾¡ÕeNÎkª²º$!„ÈZ“H‡B¯“6Lõ5Sç�eõµO¸§7÷ÓÖ§Ägcé¬Ùk$„§1i�4œ 7~»âdaÙV_÷„ûÛŽAvãq¨,o®Ån“½FBq:“ò)išmC™#É•_Ž[Ëï¢Û†X¿{»¦°|^5.‡ì5Bˆ3™”@ꌶ1†©p60Ý¿ØêkžPm½qžÙÒ�¢Àòy•y £7ŸBŒÕ„RˆÓÙ‡ŠÊùy~$yo0Ác/wc™½FåE^«KBˆœ1¡�¤ ÐÙ‰Nš¹Å+)²WX}½&Óyø¥)“Ó‹©¯”½FB1ã>¹a˜:1=Œ¢(˜¦I_¬Ÿ­”9%Z}­&‘6xxmf¯ÑôjÓke¯‘BŒÖ¸’‰Iwô‡#»Q P8¿| 65?'ö3{�zéJR[ædÞŒ*du·BŒÞ¸¥D{xÝñ¦¦~ì늩 +úž9»ýñÕ>Úzb{m,jªFS%�„â\ŒËR\�ÐÛ�n¤ßò=S1y¥ïiÌ ;Ý:/í òz[—ScÕüjvÍê’„"g�K %û8]ëÕ”‘$”´úZÇÕ®Ca^ÚÀ¦)¼mq{~·ABˆ‰6.·ì t0O=RLÃL�â³K(š¦¥3JÒ0¨/s¢ð‡Wú¸fi%ªMö !ÄX�K ùme ¨`'€bà³—[}­çä…×¼²/ˆª¨è† *†�i*¼mQ9>Ÿ—hÒê*…"÷�Ë-;Ÿ½”"{ªòÖ§Ó J/ËÉUv÷yuÿ0i’º�nšèº‰i*ø=ÍÓŠ$Œ„bœŒÛÆØÙÅçSb¯DS4UC!3ÁïÑŠ™Uœ{G”†ÉK;‚¤ô“�ú ƒ}�q«ËBˆ¼1nÃM±3§dáT€p:€'­áí„Óƒ„’ø¹uË.Nƒrêy±´ird AS�Ì !Äx÷ÖA>{)5ë™êkÆÄd×Ðz«¯sôoŒ æiVª&h²V!ÆÍ„ö²+wÕcS´‡wJ¬¾ÖQ)õÙñ¹N½¯ÈP ²Ämu™B‘7&4�4ÅN­g&&&{ƒ¬¾ÖQ»fi96Û[GA*&4ãsÛ­.Q!òÆ„?Q㙎¦Øh ¿N$ÇFI�ÕnZ]ƒÇ¡b·)Øm€ Šª²bnš+„ãfÂ?RmŠƒj÷tL ö7Z}½£ÖXåâ ×OãcWÖñá+ê™ßèE7L6ïFHB1~&åwü:OŠbã`x;ÑÔ�Õ×RºÉ®CÃV—#„ycÒfAê½³P•ƒ¡mÄô�Õ×=&Î+AUáµÖa”îÑ'„ÙdÒÉ®º¨tMÃ0uö7[}ÝcRì±³pº�´nÒÖ-£$!„“ºN¬Þ3EQ9ÚB"±úÚÇdus6MaGÛ0©Tþ@(„“eRÉ©¹©tMA7ÓìÊíQ’ß­±pºÝ09Ô•[ËÙ…"MúNš†‘QÒþЫ$ô¨Õ×?&Î-Á¦)ì="–�¹$!„‹I$§æ¥ÒÙ€n¦Ø7œÛ£$ŸÛÆ’é>tu­.G!rš%½ê½sP•–¡WI¹}„ÊæÌ(iWˆˆŒ’„âœYH.ÍK¹³Ž´™¤eøU«ßƒ1ñ¹lœßT„iÀ¡Î Õå!Dβ¬[½w û‚›H «ß‡1Y1§‡Má@wˆH,eu9B‘“, $�æ§ÌYGÊLp`h‹ÕïÃØ®Å©±tf1¦mݲâN!Î…¥ýª§x碠°wxi#iõ{1&Ëçá°)´vEˆÄe”$„£ei ¹m~J�5$�-ù?Jº`v1¦ ;e”$„£eù‰> Þ¹ìÚˆnæöÈbÅìb\v•ƒÝ¢Ñܾ!„˜l–’×VL©³š„£5´ÍêrÆÄiWY62J: Ý„bT,$€Of”´+ð2zŽwϾ`VNGf”Šäö¼˜BL¦¬$Ÿ½”bG%I#J[èu«Ë§]eå¬bZ¥{ƒBœµ¬$€)žfö×c˜¹Ý=ûüYÅxœ*‡z"„c2JBˆ³‘5�äw”Qd¯ ªs(œÛ£$‡]aùœö‘¹$!„8YH Þ9ì ¬Ç0 «Ë“¥3Šð8UÚ{£C¹Ý‰B!&CVR±£¿½œ˜>Ä¡è«Ë‡]aÅÜÌ\ÒÙ—$„g”U�oŒ’vs”tþŒ"|n•Žþ˜Œ’„â ².�JUøíeDRŽD÷X]ΘØl*«æ–°¯]FIBq:YHõžÙ쾄‰iu9c²xz~·Fw ÆÀPnŸý$„)+©ÔYƒ×^Âpj�ŽÈ^«ËMS¸°¹€V™KBˆSÊÊ@hðdæ’^®ÍùQÒ¢é~J¼6ºãôË(I!N*k©ÌY‹ÇVL89@gd¿Õ匉ª*¬œ3²â®cÐêr„"+em Ô{3sI»‚ë¬.eÌŽŒ’z úƒ1«ËBˆ¬“Õ�Tî¬Ãc+"˜ì¡+zÀêrÆDU.œWÀ¾v% !Ä›eu )(Ô{f°+�û£¤ó¦ù)óÛéNÒ'£$!„8AV@¹«·æc0ÙIwô Õ匉¢Àê£û’ËŠ;!„8^ÖÒñ£¤�Á—¬.gÌæMóQî·3JÐ=µº!„ÈYH®©85/ƒ‰zc‡¬.gLVÏ/d.I!Ž—�¤(ÇÍ% ½lu9cÖÜࣲØN0’¢{PFIB9HU®i85}±CôÅÛ­.gLV�¬¸Ûs(€™Ûû~…b\äL )ŠBÝÈ(iwìKšÛࣺÄÁp4IWÄêr„Âr9HÕ®i8T7=±6úãG¬.gÌ.šW ÀþŽA% ! ^N’¢¨Ôy›Ø\ou9c6«ÞCM™ƒ¡HšÎþ°Õå!„¥r*�ª]�ØU]±]V—3f�Œ’ö`Ê0IQÀr.�TE£Î3€Ý�Ü%ͬõPWæ$OÓ9 £$!Dáʹ@¨vÏÀ¦:èˆíc(Ùcu9cvÑü‘¹¤#C2JB¬œ $MѨugæ’vs_ÒŒ7S*\ GRtÊ(IQ˜r2�j=Ó±)vÚ#{ &z­.gÌVÏÏœ—´·-(£$!DAÊÙ@Ò;µ#sI{†6X]Θ5Vy˜Zéb8ž&0²º!„˜t9Hµž™hªƒ#‘Ý„’V—3f—,(`[k·CFIBˆÂ’Ó�¤)vjÜÓ11ÙÌýQRC…›Æ*¡˜Î``›"¡$„(9Huž™¨Ø8ÙA(•ûg ]´  €¿nä±um<ýrw÷OêV—&„*çɦ8¨qÏÀÄdßÐF«Ë³C=QEÁ4Á4!mšôÃ<·åáXÊêò„bÂä| Ôy›ÐT;CÛ §‚V—sÎáë÷¿e•�i(¤u“­ûû¬.Q!&L^’]uP뚎‰ÁÞ%ì‰brªy#“`8AZ7¬.S!&D^@�g&ª¢ÑÚNL¶ºœs2J£§O³�ÁT0 Yè „ÈOyHvÕÉÏ tö6[]Î9©,u`·�úû6MÁa׬.S!&DÞ@­w6*­á-ÄRä�¤Õ%�ÊœvUEQ”·|OÓfO-²ºD!„˜0¶±?EöPÈ,p8ÙËŽüPqj.š‹/¤©ø|«Ë;#»¦ð¾KkxøÅºAjäö�ª(L­t3½¶Ôê…bÂäÕ)e$èŠÀÄÄD'®GØxžõ½¿·º¼³R]âä–wLáª%å,žáGU Óàª%œdà$„y#¯é`h;¦‘~Ë× 3MWì½ñ6«K<+vMaa£Ÿkί yŠP8Òµº,!„˜PyHÁd/†òƲè–�½ì|¶ƒ¡žº‘¢#¼×êG­©Æ@kw YÏ „Ègy3‡dš†yb'ƒ=/t茲å‰CøÊ�4Í$yI K—.Ån·[]òY™QëAUá@w”Å3MRÈ};!D~Ê›@R‡ê&aÄŽ}킦ӱ3À‘�†{cl]»‡­kÿ ·ÛÍâÅ‹Y¶l\p%%%V—JN»ÊÔ m½qÃq\.·Õ% !Ąț@¨÷Ρ-¼ÃÌÌ#ÕÌ*¦fV1ç¿»‘T@¥¤w>¯nÞÂk¯½ÆúõëY¿~=Š¢0sæL-ZIJeËhnn>é²k+ͬõÒÖ§s ÊŒz $!D~Ê«@ªv7’4btF[À410F.ÒÆÛæ€²¥õ¼ýšw�H$غu+¯¼ò ›6m¢¥¥…––}ôQŠ‹‹Y²d +V¬`É’%x<«/‹Ù nžÝ–i¼:£¾Üêr„bBäU Lñ6Sáj ˜èa0ÞÉpz�9¥+)sÖ{ŒÓédÅŠ¬X±‚Ï}îs8p€Í›7³yófZZZxá…xá…°Ûí477³|ùrV­ZEee¥%×Tì±SQä 8I4šÀãqZý6 !ĸ˻@pk~Ü?^­„�C/Ñ;%'¬¢(455ÑÔÔÄ>ð‚Á [¶laóæÍ¼úê«lß¾�íÛ·óÀ0eÊ–/_ÎâÅ‹Y°`š6yËÞfÖyèNÒ?cª’"åe åw”¡b£?~˜”™Ä®8Îø3%%%\qÅ\qÅ$“IvïÞÍÆ�Ù°aííí´··óè£�â÷ûY¸p!Ë–-cåÊ•~koV­›�{‚tD™ZSbõ[+„ã.¯IQTŠ]âÝôÇÛ©uÏÕÏ;-ZÄ¢E‹øÌg>áC‡ŽÝÚÛ³gëÖ­cݺu¨ªÊœ9sX¶l+V¬`Ê”)ã~-õå.¸x1s Õ0Þô,&¤’8_xŒø»?ƒéöZ}YBqN "� 3J ¥tE[³&�Žw|;#Ó49pà[·neóæÍìÛ³‡¦dU=ÍñUz mÏ«¤—\bõ¥!Ä9)¨@:ÙKo¬�ù¥«­.ç´ŽogtÓM71xø0�‡‚·ŒŽŽc¨]V—.„ç¬`Éo/æØHv�2ØÕÜéWRUÅÐYƒÃébÆìó2£§EËñ•Z}yBQX�äÔ<¸4/Q}˜p*€Ïž[Ķ¢"ê>ð0ML]çwëzØß›dEm5Õoz¬ªª46Í£±i×¾çfûº�…ÓÁý;Ùóúfö¼¾åWÿIýÔ™Ì=osÏ[FýÔѵ3BˆñRP�™® ݱƒôDâ+έ@:FQPl6fÔûÙß;@o JuééÏc*«¬aõ×±úŠëH&â™[{#uäP Gµð×§~Miy³æ-aVóbæÌ?‡ÓeõÕ ! DáRü 3‹—Z]Θ4Õ{y浺¢œ7ãìÎátÑ<²ØÁøÀgélo=6bê8|€MkŸaÓÚg°ÛL›ÙLóÂå,X²ŠâÒ «/Y‘Ç .�Š•(ŠJwü†i *êØŸÔ"~·Fu‰ƒž`’`8I‰ïÌ'â¾™ªª4Lk¢aZW¾ózÙ¿ë5vmßDËî­´ìÙFËžm<ùÛŸRU;%dç-cÚÌf¹µ'„WHšbÃo+c8ÕÏ@¢ƒJWn/‡žYç¦'˜¤79§@z³Òò*–_¼†å¯!•Lp¨u»·obÇ–—éíj§·«�¿=ó(>1³ç/¥yárf5/ÁåžØ#Ü…ù¯à  ÄQÉpªŸîXkÎÒ¬://ï¢o0Æì†ñ�³;œ4Í]DÓÜE\÷wŸ¦§ó0{^ßÌ®í›8ܺ‡-žgˆçQ5�)�³™·p9󯤲ºÞê·E‘ƒ 4�ª9ÙMoô ”^ju9cR[êÄïÖ%ˆ'Ó¸÷Ÿ´ºn*ÕuS¹tÍ�„CCìÝù*{¶ofÿî×Þ²ç©ù¼e4/\Ό٠PUÍê·I‘ 2�<öb쪓Ád7 =ŠSËíÛM3k=lm Ñ3cZ�R^Óç/æü•WpþÊ+H¥’:°›ý»·²këúz:X÷Ü“¬{îI<^?3ç,dîÂeÌ[¸·GŽ^Bœ\A’‚B‘½‚�D½ñCLñ6[]Ҙ̬u³µ5D_02i�t<»ÝqìÖÞ›÷<µîßÁë[Öñú–u¨Çµ3š9w Óš¬~ë„Y¤   ÔQÅ@¢ƒžh[ÎÒôj6M¡'C×M4ÍÚÕoÇïyŠFBo´3Ú¶éØ­=€²ŠjššÓ|Þ2fÍ[‚Ífã+ !rYÁR±³ B&ݱV«K3›¦ÐX墥+FßPŒš²ì¹éñúOßÎèèž'‡“™s2oáræ.\FQq™Õ¥ !&YÁ’Cuã³—N 1œê§ÈžÛ›>›j=™@ŒfU ïdíŒZölc×öMìßõÚqíŒig$D*Ø@(¶WN Ñm¥¨8Ç©Î[è FY`B.|~—UÖ°¼²†å¯9±�ѶÛùŠJ˜=o Í —K;#!òXAR‘£‚�‡^¥ÛÕÆ¬âåV—3&>·�êR=�$Cá%þÜ9€Nlgd~ðst>pB;££{ž¤�‘ù«°É^ÎW®ùÿòø¹°æ4%·ßŽÙu^zIºƒÑœ ¤ã)ŠrÒvFûwoeïÎW¥�‘y*·?�Ç(�Ô±ÛÜû™_ðÎ §¡x–Õ%�IS�›µ;ôF˜;%G;™ŸÄ íŒFö<íÞ¾‰¯­?¡�‘×WÄŒÙçeŽp_¼—+;çÒ„'WÐ� Šè ò•/ý~ó‹Ç­.iLªKœylÃ)¢ñ4Wþýç=~ÏÓÉÚÝóôèñ팭 ²¦ÁêÒ…g�ŸX£ ¢( ¦ xô/aÏÓ¨Ú™Q³“¨ÑŽ©€O™ŠK­C!7™ÂjHÝ�=oùZ,ãç?ÿ9×]w+V¬°ºÄs2³ÖþÎ=ƒ ¤“xs;£ã�p?r¨å¬ÚÅŒnÚÓ��2Ã0@½€CõѠ݈[­±ú2…È9H}½ýØívÒéÅ•~V\°ŠðP„Ï~ö³lÙ²ÅêÏIS½^ 7ÃÌ‘® Vyóîƒý=´ìÞzì÷£AÅÿrlÏÓÜÅç¯ÃL� #óØó%�Í_1ËñiìL~çu!rYARh8LMm5ùèGY·ùyöîÞÏ÷u'ÍÅ+­.mL¼NueN:à Jsx“ìd+«¨>á÷–=ÛØýúfölß|lÏõ;™RS†¢ž<é 3EwêY¦Øßmõå‘S :�ìv?xà^V_ºûÿ—âåç^aÓ¶µ4_’Û�™Õv�ƒ ºQ ¤sdw8�kgdÒÞ¶�ÝÛ7Q5»å4kEL¢Æa«Ë"çæ¬¿xøÇ¬¾4>oǵüõ�#m$­.mÌšê3sG}�ˆÕ¥äEQ˜:}kÞõÜn¯Õå‘— :�Ž7múTê¦U±õo{è‹çþo·•ÅJ¼™® ‘xzìO(ŽñªSÏðÏ#„x3 ¤ã\|Õ ö¼ÒFkïN«K3jÝô¢V—’WjmWb§þ_GÅN�ýmV—)DΑ@:ÎU×\I:¥óççþbu)ãbVmæ¶�Òøzuí:þøý­Dƒ™[» € ¦i’ ›4:>(+ì„8HǹôÒKpº¬ö¢éa«Ë³©Un6…¾`œ”nX]N^XÿÂøý¯LàH­í"¦;>Bµv•Ê¥¼ü_]üöö ìßÒbu™Bä$ ¤ã¸Ü.­lfËó{艵Z]ΘiªÂôj7†iÒŒY]NÎûÛ3�òøC÷£ªúôWYºâ }:u�Ulya'�D§Õ匙ǩQWæ$™6„âV—“S ÃàÑÿþëž{—ÛË'¿xMs�ögJÊ*¹ìš›0t�ǺS~ â¬I �Äê+—±{s-=»¬.e\Ì:zÛnP6Éž-ÃÐùõÿÊ+/ÿ¯¿˜Ï|ùŸ˜6cîYýì¥Wß@eMm-»xmã V_Š9Cé$®\sé”Î3ÏýÑêRÆÅÑ® ½A™G:étŠÿýÉ?óú–uø‹Kùô—î¡nÊŒ³þyM³ñ®÷ßÀÓ¿ûñ˜ü" ÄÙ�@:‰Ë/»§ÛÎÚ¿¼LÊHX]ΘUÙ)ñÙФ‰ÄSV—“ÕRÉ¿ü�»Ù¹u¥åUÜú~Ú¨Ÿ§iî"Î[ºšðp�gÿ«/Kˆœ �tn·›…+ç²åù=ôÆÛ¬.g\4�tmè”åß§�Gyà‡ßbÿî­TV×sëÿ¹—òÊÚs~¾ëßÿ\nþö4ímû¬¾Â}ÿúUûº™»à>þ…oãpº&ìõÞqã'p¹½l~éÏ>¸×êË"+I �Æ—_…Óm繿¾ˆaæþ¼‹Ë¡ÒPî"™6Îýåì窳½•û¿÷u†‚,ºàb>ú¹Û°Ûúš¾¢®ºîƒ™¿¾ÃÈý?OBŒ7 ¤Óðz<œ·b[žÛÍ@¼ÃêrÆÅÌ‘åßýC…yÛ®ãP üàv¡!–¬¸Œ÷}ü˨ª6)¯½ê²wP7e‡°qퟬ~+„È:HgpÉ•«2Ý¿·>gu)ãbÖH׆Î� ¤ƒûwò“ïßF4bå%×òwûPµÉ #UU¹áC�¢(<óû çþb!ƓҬ¹æ*þôÇüø�¶Üï Ôg#MŽN׆½;^åçÿþmñ—®¹‘wð³(Š2éu44ÎâüUo#‹òÇßýÒê·Eˆ¬"�tÍsPÛXÁKÏn&¡çǨbV]f”ÔW ½ívoßÄÿÜÿ]R©$—®¹‘kßs³¥õ¼ýÆ�ãõñÚÆçiÝ÷ºÕo�YCé V^±”=›Û8зÓêrÆÅÌÚ‘@ ä׆m›_ä¿ïÿ.étŠwÜô ËÃÀãõsõõ>ÖÁÁ0t«K"+H �…˯¾„tJçé¿ÃC?ÿ¦apýû>ÃÅW¾Ûê’ŽY~ñ¦NŸCOça^~>?¶1VHgáÊ‘åßÏþ)?6( L¯ÉŒ’úó´·ÝúþÀc¿úOEá½7‘U—½Ãê’N ( ׿ÿTUå/OþŠ¡à€Õ% a9 ¤³à÷±`Å,6?¿ƒáDŸÕ匋c]‚ù×FèoÏ<ÊãÝ�ªj|ðSÿ/KW^auI'Õ0­‰å­!�ñô#?·º!,'�t–.ºr%]C¼´íy«K3k<¨ töÇòªkÃ_žü|ì—Ølv>|Ë×X°ôB«K:­5ïþ^1Û^YKËžmV—#„¥$�ÎÒÕkÞÀþ�÷û�v•)N’ºA0·ºœ13M“§~€gÿð§‹�}þ[4/\nuYgäöøxû à÷¿ú1étá,ÅâÍ$�ÎÒ‚¹‹¨™V΋yÝL[]θ8ºÚn`(·oÛ†Á£ÿý#^zö \n/Ÿüâ]4Í]duYgméÊ+˜1{ý½�¬{ö «ËÂ2HgIU4V^±˜=¯´q¨o�Õ匋Yõ™Cû:zswaƒa<òàyåå¿âñúùÔïbÚŒ¹V—5*Š¢pýûnAU5þú‡‡ ôZ]’–�@…Ë®¾˜tJç‰??fu)ã¢Ôg§Ìog(–&‘HZ]Ψézš_ýôŸÙ²áyüÅ¥|æ+ß¡¡q–Õe�“šúi\xù;H%<õÈϬ.GKH �Âå—_AE] í}mV—2nŽvmåV׆T2ÁýÇÝìxm=¥åUÜúnšÕe�ÉU×}ˆ¢â2v¾¶ž=;^±º!&�Ò(”ù*ùÙú;XùîYÄÒa«ËM#óHý¹HÉDœÿú�»Ù¿ë5*«ë¹õÿÜKye­Õe�™Óåæí7~€'ú ©Tî�Z… ¤Q*rTÐk³º”qÑPáÂíPéL`W²±F,æ§ßÿ&ön§ªv Ÿþò?Q\ZauYãfñòK™9g!ƒýݼøçßY]Ž“Ji”Jì•tÅZ­.e\( ̨õ`š e÷òïðp�û¿÷ ÚÛöQ?u&·|å»—Y]Ö¸{÷?‹Ífçù?>L_O~œÃ%ÄÙ�@¥bG =±ƒ˜ädžңóHGú£¨“"ÃY øé¾IwG�Móøô—ÿ ¯¯Èê²&Deu=«¯¸Žt:Å“¿ý©Õå1i$�FÉ®:ðØ‹I1‰«Ëӫݨ*莉EˆÆ³ëÖ]` —ÿËWéé<ÌŒÙçññÏ—ËcuYêÊw~€Òò*öíÜ®m­.GˆI!�tJól©­7Žiš¤u“¿míã…׎ðòή¬èÞ×}„ûþï×ìïfî‚ øø¾�Ó嶺¬ gw8yÇ�Ÿà‰ßü„d"»o§ 1$�ÎAñH uGZ]ʘµõÆyrS¦™¹W—ÔMÒ†I`(ÎË;:-ís×Óy˜ŸüÛm úYxþE|ôs·a·;¬~Ë&Í‚¥2wÁûxþO[]ŽNéømåØ;‰vÒFn/Íýëk}¤O2ÒMˆ%Ò„'£Ï]*‰’ˆÁqËœ;µpÿ÷¾Nh8À’—ñþO|UÕ¬~»&Ýuïû4v»ƒÿü}ÝG¬.Gˆ e³º€\¤( ~G�D}ñvj=3­.éœ †N=_”JÃÞŽÓkR¤t §CÃa·árhhã°úAkß�cý!þÆ(ÓWÄ¡i øéÿü'ñX”•—\Ë»>p+Š’¥«-&Xye-_õž{ú7<þÐý|êKw[]’Fé•8ª$ºè‰µæl †‰©˜`žêÃÞ¤s Aç@â-ß±k .— —]Ãe×pØ5œNGæß�v —#óõ7S×þW07>Ɖ£3%÷øýѰÙTü6ð»5(…h| ½{_ÅLžz…¢ªÂÒeÓ™í,9õ¨+�"9ý-C› .§ ¯KCSTœNv›†Û‘YœátäΨ«¤¬’Ë®¹‰??þ?üþ×÷qËW¾[ðók"¿H �A±£EQ艷aÆiGÙÎfSi(wgñŒ•gút¥¥$z{á$ûœUÅ=½‘ ¦žò9Þ<ê ÇuBÑÔIçºÂ±Ì_gb·)x6œNN»ŠÓaÃe·a·«™ÅY0êºôêxmã ÚÏÁçŸ`ÖŒÙ%˜Åd}¢ qHc )v|¶2B©©NÊ� V—”… šF}4J¥ËuÂoù¦¢àª©¡òío?íS¼yÔu:£™ëJ§ zúQ—¦(¸n§ ›M=¶²Ð5 £.M×ùüòUõw Ù�ٱŜ.’—½½zê˜_C«H �Q‰£ŠPj€žX›ÒY0M“Ÿýìg<ñĸ].¾õ‰OP aD"ØKJðΟ�gÖøžúz®s]§uE™¿ÎÄ¡)¸]™prŒÖXF]οþ÷@÷±WŽŽ01ý-‰«?€QYÊŸO¥ ºQú1v�ò"µå²bOd ¤1*vTÑÙMwì óJdÈé†ÁüÇð—¿ü�Ç÷¿ýmš››­.똉u%#)8ÃòxM·Í†Ë©á°i8êÈ&ä7F]E�ûP½`žbAˆžÆ±öIâ7ÜzÒo‡¢IÖíèÂ02} uSêw²b^͸lvb,$�ÆÈg/Á¦8Œw’4â8T—Õ%e%Ã0ø÷ÿwž{î9¼^/wÞy'³g϶º¬s6£®p"óש\ؽ ¯~†QY4D28ˆê/Á¦½1격&vv“L�fºa%ØÑ:À¢¦ü9èPä& ¤1RP(vV3o§7vˆï«KÊ:étšý×eýúõ”””p×]wÑØØhuY“âlG]¦ÉÈm@ƒpT'׉$R„ãá¸N$–ÆÕ{æîë† k·v±Ძx]§Š¢($ÒúIF7LŽô…Y8³\Ví KI �ƒ{%ñvº£­Ho’H$øîw¿Ë–-[¨¨¨àž{î¡®®Îê²²Ž¢€ÏeÃç‚êâ“?fÈ;—Á¿õ€®Ÿòy ͆¿²â:Ñ„NÖœYÔptÔ�éìhñêþú©¦ŸL‡­ðº©‹ì’»g²ÄP²—�Á—3ÿ÷›�Ô‰ìåÏ¿$”°º<ËD"n¿ýv¶oßNCC÷Þ{¯„Ñ)6uü ¶²²7ö�ü]7MžlkãÈq·ÜŽŽºªJ�¬œSzÚÛq~·#¯ºZˆÜ$Ç@7ÓìÚ„a¦ß´)Ñ$mÆÙÐû¤Õ%Z" òõ¯�½{÷2cÆ î½÷^ÊËË­.+/ØKKiøÔ§¨~ßû(^±ßÂ…T\s -sæð|W÷ÝwÆIšÖzœ—�WŠÍöæPR°ÛT–Ω´úÒ„�[vc1”ìËüÖyŠCUCéþœn¼z.�·ß~;‡¦©©‰;_ßouYùEQð46â9naÈÕ ò§_¤µµ•?ýéO¼ý$‹/˜UL‘ÇÆß¶FÓè†�ªÀ‡.«g0&sGÂz2Bƒ”Ç0O½òIE#–ŽX]æ¤éééá«_ý*‡fþüùÜsÏ=F“DUUþþïÿEQøå/I 8éãf×{ùôµ üã��Ô•¹0LN:¢ Hcà±qºE²º©ãµ—X]æ¤8rä_ÿú×éîîæüóÏçÎ;ïÄã‘“iÖ¬Y\qÅÄb1|ðÁ3>~zufÏ\[oôŒ�b2H ��ß^ŽMss²{vš©QénÀ=²/Ÿµ··sÛm·ÑßßϲeËøÆ7¾�Ãá°º¬‚ô‰O|¿ßϳÏ>ËŽ;NûØé5nZ»chòI ²€ü1‡â$³=ö�±’ ;>G«ªÞcu‰®¥¥…¯}ík.¹ä¾ñ�o`·Ë|„Uü~?ùÈG¸ï¾ûÐO³g©¾Ü�Ë®Ò1�ÀÔå¶�°žÒï ” ÔQËÜâ ©t5PínäüÊky[ýǰ«”ƒ•vìØÁm·ÝF(bÍš5|å+_AÓd/‹ÕÖ¬YÜ9s8|ø0O=õÔ)§(0­Ê�iÂ`(fuÙBH �«®èAº¢pi^V×¼‡esY퇹¤æýLõÍCSòûƒyûöíÜu×]Äb1Þþö·ó¹Ï}NÚÎd EQ¸å–[PU•_ýêW œz?\cUf©7·ºl!$�ÎE0ÙÇ¡ðvTVU½·VduI“jÓ¦MÜyç�Äãqn¼ñFn½õV £,ÓÔÔÄš5kˆÅbüâ¿8åãŽÎ#u ÈÂa= ¤QJèQZB¯bb²¤üj*\…uÒ‹/¾Èw¿û]R©ÿøÇ¹ùæ›­.IœÂG>òŠ‹‹yñÅÙ¶mÛISâ³S곊¥‰ÆS£|!Æ—Ò(d:3l$¥Çiò/afÑb«KšT/¼ðÿöoÿ†®ë|úÓŸæ=ïÉÿE¹ÌçóñÑ�~È,pH¥N8�#£¤Þ Ì# kI �Bkè5"é!Ê]õ,*¿Òêr&ÕÿøG¾ÿýïð…/|�ë®»Îê’ÄY¸òÊ+™?><þøã'}ÌôêL õå¶�°–ÒYêˆì¥?Þ�Kó²ªêݨy¾háx�<ò?þñ�QU•üÇ䪫®²º$q–Ž.pÐ4�‡zˆÞÞÞ·Ìüùó¹çž{ðû §û„Ȩ­­å†n �N[à0­Ê…MSè F1¤��˜dH1=Äþá-,¯x¥Îüž?9rä_ÿú×éêêbéÒ¥Üyç�x<ùÀâÔÞûÞ÷R]]ÍöíÛY·n6M¡¡ÜIÚ€Áai#$&WARÚL±'¸ÝL1·h%S|ó¬.iBµ··óÍo~“þþ~–-[Æm·Ý†Ãá°º,a!‡ÃÁg?ûY~ò“Ÿ�Fi¬Éü‚2 m„Ä$+Ø@21i~…¸¡Ú5�å—Z]Ò„jiiák_ûƒƒƒ\rÉ%|ãßÀn·[]–ÈK—.eÙ²ezè!fŒìGŽX]š(0Hí‘]=xmE¬¨z ù{÷®]»¸í¶Û…B¬Y³†¯|å+hZþwžgïÖ[oÅétòÄO vâuiô§H¦u«K¤ i0ÑIGd?šêછòzÃ믿ÎwÜA,ãïxŸûÜçP”ü _qn*++¹ñÆ1 ƒûî»�Æj'¡°Ü¶“§à)š¢eèU.(¿–g•Õ%M˜Í›7sÇw�ǹñƹå–[$ŒÄ)ÝtÓMÔ×׳{÷n†Ú_ ’® bòT ¥Í{‡6¡£3·dS}ùÛÅzíÚµ|ç;ß!•Jñ¡}ˆ›o¾Ùê’D–³ÙlÜrË-üé±ÿEOÆ8ÔÇï´º2Q( &�LLö�,bp7² ô«Kš0/¼ðßûÞ÷Ðu�O}êS¼ï}ﳺ$‘#/^ÌêÕ«¢o÷3Dâ:‰<žaÙ¤`éPx'Ád>[)++ß�·‹ž~úi¾ÿýïð…/|�믿Þê’DŽùä'?‰Ëå¢uûóD�ðÌký´´00·º4‘ç "�úãG芶`S쬮º‡æ²º¤ ñ»ßýŽûî»EQøâ¿ÈUW]euI"UTTð¶koàÀ†ßÐH°óð0vt³µ¥ßêòDËû@Ф‡8Ú À²ÊwP䬴º¤ ñÈ#�ð_ÿõ_Øl6¾úÕ¯rùå…q­¡hšaÿr<¥u„ÓÛ’9¢B7M:ú´÷…­.Q䩼¤´™bßÐ& 3Msñj¼s­.iÜ™¦ÉÏþs|ðA·ß~;«V­²º,‘öÆPf,» EQhÛò©Df“¬n˜ì?2du‰"OÙ¬.`¢˜¦É¾à&âz„:OóË.²º¤ ¹ÆŸþô§<õÔS¸\.¾ùÍo²paþŸá$ÆW8–&I3N¥Ùq8‚i@QõL*¦ŸO4ØM:ÁîÌM�ËYIbbäm  ï`(Õ‡ß^ÆòÊëònƒaüèG?âÙgŸÅëõrç�w2{öl«ËYÈ4a(’"ÉO0œ"N3N §Ié§îê=cùß¡Úì(Ê7S4ÙË&&H^R_¼�®ØlŠƒ «oÀ®æ×FŠt:Í÷¾÷=Ö­[GII wÝu���V—%,d&Ã1�`8I0¢Œ$ †u‚‘4ýÃIÒ§U…¯-ó—ÏN‰ÇŠÉÚ�AtÃD³ŸøÿŽª@m¹×êËy*ï)’¢ux++*¯£È^auIã*•Jñ/ÿò/lܸ‘ÒÒRîºë.¦M›fuYbèºI(þFèô 'JŒ¤Ц9ÕñEª’9žÜçqPê³Säuàqi¸�\ŽÌG€i€nfFS&0µ:I{oô„ ÓTphóK­~+DžÊ«@J ö7` ³ äê¼³¬.i\Åãqî¹ç¶oßNUUwß}7µµµV—%ÆQ§ ·KÃípàvÙðºìx\§þßn§†ÓéÀë²áqÚð¹íØ& t„È&yH}ñvºc±«..ª~o^-bäÛßþ6‡¢©©‰;_ßouYïœ( >—†×ãÀë´árØñ¸3¡ã÷8ÐTYÁ& WÎR8¤5”i•¿¢ò�øìù3áÚ××Ç7¿ùMººº˜?>·ß~;OþžÝd5Ó4I¥RÇŽu?çE*øÝ^·¿Ë�ÇíÀ32ŸãvÚ�UÓBœ\NRÊH°gh†i° ì2j=MV—4nº»»¹ýöÛéééaéÒ¥|ãß8öA)Î]*•¢½½�ÖÖVZ[[Ù»¿…}ûdþ}ÿ^>õÅ;Y}í‡Ï¸ˆÀaWñ¹lx�vœÎ7œi�âÔröÿœÌ"†M¤ô8õÞ94¯´º¤qÓÞÞÎí·ßÎàà Ë–-ã«_ýª„Ñ(„B!8p쯽{[ØßÒBkëº:�`ƱÇj6;¥• ”×LcÉeï%é™J[o¦«µÃ¦âóØð:l¸œv<®‰]D D¡ËÙ@:ÞÆpj€b{%Ë*ógÃ�øÖ·¾E(⢋.â+_ù š&Ëlß,å´¶¶²oßö8ÀÁÖt´:á±6»ƒ¢²ʪ¦pÁÜÕT54Q=e6eUS¨«›JI± ·ÓŽËi—EBX('©/~˜žXÕ™éÄ äÇèaÿþý|ûÛß&sÕUWñùϾ �ìܹ“]»vqà@æöZË�<ÐB4rbÇi··˜²ê)”5̧iéµ™®žJyÍT¦L™†ÏãÀí´ã–EBd­œ ¤Pj�¡­((,¯º>o1ìØ±ƒ»ï¾›X,Ƶ×^Ë­·Þšuaôì³Ï¸é¦›Æåù’É$GŽ96Ê9>tZöí!?ñ@¸£¡3çü«¨ž2‹²ª©”UO¥²v奥¸]vм6¼.§,""åT ¥Œû†_Á4 •]N­{¦Õ%�‹W^y…{ï½—d2É�7ÞÈÍ7ßluI'xíµ×øâ¿È¶mÛxüñÇGõ³'»µ¶¿¥…¶Cmt´zË|Nqy-eUSXtÑ{2£œ‘Ði˜6›ÒR_f>ÇmÇã�EB䛜ù?ùè"†¤eª¯™ÙÅ+¬.i\¬]»–û·C×uÞÿþ÷óÁ~Ðê’Žiiiá _ø[¶l¡··—Ù³gsÉ%—¼åq§ �öCOx¬Íz*ÕSš™±xͱ[keUS¨®kÀçuáµgBÇ;Á�„Ù%g©5¼5³ˆÁQÅo·ºœqñ·¿ý�ïÿû†Á'?ùIÞõ®wY]�YrþÅ/~‘uëÖÑÑÑqìë†aðÀdB§¥…ýû[imÙO4zŠùœº·†N]C#Å>'ng¦õÍÑùYD „ȉ@ꎤ7v‡êbuõ hŠÝê’Æìé§ŸæþûïGQ>ÿùÏsõÕW[]CCC|á _à©§ž"¼åû---ÜrË-hš�’Š:Êj¦±ð¢wQV=�òš©”×4RY3¿ß‡×mÇã°áqÉ"!ÄÙÉú@ %i ï@AaUõ»ñÚJ¬.iÌ}ôQ~ùË_¢ª*ÿðÿÀW\aIÇw"øó_žãËŸýÑHó-NïùÌ?±pÕµø}žLwi—¿G:!Æ.«)m¦èˆìc(Ù‹�Žß^N0Öƒ‰Îâò+©r5Z]â˜=òÈ#<øàƒØl6þñÿ‘U«VMèë�õqÎùÜúO�±ÛZö¼úÑp€èð ¡áR‰Ìj·d"Ê`ë˼ûk_²úmB䡬 ¤hzˆ�—0L“L þx:‚‰I�g³Š.°ºÄ11M“_üâüþ÷¿ÇáppÛm·±dÉ’qyî1gà¶göç8m,™½œ®Y�×};vM%�°cÛfžÿó“ìÚ±…�¾Ö¿øg^|öi.y[~Ìã !²GÖÒÞ¡Mèfꄯ™˜€I$8·'µ€iÖ®eèÕWQR™ëQìvZ4�'ž{—ËÅm·ÝÆ¢E‹Fõ¼çrœ�ª(ø]6|^n‡ §Ã�w‹Ü/ËV]ƲU—ûZç‘—j !ÄxÉŠ@ §ƒ¤ŒÄ)¾«K‡&»)qÔX]êi™†Aç/I²·ÌLœ˜É$�¦É—Î;�Ú}ˆ9ÍÍoùÙs=Î@SÀï¶á÷ÚñØ5\NÇÈám³ˆ ®AŽKBLŒ¬$ÝH‚¢À)Úù+¨DÓaJ&°C�n˜¤Ò&6MÁ¦�Û‡xpýzýý('Y * SKJð ÑÖÕq6 ŠÜ6J|ü^n»§ó�[m²ˆ@‘²"�š›S~†iâP'æ tÚà¹íƒlm £¨&¦ Ó«=\¹¸ŒRßè–—oÝŠ¢ŸzÎFI§éÙø*OwU¿å{.»J‰×Žß£�,“¶ãrرÙí¸YñŸI!&TV|Ò¹5?nÍG$=„ùæa’NÕM¹«vÜ_×4á7k{è$0L“‘µ´vÇøå_;ùÄÕõyÞú�lAßP’U‘gêËí2ÌmðâsÛð»x=v\º¡¡›!DÁÊŠ@h*:Ÿ×/ž°°AU44l\X} ã_êPo”î`‚Ô›’À4MºÉ“ú˜ßè;ëE»—¢ÄÐi_Ó]YÎâ¦*¢Ç­ßHê!DÁËš@rÛüÌ+]Íëƒ/ )vŠìeT¹™[² ‡êš�×Üy(JêábÐ>§}àĎӪŞ‘î·�b��R¿oÇ…¤Ÿ{í“:¦¦9ïRŒB!Þ$k `0Þ À¢ÒË™Y¼tÂ_/mœ~h¢(°bN1.» Es`³Ùp;Oþ–…‡ƒüð°Ê¡pq]Ý[nÝ™šFzþJŒÚÆÉx+…"çdM ™˜ôÆÛ¨óÍš”׬*v²÷Hãs7Õ%ªËH¦Oÿ<ÁÁ>øÁíô÷v²uÖ|οü&|-ÛPº111*ë3aT1þó`B‘/²&�B©RFŒrg=nÍ?)¯¹h†Ÿõ{‚'�Ò4•iµ¥g £Áþøáí öu3cöy|ìïoÇætŸÒdÅÛ(„9+kúý&º¨÷Ì™´×ô85®\Z€(ª‰]SPU˜3¥˜êÒÓ/5ïíjçþÿû5ûº™{Þ2>þ…oãpNÌ|—B们!™ù£ïäÜ®;jסÌY> ¦{ñ:�D“PUê=ã)¤�í­üüß¿M84Ä¢ .æ}Ÿø2ªz¦EßB!N%+)”$®G)uTãµ—NÚë¶÷Åië‰ási,™YA0vvÆ#mûùù�î  ±dÅe¼÷£_”0B`š&iÝĦ©ÒAådE yæNê뾸#Ó´uQSéY‡Që¾üò?ï&�±ò’ky×nE‘?yB´TÚ`Û�~z£`‚©ÀôÚ"š§•¢ÊçÃYËŠ@ŒwPç�=i¯¹¿3B{œb��Ò"ßYýÌÞ¯ò?÷—T*É¥knäÚ÷ÜlÉû%„ȉ¤Î‹[��Ð Ž5Â7ápÏ0‘xšås«¬.1gX¾¨!œ’0"Ù+(r”OÚë¾´3d/œÍo0»·oâ¿ïûŽ„‘âûÛH¦tÞ|*K*m2ŒÑˆZ]bΰ|„tt1Ãd®®ÛÝ¡'˜¤Ìo§ºüÌKÌ·nú¿ýå0 ƒw¾÷“\ô¶wYö~ !¬cWÁ0Ó¤ SOƒap¸/Š~ŠÖfIÝ g0BUéÄ4‡Î7–ÒÀÈíº)¾É™?2 ƒw Ð4¥ìŒ�›Ö>Ãc¿úOÞó¡¿gùEW[÷f !ÆU:m iRiƒtZ'©ë¤Ó&ɤN"m�L¥‰' âIƒXJ'žýᔉ”ô ;[–R,"¦‡ðÙJ)vTNÊk¾~(B œ¦¢ÄAÍ~kYÿÂxâ7?AQnúè?°tåV¾]BˆÓH뉔A:¥“ÖuÒ†A*­“N$Ó:±¤N2­ ˜xR?Ý©7'åvªxÚÈßUÜN�Öî¡ØÉÛ�) 4”9Q8åqoâ8–Ò±Õu¾ÉYÌ ë&ëveVÖÍi(;ícÿöÌ£üñ±_¢i6>ø©dþ’UV¾UB”Ì�™™@IézjdÄ’L¡&IÝ ™4H‘Xšp"ý–9œ3ÑT—SÅåPð»lxÝ6\—MÁí´ár(ø\^·†ËnÃëTPÕ·N»·vÇøÝúÒ'éøbš�HÔ–@gÐêw5ûeG MÒrïW[‡ŽêÔ•»)/vŸòq~âyîéß`w8ùÈ-_göü‰oô*D>K¥ âÉôHȤ #e’H§I$Ó¤t“dÊ ‘J“L™DGy&‹¦*x]™pqÙ5ün[&HŽ —]ÃçÖðºlxœ*š:>˱gÔ¸¹h^ k_`(™“¶Ìs›À¶ƒa†c:«›+NÊ~ÅÓ±,�z„hz·æ§Ô9ñMG“iƒ »ƒÌ¬?ùæ[Ó4yêáX÷Ü“8œ.>úÙÛhš»Èª·Hˆ¬¤&‰¤~,`’º�>rk,žÖ‰ÇuÒ†N*¥“HÄRƨn�eÂE;".‡ŠË¡áw«ø\ö¾ît(¹í8íÖ.^9§„9u^öv„‰$ j˜̨v3Móèº^vÇǺX½ ƒÑ�D]H, ¤þ‘ÑÑd-fؼwˆhÂ`J…‡R¿ó-ß7 ƒßýÏÿÇ+/ÿ—ÛËÇ¿ðm¦Í˜Ü�ºBL¶ão�Å“:ñT&XRé4ºaK¤I$ RºN2iŒzäಫxÝê áâr¨ø�6|õ„pqÙmøÝ¹9Š(õÛY9÷Ä_v]�›¯¬ãw/÷p¤?Á__íâÂóªp9¤çåÉXHƒG—{»'~¹w<©³yÿ03Þ::2t�‡ü!¯m|¯¿˜OþÃ�ÔM™aÕ[#Ä99aÞ%mOéÄ:é´NJ×I¥Mt]'–Ò‰ÅubIƒÑNµkª’ ·mä™v¼‹Ï­ásiÇÂÅçÒ ¾…ŽÇ©ñ�KjùÃæ>vµGx~K7+æVRV⵺´¬cI %õáT§ê¡Ü]?᯷ao�xÊ`Z�—"¯ã„ï¥Ó)~ýÀ¿²sëüÅ¥|ò~šo‹Ǽ9\2s0:±d]×Ié&z:2±dŠHÜÀå’±L¸hcžÔg¦i ׯ¬¢Ô7ȺÝC¼´³—ùÓŠ™y†ÅU…Æ’@HŽŒŽ¼sP˜Ø_ŸÂ±4¯ì¡¨0ëMsG©d‚üOìß½•Òò*>õ¥»)¯”CôòÕðP€_üø_YsÝß1gÞ¢IíAøæIý¤n�J$R)’É̲ä”a�Jê$S&±Ô9Lê;5K&õÅÙ»xAÅNžÚÔÇÎCCD: fTH?ÌÖÒÈQåS&¡;ú=AÒºÉì†"<®7&ãñ(¿øÑ�:°›Êêz>õ¥»).­°â퓤¨¸”—×þ•_ÿò?©¬®cÊ´™¼ãÝàÒ+߉Ï_tÖÏs²IýT*³±2žN“L$ ƒT*Mj$\ò}R_œ½æ)^ün�G_îá`w˜H\çü¹UØ5ùo8é�”2„S8T7®©úZCÑÛ[C¨*4Öûz,æçÿ~ímû¨ª�§¾t7EÅ2t.wýëOùäû®¤uÿnZ÷ïfÝ ÏPY]Kye- –¬âòw~�º©sH¥utC'7ˆ¥uR©4É´I\&õÅ8h¨pñÑ+êxø¥zƒ1Önë`ys >wa¯À›ô@HtbõžÙ~?zíÎ ºó¦árd.5<ä�~‹îŽ6¦5ññ/Ü�×wö¿‹ìõæy—X2M_?�Á~û  ¢›oÜI§Stu¦«ã0;¶n䱇~ŠÓíç’ë?Íê·ü-¯!“úb¼”úì|ôŠ:{¹›C} ^ÚÞÁ²¹5”î ¼I¤cÍT'¸;Ã@(ÉÎCaì6•)5%ûøÙ¿E_O�MóøØß —[šf£7‡K0¤··—��~�>BÁ Á@&d�†‡‰…‡ˆ†ƒÄÂA¢á!bá æ(î•)ŠJii9ïzïÍ|øŸ§¤Ø-“úbB¹*ﻤ†?o`ë�0ëwv³¨©‚)Ugw$N¾™Ô@J›I†RýØ'Õ®Æ }­_`š0wJ1N»F` —Ÿþà› öu3cöy|ìïoÇá,ÜßD&ÛÑIýp8B`p�Áà C�   ‰  vèï!&":<ˆ®§OûünoE¥ÕøŠJ(oœEIq1Å%%”––RZVNEyå¥%ÔTWpûW¿Äë¯o?ö³eee455ñå/™÷¾÷½:bR©ªÊ5K+©ð;ùëÖ^ÛßG(šd^cáM#Lj â]˜¦I�· U™¸ûäÝ�{;¢¸� UEôuá�ÜÎPp€¹ .àC·| »Ý1ö*Pºa2<¦¯¿ŸÀà �à �À ÃÁA‚�A†ƒBá ¡`�h8@` —á@/±p�t*yÚç¶Ù�¸½EWÔP[7 I þ¢ŠKŠ©(-§¢¢Œ²²R**J©*/§ªª”Y�Sp9Ïî�r<ç+ѵµµÌŸ?Ÿ»îº‹U«¤W¡°Ö³Šð»5žÜÔGKDZDšÅ³* j5ä¤Òñ˽'Ò ¯g¨6O-¦¯«�Ÿÿû· ‡†XtÁżï_FUeÒø¨SíÔîq`߆ƒƒƒDBBÁA¢#·ÃÒ©Ä)ŸSU5ܾb<¾ܾJʪ˜Ú8›¢²rJ‹K).+¥¼¬‚ªŠrjk*©®ª ª²œŠò¢ ŸÔ¿ÿþûâýï?ßùÎw˜>}ºÕÿ „8fNƒ—Ÿ�G^ê¡£?B4™bÅÜöÂøÌš´@ÒÍ4CÉ~TÅF�gâ>ŽôÇië‰ási¨ñ^øáD#!–¬¸Œ÷~ô‹yF'Û©ŸHê¤Òi à •2Iè:É„A$ž&‘>õfʧŸø {^}.3bñãöãöQRÙ@yE5Uµ”••R\RJYY åe¥T”WPS]Fã”ZÜ.[VNê¯^½š}ûöQZZ:ö'bT—8ùÈÛêùÝK]t“¬ÝÞÉòæüžü_�7i�Htc˜: Þ¹hÊĽ±Û‘Õ9z¸ÿßþ/‰xŒ•—\Ë»>pkNm>;éNý”N"™B7ŒÌ!b)�¤a‹ëDiÌsh¿t3å›wê_øóÿ¥Äï¡ÈcË«Iý .¸Àê„8£"·Æ/¯ã‰ ½´tÅxéõ–̪¢¦,¿aMZ ½qÔÄø®®K¦ Úûâ¤t“`$E{_œôÀ>þ÷¡Ÿ�J¥¸ôê¸ö†�MÖežÒ[Úï§ Òºži·ŸÌ´‚IêF&d’:ÑQžL©© .‹Úï !Ɵærãêþ¶c€ {†yeO/ g–2µºxìOž¥&%� Sg(ÙƒŠJ�gæ¸=ïþÎOnì2g�¤t“ÁŽìñèzšËÖÜÈ5ï¹yܯçÍ;õÓ†�ž6HééLC˸>²{_'Y í÷…ãOQà²óÊ)ñ:øó–~¶¶ K¤™=¥<«n…�—I ¤@²ÝÔ©u7aW�cB '˜àñ }¤õ7>éûmaÿºÿÆ4M>òÑ�±úÊFOÿ<ÇßK$3�‘“iC×Iñx&xÉÌ×G;rÙ©/„›Å3ü{4~¿¡—½íÃDc)5U¡æY»¡I ¤Á Ø ûò®à aÔ³ÿelø-ŠMËoÂ5å"ú‚!†Ã:áDæ\—h*Ó¸2‘H“ÐMâ‰Ñ·�q;U<mäï*n§†ÛaÃíRpÛ3»÷Ýv·KÃãÔdä"„Ók<|øòL»¡öþI½“•Í5˜Š¥�« ¿Ó4$zPQ¨Çù£Ãý±cÿ¬§´oEUhºðCTN¿€�‡#ì<9ís¸ì*nçÑPQñ8UÜv �Ó†Û©û»Û¡ávfF!¬RYìà£o«åÑu½t &xöµ®=¿–4ôÑ�>’•&<�‚É^t3Eµ»‡:1�4»“yW~–øpeSÎÀïÖ˜[ïÁíÒ2!ãÊ„ÊÑ€ñ8Ôœ_1&„(<>—�]VËS›úØs$Âï7tòŽe•y½ † †ã`BY‘ »-·>ã&<�Ž­®óŽïqàS+ÜìëŒ[,à)®ÁS\€Ý¦pÙ‚2æ7f?(!D~³i ï^UÅ ;Ù°{ˆÇ7ô2£ÆM[w»M!­›ÀÔ* f”£æÈ ˆ �OÓ4 &»¨s7�ës_¶° ›öÖ7YUÁëÔ˜;EŽBä·Ë”qýÊJTLtÅÐM“xÊ m˜†É‘Þ¯ì鵺̳6¡�4œê'e$©tMÁeßÑJ©Ï·.¯£ºÔ�Í–Y­©&SÊÜ|øò:4-7~#Bˆ±˜7Ňf;ùç]Ú0è ÆŽ&Gù¬Ö˜Ð[vƒÇ6ÃŽïíº£jJ|üÊzቔ�שá÷äÏŠ!„8“�á$¦®'_Õ `28§È“ý ¥'ìÓÛÄd Ñ@­wÖ„^D©/ÿ{< !ÄÉ&˜Ê©—Ø)Šš3mÓ&ì–]85HʈSæ¬Ãk“Y…b"”ûm§]´`Ån«Ë<+Hñ‘ͰãÜ»N!ÄTUåòEe'�7×4˜RéÅëÊ�©Œ ¤ÁäÑåÞ{ö‘Bº%3Џöür”‘[w6MAS¡¾ÜËy3Ê­.ï¬MHl†SzŒG5>»œ;#„mÁ4?¯ì¦;˜äây%8Ü~œ9v°ß„Œ�ÞØ +£#!„˜ ºnÒ7œÄaS¨­,ɹ0‚ ¤cÍT%�„bRt%Ñ ¨*qNX]͹÷@Ф‡ˆëŠlåÙsçÞ¥Bä²ÎþL û&¦gèd÷@:¶Ö'£#!„˜,]ƒqüîñ9sÎ ãHñÌfغ êÎ „â­:™’_FH1=LTÆk+¡ÔYeõµ !DAˆ' ‚á4^—†Û‘{‹Ž×@ŒwP/£#!„˜4™ÑQEQ`œ©dþhŠob{× !„xC×Èíº"_îÎÁ8RB�MáV}”9ë­¾.!„(�1ü $™Ûu²ºN!&W×`æ¼£_ö1q:ãH�£›aeþH!&M œ"–4(óÙ±izæê„—ê“FŒáT§ê¡ÂÝ`õ5 !DÁèÌÌ•ùsûvŒS &Žî=š…Bn%„ù c$�|^ $ã=Lñ5[}=BQP:G–|—øs{É7Œ2�Nv ®jj §z±«.*]S¬¾!„(ºaÒL iàwÛ­.gÌFH¦n››â¤ØQEÜŒ`bRïž…ªäîa!„È5½�º~×I ¹fTô©ªJ¹³Ž»UùÚÀŸ¨÷ÊQåB1™:™åÞÅ9¾Üû¨1Í!%õ8}±ÃØUîéV_‹B”Αß¹|äÄñÆH]Ñ ê¼3±©rºBˆS8º ¡4–|ÃéHtõnéÎ „“)žÔ „Óxì.GvF;¯uÎ�”6’ôÄÚÐÕÞV_·B”ΑvA¥%ù1c¤®Øt3M�g&v%Þ!„ÈG;4»ÝV—rj¦9ª‡Ÿs ‰ì Á#·ë„b²]ÐPR”ÅóG“qË.m¤é޶¢¢Që™iõ% !DÁéL (PìÍŸ;TçH=±VÒf’jw#v5‹ÓY!òP0’&š0ð{Øm¹Ýáûxçt%Go×ÉfX!„˜t�ý#·ë²ü„Xs¢ç� Ó 3v…Z�U.„“­kdþ¨4Ëi´ÝŒFH=ñƒ¤Œ8•®i85�Õ×+„§c¤ePÖoˆ5'xQCGx ^Y]'„“Í0LzƒI4üž,ïð=‘#$EUèŒf©ÎÛdõ¥ !DÁéJ’ÖMJ‹ò£Ã÷ñFHÓ<$ŒÎÜšßêÚ…¢àtõ�ô¯Ë�ߣ\Ó0º@ª]PÈê:!„°JçÑ 9Ðá[a¢VÙ)PÛì ^º3!„%:GGHY¾ &®SCe£w‘ƒRG {±Õ—)„'žÔ ¥ð8UÜÎììð}¢ !M]T@½o®ÕW(„éhCÕº2ר÷øL6Eõ"»³?¼|jævݾy?áÁY}­BQp<åÓ¨lºˆ¶îç±¶MÀñÝ”cÿ®(™±‰¢(o¤Œv¥Áh“oäù"áð¨~ô¬é/?ÚIi½‡Á#‘1½¡B!ÎM(´ƒž¶V—1as´Í†„Bˆ �?mb…Bä4 $!„YAI!DV�@B‘$�„Bd $!„YAI!DV�@B‘$�„Bd…ÿÃYT| ¹%tEXtdate:create2025-07-09T15:55:43+00:00r¬5£%tEXtdate:modify2025-07-09T15:46:28+00:00í ´¡(tEXtdate:timestamp2025-07-09T16:08:22+00:00 ŸåÏIEND®B`‚doc/design/index_validation.md000066400000000000000000001126351524103652300167500ustar00rootroot00000000000000

S2ShapeIndex Validation

Better living through invariants
Provide the ability to validate shapes in an S2ShapeIndex according to one of several correctness models.
Author: Sean McAllister
Contributors:
[removed for privacy]
Status: Final
Created: Mar 21, 2022
Modified: Jun 22, 2022
Self Link: [removed]
Context: [removed]
Visibility: Public
## Goals Build functionality to validate the geometry in `S2ShapeIndex` instances with a configurable model of correctness, with an ultimate goal of providing functionality to replace `S2Polygon` IsValid, and implement an `ST_IsValid` predicate. ## Motivation `S2Polygon` provides an `IsValid()` function that checks a number of invariants that are expected to hold. `STGeography` is valid *by construction*, and `S2Shape` doesn't have a validation function at all. We don't have the ability to take an arbitrary S2ShapeIndex and verify it meets the constraints to be treated as a particular geometric object. We'd like to be able to take an `S2ShapeIndex` containing arbitrary geometry (points, lines, and polygons) and validate it as a single unit with a configurable model of correctness. The goal isn't necessarily to validate the consistency of an index itself, but rather to validate the geometry *in* the index to verify that it can be used in situations where e.g. an `S2Polygon` or an `STGeography` are needed. ## Background ### Why Validation The purpose of validating geometry is to ensure that it meets some set of constraints that let us reason about it and make statements such as "point X is contained in polygon Y" robustly. It's beneficial to think of geometry topologically, as sets of points that divide the domain they occupy. We can define multiple partitioning schemes (such as points in the interior, exterior, and boundary). But the simplest mental model is to view geometry as point sets partitioning space into two pieces: points that are part of the geometry and points that aren't. In the most lax sense, valid geometry is just geometry where points are unambiguously members of at most one of these two sets. This immediately forbids polygons with self intersecting edges:

Not least because determining actual points of intersection is numerically difficult, but because we have to make up an arbitrary rule to determine whether the overlapping regions are part of the interior of the geometry or not. Note, however, that polygons with multiple disconnected interiors are allowed under this definition, since there's no ambiguity:

For S2, it's always possible to rebuild geometry with e.g. `S2Builder` to remove any degeneracies and ambiguities such as duplicate edges, reverse duplicate edges, or polygons with overlapping interiors, but this can often be cost prohibitive, especially if it's known that the geometry was originally valid. We would like to be able to simply check that it remains valid according to a specific model of correctness and continue using it. Validation lets us verify our assumptions and operate on geometry with confidence. ### OGC Data Model The Open Geospatial Consortium (OGC) defines a standardized hierarchy of geometric types including points, line strings, polygons, and more specific subtypes. It also defines a set of "Collection" types which aggregate geometry together. The type hierarchy can be seen in the image below, which shows the types and their dimensions.

A 0, 1, or 2-dimensional `S2Shape` would correspond to a `MultiPoint`, `MultiLineString`,` `or`MultiPolygon`, respectively, and an `S2ShapeIndex` containing many shapes could be any of the above, or a generic `GeometryCollection` containing a mix of dimensionality. Note that the OGC types specifically require linear interpolation between points, which means that edges are "straight lines" in the chosen spatial reference system. Using straight lines as edges has shortcomings when working with geographic data, which is referenced to the surface of an ellipsoid. To address this, the `Geography` type was designed, specifically representing edges as geodesics. #### Validity There are some geometric configurations that are simply not allowed by the OGC spec. Beyond the basics of requiring points and vertices to be non-infinite and non-nan, there are restrictions on some types we must check for `ST_IsValid` to be true. `Points` and `LineStrings` are inherently valid (though not necessarily simple as we'll see). Polygons, however, have several restrictions to make them topologically reasonable: - May not have any cuts or spikes as they affect closed-ness. - Chains must be closed. - Chains may not cross and chains may touch but only at a vertex. - Polygon interiors cannot be split (i.e. they are one connected point set) - Chains can't contain each other (i.e. they must face each other properly). - Said another way the winding number of any point must be 0 or 1. Cuts and spikes in a polygon are forbidden because they can make the geometry an open set (i.e. not equal to its own closure):

Split polygon interiors are also forbidden, and interiors can be divided in non-obvious ways that have to be detected, such as a single edge crossing the interior:

Or, being split by a chain of connected holes:

#### Simplicity The OGC Simple Features specification (SFS) differentiates between geometry that is merely *valid* and geometry that is _simple. _Simple geometry is always valid but the converse isn't true. A simple example of this is a `MultiPoint` containing the same point twice. This doesn't qualify as *simple*, but it is *valid*. *Simple* geometry is constructed in such a way that it's possible to unambiguously categorize every point as being in the *interior*, on the *boundary*, or in the *exterior* of a feature. These three categories of points are used to define relationships between different features using the dimensionally extended nine intersection model (DE-9IM). For the built-in OGC types, the rules to ensure simplicity are summarized here: - `Point` - Points are always *simple*. - `MultiPoint` - MultiPoints are *simple* if no two points are equal. - `LineString` - LineStrings are *simple* if they don't pass through the same point twice, excluding the endpoints for a closed LineString. - `MultiLineString` - MultiLineStrings are *simple* if all their elements are simple and intersections between any two members occur on the boundary (endpoints, closed LineStrings may not touch) - `Polygon` - A *valid* Polygon is *simple*. - `MultiPolygon` - MultiPolygons are _simple _if all members are *simple*, no two members have intersecting interiors, and any two members that touch do so at a finite number of points (i.e. not along an edge). Ultimately, we'll want to be able to determine whether geometry is *simple*, *valid*, both or neither. ### STLib #### Validity The OGC spec allows `GeometryCollection` subclasses to place additional constraints on the overlap between elements, but PostGIS elects not to for `Geography`, instead treating it simply as a regular `GeometryCollection` with an appropriate spatial reference system id ([SRID](https://en.wikipedia.org/wiki/Spatial_reference_system)) set. [Simple](https://github.com/libgeos/geos/blob/f2784527e9b397817ccdcba207bc17b21ea0c976/include/geos/operation/valid/IsSimpleOp.h#L52-L94) and [valid](https://github.com/libgeos/geos/blob/2b1173ffb6631762cc438dee5ebc67b65b83ad78/src/operation/valid/IsValidOp.cpp#L250-L259) checks are applied independently to each member element, and elements are allowed to overlap. This presents issues when we wish to process the geometry robustly. ##### Higher Kinded Regions We can classify a particular pointset by the [winding number](https://en.wikipedia.org/wiki/Winding_number) of its points. Points that are in the exterior of all geometry have a winding number of 0, and those that are contained once by a polygon have a winding number of 1. Additional nested containment increments the winding number each time.

The DE-9IM models relationships between regions of winding number 0 and 1, and the boundary between them, for a total of three region types. It's possible to extend this model to accommodate regions with higher winding, but the number of relationships to track grows extremely quickly. The DE-9IM has 9 total terms and thus 29 = 512 relationships. A model supporting winding 2 regions and additional boundaries would have a total of 6 types of region, for 36 total terms, or 236 = 68,719,476,736 relationships. Modeling winding 3 regions as well puts the number of relationships over 1030. The vast majority of these relationships do not have a meaningful name in human language and so aren't terribly useful when trying to do "real work" with geometric data. Even the DE-9IM only names ~10 of its 512 relationships. In the interest of tractability, it behooves us to limit ourselves to regions of winding 0 and 1. To avoid needing rules for higher-winding regions, STLib adopts a rule intended to disallow them altogether. Geometry in a particular `Geography` may not overlap in such a way as to have redundant information. Representing multiple overlapping layers requires separate `Geography` instances for each layer. ##### Dissolving To enforce this, STLib operates on *dissolved* geometry, which is a canonicalization process that removes ambiguities and redundancy in the data. It's implemented as a cross-dimensional *union* operation that merges geometry and only leaves geometric features that add information by extending the covered point set in some way. For example, when two polygons share an edge, the extra edge adds no additional information and raises questions about the closed-ness of the polygon, so it's removed:

Sharing a single point on the boundary, however, does not affect the closedness of the interior, so it's left unmodified:

When a higher dimensional object overlaps a lower dimension object, the overlapping region doesn't add any additional information, so it's removed, with the lower dimensional object being split as needed:

#### Simplicity These rules are intended to prevent overlapping geometry, so that a given `Geography` instance partitions the world into two sets: contained and not contained. In general, this means that elements of a `Geography` must be *simple*, and we also disallow features that don't extend the covered point set in some way. Additional constraints that STLib requires: - Reverse duplicate edges aren't allowed either since polylines can't overlap the boundary of a polygon and polygons can only touch at a point already. Duplicate edges are always forbidden. - Points may not overlap any other points or vertices. Eventually, we will allow polylines that self intersect as in a GPS track, in which case we will have to have a separate check for self intersecting polylines to verify simplicity. ### S2Polygon Validity [S2Polygon::IsValid()](https://github.com/google/s2geometry/blob/master/src/s2/s2polygon.cc#L225-L232) does the following checks: - Vertices must be unit length. - A loop must be empty, full, or have 3+ vertices. - A loop can't have duplicate adjacent vertices. - A loop can't have antipodal adjacent vertices. - Loops can't share edges (no duplicate or reverse–duplicate edges). - A polygon can't have loops with zero vertices. - A polygon can have the full loop iff it's the only loop. To ensure the polygon is suitable for point containment queries: - A Polygon can't have crossing loops. - And no loop can have crossing edges. ### S2BooleanOperation Validity As opposed to S2Polygon and OGC Geography, the requirements for geometry to be valid for use with [S2BooleanOperation](https://github.com/google/s2geometry/blob/master/src/s2/s2boolean_operation.h) are comparatively lax: #### Required - Polygon interiors must be disjoint from all other geometry. - Duplicate polygon edges aren't allowed (even among separate polygons) #### Allowed - S2ShapeIndex _may _contain any number of points, polylines and polygons - Point polylines composed of a degenerate edge AA - Point loops composed of a single degenerate edge AA - Sibling edge pairs such as {AB, BA} - These may represent shells or holes. - Or may represent separate polygons touching. - Points and polyline edges are treated as a multiset and may have duplicates - Polylines may have duplicate edges and self intersect. ### Interior Tracking and Edges We'll discuss briefly how interior tracking in indexes work and why this imposes constraints on the type of edges we can have (i.e. duplicates and reverse duplicates). Each shape in an index contains a flag indicating whether the center of a particular cell is contained in the shape. Put another way, we create a mapping of S2CellId => [ClippedShapes] when building an index, and each clipped shape knows whether the center point of the cell is in the interior or exterior of the shape. This enables queries such as `S2ContainsPointQuery` to draw a line between the query point and the cell center, and merely count edge crossings to determine whether the point is inside or outside of the shape. Conceptually, tracking each shape's interior is done by drawing a continuous curve between cells as we build the index. We define an *entry* and _exit _vertex for every cell based on its *ij* coordinates and move from the entry point to the child cells, to the cell exit point. The entry and exit points are chosen so that the *exit* vertex of one cell is the *entry* point of the next cell in the hilbert order. This ultimately gives us a curve that continuously moves between the cell centers:

As we move the curve through a cell, we track which edges we cross and toggle the containment flag for the corresponding shape. The net result is that no matter how a polygon is distributed amongst cells in an index, we always have an accurate accounting of its interior. *But*, this requires that every edge we encounter moves us from the interior to the exterior or exterior to interior. This 1:1 requirement between edge crossings and interior transitions is what gives way to the rule that we may not have duplicate edges and that polygons must not self intersect. To visualize this second case, just imagine the interior/exterior arrangement of any two crossing edges from the same polygon. Interiors are on the left, so the opposite side of each edge must be the exterior. No matter how we arrange it, we can't make crossing edges consistent with the 1:1 rule:

Similarly, duplicate edges require us to toggle twice, so we remain in the interior or exterior, but since interiors are on the left, we can't have interior or exterior on both sides of a double edge, because one side will always be oriented incorrectly. *Reverse* duplicate edges, however, present no such contradiction and are allowed.

What's more, even between polygons, duplicate edges represent a double containment issue, because we have two interiors on the left, and polygon interiors must be disjoint, so duplicate edges are prohibited everywhere. As far as actually detecting crossing edges, interior crossings are comparatively simple. We can check each edge pair in a cell and see if there's an interior crossing point with `S2EdgeCrosser`. But how do we detect whether there's a crossing at a vertex? Such as this situation:

The answer is that we can number the incoming edges as -1 and outgoing edges as +1, and visit them in a counter-clockwise order. We scan forward from an outgoing edge to its subsequent incoming edge and if any chains have summed to a value other than zero at that point, then we know we've got an edge intervening and thus it must be a crossing from one interior to another:

Note that, to support reverse-duplicate edges, we must be consistent in how we order edges with their siblings. We take the convention that outgoing edges in a sibling pair must come first in CCW order. This means that if we start at an outgoing edge, we'll always encounter its reverse duplicate on the next edge and stop scanning, with no other edges able to intervene. ## Design ### Predicates
Predicate Description
ContinuousEdges edge[i].v1 == edge[i+1].v0
MinimumChainLength 0D shape chains must have exactly one degenerate edge (a point), 1D and 2D chains must have at least one edge.
NoAntipodalEdges No edges with antipodal vertices
NoChainCrossings Polygon chains do not cross, they may meet at a point.
NoDegenerateChains 2D shape chains must have at least 3 edges
NoDegenerateEdges 1D and 2D shapes may not have degenerate edges
NoDuplicateChainVertices Chains may not contain the same point twice, excluding the endpoints when closed.
NoDuplicateEdges No duplicate edges at all.
NoDuplicatePoints Any points contained in a 0D S2Shape must not overlap any other point or vertex and must be represented only once.
NoDuplicatePolygonEdges No duplicate edges {AB, AB} between or within polygons.
NoReverseDuplicateEdges No reverse duplicate edges at all (e.g. {AB, BA})
NoSelfIntersection Polylines may not self-intersect, excluding endpoints.MultiPolylines may only intersect at endpoints.
NoSplitInteriors The interiors of polygons are topologically connected (ie no pinch points)
NothingContained No geometry is contained in the interior of any other.
OnlyPolylineEdgesCross Only polyline edges may cross, and only to self-intersect.
PolygonClosed If a 2D shape chain has more than one edge, it must have at least 3 edges and be closed.
PolygonFullOk A polygon may have an empty chain if it's the only chain
PolygonsTouchAtPoint Polygons may not share edges, duplicate or reverse duplicate. They may touch at a point.
Single2DShape Only one shape is in the index, and it is 2D
ValidCoordinates Points/Vertices aren't inf or NaN and have unit magnitude
ValidDimensions S2Shapes have valid dimension value
We can distill these requirements into a list of predicates that we need to show are true for a given set of geometry. Different subsets of predicates will be used for different validation semantics. We define five semantic models to cover the background cases discussed above: `S2Valid`, `S2LegacyValid`, `OGCValid`, `STLibValid`, and `OGCSimple`. `S2Valid` is the most lax semantic model and does basic checking that interiors are properly oriented, geometry doesn't overlap, etc. Degeneracies are explicitly supported. Altogether these are the requirements needed to be able to use `S2BooleanOperation` on the geometry. `S2LegacyValid`is intended to support `S2Polygon` validation semantics, and is a combination of `S2Valid`, `Single2DShape` and other predicates. Finally, we differentiate between geometry that is merely valid according to the OGC specification with `OGCValid`, we add additional constraints to check for dissolved geometry for `STLibValid` and, lastly, we check for polyline self intersection for `OGCSimple`. These rules are shown in the following dependency graph showing how predicates roll up into final semantic categories:

### Index Confidence Given a pointer to an `S2ShapeIndex`, how do we know that it contains consistent information? It's possible that a user could give us an implementation that's inaccurate in every way about the underlying geometry (inconsistent interior state, etc). It's possible to bootstrap confidence in an index, but it requires repeating the interior tracking logic that would have been used to build it and verifying that it's consistent. This is somewhat expensive and, in general, we don't expect to be dealing with adversarial indices. So we'll take the position for purposes of *geometry* validation that indexes were constructed properly (e.g. via MutableS2ShapeIndex or similar), so that the relationship between edges and cell centers is *consistent* and edges are in their proper cells. ### Interiors On The Left As long as we don't have any duplicate edges, we can *assume* that the interior state of the index is correct and check edge orientation independently on a cell-by cell basis. If the interior state *isn't* correct, then we'll return an error that edges aren't properly oriented. We have to be a bit careful, however, since we can have multiple edges of a single shape in a cell, and they are not, in general, oriented the same with respect to the cell center. We can use `S2EdgeCrosser` to count the number of crossings with other edges from the same polygon between one edge vertex and the cell center. The containment state of the cell ***xor*** each crossing will tell us the orientation the edge should have. We can see below that edges that should be oriented CCW with respect to the cell center will have an even number of crossings and those that should be CW have an odd number of crossings.

We know that every time we cross an edge, we toggle the interior, and that interiors are on the left. So, every time we cross an edge of the same polygon, the orientation of edges relative to the cell center must flip to maintain consistency. We also assume that edges and cell centers are consistent, *but* it's possible that they can be consistent, but in the wrong direction. The interior tracking for a polygon is either entirely correct or entirely wrong. But, since we assume consistency, we only have to check a shape's chains once the first time we encounter it to convince ourselves that all the interior flags for that chain are correct. #### Initial Seeding So, we can draw an imaginary line from a vertex to the cell center, toggling as we go, but what do we use for the initial interior state at the vertex? Since the vertex is part of the shape boundary is it contained or not? And we may have multiple edges incident on the vertex. To resolve this we can note one property that's very useful: The interior of a polygon is always on the left of an edge. That means if we start at an edge and rotate an infinitesimal amount counter-clockwise around its first vertex, we'll always be in the interior of the shape, from the edge's perspective. If we keep rotating, any further edges must toggle the interior or they're improperly oriented (see above). Given that, we can take all the edges incident on the vertex we want to test, sort them counter-clockwise, and toggle the interior bit on each one we hit until we hit a synthetic target edge we draw from the vertex to the cell center. This gives us the correct starting state and we can proceed to cross edges and toggle the interior normally. ### Connected Interiors It's possible to have edges that split interiors without any interior vertices:

There's no containment check that will notice that the diagonal edge is in the interior of the polygon, nor will edge-crossing tests save us. Fortunately, there's no way to add an edge in this manner that won't make the interior state inconsistent, and thus either the edges in the top half or the bottom half will not be oriented properly. In general, split interiors are allowed as long as it's not due to an aberrant edge like above, or caused by self-intersection, S2BooleanOperation is fully capable of handling multiple interior areas. OGC semantics, however, explicitly require that polygon interiors be connected. And, in general, interiors can be split in arbitrarily complex ways by chaining holes together, including cases where the holes are disjoint from the shell:

We thus need a robust way of detecting chains that touch and working backwards to determine whether they split the interior or not. We can reframe the problem in graph language by considering each point in shape where more than two edges meet (a _tangent point) _to represent a node, and each path of edges along a chain between tangents to be an edge in the graph. If we do this, the three shapes above look like the following graphs:

Note that we do *not* completely connect tangent points on a given chain back to the start, as that would always complete a cycle in the graph along a chain, and isn't necessary to capture the connectivity of the chains. If we removed the outer three holes in each arm from the second example, the graph would become properly acyclic since the centermost hole does not form a cycle:

If we consider any shape where the chains never touch, we can see immediately that it will be a null graph containing no nodes or edges, and thus trivially non-cyclic. In the case of a polygon with one interior ring that touches at *one* tangent point. The graph would contain one node and no edges, again trivially non-cyclic:

If we allow the hole to touch the other side and split the interior, we have two nodes and two edges (one along the shell and one along the hole), a cyclic graph:

To split the interior of a polygon, we need to form two interior regions that can't be continuously reached from each other. A useful analogy for deciding whether two regions are connected is "Can I put a pen down and draw from one region into the other without crossing the polygon boundary?". If the answer is yes, then the regions are connected, otherwise they're not. The only way an interior can become split is by forming a closed loop around an interior region, either by connecting at least two points on the shell by a chain of holes, or by drawing a connected chain of holes in the interior that separates a region. Either way, there are points on the polygon boundary (interior or exterior) that you can start at, and, moving along the boundary of the polygon, return to your starting point. Polygons with disconnected interiors have *cycles*. But, is the converse true? If a graph has cycles does it represent a shape with a split interior? The answer, in general, is no. Without even resorting to the fact that S2 works on a closed 2D surface, we can find a polygon with a cyclic graph that doesn't have a split interior, which is simply the complement of the third polygon example above:

This looks exactly like the graph for the complement polygon above. We'd like to exclude these valid polygons from our test, but how can we tell them apart? Let's further consider how chains might meet at a point. Since we're already going to check for crossing edges, and properly oriented interiors, there's only two ways that two chains can meet at a tangent point: the interior can be between edges of the same chain, or between edges of different chains. We can call these two situations a *bounce* or a *pinch*, respectively:

We can see in the first example how each incoming chain "bounces" off the intersection point, and doesn't rely on the other chain to define the interior; if we pulled the chains apart horizontally we'd have two disjoint chains each containing the interior. In the second example, however, each incoming edge in each chain relies on an outgoing edge from the *other* chain to define the interior. If we pulled *these* chains apart horizontally, the interior would stretch with them:

We can see how the "pinch" configuration in some sense separates the interior in a continuous topological way. A bounce is equivalent to two shells touching at a tangent point, while a pinch is equivalent to two holes touching, *or* a hole touching a shell.

We can easily detect pinches by looking at each ingoing edge at a vertex, and seeing if the next edge (ordered CW around the vertex) is the next edge in the same chain or not. This makes intuitive sense because we're effectively saying that, for a bounce, there can't be any intervening edges between the ingoing and outgoing edges of a particular chain. If we restrict ourselves to building a graph with nodes just for pinch points, then we can detect split interiors by detecting cycles in the graph. There are a few special cases we have to think about though. The first is a shell that's pinched through a self tangency:

This is still equivalent to a pinch, and splits the interior. It's somewhat special in that the two chains that are pinching are one and the same, but, we can treat it the same as a pinch between any two chains, we'll just add the same pinch point *twice* for the same chain. This will ensure a cycle in the resulting graph, which we'll detect. In the case of a hole that's self tangent, the pinch becomes a bounce, and we'll safely ignore it:

Next, there's no reason that a tangency has to be between only two chains, for example, here's a bounce and pinch configuration between four chains, we can even have a combination of bounces and pinches:

If we look at a shape containing a pinch like that, and its associated graph:

We can see why we were careful to define the graph in terms of the tangent points, with edges connecting them. The central point shared by the holes on its own doesn't generate a cycle. If we disconnected the holes from the shell, the graph would collapse to a single node, which is trivially acyclic. We can gather the information we need for the graph as we work through the index. If we store a mapping of `S2Shape => [(chain, vertex)]` pairs for each shape that has tangency points, then at the end of the validation process we can use a [disjoint set](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) data structure to find cycles as follows: ```python def CheckInteriorConnected(tangent_list): tangent_list = sort(tangent_list by chain) # exact ordering within chain is irrelevant ds = DisjointSet() # Create singleton sets for each point for value in tangent_list: ds.Make(value.vertex) # Add edges, if we find two vertices connected, we have a loop for ii < len(tangent_list)-1: curr = tangent_list[ii] next = tangent_list[ii+1] if (curr.chain == next.chain): curr_root = ds.Find(curr.vertex) next_root = ds.Find(next.vertex) if (curr_root == next_root): return Error("Disconnected interior found") ds.Union(curr_root, next_root) return true ``` Note that we expect most shapes to have zero tangent points so in the common case we do no work (O(0)!). In the more general case, the disjoint-set has ~O(1) complexity for `Find`and `Union` (technically O(Ackermann-1(n)) which is < 5 for all realistic values), so processing the edges is O(n) and thus the overhead is dominated by the `sort` call which is O(n log n) in the number of tangent points. ### Validation Process Details With those tools available, we're now ready to define the validation processing. We can break the process up into two stages. First, we can run any checks that can be done independently on the shapes in the index. These include: - `ValidDimensions` - `MinimumChainLength` - `PolygonClosed` - `Single2DShape` - `PolygonFullOk` These are easy O(1) checks that don't require index information to verify. Checking them first will at minimum tell us that polygons in the index represent some closed (possibly degenerate) loop, and they provide easy criterion for short-circuiting the rest of the validation. Now, we can begin the validation process in earnest. As we go we'll maintain two additional pieces of state: a map from `S2Shape` to the CellId where we first encountered it, and map from `S2Shape` to a list of (chain,vertex) pairs for separated interior tracking. We'll proceed cell-by-cell in the index, validating as we go. We'll assume that the index is valid until proven otherwise. The following pseudocode shows the basic logic: ```python # Initial O(1) checks. MaybeCheck(Single2DShape(index)) for shape in index: Check(ValidDimensions(shape)) if (shape.dimension() == 2): Check(MinimumChainLength(shape)) Check(PolygonClosed(shape)) MaybeCheck(PolygonFullOk(shape)) # Store tangency points tangent_map = Map() for cell in index: # Check dimension 2 edges in the cell for duplicates. By definition duplicate # edges will appear in the same cell(s). Check(NoDuplicatePolygonEdges(cell)) MaybeCheck(NoReverseDuplicateEdges(cell)) # If a chain touches itself, both edges will end in the same cell at some point, so # we can detect duplicate edges locally by just checking the edges in each cell. MaybeCheck(NoDuplicateChainVertices(cell)) # Maybe we shouldn't have duplicate edges at all (e.g. for OGCValid) MaybeCheck(NoDuplicateEdges(cell)) # Maybe check any points in the cell to ensure they don't overlap any other # point or vertex. MaybeCheck(NoDuplicatePoints(cell)) # Check basic validity for edges (doesn't affect duplicate check). for edge in cell: Check(ValidCoordinates(edge)) MaybeCheck(NotAntipodal(edge)) MaybeCheck(NotDegenerate(edge)) # Check that polygons don't have crossing edges. Check(OnlyPolylineEdgesCross(cell)) MaybeCheck(NoChainCrossings(cell)) # Disallow degenerate chains for STLib MaybeCheck(NoDegenerateChains(cell)) # Find any pinch points and add edges for shape in cell: tangent_map[shape].append(TangentPoints(shape, cell)) for edge in cell: # Check that edges are continuous. if (edge.shape.dimension == 1 or 2): Check(edge.v1 == next(edge).v0) # Count crossings and check that edges are oriented to keep the interior on the left. if (edge.shape.dimension == 2): Check(EdgeOrientedProperly(edge)) # Since there's no crossing edges, we know each edge is either entirely inside, # entirely outside, or a vertex of each polygon, so we can verify NothingContained by # checking the first vertex of each edge against each polygon. for shape in cell: if not shape in first_cells: first_cells[shape] = cell if (edge.shape != shape): Check(!inside(shape)) # Check for disjoint interiors. for shape, tangent_list in tangent_map: CheckInteriorConnected(tangent_list) # Index is now valid. ``` doc/examples/000077500000000000000000000000001524103652300134425ustar00rootroot00000000000000doc/examples/CMakeLists.txt000066400000000000000000000002671524103652300162070ustar00rootroot00000000000000add_executable(point_index point_index.cc) target_link_libraries(point_index LINK_PUBLIC s2) add_executable(term_index term_index.cc) target_link_libraries(term_index LINK_PUBLIC s2) doc/examples/point_index.cc000066400000000000000000000032201524103652300162660ustar00rootroot00000000000000// Copyright 2017 Google Inc. All Rights Reserved. // Author: ericv@google.com (Eric Veach) // // This example shows how to build and query an in-memory index of points // using S2PointIndex. #include #include #include #include #include "absl/flags/flag.h" #include "absl/strings/str_format.h" #include "s2/s1angle.h" #include "s2/s2closest_point_query.h" #include "s2/s2earth.h" #include "s2/s2point_index.h" #include "s2/s2random.h" ABSL_FLAG(int32_t, num_index_points, 10000, "Number of points to index"); ABSL_FLAG(int32_t, num_queries, 10000, "Number of queries"); ABSL_FLAG(double, query_radius_km, 100, "Query radius in kilometers"); int main(int argc, char **argv) { std::mt19937_64 bitgen; // Build an index containing random points anywhere on the Earth. S2PointIndex index; for (int i = 0; i < absl::GetFlag(FLAGS_num_index_points); ++i) { index.Add(s2random::Point(bitgen), i); } // Create a query to search within the given radius of a target point. S2ClosestPointQuery query(&index); query.mutable_options()->set_max_distance(S1Angle::Radians( S2Earth::KmToRadians(absl::GetFlag(FLAGS_query_radius_km)))); // Repeatedly choose a random target point, and count how many index points // are within the given radius of that point. int64_t num_found = 0; for (int i = 0; i < absl::GetFlag(FLAGS_num_queries); ++i) { S2ClosestPointQuery::PointTarget target(s2random::Point(bitgen)); num_found += query.FindClosestPoints(&target).size(); } absl::PrintF("Found %d points in %d queries\n", num_found, absl::GetFlag(FLAGS_num_queries)); return 0; } doc/examples/term_index.cc000066400000000000000000000102101524103652300161010ustar00rootroot00000000000000// Copyright 2017 Google Inc. All Rights Reserved. // Author: ericv@google.com (Eric Veach) // // This example shows how to add spatial data to an information retrieval // system. Such systems work by converting documents into a collection of // "index terms" (e.g., representing words or phrases), and then building an // "inverted index" that maps each term to a list of documents (and document // positions) where that term occurs. // // This example shows how to convert spatial data into index terms, which can // then be indexed along with the other document information. #include #include #include #include #include #include "absl/container/btree_set.h" #include "absl/container/flat_hash_map.h" #include "absl/flags/flag.h" #include "absl/strings/str_format.h" #include "s2/s1angle.h" #include "s2/s2cap.h" #include "s2/s2earth.h" #include "s2/s2point.h" #include "s2/s2random.h" #include "s2/s2region_term_indexer.h" ABSL_FLAG(int32_t, num_documents, 10000, "Number of documents"); ABSL_FLAG(int32_t, num_queries, 10000, "Number of queries"); ABSL_FLAG(double, query_radius_km, 100, "Query radius in kilometers"); // A prefix added to spatial terms to distinguish them from other index terms // (e.g. representing words or phrases). static const char kPrefix[] = "s2:"; int main(int argc, char** argv) { std::mt19937_64 bitgen; // Create a set of "documents" to be indexed. Each document consists of a // single point. (You can easily substitute any S2Region type here, or even // index a mixture of region types using std::unique_ptr. Other // region types include polygons, polylines, rectangles, discs, buffered // geometry, etc.) std::vector documents; documents.reserve(absl::GetFlag(FLAGS_num_documents)); for (int docid = 0; docid < absl::GetFlag(FLAGS_num_documents); ++docid) { documents.push_back(s2random::Point(bitgen)); } // We use a hash map as our inverted index. The key is an index term, and // the value is the set of "document ids" where this index term is present. absl::flat_hash_map> index; // Create an indexer suitable for an index that contains points only. // (You may also want to adjust min_level() or max_level() if you plan // on querying very large or very small regions.) S2RegionTermIndexer::Options options; options.set_index_contains_points_only(true); S2RegionTermIndexer indexer(options); // Add the documents to the index. for (int docid = 0; docid < documents.size(); ++docid) { S2Point index_region = documents[docid]; for (const auto& term : indexer.GetIndexTerms(index_region, kPrefix)) { index[term].push_back(docid); } } // Convert the query radius to an angle representation. S1Angle radius = S1Angle::Radians( S2Earth::KmToRadians(absl::GetFlag(FLAGS_query_radius_km))); // Count the number of documents (points) found in all queries. int64_t num_found = 0; for (int i = 0; i < absl::GetFlag(FLAGS_num_queries); ++i) { // Choose a random center for query. S2Cap query_region(s2random::Point(bitgen), radius); // Convert the query region to a set of terms, and compute the union of // the document ids associated with those terms. (An actual information // retrieval system would do something more sophisticated.) absl::btree_set candidates; for (const auto& term : indexer.GetQueryTerms(query_region, kPrefix)) { candidates.insert(index[term].begin(), index[term].end()); } // "candidates" now contains all documents that intersect the query // region, along with some documents that nearly intersect it. We can // prune the results by retrieving the original "document" and checking // the distance more precisely. std::vector result; for (int docid : candidates) { if (!query_region.Contains(documents[docid])) continue; result.push_back(docid); } // Now do something with the results (in this example we just count them). num_found += result.size(); } absl::PrintF("Found %d points in %d queries\n", num_found, absl::GetFlag(FLAGS_num_queries)); return 0; } doc/examples/term_index.py000066400000000000000000000075301524103652300161570ustar00rootroot00000000000000"""Example of spatial indexing with S2RegionTermIndexer. Information retrieval systems work by converting documents into a collection of "index terms" (e.g., representing words or phrases), and then building an "inverted index" that maps each term to a list of documents (and document positions) where that term occurs. This example demonstrates converting spatial data (points) into S2 index terms using S2RegionTermIndexer, building an inverted index, and querying it for all points within a given radius. It is a port of the C++ term_index.cc example. """ import argparse from collections import defaultdict import pywraps2 as s2 def main(): parser = argparse.ArgumentParser( description=( "This example shows how to convert spatial data into index terms, " "which can then be indexed along with the other document " "information." ) ) parser.add_argument( "--num_documents", type=int, default=10000, help="Number of documents" ) parser.add_argument( "--num_queries", type=int, default=10000, help="Number of queries" ) parser.add_argument( "--query_radius_km", type=float, default=100, help="Query radius in kilometers", ) args = parser.parse_args() # A prefix added to spatial terms to distinguish them from other index terms # (e.g. representing words or phrases). PREFIX = "s2:" # Create a set of "documents" to be indexed. Each document consists of a # single point. (You can easily substitute any S2Region type here, or even # index a mixture of region types using S2Region. Other # region types include polygons, polylines, rectangles, discs, buffered # geometry, etc.) documents = [] for i in range(args.num_documents): documents.append(s2.S2Testing.RandomPoint()) # We use a dict as our inverted index. The key is an index term, and # the value is the set of "document ids" where this index term is present. index = defaultdict(set) # Create an indexer suitable for an index that contains points only. # (You may also want to adjust min_level() or max_level() if you plan # on querying very large or very small regions.) indexer = s2.S2RegionTermIndexer() indexer.set_index_contains_points_only(True) # Add the documents to the index. for docid, index_region in enumerate(documents): for term in indexer.GetIndexTerms(index_region, PREFIX): index[term].add(docid) # Convert the query radius to an angle representation. radius = s2.S1Angle.Radians(s2.S2Earth.KmToRadians(args.query_radius_km)) # Count the number of documents (points) found in all queries. num_found = 0 for i in range(args.num_queries): # Choose a random center for query. query_region = s2.S2Cap(s2.S2Testing.RandomPoint(), radius) # Convert the query region to a set of terms, and compute the union of # the document ids associated with those terms. (An actual information # retrieval system would do something more sophisticated.) candidates = set() for term in indexer.GetQueryTerms(query_region, PREFIX): candidates |= index[term] # "candidates" now contains all documents that intersect the query # region, along with some documents that nearly intersect it. We can # prune the results by retrieving the original "document" and checking # the distance more precisely. result = [] for docid in candidates: if query_region.Contains(documents[docid]): result.append(docid) # Now do something with the results (in this example we just count # them). num_found += len(result) print("Found %d points in %d queries" % (num_found, args.num_queries)) if __name__ == "__main__": main() doc/pdf/000077500000000000000000000000001524103652300123755ustar00rootroot00000000000000doc/pdf/dd-index-validation.pdf000066400000000000000000033607301524103652300167300ustar00rootroot00000000000000%PDF-1.4 %Óëéá 1 0 obj <> endobj 3 0 obj <> endobj 12 0 obj <> endobj 18 0 obj <> endobj 19 0 obj <> endobj 22 0 obj <
> stream xœ}�½JÃ…¿Ô‚(Šƒ28¸h“¦iRpi"×V¡©S’¦AìOHSôtspu+.¾€èc(âà#ˆ ³¤AR�xàÂÇáÀ½÷@®�— ?ˆÂFÝ[V[œG@`*ÛdK€ï—$û¼õO.K oä@¶¬6`ÍOø,f'á˘O£ asxÐ0A¸6ývfØ Â8ÿìô{c7½›%opØZÀ:u† ñéáQ¤É ÇØÑ0QÙ£F …*åéÔ�(£SÁÀÀÄDGACAa•jÜg²rxúÌ]¥žs PxM½� ¬œÃýcê¥vhO­<�ëváó–-X}‚Å£ßb3~ÿü*²Ï—mDJHÈT~…ÍK½ endstream endobj 20 0 obj <> stream xœ�ÔÁkÓPð ëpžv=zPz1M^ÒÖ‰þÞK¼Ì&µÂЋWÿƒášÎ�1ØyàPÆ’´°Ž!‚ØZðOæµ—¹Ñ—IØ–¡®•H’®MÚ¬SßS›÷Éï÷{¯e˜þE!Nñ-J”�HnšÚ%©r»0°)´OXX 7%Á”zH‡Ê À.ISI< ¡ à”@‰Ü‘έâ}ȤšX¤0|{/¦„(Äm‚HàNïAê/¿$wag»£;ó½D0 ê´@~â;N`àN�±^\ï›'õ&lkžD 2 oK3b$Â0L»vÁ©3vñ*͠๘„ßÇœ¬ÿ˜ì>áM‚HÚÆÎÀÑ·kOª±V5öãíø¾Ìº½d“ðÍ ~Iú–�øùµyÙzvÓö;áºÕ–‚©`·N«;©Æì¹+ÝvÎwT!N«6rR |®CÔãH§õŽÚï´«±ÊÖ X�þ‡¾Š¶çŒt‘£�—ÔMV§Ók�ƒŽT …CV�ñìa»6êõk|Ÿ*ßGzŽ7q}Š/å}'„¨GÄMÈ� ^þþ4êÔÇ>¿¿v×xˆôœ¾”7&Óï@½wß’+Ë÷¿d ‡¡bŠ6ž=‚Ë©�Ío%�–ë"ÊÈA’“HWÜo5EX{š\Yö§Ús ÇXµýqe™­dy½Ÿrc(‚þÈEN?I¿žÅ¯ho2E—ò¶’åÊŠPÊG8QÖžÃâWR°aÁ†9;xIN9ºªAjý ^ÚÆóMX9 à ]æJnƒ‚® Gx=ÇV²É73xi;ò7ë5(#CNiYd(H ƒš‚ …+å¹’’ðF:ü ¥eE]4Ù;)¥‡è ï�#wzµ‚ë4Õ‘õ endstream endobj 21 0 obj <> stream xœc`À x¢_¿ÿøì`dQ–ê÷ÿ¡ày2BXâô$°ž*¬ðYøÿjˆ0Çy0÷ýúöúåŸÂ Í ÑßÍ ¶Àd¸°È«ÿÿÿÆpa>Hy7¦Ë÷ÿÿÿÿ•¦8ÈåË!L„›¢!œztñj§]¼ž�áóÿÿÿ磋Ç30ÿÿÿïHhŃ@?HÜ›�¡D#Ü1äK™¯@ñÏ60a›ïÿÿÿßbMiøñ"Ⱥÿþà0¹¶êv}tr;$C´|F çÿÏ% fêÜG~¦ wƒÀìß0ÑßóQÂJ¡þð÷ÿÿ?®WÁ A†ôÊ endstream endobj 23 0 obj <> stream xœí]Ýo7ß¿‚ÏJs8üŒvl÷ÐÚè½¾6‡ƒ“^s)pþ�»úØ•ö§å¬6’⺙#’Cr¾83i˹ýOeÔ÷º÷gÌV=}lþh ÄzoÛtŠ^}þµùù;õ©ù£aMÖ·}·Ÿž>6¤Êÿ?½S݇Ïš«w¬>ü·¹úûïŸÞùüçÓu}}õÃÛ¿Ý)£Þ¼¹½{ÛN“((2>”~k~l~ìOoMÖ·4=¿”ƒêÿûÓ;µß¸Åëö±¹zÿŸ_>]__Ý<}ùó—çÇ_ÿ÷E]?Ü?’ö´²mË7}Ú=½ýö›ñvFã¸ñö•Øÿ¾o7h|4/3þŠ&÷ÛÑþ€õ®]ý÷Áº|_¼?àÑ8è|ÑþH׋莿ýÜËèâs[�Od;>±³qÓ>`°uƒ¡²t¨Á*F†ª’›p>±ÍzHŠQ¬‘bãTňÀ÷¿Î©÷©pÝà��’ ðK7À¨I¤EàºÐ¹€ýY™D'—†p½O©TBãƒï‹¥¢4”bý†f Å>”ýù¾†„aª‘0 Q>lG’ Í‹(YH��B@;¤´$Û©dƒöÄ8ž¼ÂG@fû‹Ž»à:o�ooÆ”ûºÕ¾»€œó2�ö}›kÇ�µVG{ÐqD)£‘Þ‡e‰ƒ:ByíŠuí§·Š¥ÚZˆç‘µxÍk„Z‘ä=é�F*Ëé�ƒdòæâУ˜±à��]�ÃÛ‚‹1>ãîŒqÁŸK[ÛÉÍÞ»�7ÛNåKÇDêIf�18딢«Z& ¼.‹b™�6>s´Êz3u…B  ÒÍ…]C]9 *ß~òÎú¸¥ß1¿×‘ÛDƒž.•IK0k{tåoï¶g¾€u á%šXåncØiJf­ž6 +$]ÎNQ*ž«»(}eƒ]eÖº÷=(I¤^¨ôþõ”›NY…‰mZ+ª%Ð]Å4zÿn½E�*âE³íÒ+´IûìLž"³VA9‡äö=Ü#€ Ùë!º±ìöÞÙÆjnZ†�8O™}ˆ“¤÷”…üt«{Á¹9Œl ¸é \’Ç~‘ÂdZá«èrÛT„rnƒþ™bP:¯¹q¯q+”“úž¬.æ‡1^}lR*$ä0hn²Õ‰RŽqÐžÃæÛIgN6&ÛotÚ[õÔ Zˆ:¶~î5k›K_µ�…u**Ó�Úb´m{jRï¯ç†µO­í5šÍ ßk3ü/¥D19ÛÇæ©1+tŸË§íj6C÷×=ܵ§æ_Íoß YxŸ¶Z[££'dŸ#^< ìäýdp÷fáý��îäàû«ö"tM¶%ìˆ+§d¶´uðÚ6}Ú¶&íÙ뼡m¶�]æ~#ë mo[œNaCÛÛfÍÄÁ›Â›‰Xóš¼7HmÛž:ì· Ï�Ó”Ë(ý®Ú÷/m1xjÊß-ŽÏíÇí¶Cõ—»·_…ªß�Šžó€ÞOi.¡GNìsF4/]£e�ÊezgO©Òò«J{Y* Äà…j!•Û_UÚ_W¥õÒvÖ.�uêÎ¥zì�sÈ”Ç^êV†îZaPÑHS_PH*\‚bô&)ëíòŽgÐŽ /×ÒàZUwÚ4rf¹ Ú2<1ð@‹ÜÒ€ýB‰ö"Œ?—ÝÚ�1±�âØ–°ý•%–f‰A¼ã@>ÿñQ:”¹wÞLÈs« el¦OB7F¹˜ˆfÑIHs1—‹r켬†¨mûÖ¯{ÖDı3ºvç]ÄÊ’fÞy ¸Žæ²qš]ɬÄYsÈÖì  ÈúmËHŸ!‚£é>< Ó.ö§wªû ‹Õ8«éí犧)û!’ =×qPØg#¶Afd(ÀXÁÒ=ê�°Â ¼O>¾’LŽÐeÔï.\9Z Š`Á•CòÁsÀ"ò©Û+zI–}Æñ!ŽÏÑ æ e 58¨ Õ 5< ¡î`@pý¡ðQYf;ØÐu×øâÃ.*ÍÅ“Ó>ÃÝi“‰W�Ä«ó¤�K®/]yÌÌ «…³�)øíc¦Û;€=¿E=nÀ€�Ce4ùƒt/x€;‚!÷�üëèNï‚Î1šÒ�òt+VFXÆÉÔ�¨û %V_ pòÕ–,’ú±°­åcUºúñ†4�ð #Ã&Õ�”& õÀJ_®�“t¡ý€¡‹±‚'ˆz`ò–S Üv@+Ÿa-C‹› g&ð`hR lhR9ÐÛA †‚æÎ€?FÌÉ: ÙÅë€F²먛¡;ÃöE&.Æ*Š'¿Atð 6�÷†Bf4\ ‹Íh‚—”~�%V�ÞDÐnÕäÀ�[$êñä�k# NŽÐ•¹GÁ|Ó%úƒ¦îr.¹RðV�Ç Z(Æñ2ùÄ'¼‰’÷š‚·žûG¸Ð]]9Ý Dðõ°â9D>ƒs\ ­ÍšÈ¦4ÅUZtˆLILñËùÛšzSW5ÉíUî+†7xSË,šàbG5±³w÷›fŽ£6lb˜-Ë  $ä°ÏëÍ�ap(„•Cb‘E) gñ’QÒlJÐoÊt€Ü&¿�ŠC6Pß/;¾jŸà¶êëb¡Ug�±=ÞɼnQhu]pâdu÷‘jgÌskI!©àî)…gïDƒy5/AF’#M.›ûg²��D¶# Éʬ F ^œ­b9j29ò»]´�±Èp#º!ŸƒÝ˜H9NrÛ I/™‘á�¢mr{hFM>#@”&wXœ,A“.&�s©?A“ðð!#²ÀTŒn«8p'ž"D&¼ÏÈS‚[Õ¨ØÙ�ÙT¬_ÏËñòM\Ðݺ¬#ÜŃ9¦�! 7hÚ-„ߘO‘ˆå=ÒÒe/ß§4)kâR¹®Gp˸º ¼0¡œ,|Å‚—2tUœ‘�†.—^,;‹Ái¢ŽŽÙOJ ¨°ä©W§Ë¸=µtpŸcÖ‘\vSû íy’ô’ÉZry×± Î˜{¹¥írÖ!D?E|iˆ{ò:„ò°fŠžçÆÏ¾9}è]ÔÁ¥`gëÃKH©¾`]LÐÙ—'iNlÎÈôäËPNË/%ò‹öœŠ³T/7GÙåƒ?Uô­=è9…3í¥{ Oâ €T �UprŒ•8K3á“,�ôËðLÄ9˜(G&ËøüÈÞ<‘ƒÉ™Óka¢7J®Kç„/áêžú‰Ég£¡p‚tXìÌëRÜûɲ3†º«9óãr-JŽÕåæözª«Û¼'�áe*%¹³YìÅI“âœB¹3÷¬™ŽrûTÄÀÆŽü™ù‚¶¼<ÍŽ‹¹œ\ñÁ'R{>¯ª”Žuop&^z ”ëÝS+WBR¾î«ô4~„æÀJ ·BÛ>CO#º’…�=¯ªÓÓ#Aü–hÀƒý¡ê^çIнDë�V²‚† \.åÅty¦°<¡gSxéѳ^›±ûnFZ^!æWõ¥êÌñ&.§If\‚á+áoù/ëæúíÕ¢‰^N™ú’ú›‹œ¼£q±htކü”^2^-÷ÏË+áÈ{ CcÁ´4¬¹åumÄÕSpÐ_ìY:U0©”�|9¶¡ØÅÁ^þÄ.PÎROÆŒ¼3¬°ÅêÁ\ê{cùÑ¢MÄ >ãÔþƒþTTÇ‹‹ÑÈëÚȽ °øI]Ù—*_Œá�¤à�8Ê4ã<ª\gUCáu@o" ¼AÇ$¬CuâmÇ®È8°vŽ8<[W�ªÎI5·Õ%z–—s~-—W¯C_Ëå æxñåòÄo"°'caŽÏY33ÓA¾‡^RñûAL€ðfÙBœÙ4#0zÖ|I1e.XiÎq܈]�â‹ñ’eoåA>ˆ®üÇÈàÏù´ïÒŠBõ¬C>üZ#b�"wnbz™¨„ZoUÍÈV|q…)fMÞÇÔ'†×º�g-àîY“aGSü)�1üuèš i“œ‹³éúµÂÑÙ9�SÖ!Åä¦8av 8‰Þ‘ÇÎä•Ä¥=­@¶þef6yõãÌÖTþ6óþù˃9b^NÚXI‘±¤3—šW‡Ê…om·DÉ�:Ÿw·Àp¨;€=,0<@�FwÐMÄ=ЖÀÉ  o;À½Š`Äè¢Ä¡»k‘£½(ÉU5þdÙwJt§­å?J…CTɪ�ML¹|xnÞ7:2³Ò)š tNŽÛ1ö»Aòjœö«qºÏe¨n¶üâ½+åmjq Vû²âîSoQÁjWø;t¼½ýs;D6:XP¨\ýÃu÷{;{ÙÏÿÖ¤ë3 endstream endobj 25 0 obj <> stream xœí]‡WÝÓþýéœWÙ‚]c¢‰ÑhÙˆ *ŠŠ "„Ý¥‰{Wø¾»wYQÑ ”…eç<''1&²eæÞ;óÌ3ÿûŸbEiÅ¢$ƒ F°(ø=‹p(Éb4+õ§SL1Årh8Éb$‹QàW4ø{Œæ�ú3*¦˜b¹2Œ`pRXú߀Aé„#œb0’Cè@RõE¤þàŠ)¦X %X”`€³§ˆ,Jq(éCIŸFçEé@…Á‡vT}5íOýýÉ Ø¤ÿœI.ÿ9‹� ~ßCqÅ!‡ë8Mw°š I}{äi$ÿA×éöËtÛÿÛ*Ò-õ'RL2NÊù³îu[¥°Í €ƒ  Š€ù>çâ ØrЄô¢]�j2„½ÿÁžƒ !ü4y'C¼ú~ðSÀ"@~!ýààÓÍ"™²¿ª�“ú!äÕ0Šk ÷I2®ÖùÔ:¿Št£¤¯‚ô+ñ¶Ô !¼;õÖË0’­2úëzƒu½Á*ƒ¿ÒàÇ©,ÆŠÏ{ñGîÅg&Û•Dœyñ� Å‘Ès’à�‡q¦Rëû™6NÝ�êøC¾¿/‚BÊ›PCÀ¯óÑŒô¢ü¹ ÕªÚ·kÛ6š›¥~æÿÈDø.„Ï‘L5j$H2.õT,†ëüÁ�™ ð¾“úUÇinbýz}'þ®PÌxrž–¸Gó0ç½›ñÜNmÞL¬_�¯]Y\—×å�ó¼tÞç83ÍŸf£”ý˜˜>ÒÚµ¶ÃΉƒö±ýVË^ËÈnóPä‡yç[†šc ÒàǤ 5InþÎ_QüžÎ‰»PO¡XŒ?õ€€Ãoi0�ðî Úhn^¬èòd?ÎP Js(@uµa£¬×©²Zß{îåz�òÕåï6IÆ›Èh~ßDÅòmˆŽAt ªcqÝóA£Øjc™ ÔÐþß–Ý”îŸ7À8ƒLn⌴A& q1Ψ¬Vµq㽟…Pl¹þ�¬/vƒõä¾Ôo¨b¹2�΋>pÖ1âš‚Ql‡õ`Þwï Æ:­ÉUè¹ =X‚»&ÖÂ1i#@ނ̲_23d&7ø ãAfdõÒ¼tn^:7-œšæOõB�9Afò°}l¿}l¿Å²Û2²Û4‚Lc¸®7X߬äÏM’™—§'¦_>øN©ßSŲoh7‡êXLÇ€|~âécÛ>¾?ç½Ov‡%ÿãØÚÕØÚÕ2÷(¹oÊ 0ά<Ç™ÛÏ­m3)Îð;óÒyŒ3vgH¸™ã̈3̓; Î „áf&›q†R"€Ü¬¼Û§†‹~7—¼üÛŸõÞIî ² a?#šîaœö3kBœùk=x'�Ë){9Y…Á‡Ó STÞíKÞõµŒìÎxn%WH…ÿ#N§Š8 `J(~CH/RÄ>ÀÞIJòßßR|_A|hå"å6@ÝÁ¨Ò¢FÈÌ*µ¤û¼_‰ŸlóPĶq#ù‹§ p`u_7ô…“Ý_¥Š—ýÚ“úV싆Âåǰ\^úþ¤âû Þ�3ð4뽃‡ÄònŸŠÑªÉ�†ðc¤1„y~²ï§&ó(P�Œ–‘]@°¤85ÁHý:+ö ÃM[˜Þ‹Sl5záûƒ;ãkW’¿W ŠC+�*€,¦S2�E`*Ò]FxÔÔ6nÚâ c‚ï7)¾¯àóX >iøê¦ôc©ßnÅ>²ŠŽ=\Bt,èçJêiì[\—’¿K ŠãûðEª%"JsPaô}\ªèØKî™U|_Aæw_Á× 4JsPaY½Ù[ÙãÓPÜ+ßÿ¦ø¾‚,ÁŽU÷ /¨žP*…bà¼Oz0ýv½Ù›\ºmè 9/Üaéß²�nêæÕ4§HÀInÐ÷ËH¯ßòìûõ½AóÒ¹âû ²ŽiÏ­@ ê‹”ƒR{@éZsóbmǺF»ùÊ÷ëß—»®©ÐЂòAj½¢-�ZfcÿÄd’›=ëLŠï+ÈŒs'ð•CV­UÊ‚ù3èûe�Q•*žÜÇWk ö9ÎJA¦CA!ÀÁ<-BZQ¨Ay±÷|¿¦ø¾+¤ø¾‚¼¢i0Õc…”c‹ÇãSîèßþ×¾_e ˜æOßW ú—ÎÄWW´rcÐ÷§ÜÑx<ŽŠï+( 8OP:ç+ƒRûŠ %£}ï­ïf£«Á'É_ ÚF÷øY L—5�+ á¬YBã�Iîã«2ø ³Qg@ñ}…‹ë¾œ`³º~,µßÈÁøaUɾ_¡÷Söc§²î+(0¸B±J½ŸÏúŒv…!œ‘aÏc_Dñ}Eíä!ß#Àâz_½Ù+µ¥!„.úùfÝWöü ¶Í8–±Þì­êQò�Ÿ3„ôƒqœ‹€±nB+ŸFÏÓGÊÅ‚ºÞ dW”�®á:ŽèÆ"äóH> ­ø¾‚âe� ü@ŠU ñ˜š#YAU÷Ü¿�SœÖv¸¤ø¾‚"Äœ÷^h4re´B z×`®]Õì+ß_T|_A1ãû@fÊ)%¤00µ™ò�a¬I¹>Œâ:'̃ä�O�‚ Ñë8[Ñnå ðl@ø¯}ÿ>�F�‚<`Éÿ(t¬ð³§¥v»‚0” Rýd É÷Ùö±ýÅ÷Èp˜ÆsZ¤v>‰ †A ÐM¿öýyŸâû ä q˜Èt‘%z(׃‚÷BŠï+(%¸‚± ž!¬æ).Rûb¾MÈóSL¹þÅ�åVËž}ûNò§£@AÐa=€ ášR&‚ë½íC)>ÏŸ$ßÑ2²;ãQ|_A !y˜H3)ÿa"Nû0ڇ뽯|ßüq(P�gˆÃDp’m ö¥vÐBzÒ‡R¾ Xý_¬û[Šï+(]ÓGð  &¼*Ò-µ§fß*µ\çÅ/Bz“}¿y(2¹q#ùýW @ZÌl%†‰�îrrKjͦ!†0Bù1‚­ÔzßW à=ÃD@Mp[j¯ÍŽá¦-LïEi1„“¥{š‡"×’ßp ‰a"œ †‰@ßÇô^Ü´>¢ï]I~«3Äj0f˜;iµìýµîO(ÛY‚ƒ}&¢î.ÖÆq5µ }Kø~“Y¾¿¾v^`ä êBcH‘W�4Eø.!®�Ç ©H·šð äv­–mвmm�±¢c׆þÿ“ƒqœIë~cØâº”üÞfÓ[7èK÷‡ø>–ü³)�–Î…VA’Eè‚cÇãq›;ú×R‘n�ŽÅôL[WAoü׿ñ_ßB+:ö02É÷äãûõ|®&%”j¦‚Ì!Ah)¼qBpB°âÔ]ŒO]ª¬VU_!’7ÆáQyù>öŽûó)Žˆyù|ÔueÛ¼™óÞ-s�Ê$b_ÀŸ±=(ÐY`ÃD’í²F’§ð¤Ä·þÐÈê¥;,ý�Ì>ˆ)Qið×÷ îü¶ìþµÓGƹ“þųçÅÄúµ}ûn‘}PÆ)HÆèê%\[áä;©ýþÙþlòÁÛÞÐv^ÈÕ÷!*ôÜ{—ß<ù3¶÷s8ò­?\c À½\šÀ)®¦'ÐØþ9iÛ×ÙŽô³Ñ>Çs Xâ”dc‰`-œ&B25Läc÷¯6äíûúÙ“”ÛœæÞ^þjðÉÁ<Ø=·îëçEÿâ™aîD7uÔa=h±ìþÜ©ë ¶Ð4¡Ñsu¦àw3¿£˜8 §�Œó'æ%þè±q3ç½_ñ?–ÂS�=´¶Cþ Ààt ùçvWòû–ü0ï¼¾|Š�\ÿ:+ÀŽ-s�sÞ;ÛÆÍ¨ëʼtnœ?!§�:'~Ã@a jÞß{¼E•1ÐÐjŠ´�îuMÒ³Ñ^ÇÙ0¿�˜õÞ-) Š‚‡mãy˜HeÁ A p6yo'Pß”ü¾å ÌÃs"”暇"ùÑ.s…bK܃}ûnbì(úgúÙ¨ÎvÔ>¶ÿs(Ò8ŽXÚG�JƒF‰?c{Ýü¡d'V/aSÙKHŽ:S�R~MÁ ù@•ŸIùFõ9N%¿iù=s L$ÿ$)á >-0÷S[·ãî«¡• ÓÂ)9}Üi=hµì}7ïÔš‚:­(�QluOàŸšèß×M�æâ˜Ú¼™÷Ý+sÙr :1LÕqhW@jïÿ_5Â!½XªÐÐ’üŽå®P¬Êú¸­î"îkXMD‰±µ+ó28tÓG­-#»�ýŸØK`WÛøaÞiµìuMêí`#aq��ļï^©qdq˜Ú@¤VW©âhËA5‚ú’“WŶYöJgÇEëzC²¿dþÐñ8ã¹_»r^˜æO >5ÑjÙûaÞI3Jhh®Æ(„ˆÎ‰Ê~Üç!bŠ?k(»ˆ�ñÆÄD²‚ˆ@’PÖA€_ý«Œ(×oß¾›Ùº•½#¼~(ƒ Ø[2GžàÇ—¹ÇY/ÈKÀã1}ü×zðkx÷[î”ÒJGô‡~ G:x²„iþthåÂ꾞ݾ[*ù\D_b˜Xyù”´uþ<»?P0nÛ�î�ÓÜT s_g<·p]S¯4á <ÍÁÁ§.)ûqç8k|ëÕ¤"¾õ‡ZFvá¼t>¾v5㹕ý¤ÈÕàSÓàsÕ !Œ`P�!òz"@�‚7�1‡cLÍ}_Fçtíš<”ü“È®` ¤#6oF]—ý‹ ´¡�»}gu_®œçNºmGB|Yˆ�‚Nqõ½ÁŸÃ‘Ήz6:°t6õÞ9‹$9¹Ä=¤¼@XŽÏ�ûã<)QÌüS3Ç’ßiѳeMƒ;’�FµÈ=NoÝŽº®úÏh{´sâà×p¤®7ôñæ¡ÒàoÿÛ#§�ϬîëyßýZ�Q¤F]Wï’Eó2RD­eQ.†?´c|¿Äs2îp¼¾04†W.$ÿ0 þ‰%?¨bŒº.ûgÄôqûØ~ÓàNMÏG;‡šžàÏ!°g0ΟX\—sÞû2'—ý�£®«á•‹Yo–·…£®Ë÷"Få<Pѱ‡j ð?ñçPDéI�ª��B[,| îpÌÁAR}úCJÞ{}'þÛ¦»Òö¨äŸDA.à >Ù·ïFW/M §ZÛaóP$eXÀ)®É¼£›:úmÙ{E­Ä)®ÖÌ" ªmt/u |9�Mä IÆáϪ¥ÿÉŸŽäp0÷¸OV¹%„eîqrãºéLg;ú5©þWùRCs=ó'ÙùÑþÇ:þÔ‰€tœj^F8‡¤ ”àjˆ‰´FàŃœ�m£Ú  oXdF]—¿‡wߊɊ\äZ8õBáŠ�ê|0}!Ôær6^èù,TøÄHnÜ]Ò¥®P n'Ö‹¸@Aaœ?ÁéÔ ®7 ²yÚ ØT輨·>~ÖFæj€ðC Ä¡æ¥sÉïsÖ1ï½ïY8¥ìÇKç+þt“6ƒËç%Õú¤àŸ°¸.5ï$êg¼Q4Ο«?üQ£Ë‡<®ó£ ïO8nÈ/ßåÇu¶Cœâ4|¥X£÷khβš–�)ìÎèu”4JA2@hê¶�’,9ý•ƒd›Ð~”ðãÝÁ¼¸?¾ ùy¢˜%ï>Æjð©Óz�z¹§¹ç‹6wt”Ø·ïÆÝWÚÉÕªï,&[Lu½i ljh®¾ð¶�íÓG=s'‚â ?DLò»¡ G˜X¿†«ÃgÓhæÄœPà’‡ÒùèýG÷Þç�%ÙÖ¹f¶në{CðbkzÏ’ûhåø8bOµ û'g\!ÐW2µy3¾Tý ³Q­í0I7ïß§ŒWŠ7}޳!§�…P¶E�:þMI¯Ä aÛ¸†„l~šþxæOhŽ%Ü_?+·Ò¿ˆ>Ǽ½u½Á©Íw86´rñ{lø;¬û¶�|�f¸ù_›\ó ‰Á§×Â@ZSłҚícûÍC‘ºÞ+Þ$Do‚âÂ0-Q¬bdò´ ï¦ùýó¾{È5ÅNMx‘¼tý—“!5éGÈd5wX$¿o¹À÷ð3A«nÛÿl�Öë×/À¯¤>†¸…°ð}ëŸÍYÊwtwÌC³”Îà1u\Í«×ô{æ¢J{ø?±Ì=Â}u:ãcœ�'¸;µ?Ò]Nxòàþ¸i ¥™rRø¹-#»²Ìl�º.ah­Ôû_óÓ„G?Ì Øß6ÛÄÆsz$|Q4Æ(zóÛü«{þà€�Æ�0Œ¢t?îÓwáeî±¶'¨IÚ±hhîû@Ø”áÛ’]À~ÞÖ±_àÅ+ðûT¤;×îßܼX¥ÝÀM[põ—eéߊÓGðÆþ0ï8¾:É˼tÞüw±¡ÿe#@8&9'0YwWTï‡[ˆtÊ�â£Õ²§µ¾:bˆP­£{o,8Í_Jt—`>°Rïÿ8¥#L%YDÇàWM†ríþñx|`"ØÜ¼ŸfMOp‰“[éß¾}×Г~ ¹‘Éöæ;ÏÍè/6YT>>ÜOn\¯\ô:éþŸC‘†þPeñ!൧ úѼBCèãìºi^ &üj0 $@¦ÜÑx\˜÷Q¡÷g]ÓLrô:N…¤Ÿ)øÕ?MLmÞÀ»$3e$˜‚˜Þº�ºšúÙh×$¬b„?VÏKFú •%‹�¥�:IG]—ðV#|þ??ºß(ÅtYw`Û/(ýË«É}™{lÙ…ïgÇø§“~oÑÁ“ºm¥5@˜þ³}7°|þž<J²J>ðŸp5‰·c%AãO¢]CFò#ú­&ü`Ø7%týÉKçvbý¦Ð54×—�îÝå½S~Û¤ôQÓLéþ™ðÞK p´ôoË‹²à’ÿ1qc9’Œ7‘ùhüQë|p§Ÿ q.; f…€ä¤ßwóN:õ—tKº¿†KúUw_¥U£ ŒH‹ì, Î{…×ÒŠý0ïÀvTé®%#$™óÆPú'8µÎ“ÿZ ºš÷Þ7&VÄôQ¶Ú™ÝáŒÒ×'h]²ÄØÚU•ˆ¨Tè9 ͉ª¹2ÛCæ뇰M ÛvOXÆö;�(É–wûʉí<Ôþ00é�Kÿ¿-ò)ý9/ ?¿º'ðö¨• Fyy–c@6÷*¬…c6ž™0Í�‡†;[Œâ²{Ï凭ÉUܽSâ„Yzæ˜l±0(¶XóSßl.ïέÖ÷ÿxÑ5¹-Nûú>–á|Ùÿ(6QþÛ[Év®¾ed ò¥Igˆ®‰CX%Q¤?€ghö’˜;Faò„ú5"6˜¬WÔæÚýãñ8mßQ‘n”ÏèÖš‚òà“''ýr¡b:ﻇkœu$„}ZFv—rLFmìË[)%ëp0÷°]±edW~âÒbŒœ‚Ž¿f�Ô�'ç²âñø”;j´ï%Füp(ý î_ì¥ÿ) 섽*¦ùÓ\w£Ø6äÙ�kÌzïàÑ©Ãz t ‰˜2Ú¡Ë;) ”ªèù5˜²è¡K�îF‰qPóã÷ÿ­–½â-g»Ã1Ãl¶N4ô‡ò#^Ú>Ⱥ©#É/¿è0™¹êVî«ûÚÀûû‚nHüb‡õÀøÓ,N~û›• R Ùþgu˜*ï/âÒ¿ƒ}ç¥vNäG�bÉ/èºÌÊW*9§u]Áˆmš?•üÃH‹9ï$O˜×“¿>»}¨æp½·³m"+ e÷ÆË$¿_ƒÅu ·”UÆÀØZ>f¯…c‹ìƒ~6¤«í¦à-j·æeN›M@XÉLðo_ÿí/žl†FûpÓVæMðýÞ ¹ÝZæ <‰³’ ï.æž�³Ì=¶�ïóâÌÂ}+:1�Bƒa6 µYFK²¥ÂŠ5ñ�? Bšjnu_ jÚÂôY˜ü^ûv…Þ_\]-ÉI¿ž…œ'ýàx—êžÀ«Þ· šSHn¢Ûv›*´#`Põ‡S·`/Fr•Ý[ÍÍ‹G€Ô}Ѱ€Üá¸qîžÁúBö|QÍ;¬ûoõp0Šm2ïH~OŠî°à•r¡ú4¿ÿÑÐÜô‡ïðÐÊ|Ùš›kÚ×3ŒÅ`ïHA… ë"û¬æÝ5y˜·ì¥;Ãß‘ÃÂH.yc-ƒÝU5=�¦$8ÃCNÁ¯-ÿ²ŽÕò „d K ÏHí†{€; Å ÃyÖ²*$ý*ó~fù`€`ÍMo)-o™b5ø¥0ê{C²œÚŠ¡ijïô:�Ðx�ðËXÍ;C8؇Jƒÿm2—E+eá`v[ ÇüÛ+ä7ó p‡ã­–=8�ò³'�•ÀlvC(6+ZÁåßN?�‡ ³žµÌ=þ¶jÞ`„_pï>I<Œó°~ñzã8Å�ºòAF*Lo âØÅÞ¨ò :¾îùå¹P‰¦3Ÿ®RÅÕmBRýk3òr 8ÉŸ•*ôþ\ûd‚•ÀÓŒç*¹ÃñN¾£8E 3‹w_Á‚¯l´×úg0k4îþâb!* ÃT^æÛÐÄ÷‘…4ÖíÅ¿Á¬©yçîp¼kò>ÜÁf·fÉ:xV:H «û:o†E·NH‚%X”`4ºL)‚@”ïþY0*÷sÞ;ØqŸ]5ï<€LD-¼®…8)£þ]4/dÌyïa;ó6Òyï=ÌDit^ŒÈT:¸Ç¾§¡…�€…�r1/�C5ïZSp²E·ô³Qù X‘äô±�n-N±ñÿc]/¨dµdIxj®ò‚~ŒZŸQ6`š—…5AiuA�š·ETó.ˆ¤ß× Nw¥ìt°*v¯Ø8ÐGÜ�šÙb8L{ná;¦ÖûÕtFÙ€x<Þe�`R�tÉú?i1°x�¢’-±qKQŠ�ÿå³ÄUÆ€#«é,HŒeAŠÅÈŒfˆƒfa~6¨$¯+Pó¶ÃsMã@¸èړ߃yé^”vò°ŽW2@²Øx±00 bãÏV–�´ãî«DO pÞL"€Lf¡vkNïÆŒç¶}l¿Ö¨ë vÛŽìüïþ{FøFœ0÷ËKáÉêÒ¤‚3(°éÂ…N´ðƒä€òvnv×ÐwŠSw³ª¶¯ŸÔ$WFúa¤ÊÝ‹j^>Ç)NdÓáÀS>ªŒ¹Uó–ãkW�ÍØ6º'³ø&bãMƒ;…ÜÊj÷ÜœvîÈ Ã‰ÖBUWÖùõm@éW'Ø­9Ú„Ïyïq:uWݯ‘Ȳ¬ûj­îkø&´Zöyü¬`�¹‡T±‚¶]`îMó§:Û‘iáÔ¶uåÐs:FÊŽÃéÎh¤8I†9ÓjÓM½åÒÃ�ÀàŠüù3“×|-¸ed·�—­"ÂŒçÞÒ®‰‚à f£8ÅBñ(@fæßö&sÎG¢ô/ 9g’Œ7‘'_�‰QApdyÖeÐR6Õ…ÄE̦·n !¤y("ã¦×|bÂ} OXôŒÄ¯Ð@‚Äò ƒ¹§²»B1¸Ù@I®žÜÿr@I!8HÁÍÅçü5yO›To— åûŸ˜ñܽëwóNÖg——&ø\+x‘z’‰�»ÃqØÆøµyéï™;~"ÁbÄó�(Åàz/Ü–ç"aÕç8K$K�@;罃»±?,ïìGÞ{m$d³Ø=wØ;º1(ÅæAéÈ™\‹J|1È»¿ !ž Ε+«3±—É@LRÌÒöháäsr�æÊ_4ô…Š¥¨]à€ºÅ}¹áîSX`ÆÖ®Œó'ícû }¡” ®<«GÒ3Çâý²rHb† ›£>ÜEöáû@XCs8ÍÁ_ÿZºl‡‚ê—y'»Œ©B†ƒ}¨çS¸u½ÁÒ¹êœBË¿H¹ Þ¬Ÿ¦¶nÍKç:ÛQóP®¶i¢ÒàÏÏå/s�0 ™‰r’hÔÚr˜\µmÞô:ÎÏDy„‰õk¸1.@€œ>2ØÿXÝ� RB@±ñ†.W=éyu?7<'Ü'ÂÂ÷8¾veš?íœ8øÖŸb‰Ç)î[¨sâÀ4:¾vµâ¤f¢úudÀi®w!Ù Q9%œþ IÑ1Ï þž÷Ùa(”8‚.n•1�Ÿ!§ò†{ëd£ªa¹úG£~[T‘ÝØŠ2uß|Í­ljÊ™(½Ü9/ˆi°ÄW¤ZâkŒ�–‘]búhÈy1ç½{Ëñ^ ÇÚ,{8͉[œâ:ó;y‘}€•´ú2Á”wûÊ´^Ugºj£ÖÂÏÏIB\)1À¼Á|jŒ@�Æ)El<3lxN}õßY]®þÑdô-s�ÐýYMŽp‰7ÌFÛÇö?^âûgë×é§òÆÖ®ÚÇö›w:Æ÷%éb†5Ï §êô–k}jmZçµ–E©€�Ç—ä"œO¸‚±^f lÚ�'5:oƒ€³²±›^õñîïùÞ2åd(½ ü«Î‰i/gD dð—Â<Ùµpì?5OþVO“׽޳®ÉÃæè-ís ïþ^ ÿÞé¬ï µ�íçNÆÖ®d<Œ¬Úx¯"YN†ÔDZ:B˜ÎG‰5æ=øæž‘ayBö=5îpìoBp¸u› îplvûnÄyAÙ�[vk{R¼óMÄÚFU‹¢ ®�ÇýxHòOžk¸B±÷‹’ Æ‡¤ÇÄu¾J­r™ ¡�ÅŽég£0WÓÐ’}ÕÌêÚ•«­âŠÿqbýº×qÚi=ø>~;­ £À‹Ñ>¾ß32î¾ZY=S›k{ž:!'Ð?U(*¸9‚;�—ˆ,N²U�›éD€J­#|ðN6~zëöƒãgš?-ÒDMú€ª˜<_Z2®»$p‡csÞ;‹ëÒ0mµìÁ‡þšc£§x­í°Ïq6µy“¼3ÜØÇYçÄÁóNªS<àÞ´�í§³ÄgXbÆh§X Å7§è¹ZSpÎ+Ÿ¾Œ_ûâ�E FeäÔ@FøsýÂâ%Ù²p‡c†Dzð[økã‹Ã+‚Ö¨ÖVè‚Ãk¹_â3�;«2¼þHÉVýò`¡Ï$&àÝA”¾_F³*ã§åÄ!b(ÉÚ &ø×5=ò™/ðFV/Ááñý‚Úµ&/ñ)鵯–xiõ¦·nðT„œæ ³rH¶´ñS„xÙï~Öñ“ áÛ P’5å±³é XIš1$ï~¢Q— 8ügL2ÁáÕàÓ´4ÉvOý|§I¶¦'ÈÓk£#«—<½¶€â•qþ$e¢ èb™¥g¿dˆÙí;árèJe:PIŒèÏ¡Ìi¶ ªÕš‚¶"œ3˜&&‚ÿ-»ùÙ<;˜‡QוqîäÏø~}oŠ%^CsßÍ;ÚIP˜›Ü¸)ð,KÞ¢±¿S^Ÿä’Á!à(È0”“^„O!Ö÷Ç�g óº£Gµôd¶Í¨G÷s8’uw[ >7ɶŒìV¥¾ûg“l!cÔu™š6OqÚÉ‚Pþ2˜!çÏá3t~|€GEº…d`av®PŒHLîþaÞY�©ðÐå}j�.s�C+¦…S«ûú³q/} Ø$»\䌵p¬¦'ˆ¾áÌàWìå€n›ØÌd8@šŠt«I/ü?'Ö‹©UmÔu¤ÒàÏÑœ&É1罃#VkŒAŒÂJ½_Cû«��hœiê`È IöÀ‰ÛXÒê�Ó¹šç•7ˆú`åC³áþÐÄ·Â4_diÒeî±%Yn¨ šbÞw_ñ¦°—³y~9s‡Á)>Yãí7Wèý?Ì;Ï:E²Ùû2úùiÎ8Øó|7‡¿õ‡º&抿”L ¡@ £|Y‹€À'Ÿ‹!øÏrC½Á¬KGJW0–²°…’€C+oŒ¯afë¾ò¢tž„í òe4>ø••Ó~„oªËËȃ\`Ú#ôa²ë'šØ¸~«Kùš{£÷ÿŽtOîÍ´ç¶:=¥‚3ðTÇ˳wX Žèž!ŒI³B²’­ÌPõ ½ùÅ›ržþ&ä†Z†w—ä2¡clí*åAÐk•1 ¸ÃqHùÖ’�„+K”lüå-_Ÿ–ÒT}ub•)ö¹ÞÃ+°ˆVe Œ­É¡Ÿh�¹Çß)m×I7o€µ*ôþbOø¿EŸöŽ1*U¼¬ñë3Cß38ƒ %Ycñ7¨:؇愈bçÄ� ¶Ä?‡"onš+�� éÀ¶y«œR ËÜáœ<…Q¬æW@¥úúÜðw#Cî^Ûèžä×›•;fH’*v}þE'˜LqÑÐ\Qp8ó†eî–Mu¹‡--ÌKçð¹77/Öv¤«þñ)+ײdÛö$¿ÞlÁ¶yÃÓBäÐO´|ÒÏFú‚ÕÆ@ÓPddUÎòŸ�ÎŽÀñ7òS˜t‡ãpêJ1UÚíôÕ?>ee]œªMXbä¤É䆯÷…ôàÈ®2ÀW–€UòJƒ_–âÀ#«—ð®&C2-à/˜ª�Sw?§—%¿êìbÈy‹æUÆ@±§:¼Â¸û ¾·rÕ]Dr'¸êô|ÍÄ߆٨äW�uÌûî¿”ŠÜPéÀÁ>Àm—áK›ßø> l²€REjS´Zä� |‹µpŒ²Ã(÷ü3ï“[Á¨Ô°ŽÁa¬¿†#rm…U-„3þ²Òô�Uun¢¤*sJ~á¹ÃÄú5LË =XâÐò£3«{²a½ÂäÆ Ü ¤!²ÖðžÕ¶»››áO\”5Í,Ynèϸœå†dŒç<·WCë§�èzc€�™îXð/[sóbE—GÞI•dˆýD@n¨€5¼è—ä™ÒE×Íš>ì )°r=«¦r»ÿ ö¡$«—i^åf·Ÿå†(û±\Ï’2Ãjð v@Ë5aÑÎÏ–ÅÀ€)×ç6(’�n±È|è’ˆd¹¡&óNNEìdp@­)(c•ƒyß=LY#ºìH�¥iõäžšf!¹Bò›�OŒº®*rCÊ$ßB†(ýa÷ÜJþarå ”]þ"À*J’q¸ –Új¸È>ü~î'’Yo©<�$ý!ç"Î"û�hó!9®¾2’Œ×�¨¯h)=æ¹; Òƒ�Qߜڒó*StpžêyÙ·D馎ÄJæ¼øÊÐÄøzF&#,?‹ 7‚rC†Ù¨œä†ŠpJNC_HÞÕÛ•Àd°ƒ#@~7‰ÀÁįáRI¾…\冊PúC£çd öù1è٨؎|f p¶¬¼å!Pz®Ä—?‹ë²R_.»n©"/ý–Å!¹'i��'øÊa”ßhϲXšVÖxªR É@…9ï`š…ô Öv(¿Þó‡(ýÑ-Gé�Wè™´@ãñøÔzö¥ÀÒ‹Qu{&µ“‡S›7%¾x9¾<$ïñå…w8Þ2 ˜±�r”þxW(cF°k4ϾØ?�W!2��)‡Ó\}oh¶ÈU¶2ÇäÆMmiŒ//(ÐPúCï/…Ú4¤: $G’ñf"š÷‡ È’E)ùaUòîJ+þGah;¯¦(cBZ�@öÒÉp‡cpàB²Ud˜$%Ù€ä·Ã!«Svó¾ 7Ä *V÷(rC9„(ýA•F‹ÊÐÊô5é.#=ùw‚Aß‘¦¯*1žðxÙOUú‰²Žµpì»Ü¥?’áÇø^'„âÒD¨DôÎl ÍI~£ ®P¬{êy|¹C¦ãË¥� ¤?d$ZûF]‚hEǦ͡à?"Å¢`rPê PQÙ˜OabýºšOVèýÊðŽlJãÊ[úãà†£X¬;Pѱ'Yxßý‘D6@k;,ÞÁ‚¹ÀŠÿñwòør%=øyÌnßuX÷kMÁ†¾à߉8&µG¾Ò¯0±~-8ZWÕqR¹¿øN„W©^£@�†ý³¦ùSÙg?…çñå¦à”"7ô ._à‡‰ùgþ5kÜ)ÊO8áŽb‚C»RGFù* >¼Ïšðýx<Þj «)FLÔš‚æ¥óÒyLÿČ綡Oé'úæ½÷oç!ÂU¦Dº³§=·ð’Õz?BKÐðÖ* >œf}þ³íûSëQÛz´¼eO¥ŠcI;„æÛ†²ä X >u&ú‰~ GÅ?¡›:ÂRÕž4z¿ü¦¦D+Ï0AHNMrj}®æeËTªxycmÛ­&C(ñºÛF÷”#«B?Q¥Á?ê*9�…OAœáò É’ÓòoNŸõ Z e¤¿œ”8�¾�áeD@£c+µžgþ0ÉuÛ•©|æy|¹ÒO”3ž;½=š< ù­´j;¬ÂŽQM€ µgÎ*µ\çÅ_2…@£ç(ûq‰œà>†;7͟žֆ¾¢_ž­{2ã¹5€ È¡÷h'b�ýéÒÁ<Àü§ZçCò¨š]ãÝŸ—Ö=Ç�*c ÏqV T®bÈ K<=èǧ6oˆé#Øø&ÌZ-{æ•óšžà«TNs¿Fä¯N£åYO@ Œ`Ôº|K�e×P^ÐX@â96ô…,Ê)˜×|7{-#%$7ä ů׮:'`VDä–wNŒ¯]‰“[Ì÷�0Ns8ÅUÐ~œâZG÷d¿�\æqÖÚüY%€Ì %˜òž5•՚ϛ#Ó[2ßÎ¥ƒ!çE…(7ä–s§›3ðdq]vNT$9~­)¨µޝ]½·3œÜ¸1-œö9ÎJä¸DN‹\;¤Ø2˜Êj-ë_Fô[{ÉÅ‚ö±}…Q¼ä†và ‘ßøòÿã�ó¢Õ²—\߯ë ÓG Eêœ�§Dxô¡Rh�æÚ*:öð®ÖÀ»ƒÉ¹…QüRn(,¹!óÐç8kŠ$Ÿå¿õ‡ ³ÑYOôÈ^ ”'ÛH ž7ûƒ˜Î�é8\÷¼TÅ€¾q]SärCsÞ;Óü©Xñ„]-ÍCÓüé‚Ò&ù!\ÁX”£¸òi´@ói¸Î�J° £8ËþÇÖ„ÜП±â�JY˃Žßç8+‘6ÞÌaZ8”@¿N-Ðü›šb ö½x<ŽR€îïÀwóN‰Ïì6/�CJL­)8Y¨åo±–e“kyCÎ §Ü“öÙÅZ8·Á–u‚ µkæÏxõãè_kHEº1’ã@ËÈ® ŽÃ_Æœ÷Ê Áô`á�(`-Ok;¬J*âWòµ<‹ëRöÕºÁ¼t9Ï*«µ¼Yj§”ÀT¤»œô $: (FÜIvN”ì62y|ù�ÁiÏÑ® PÄO®åU°ˆ_8ªáÇëá4:’A�›*«Ujw”Ì@géÇ_Š’AFqÉ*lŒ­]U%Æ—ç½-n%ðô¶–W¯Ôò²Š§ ZM†*dÄø²)ŒâWXæ^Ê å~§í`A-¯edKr|¥–—#ˆÇ=œäªIÉÄ ÍFñ+<Ë õæJnH,â'§ô˜w ³Q¥Ë;G[»JtÑ2²deh)Å̓;¥É(¶{nës0¾|Î{jyý©jy%Ó­ àôI„d´ÓJíp…h £8«Á§Dï/7ôU}îËëyæg }yKç%NÑÌ&7n]^D¾$À¬˜Â(N_ÓƒzÿÈê'ŽE®Plbýš˜>ªN*âWêýícûCÎ ¥–—g´Œðép¸cÒ+µ“�)ŒböYn¨¯wÕ£ë[¿ðßÍEÎK ¬ó¹Óç†\ƒ?9¹úª!WA>aß¾KÊȤ8?&2ŠQÒWÊŒbØOTIlojªYÝø«ƒÀæ"Çj*X�3Í´�íkôI}y&PË›X¿.ÍÂJáàÏØ>x"` /£d¾`(é3&ÅâëýݼS°4Úajë¶S·¸�w¶îÐÓê¬Ï‡ƒ?Ú:Åù­?DÙ�•"~�`Þw/ÈnëD§¸ÿM`�FTmB=3Š�F±·„ªWÎÀ“±g�źß^LÜ¿þ/F2Mƒ;= J_^ÁAT�GV‰šª�+ëâÔ:?bc òFrÚÉ’Ð(žñÜêíÑoý¡–Žyèû,ŠÎ4võ/ž|¹R  §p°�j¥&9ÙH�Inˆ!ŒR~:€$δß0wâ ÊíÀëÇm7äôQ�é¹2ÒÖn÷¡ŒS ééC%ÅW˜HL—î¯.žqEa¼ûƒ+KFqJq]Ssô}üÎ'þ6 „._¡aÅ/h�*%€Ü™ÌÅ)Åu…ÃÁÖ›½,Ž‹î¿ØÜÌbÃol 54[¤rCre�>?>¥�K+vF±“ïËkÛ¯Håø*«UmÜhíœÛÝE­*ÕªF㩨dP”AÀWè_üÜ�2¾¼ à <%Â8g´Ë_ Lr+FFñr*q]ž9–Œx<Þe�¨{ÖÊû—UVëŽûP”K¸ÿüÿYU*èþ ÿu ñÌ—�ý´�‡qþ*�€2–»T¤À$·¢`§×…]Ò€ú±FûÞ”;�¿��‚îï./_.+³ªTð‹ ÿE[ýßÖöYŒöŠ1„²Ë R¤p…-P„dÿö¿~ŽŠåÚ £%8$i*¥äŒâ·âºÀŽÅÜŸ`‚CÈÀ×®£½8/=!ò¦šÌ;…�w¸B±>Ç™¨ZÖÍö ®XZ†ÐB�fL Å ÊÄHNCr�)ʧ1³Ð/•—øa”~Iõþag¾å†Jæ¾ul§`Ï5_ ÙòŽ ªQIHi’0Š“r_×ò0J¨ a¼PŒ&5b”ô« ¶¼Û'þÐΉ¥0§˜Ý¾Óè¹äcÆŸÅT¤»Œôdý+ö)KÖ(NvƬk§×EóŠŽ=p6!AoH®kCåÝ>à ˆ{p85Tü›ÚRT¿r…†Þúrü±ˆrr;§ÏZ±4 Fc5Åð”Bî™QlË”Qì > ¯\üÛ×ÐÜ›ÀG’ñ2’“ÚPEÇ^Þ®¦ »¬»8QÓ©äÎ"¬…cÎÀÓ"÷è`†�—ø;î�*\ 3ÄF™0ŠÅÇT¡Œâä}²3ødu_�º.? Ú-s�æ¥óW›ürÏà| ¨ËºSOî5‘Ç$)Y*!ý'-ñ!Áør¾,b÷ÜR3ÑΉãüI)$ ݼÏ.ñ>kß¾³{n'Ö¯ÇÝW×åÐÊ…yéÜ´pÚ3wBÙ�Éé#­í°ÃzÐ>¶ß2²ûs(òüó­?T׬6Þ’µ>§D€4àþ¼GàI«Æà“„1ã\§A£A…Þ�QìÏ¡Hò ƒæ¡×qúª–6öËãXË›~SË“ÊÄ,¨ø�«Œ�ß#»8ÍAÎ*ÿ¶×QpÛwðj–üÀgg½w3¼ÏZÝ×Àg�‚Ïšæ�ÏÓÇZÛáß„Ïþ†>®ë VÉb)9AÒ¬”�úP,µá0]ó’Q\e¼âçà4�Ú˜Û¾%®›¨å�¦o ü@ùè€îO°h7‡’o�*ð2¹ÑlP©]¡ç¥vÎ{7µy–Úµ+Ñmûg†Ù(ï¶`©íœnÛjÙkNZjkŒ�TGª¬ƒIñE ìâø·‚“­(ÞÁâ ®D{Û¤+¹š¸ž©7{‘w"Js¡D€‚¶gF1¨Ë§z%à£Lú#|Üj-¯ùÀG€¢èûF»9M7Sßé}ï2ëLÁÏíäðY‹ërx:ì©iþ”²GI~�íä×Ùß–Ý–‘Ýæ�F~�­îë,öîY8WÀ@Ó=–b“ˆ »0tX°Í£hW7m¡”/éŸ3 ¼ 0¼ˆó<|  ¦ãÔ†�²^§Êj­7{5&Õ6üà%Q"@ÁÏ(^A ›½ÃðÆ3ˆŽEtàùJýÙ?g•Ý þ¾CåÆI™äõKÜF¬ªÂÿ$RxÃx98À㢈!¬êôªuïÄdÑ1ÁÿŸøBˆÏˆàÅ áJùpÓV.î*¿@0�G K¨ÂtsHwñ½$%k°N÷îËF‰KFK½!„×q(õþ,�â¹ÄšÈbƒðë¬P^$à²Ë à�>„  t RëÁ^¯ªÂCDœ ^.²ü7S,BÊIÁ©: ôTõÊŠ©'÷H2é�åz~£¨A@ê�¦XºV®åÃ8‘Ê;]²bu|ÑÊ �Št#:ÈQ|½›…Kj²Ã.° ç×\#Xœ`4:oñ†Ç �$ãMäq=±‡�ŒšA@êO¤Øç¬¬‹Uµ½·8ry ñäÁxRÄ¿S}{¥ŒRºR¬”MÕÆ•kY~[Ë%§þÄ�ª "t¤GàF/"€ ¸¤(Y)V†=7ÐQ7·0`Â6X&‹£À�$¼h¢/  tüÁœRÜ_¶öéµDf endstream endobj 26 0 obj <> stream xœí�{pTÕÇÏæEBc @�<âb´ÂV*’¥«b!U±[ÖÔ±ÃRÛâ¶UY¦Ð™ÅY,ƒf¬èL�*+£Œ14vk›¡�(N|”.iŒÚ$K$�ÝÍc·³!iIroî¹÷ž{ûÛ{>2Ãå{>®»÷wïïw!1ˆõh0X]�"ÎX G"áÐZèqŬPd€�:I<á´Ú³ßb™ižœ=:P\PIŸßßà;U[ã}ÓãÙí~ҵŹÁn_e[n-²XÌæIÙi1çÎÏ€øwrh”Uizýþ3¾jk¼UQï;][œ�Úí+mˬ‹-óÍæœìTæ)×µ‡º{v�ü÷T@~yX�U ~³¯¾¶Ú[áñ”»Ë\¥N‡Ý^b+¶Z,æÜìdY1ˆ^³û¯‰š‰`Èœò>mœªô^`6çf'ý?çŒÁïþ®û mÑqÍ‹€N)ù[}¾ºÚw½‡Oöþ‘Ú™3÷÷J¬*ùÚÚØäíé�6¤€ðÐÞÆbZYZ�"wB›g²+­G¡ƒÐêD™äꆶ£”Ó ÐòDÈquA»QNÿ4h}‚L,ýÚŒ*6@ `Bi;´•ÔC+E¦ó<´õ| Úâp2œ~h#,xÚ㥤;þ íƒ _ÄÎã•tÇYh̰BËdœ½ZCöAë Åþ´¦\ˆ�@)ö&h ¬Yí4¹Äí€=ÀO­l§¡ hAïP§ÿ€^¿F¬tú ôâ5ã= §¦â÷¡—®%³`œž„^·¶< ÕZ ½j­i0éîô8ôšuà&��ƒ^°.<£§Ó·¡—«mãtsºè-èÅê‡^ï¯V@¯TO<º8½ÑPN#‘ÀåÚ;½Î£Q³dìòC­�^k<§‘ÈÛÚ:-0¢ÓH$œ§¡Ó|Ȧ^P6jæÔì6ªSíÚ-òÜ›zÙq½NgÛi$²ƒ½ÓéH›zÒ̺ÝbjÒ¦^¦ÜÊÔ)ÚFiƼÀÐ)âFiÆt2›¿DÝ(Íš5lœbo”fL% §™Nì�ÒŒaÐn�ÒŒyH¥Ó8i”fÌqE.Sn[60gŸî8½€Ød¶|§¦Ñ=fþ’:þ‘ÿ@§�U¶Ê·zôâßôóÏ©(gd·[|:2 åZ}:1ž“k5.;zY#»ÝâÏЉQp·L«·CF�Üý&ñgS³eIM«�ŒY[F&¼  ç*¿†ÚêSÐiñêù1¥Ô_@GEEè*©¶~è ¨WÓH-ä¯ûä �:«:%6º¥¥N‰Ã‰^méGRjºF{ØZ$%5ñu茨èï‹B÷K~TwAçDÅÇw=}`ÓtI©N蜨h™))4ÊjC¶£+%ôM*©E†ïŸ”Ũ¤Îá/ýå°�Jêÿ‚Î‰ŠƒT{±fœ€Î‰Š¿Sík•t:'*šr©þÿÿtNTtΣ’º:'*úéFÙWñU9)[çùºùÇU9ËE¾Yí�ކ˜£"V ™ 3¢ üF@9âDZò½ªT Ú¼:f^³º:fúÄ¿ � 5¿±jjƒN†™À"Zùvuj tACÍ—YÂVmÐÁp³AØêUйps.UX+ߪZva«UйpsZ¸9ø×й�³RÐê]б�sRÐêTèXع]PëYèXÈ9"hõ èXØ|zÍǬTòG!«Ë¡S¡çëV§@‡BO»ß·õ²‘Z› SÅÝ�#�c{ :R<úÓ«› Å}W·º:P\Ðan5:P\X0â+ :QÍ¢˜CbR ù:^n·Z� -o‰K%èph±Žaut8¬C*ϰ•1öéÖ§ ãá¤~ì³BöBçÃɨÇÃù t>”4Šl0Ä7 ¢DêæT>Ó.ŸsiVÉIèˆqJIåɧ]d,èÖAgÄÇVI©Ä�]“¤­&óÓ×eò”´TBø¡Öòè™Acõè˜ÈØC#•<ýTç‘ë sââ•T’Ø :«¤:(&SJ%eÐI1Aw;!¤:)"þF+•äCGEÄÔV.@gEÃû4‡[ ®hù½Ô‡ù{VJþIu¸ÝE©üñ -t‡[FÉâRii¢:†y€oóãXhùµT²†ßPÒ’Nou?8”’ÍôR ù€sEÅ…l9V¯n FçÜ«<бc—©„L.ûüB]‰‰|ëtðX&(¶åª %�ÐÙc—] ¥BÒœíÐéc”Þ«”[%$§ŒßQ®F*!dz9ŸnEx®J«„ÜÀ�hÉ«ª¥FGÜù¡âÃYÈÂ*I²ó½/ÁËD*!$ÝÉü�%¬¬’ëæ�³/rŒ�Ôè)X¼ŠàN¦V ¯b£|4öp•L¶3Ћçû¬¥BRç¡—Ë™$ ¬2Á„^$£w¬b„‘«Xéá*å·Š}T;©Ñ*Ö˜ãÙÃUª0fû˜¶R�YÅÒ W©ÆpUìN¤®Ší™®�UB–¨ŠÝ­—Ôhëƒ^­NôÑ W1"uƒ1ªØ—õ”J™ø¤Þņ¯×Ù*!æÌ«Ø`ŒmY©»TæUlWÅÝ‘#1µ L!„U†Ulkyñ¸[»#¯$/Ž¡ÖoáÃÖt€IÛè.N"$³5âI"Ä;Z—BYU_ÅúÊ ‡˜nÞ?ðxØúüÏcãqn�Œá*öäº÷×—æ ]± &�}W•Ø­¤Ší¯v^-vÁ´˜Xþ„ù;@ÙÈ­bƒ^ÇWƼàÝmZÙ¢e­nòÄ‘SÅvU”H? žüò!üýt•†¤Ø©Nyo+·ÑMؘ°÷®Ý›4WFÅÄ�RUlÓÓKèGAÉBØV„&-]ÉÁüòUì§®2ïU²þ §Å‘ôieI> ŽG<±¹@ÉåJô~¥Óå?;ôÁð³·£œÑUlm©âç”yÚl^ð7××V{+ÊÝe®R§£ÄVl-´äf'2nð!gÐÍÖ‹J’~ÔrIþP•}ä9°²¸LùèbÀÿ™¯ö¨÷uÏžç\[œ?µ¯\a-´Ì2ggŽý/ÚJ»ÞU±5`ýЯVÿÁ{Õ¾N_Ð-á.äoò�8æ­ðìu»¶:²¯ºÇºØ2Û> stream xœí]û[ÓÈ÷öOïó¥Í½¨Èºâª¬.Ðf2“¶€xç²ÈEQ( ¶ÉLÚrU]ïý~NÂ"Ë­¡Mšú>çÙg÷‡ÕdN3óÎ9ï9çܹ3�P; µS™<¶xDy•FºÌ ª�j ÔN¹˜)iTÔ¨DX¤Ë�)j¦€Œ ­ß!"p´„ilø­„©Œü'b2²šQ>è§kÀGÈ5S!¬?ýyŠþì\“1kFy!9¾=úð ²ÆxD¯Ý[ž[,Î-Ÿd´?X‘01 tŒÐá¹õb±ôc6à=${o1›4:ÞŸ[,ŽÌ»zgIÖ¯™Åb15¶*¨ xÚÐŒòp¸cFÆÞïºÞ±Á¹/—z ŠÎÕ”0qƒú„ŠWÐú%uEP³R"à“šy­,²w¨MÛA S[œ� ìXâ|æ-µ²‡`ÇÐZÙ+9²ðM!LPáS’tïY´lK5ÜDöNdÏèf÷ÄÆ…\WE�†cYVëV“ž õ,yþ5 "ä>Œ ©üLÞí¨=5~^Hå$�J=ó‘>�µ4;i\RÙ;þ§~#<™¡ž%ž°SœíkÜ”°!6ž9Ùø.jm]î-È:hišn¿òöѲ§WJöޱÙÂöƒ™O×î-‹˜Ê:u$‚‚J¹ØiGº@ù¬vgºœ#þP›Ém_»·,ë,Գч< ¡;d/ª{CöŽ·Iº™ß8ŸÊÉö)惛»æ/Üškk›ôê�‚ gømÿùhÅÛuK¶;Öd~ç±&ž}/Ùûã®gd¯¤�,|ëZ1UlaX[Û¤ÒõZÐhÕkT 4ožOæž[[~,[— “ÓL¯j—ì•Ù+Ïfòp\¹»$iTÆàwP‰#CŠg•®O^­:hk›lîZà±%b6²ðÝ¿³>°PÎϬò'÷›ì•´Iógr|£9i)2ƒJׂ¤\*î}Vñ–¿^ÂÆ¥ÓÞ‰~¯Õ£ÙÏÞ¹òK؃oÙ«è>R‰¥ �¸ùhÕ €@440À¥^ بåà° ±æxF&ÌÃðÈñö÷«¯† ¼L<ðþn÷øSuìyn«oêãe;9(ê�5*CÐ3bjÞ#�yƒ0ÊóÀ” >íϨ�g¾7',ÐN{¡ñØ!{Õú麱'™ÚÈ[™@´YШ˜š±‘[N×D|¡â%íMå%LÏ­òâLÑÍ‹ÝyE§¡P1Üú¾’ Šì•4ç ‰†+3¯Åb±sp™ Z*ì(«e�%Ç7Y™ik«9i *�\]«äE òHÕƒøð/e5ñXáP†=·¶DÍNæöNyâzOaÊÙר'{%m7>,ƒÔÍŽ£ŠâÃÝ•²º:68÷%š`Bꕇ±nÎ.±‘ë„ì•´½ña› @|8’JŸtY f®C¦#îNYí·‘±uIZî•ßw¼£‚Zgd¯¤=·¶z'?4'�óêÉVlGY­ÑÖÞ(«}µ¶»K‚êý}6\Ïdï(}ýýúýeÙN†ÚOàúJsÚk�ìê©Q+ " áÕãÄ–Cöäz&{{mìõ÷ö‡+N­(t ‹³pç \Á¯C(­zÿ¹g²«ÊßHÑ¡@ÛC½Ö.²Wû‘½’Kt«NyÇé ²NÚ'PD¦m%XçЛÀ_g× æEgñEÔd×Mdï �g¾ß|´ê|類%�œØé°qÚŠ"óbw¥Êjoí¯þ5AƒBW?\îÜ9E7Õ¼ZodÏqºD¨ˆlk"W^~'ÔN#1“‹ÃÿÄ eµ‡v>iE°Ù¢­úâøs碉lK_F"´^ÈÞ>§‡¹°ž/;©ÇÅ€ ʺ—ÊjOlÚÚ1ô7ø][÷Úç;héËȺYdo<óÎtHcA×—°Æ*qºMu@Y­$˜çÊêÊ­?ý9š°Zð²¯]Mj?²·Ïé‘x6«´×�-¨Æ ¬~‘«žìÊ¥áÑuCù¶w~>Nd¯6ÉÞ“�."Ïœ¾WY-c6úÚGeuÙvåNÁjà‘“�D ’½}NDza/œî ÅNõÊ:»=廲º KŠ"¦|§ÅÇ|§ý"{5Èš0~v®‰ÐÎb˜Nù¶‡­ü8Õh޽–1½ñ°æŽxÇF_—‰%!ÆwZ^½õQ²—€4e°doŸÓ…�zÁIFÐàçt>aùTE ‹ .»é$ÃÅ@Jz¹¯°ïy‘ÛŠê� I�­–ב&ŒæC(} ÙÛuºR“Nw02÷>>¸,A³¾Z¢ì³øãwPùå.aŸ¦‰ñC"wž}Ttjïå´ß ¡4¯e�ì(0ßëthÈ —šsú.à 5ÊÛ=üIÐÅòÇ[ko^PÍ)M‰9½ Úý¨‡ç¿üsÒ…bkoAÂ4Ö¿*ß*MY´doŠþÇéN�³Tó�Oan ‚†$2a>Z­)±ý®Í¶�j‚°^ºq ¯YœÎ=ŠÁ>žÿ*s:b…2Vl/Ùû5þ ®œ¾ 1–㺘͋Øo· 5˜Á~õ†Œë–�±hw›¼vÿ8AÝŸ�`b�¨Zå%CÆr9…« avĬ/§ï"ÔNÉðZÍ¿î§îcJ˜FuÖ;yœ°pŠþíÁjRYÍX[³‰!=+C&f]Ï;.‹5Kü®ß_€“”v“ÏÈØ” -9k �®+öDÝ2>|ˆì%³J"+âÓ3äº6‰_TgÐ Ý…ë…8$j£:+ùgÎä·£ Øð¹ë«U˜¥[°ö™"ÉÈ„þ5°x#…¡—_�¢n& HÈäUz«ÕÍŸ|ÿù?;}V/WÔgõ4Ä™*p`"~‹ÏŠøÍä·þÌ#"\ò±%j]÷¸Ü·(bi_j̦߅|k%õø�CüšVõËp†_}u:*] ¢jð.¤•{µ.ÿ–‘…o²­ˆÄOç ªòñ›Éo#èN9•Êš)«n{¾íKÔº´›ý«2fq�ÕßÕÌWT™ø ¦¿4',…0§[5w’Â: j0Mõ„ièIº)ÆÇhÕ´ýuŽXa”÷5â÷<·•&„òªá…æ7!Q«îOÔº´Äø{[ºI¹†÷ Í—ò¿ˆŸ×¿þôg˜jA(tëB¯ywÂ˽hê<•ã|ò~Ì–mÀIÔþ^n¢Ö?ëžØP0³¥§ŸÛ¨”'T¯±Þ_ÏØ¦ÓÕ¶j�|Ïvµ�+HÔúaƒk fˆä…�Díѵ�ØØëï†É¿œ?ƒØp¦´xž¨­ÜÚî.I˜FR¯ªÖüð YįDmyöðÅ'3˜}{:èå9µàQÖiGV…D­Kƒ ]2'"“K¥Ï¬„£ ØIÔ&¬À=¾k÷_|RtvòtÁb'Q;d¢vŸ©�ß Èß\U[4¨¨­�ÉÚN×n^£�²M_qE]G¨¶µi§ÑSG¦)Öp½�¸¤Ö\¢vdá{”¸íÚÝ@Ù5»õq-%jSO7$èÌsæt¹Õ„SQ«èÖ@º†Æµüqo™GŒÇgH‹[}4uµ–¨M¶%L9½ÀáÒ(Mp£5SY«�iËï¾FL$ŒÓËi¿Ù€Kð( rwÌ$bJ„žOZdt=ؘž6òÎ.ÌlÜè}o§D»† A:gEJ„^êÉwO~pß@ÉC;ŸÈñ˜%ÆÖ‚^˜³‚b±ø÷ÜûäøgO<�M0§ö³oêcÕÆ1C––@—õᲺ¬7P  çáoëüõUE7[ú2‚jFuuqíÞòƒ™O~·|L<�><ÎôJœ]´ôe¢‰l4Ó ùN(„Œ&à®Ý1¸VIË…ãíb*ÏifrÌÕxåüøÝn†&hf8–5Hï^è¶RO7¼�ýŽ.|“ ³�žFžÚB8–åì‰Æ695koôÚýåG³Ÿ=‘uÁˆyÍìXjìö5 Nµ§uÇA·Ïk¦¢C¿”Ρ7•DžÙÕ#] Jn :µÓ¦N“‹Cý;7DûVøÛíü�érndt]"Ðõ«fg5p\Üà‘yA[B¨ÈiFT‡Q&kî7�iíU›ãÚŒ:BÅ+h½U[µ”geÍ”0»Ò·øðŧ’L cpMÆŒSÍ3ØEç4üŽ !õ240 ¨0§>ª[É'Geˆúg?ÃpäF+õÓ‚ÐÀ@¸÷×�AgÅ!âÔ“�™Üv€ûBÇA×î†0ã´!g¶ÀÒpFÖ¡?ØæóÜH20ã�~¡�­þ”BÀ‘6"ñ¬¢3Iƒ‘¬3‡"Öu íÿd‹ñ` endstream endobj 28 0 obj <> stream xœÍ\klTEžmÁ.DPyøàM´* E#Ñ‚J$Q“òPŠI[£QüG)5&4D¡@"PH°E"Á‚)P4` iJZ,Dä!ÁF±-Ð}Ü;÷î«;f»Ûî}Ì{÷öúýÜ�9çÛ¹óÍ9gfî�Mx·ŽÍª=ç°3¶ë^·9p¡ Ñ6Þå6 œGHW*¹Mƒ�·‚!ØU6Àm", RQê?Å·©0ðe%©^Xà6:¦@”l™é‚ÿܺqœ-Ï÷Eqõ×ǦeÇú�o_Ë9¥ƒß=ì433fC„à|®¦)9¥ÖöŒpœ]Ão%œj%\�¿ˆ™"Vßé8Á<'ÂI%Wñ´NË)5Pžç<É*”^—»r8šŸCVo”æöÏÂô) ÑqEÐÆ¯;ÎsH‡Á¡ÖÄN9Ìrê£Ú:Ça¢Gu£¿ÐÕ1Ì9õýÈÓS�äù�bv½YÀê2;¤ŵ#ããY`Õ0ê2C£]N)Äôºû�á™ßÇ9Ò/•Þ!ÌsT€Ó¼ºƒ�KsËÉ€`¨¾H,¾æž‰ò‡/lìà–“ñàÍj‘ÂõSþáÐGlÉÉ€�Ö¸œ7¾ÎðÑI´ò›Q�øš¬Ž9q˜hf™¨œ àŠ¯ž“a~‹ÚûD;^ 9ÀޝkY!ɈÀSdCRr2§Æ×BZ*bCˆQ& YÂ"ª^[Mˆ¯¦ê˜�fÚ³‘—“P?‚�¯ :Gç>to¤]š�œ ˆëe6Û«D&(B~ê¾²WÌ зÊk5] ¨Ô-{`{¦rJî±Ù÷‘ãªc®Sy‚É’Ñ) G€ƒB!ô-�(8›M5PŽ�¦ïˆ.Ѱ”At)o†¥¬Àý‰Âs?È:MÈ“×=‘&ð^!WÇèÌýYY9©ÁuÄõ:ñ@ÒÈâ)�h4ÁBñ"Ʊ©/!'5XE9Ÿ`VÇø_b–�&xŽ»øH#<”MTPNŠREß|ß.“<¶±yP# '&M0_*„ìã!Ê/'�IŒ–Z—••6Û‡êð&Q•ªsÒ9§BrDý/˜ •jðq¼ ŠœtmÇb܃JÙz!l ¨» ï‚(' rÓ…ÒÛš å()¯c}ä$B «Ž ˆï1[š–¶v[Öƒm9iÚ–»¹iÏ÷’¡à2³©5 KêZ¬»œÄhð‘|A«N0›jJ~Š?”m¶ÒÜ!xÄtP~#K1ï {“�&¼ëç £œtašx*¥÷‡Nš-Íõ'?†…8?·¥å$C3�Eª`)ŸB¸Ülgs*Ÿ�·bwá{å¤k;î“¡ ˜zC"eFÈÿœÙÌ•Þ/ì‘NRNÐŒü]tÛ¡gD͵ì°ôêq3ç¥9Sš ’�ÔE³�…iµÀu8'KtíóŒo¿IH*¾Ólb¯a¦Ã0>òª²rIOXR�Åf�†ï¢‡²A‰QIAóø8SèQ�¼â:ú¢Ðã÷™{—™fyü"Ï>Yäå§!ÿkæÎ æï•žJÞšY­·œTäX£ÏÙ;£|’Ò}¯Z;N³fÆpƒ£D¹$Øó³ [²r–é(V”Ò:Š0Ýšlí¢Gœ%Ê’¬ŒéäÅdßêl‡™zÖ“—)í:Þû�g÷iÄS­Òmv&x‹uüŠ¥ÿïþWmbµ/`¯P¢µnó ÷•ãºõ¸JëçTâňÊ[¦«ƒúV·1`a‹’>°jw)eæÃ“‡µÔz¥>ã6©‡±Ä‹³®là‰áуZ¸~b¦Vþi¬¨Q endstream endobj 29 0 obj <> stream xœí�ÛnÜF†ïç)ú:ÀR} ›$ °,ÉØ‹,àD@ö6ð:kgí8À>þB£‘5”æãÔOöpÆŽc �Ufwuõ¡þ®SW1õëÿœwÞý­ÚúkÛG÷æýêãꎛƻû\umã>½]ýòƒû°ú¸JUˆÍúÛÇŸÞ¼_w÷ç§Wîþ‡OïVg¯’{÷Çêì¿øùó§?ß|vççg?¾üû•óîââòê庛.d|“ïzømõzõz»ûèûꎷnÿU}vÛÿÿé•{þËG¾.oWg?ÿ÷×ççg/Þ|þó×ÿܾýßgw~s}s}¼ºpîŽÉ³›Ú…èn[…{‰—ÛP娷.öîöýêÜ{__¸Û¯®¼Ôí¿Ü¹÷éþ—mÕø¦kúú ¡n¼¯/½¯ûõ?aãå6†�\ßÎá¿õ¡jëàÓž„|$þB¨êÚ}ü5ÉûúÅ‘xŒMU7©�{eè}hgðødKØwd×˾αuU©]ïˆg¿œ²#Br1T)=ÙU¸Û¬­ !T¹{�JØ!ŸÖ¿ ±jûÜGß=Êë%R®‰3R"R®�ò‚(Éã7=r}cŸûŸoIOZ¯!¹ÐU9Ó åXµ]雥ÐÝ�*T¡Om“ÃãxQ6‡Þʦ‹”ÍþØEy‰à79ØÌ…Ö~Ãý<¬ áÄgnVƒ_ÏëO¯ÜýŸÞ)ë£v!U)Þ«~X$ýøêh6ê­ïsW‡úéâØAð@Ø´¿ã‹K $jj³¯…¦6³µƒp]nØ}�M%"lÖðŽ>Z"ÔÔÔ�Ü}�}l¶ÂB”¥K_àDñ|trS8òí•s|Ž ïMnwp›0âvSƒ%jkꆚz!7å©©ž¾ v6EBt>sä ¾¬vSSƒÎ}à ÞÈãèT‘0Er-�¾Àu5‡i]Mè|»©®±ÛúxAú› &Yᎌ›Â©½‚¦«Ý¶v{¹ók;þyÎád0l;14c`‡Oy;ºªdý† \VJ +°)BAÌ.B0êƒe… 8Á d;8꜅¨Ï9â&¹)–.É ñ³KJ‰uh^àø'åªkv;&56 L=6�@"IÄU >'œM¿¡&QÇ‘RCM]»ˆ7æ©1“Ø55ʬ$¬ •h ƒ¦Pº´£BAt-Ø[°¿Ãà�;ëéÞЭj¼6T®ÐTJYmŠa±‹ \;ŒÿT±'41àÈ™€ì&^ 2Ìcx„ÒE“~a‚Gxâñ�X`px´@às¨ qE¶VàùÎòM—`Û#5…¸ÉdI°�6ÒìƒCf`¡¢Wp1Ø0�i‰¾¨c»iGÙ°@K�»$Ý„e&ø,hVÂ97Ùi&oµS´¡4¡0¦Ñ�¨§u3Æ1M>xG‘ _H÷òLðoɲÒû`vegO”¼à%’™#:<!�]3—"» M%xò)/;AøÎnÒo¨LãÀ+-ƒÝhºhÏs1¡õh Ùm8Ç�(ûÐ-†´vs>PàèˆÔhúbйɀ3ÓUX±˜©$÷£°‚4{À˼¬”&„¨x#5Ø5…f }äœ: úÊðßÉ`�‚ìÚ.ÁxÊã!ˆgÞuá¢��]>Ì7¡©Ä4r[ Z]L#Ç»îLG !”`ri úÀ‘Ó$Ð1Sí4©�·¨Ôdb`¹ÊD“Á`‚Y)AS%ª¸ÏIˆˆ´Øt…1;{ܼ§]ºÑÚ °BV|zX¨ÍÉoóÀÈ&† \•si°ž¦êaºÌ.‰$}‹±&å#”)�`^`ÇLÓ³ Óè¦gÓíØ¤ŽgÞŽmbŸw;6YvÐm2aɾ�ÒåÀ]³›¬G¦P»]:¥È�¥¯]¶ˆ`Šîþ�/R²q°A(É�ǽ~ewö£úl°)9RB·¡Lè\ò,—Å´ˆEdi´t„Á×ÿ£Â£’éM $ùð| ^›uÝSÐ…Pìpõ =it‰¢XÈ.r¥%`äü];Æt�ußd¿¶9Žf*y=Õd�¢.ª¤è>,½v †_£Íq 8!ð¨à‚÷ }ß/pRpÓº2™ä’éIÖ'cš—Š5!eÚ¼q¨@g4ªš*ÊØ¤«S¨àŠm>¨s6~a˜ì¼Àó�Ùo^¾¶b`{Þù„ 8ŒËÑ/Rr ;ÛQ$0Ž×Ô †ø4íhþÔ„*)YX�¡¸LYrD‡Ì×–�'$YSéŸ ó�sNqRìÌÓrL›Ê7Õ÷´A°‚n_lJOÖ�†åªïLÈ×.ˆ´ÐDªãXYˆ%ýÁ¦X,“We53MjžK–]™�Æ¡/"|È\Rç¦Ðh“kùt“Å›ñG ôP\¶ŠáÕ\÷ôéÅ×¾Ç;Kg_ÊÞ¤¯Djjr9*A¹N(mgª`ò—ŠÛâù >t3‹dO¬±0&èåóT6¥Ö¢rL2 Â²r¡ªé?e€rz9‘“MËÎ{Šý]ÅwuôÀf ¹ê¼^Q |™GW™î`Å©•Ýq|Or¦:{`ôU"‡™éîvèyGGõu+ê2¥Œ{¹,¢ } 9 x –!˜¾JlAѦ>ôUR²DKÁWô7´Vè¥Ñ™£×P³úOØ“÷ûǃV¾Uò™}Ìš®²Q¢d�zV|²¯ƒ z¾ É �ß&8Ù¸­.CÜ‚¸y†�ÁŒ¢ìÊ%-Ê3Zô]91¯ìÊ,¸½ ¾ë*ŸÃ¼½Ë]'Jújå×4Ñ1ÉÈ :!È —ƒoݺg A·Ý~äç»Ø\†ŽIȾ™P{€M@•o‚«š\·®J¾ïÖÏÙ?ý�övCz§I}åCÊ;ôNÚ¡wÂCDCŠm—›ü…pyß¡ñ@¨k"´@H7ôöq¥L׳1¥íé:Ðëä!V}ɆutÚ@¯œmX0ÀGóQÏ™] ú%?¿¦;ÒôDýå*Z/¢­åŠ‘%A_¹7B¿•ÛÓóq¨šï3-�rˆ4Z£8 Ìôüƒö{ QE�X 1‡Y¯7hz¡D/Þ1@µØÔ¹ºùsñ‡;Êf=Ђ³½7oÁ `8A·qWwßÝÆ…t¨î6.‡šËËõÓxΑ°DîïéG£Ù› ¦<•¡G¦ëf©‚o¶–{ý»à3fzà§|¹©-øÛ ÖšÃølï™ SCè"çê.]9,~‚Kw1,�ó(ГÑPaè7>tWè5/e„2A),²€ŒÓ×dG3ªjÛ–,¬Vî­Óï>A�›Ì1Ê¥KA(z•$ŒÉ’‹CØÓM*£­m\™’5É(a|w +yíNp2ê%:1KMGA&«Ë ó\L$;Ù‡JOÓt£•ØÙsñ•EAèŽtåÉáä:n*øŒ-7E˜æDñ†loZ¯Ëný¹)½háÕØO’þ½ ºØ-z½þüWÁb$Dî\~{lB'„yh Âz­z RDA”†7!,^¯L¶Ç> stream xœ}�¿JÃPÅ· ":888dpÕ&iISpéŸX\[…´[’† ¶IH#úÒÅÅŹø ¢/àˆ..>‚ƒ8ËMÀ$žåûqî�ï~*H­ª0 Ó¤ßk+öp¤¬} ÙŽ7‹)—€ï·<û²ÿO®LëcæŸ@šØÃˆ1°ä|%ÙÍùFòe§ ’““~İ,±»Ä^œÈü3p8�\xÅ¿ÙðÃÓ`»ôˆˆ˜àSeÀ9g8TiÒÄ¢Kƒ:&G™cЦA�uZÙ´¨cf®!ûÌWF 0¿`å¶ðÜ;xšÃÎ{áíÝÃæ5<¾^Ñqì$Îo{•Z­ä&åÏM Ç„x  £¢aüþÔGÙ endstream endobj 33 0 obj <> stream xœìýÿSSgþ‡�ÿ_¼Þ3¯ìû=Ç ³/—©ã`¦2tv7elÝEȬ´‹u-mÅÚB-P)Æ/€¨ˆ"¢¤1ˆ &*¿@Z+ÐÚB[ÒòÙp‡ÛÓs’òíœ$×5�ôäääÎ!ÉÉ•ûyß÷ò2¤< ‹Ó3^B!„BHJdvn^o‡°äóõ9ŠvÙ²LfB!„BHj¥lo…gbRo«€Œfvn>{s^–Él)°¶´µ{&&uÿÕ…B!„Iººõ�vñ}¾¾Ñ®·[À:ÁôèqöLLfoÎËÞœ72æÒ»- K>_}£=ËdîêvèÝXƒ……EùS€2õ�ö……E½[ Ó3Þ,“9{s^z82@Ʋäó‰qmt™>ç€0Êʪڑ1—gb²«ÛÑÕí(Û[!ì²¥­}ÉçÓ»™ëCü¦�T¤K>Ÿ¥Àj)°êÝŽð/K�uzÆ«½uzÆ+ì²h—-…ÔrÉç£ �èsÐsd@–|>áŒõ�öðÎ(þ‚–kªüE,½äi⨥Ի!ðY¢a§ÞȘ+…†+z&&³Læ =°�¢X ¬e{+ôn˜�›RÙçˆü^Ó3ÞT™^µ«Û‘e2§èŒC”²½x¥A�K:F¡‡±Ü7™¯Ô»OðJƒ Ä0–>Ç……EÑ×iäåcðJ€ô¯4ñ#¹Þ±™É¯H?ðJ݉ïÄ;K>_eUm$sÉê^ ¦g¼]ݎʪZq¯¬ªíêvx&&õnd(x¥¾´´µ'b J±ö¥—¶Ä+bddÌe)°f™ÌA“½9Ϙ¿+&”Ù¹ùéo¦=kC�WêHBí/AÆ#x%@,ˆeÊöVh5³h—-%ŸŠâ °ˆ€Žà•º�œjU.m‰WD�R*»ºÊ5›–|>ÏĤøEQª¥®�MK>ŸxÊx%€Žà•É'™³ëM-ñJ€è�Ri)°†¨>ç€TË5—B^ïjÂq\}xÉç‹ügÕð�;=ãÅ+t¯L2R*[Úړ󈱯`GðJ€(XXX”¶¸¦=Õ7Ú‹vÙººAQœžñ*Kg³7ç•í­c ªýEåmÐbñ�B\ÝFÆ\•Uµbaå¢]¶–¶v±ÿ’Ï×ç(Û[!=ÔÕpvn¾²ªV\1åãÊãÈ}”m+ÚeS~«iik—ÿísˆÓ"¶ˆ„[Ѳ½̃9xe2Š—e2'Yñôz\-x%@È^È/ÙâC8h‚zV˜ý-V•·Êãh�f™Ì•UµËËËb ˆ*Úê�‘1—¸liS´Ë&»/eO¥*âVi¯ÊÝ„‹‡º&JQ5Ô¯LúÊÝÂÂb’ûIƒ‚WD�T¤XzДºWßhŸžñNÏxûœÒàTßTÃ9Å„«ž‰I醖«rÙ)Xßh÷LLJ‰Ç;ˆ%Qä“Ê2™••®J ”íTšföæ<±ç’Ï7=ã•Ñç;«NšøG}£½«Û12æ’Ç:uvn^)Â!xerD}Ç9&s\g(ðJ€(�JËBÙ §º Èÿ«ZÊ‹”Ü_ûs¨TKåM¡º2•C>ËöV(RN4ÔÕí�¥ªÚ¹äóíj”�ªª“£ôVÕS�OM;rS6‰"X€u�W&ãLž#/Ê•Uµº”÷à•Q ªðŒÙù´Î31©R¹;õ”·*;7•;+ûU²&•SÖÒ=røÇ]Ó+eÿ¦öqUM•ʩꊀ5Á+�¸Þ)ǃèNB×Í ^ á½rzÆÛÕí¹�”¯ SôÈ¥:äW‚ðû+»ü´�Tù�<¸vÄ¢TNù¸rK¨Òíã®é•Ú ²I*”~­õM^™Pt4¸ðèe»x%@È:Ø W“0³ëÈ}d©jNTU×^(Y“È»È-aä7T¤Ö+åãZ ¬AÛ)O…öé‡òÊ OAže)‘ÜhœŸ‚R¼2qˆËS˜™ÌõE—ê\¼ Â+R$^©l>‘<¢ry :ùOø›Âxåš‘��WíÒÊ÷"€(À+�fȉ„äÏ&„WD�T§'“Ñv&*'à U4«,�•3ó¬×+ÃôW†ñJ9êS>Ó²½áÛ)»£óJYR+»he¬îkr¤"xeÜI©$yõ¼ ä¬;^²µ^)§9�pFÙ(ê`µ[$kz¥ôYù¸‘�p\Ó+CU ÉÙ{„­‹*#í$? xe|™�›¿¦Ð¯�ÉTK¼ –|>9®0’.K­â­9� é\¡ö׎sŒ‹WÊ-‘¯¶¼¦W†º£œ½Gô–Šg¤ï*Ï© ^G’Ü÷Gdk¢¯§x%@tHÑ[sð‚ü…Sùy+‹<ƒ®ß±äóõ9”‡ ¿Þ‡<šrÕ’¸xå¢|šAûUíŒÅ+•õÈÓ«ûŠ`) ^/<“b¬b,‹VëHrÊwñJ€¨ŸÒá— ‘õ®Ú’N庪ùN¥^)«OåþªKåõB¥rqñJec*«jUí” ©¼TÝ¡WʈŸ…ƒJ4D^Ä…)És«Æ�%ŸO\ͧ–x%@ÔÌÎÍ+ÕRxP}£½¥­½lo…죔Rj±HiabáKyLeç£jÿúFûȘkzÆÛç�û«¾?ÄË+e—¥¼—gb²Ï9 §R­Þ%;OÅqä”>‘x¥rAÌT,70xeìˆa/©.•¡– *ˆÅ+bdÍ•8²7ç…ƒ)Jk‚Þ+èRËaö×zk¼¼2¨A+Ÿ�ªS9øTÙ‹¡WÊóªò"¯ŒQtáÜï)�¸'bUh¼ v»º¢›R(Uöæ¼²½õ�vÏÄdx9Zòùºº²S,çf‡x,ù@òQ´{ŠöýR!¶k±œ�›7i; Å�ÏʪZÑ΢]¶–¶öPÏnaa±²ªV>Џ~…i�’  YÀzÁ+cGTæèÝŠx"ì/å@x%Š5Wê€HÀ+cG¸’¨¢Šñ+jfçæUmnikÏÞœg)°&¢ñx%ÙYi)°êÝ€Ô¯ŒQÆfœ‹˜îÀ8Ž9=ã­¬ª 5dF\^TÖ‹W€XòùFÆ\rg: fм2^ˆŽ¿‘1—˜ŒNF9]"F,®9»S£ÊôŒ7¡�Ä+@_´“]´Ö^™ÄäFXˆD.#¢—áâ• /ÚõVôn@:€W&�‘1—XŽD/§n«Zž,Éà• /b†ÛúF»˜Aïæ¤ xe2™�›×ë§Q±ÌtÐåÉ’ ^ �~à•IF ·L~—åȘËóà•é^™d<“º,’%&€MòƒjÁ+Ò¼2ɈéFÆ\I~\ÝGV ðJ€ô¯L2K>_–ÉÜÕíHòãêò ZðJ€ô¯L>x¥¾s@|Á+“O&{¥˜>ˆyÝÒ‰ìÍyxe’Éd¯+­ô9ônÄ ƒèFF‘É^¹¼¼l)°í²éÝ ˆbÍ :�’L†{eK[»VÒ€¸P¶·"{s“¨$™ ÷Ê……ÅìÍyÙ›ófçæõn DÏ’ÏWYUk×È(2Ü+Å(K¡– ‹z·¢aÉç+ÚeË2™ëíz·%Á+åİY&sÙÞŠ®n‡gbrzÆK!„B1~úœÂ(V©#x¥`aa±¾Ñ.^�„B!„�Jöæ¼úF; ê^©baaQ÷Ÿ\!„Ä=ýC¯Yßн„B½ðJȬ;‹³Lf½[�žà•� üÏŸ²³Læ‰õn@‚W@Úóý‹bNÙÞwõn @‚W@ÚS¶÷]á•ÿ»áÿôn @‚W@Úó¿þOÎøý‹z7 ÝÀ+ ½‘E°”Â$¼ÒYK),@‚À+ ½QÁR �ðJHcTE°”Â$¼ÒU¬ˆiCŽÞíH+ðJHc6ü9Wë•”ÂļҘ R™e2W×ÔéÝ4€ô¯€t¥º¦.”Wnøs®Þ­HðJHWBÁŠèÝ:€ô¯€t%ŒTR GðJHKÂÁR _ðJHKÂÁR GðJHKÖ”JJaâ^ éÇšE°”ÂļÒ�M¹–H¼’RX€¸€W@úQ¶÷ÝmùVeþÙþá–ª�Ûò­ß¿x¡wcR¼2�mùVz'^ ™^ �8ðJÈðJ€Ä�W@&€W$¼2¼ qà•� à•‰¯€L¯Hx%dx%@âÀ+ øß ÿ‡W$¼2�,“9Ëd^òùôn@‚W@Ú32ê^陘Ի-i^ iÏÆM[„WÖ7Úõn @‚W@zS´Ë–e2ÿek~eUmöæ¼Ù¹y½[�nà•�ÆT×|že2ÿ?ÿߟ\X˜�›ÏÞœ—½9�Q–ñ¯€4ãéôÌeÇ•êšÏÿ´1'ËdþŸ?™\X7�ŒùZí²-,,êÝL€ô!Ëd¾Ðíø}y9™Á+%³só-mí–«øC!$¾yõµÂ§Ó3ÊÞ>瀸©¾ÑÞ瘞ñb´Ð¥)GÀ+_NfðÊååå%Ÿ¯²ªV|·)Úekikïêv�8fïþâôælyuïþü„&ûÞ­4­ôîe™Ì–|kÑ.[JçXsÛeÇÙM©bzÆ[¶·Bwç%$L*«jûœ&¤ 1zåoQ¯\òùÄ<õ�vj±âÎ’ÏWßhÂÎ‘à™˜GÆ\õ=vzÆë™˜LÜ\#c.Ý{¾HÊÅ31YßhÏÞœ'.dõ–€ÔExetzu2Ü+—|>q±èsèÝ–ôD:»Þ H <“Y&3¥ Q³Í{R¼2ùtu;²Læ‘1—Þ IOÄ7d¤ r,ÖìÍyÔN1ÓïP0>Y&sg·Ã÷ûrüó[Èd¸WfoγXõnEÚ"Ö§£j BÄ·ÖLþL08Ó3^Þ¤`|ü^yÑÆ‘Lþx\XXÌä§ŸÄ\z· eü`dŠvÙ²7çéÝ €pDâ•KñN&‹•øÕÑ31©wCÒ–L~uD�˜äJïV@8øýŒO–É|þ¢#îæˆW†BxåôŒW'âô2!@ä”í­(ÚeÓ»Q¯Î—02IöÊ_W‚WriHœ^€õR¶·¢lo…Þ­€ppuã#¼RèÞ¯¾$¯äÒ� 8½ë¯0>\ÝÀø¼2YF‰WriH(œ^€õ‚W®n`|”^ùK²‚WriHœ^€õ‚W®n`|²LæsI3J¼’KCBáô¬¼Àøpu㓯ü9h–^¯äÒ� 8½ë¯0>\ÝÀød™Ì]¥ô%!x%—†ÁéX/x%€ñáêÆ¯L2\ §`½à•Ƈ«á•‹KËÉ ^É¥!ApzÖ ^ `|¸º€ñÁ+“ —†„ÂéX/x%€ñáêÆ'œWþºF¢ ^É¥!ApzÖ ^ `|¸º€ñÉ2™Ï^pDmˆxåzáÒ�P8½ë¯0>\ÝÀøà•I†KCBáô¬¼Àøpuã#¼ò§_—“¼’KC‚àô¬¼ÀøpuãƒW&. …Ó °^ðJãÃÕ ŒOÀ+Y•¼’KC‚àô¬¼Àøpuã“e2·_p$BñÊ piH(œ^€õ‚W®n`|’é•/VƒWriHœ^€õ‚W®n`|²Læ3/Ò—„à•\§`½à•Ƈ«ŸH½òçx¯äÒ� 8½ë¯0>\ÝÀøø½²Óñâçå’¼’KC‚àô¬¼Àøpuã#¼2™R‰WriHœ^€õ‚W®n`|âî•ßG¼’KC‚àô¬¼Àøpuã“e2ŸîtD"ƒq ^É¥!ApzÖ ^ `|¸º€ññ{åyÇ÷‹ËÉ ^É¥!ApzÖ ^ `|¸º€ñÉ2™O�wÌ/.'3x%—†ÁéX/x%€ñáêÆ¯L2\ §`½à•Ƈ«Ÿ¨½r.†à•\§`½à•Ƈ«á•ëvÃ…˜’É^9;7_¶·bvn^'œ^€õÒÒÖÞÒÖ®w+ x%Ÿ€WÆæ‰éá• ‹#c®ÊªšmùÖ,“9uóú›%e{+ºº ‹I8oK>ßÊy«-z³D÷çnœ­üZÚÚù�QÌÎÍ·´µï)¯ÈÞœ§û‹0-“½9oOyEeUmŸs`ÉçÓû�$ðJ0>Y&sÛyÇìÂr2c@¯¬o´‹/-rr K‹S=rrÅÓIt7DŸs@~ß++¶e,Û g¦ü]¾§=³sóò'©\‹µ¨´‚$.Ò1GÆ\zÿå’Á¢xÙëÝ€�à•K>_Yù»Y&sÉþ·O;Ûž\O�tw•ì;Ëd®o´'èÔ /²î9×¹äv/ß»GTY­?På?K»l¨e3=㔇šýžÅá'Ë$ÑiíqåZü"�ZÆ ÏÄdK[ûë»Juï•&$µòú›¶úF»gbRï71€Î„÷Ê牉q¼rÉç×Ðòê÷t7ÁD¤¼ú½�m!ã•åû1Ê5Ó×zÊ®ªjâþW#à™˜Ì2™7æä]qÏën[•Á)߯œ¼ìÍy ©Ž‘%Ÿ¯¥­]|C~õ�o×½÷ñ¹ºOd:üùt%5LmG}íÙúÏdÚý9´’ÏÛ”©ko¨;ÓP/sÚŸE¾8ý…ÈáÓ_>H£?‡OþR¦ípÓjŽ´>r2ûjŽúÓèOkã±Õom<ÞÒx¼åËã-_žøcš[¾lnþ²E™_¶®ä¤?M2m'šÚŽ7�RæXÓ镜y™#gŽi?v¤ýè‘³ÊØíŠœ[Íy»ýü‘@:Ws!�£šŽv­æ‚?Ç”é<"rüüËœ9·šŽ@ši9«Iû‘Öv»?gü9©ÌéÕœ²·©ÒÈ©“/sZ¤Õ~ºõ¨?-þœQ¤½y5'Dމœ=qììñ@:”9ȹ£/s^ľš#�ˆóáOÓñ "_ªÓÕ(r¢ëðË\ùŸî/Nt7hRâ’"—EêVòŸª#ù…�_c*«jø 2™,“ùä9ÇóŸ–“ãxeW·#Ëd>ÜqDwLPœSÎí…;²Læø~ïsù{BTé®l©ÑkÙçˆã_ ¶|+R©W®¸ç…Zêý*Ha·ø{~ÿyðí+/œ} ׯ-\¿öÓuçJúºÞÿãõþ®¯dàÇ��7V3øâÆà7†Vró‡7¿÷gx%·¾¼5?8²šÑùÁѹÁ1†nÏ Ýžõǵ÷ì�ûùÐ�ç7Eî>¿y÷»›÷V2þÝÍñgÃãφï¯ÄólØóíðÄj|{ëÁ7·&Wòð›[½þLù3òÈ;òhfäñjžÌŒ<™y:=útztzztú©?3+ñ>õ>ûf5ß>ûöñس•|÷xì»G·Ÿ¯föÑíÙ©Ûs+™ŸrùóÐõýJ~xèúaÒõÂ÷‹I÷�“î¸ZÉ‚ÈÄ�Å•ü“XÅ'G›ûúû®ã•x%^…WŽ<ùmäÉïçœüe±»lz¿­ôAxåwô¾DÇ ^)fWKãÎJ™í…;¶å[ãxêü¢Z[§»©¥VD—er&é…¤!ª§|ºëUƦ߳˜„9ÊÒ1÷Zʼnª«~©Ä+ñJ¼2&¯¼õä÷Ï›{ ò- ù¬Ë+'¦ç]¼®Þ“ç¾ÿV%å¼²s¸KwïKtjšëâX +f¥ëj:ª»©¥V<=þ¢kÆõ§e{+r-VÝÝ*Ó_hÛS^¡÷k!%ÙV`Ýœ¿ýë¯á•x%^¯¼õä÷üB3÷Bf"¼òÙOËaòøùbu�=ÂI±žý¸¼f â•bpe�»GwïKtN;ÛãX'&|ÜÓãÐÝÔR+ ££yåCù׿ýË^è.V±òˆÞ¯…ÔcÉçË2™«Î~u±¯Ä+ñÊxyå‘•â|FYB’e2·v8Â8 ÷{ßÖÕEÙÒÒ+u—¾$¤s¸+î^9ÝçÔÝÔR.yåCÁ+�¼2:ćy³û ^‰Wâ•qôÊËÃ^–@‚ÌdM¯<|¼]:£9'ï?•µ­ŽPiép|ûãòš1È·k¼2:ðJ¼$x¥‚WF‡¸^ž»‚Wâ•xe½òÖ£|ÑH2þéÂÊàî·*„TŽMx#qF¼r]éõôÖ4×Õ4×%t˜'^i�ä•q¯4BðÊèÁÞÅ~¼¯Ä+ñJ€Ø‰Ð+·æ[ã%•)á•Î)§Ð=e:‡»DœSÎø_–É\Ó\—i^¹0::ÝçYÕ]úðJˆ‚¸xå÷|k�ëÒ°÷Ò°7Éë`ö{÷U¿>¨Ù¡»$â•I¯Ä+ñJ¼ ޝüæÅr¨ì;P»æ>ë�AÞna¼Rê^¨lÈÉ­i®‹]0ãå•=îž0Âk(¯œîsÖ¨ÊÞ´EuJ-Û Zjëf‡t·?¼"'¯œò)�N™�9yÚû=‹É12¼23Á+ñÊH¼r¼ÿÖxÿ­©á»Ò+Þºw÷úè�ë£ÏÆëè•££�o zn zðJƒ°¦3žw ˆþJ¼2”]ÆâƒÎ)§èíõôÆrœ 9¹aÖL1ŽWŽœë\ó¬¦ñ &yåC‰Ú+¯¸ç7æä…/lÌÉKh÷å÷¼| }Õö¦Ž�$˜,^iâë•ÎoûÎŽt|Ö^h%G.½<Þ}óùu¼2 ^ùØëѵëç�œ8äÄ•“íS׿ÇîÄË+ŧDéî·¥W–î~[l¼s}TG¯ÜUòŽh^ `ÖôÊ©g‹âmûÕu—Üè�-y»Eâ•…¥ÅÊí½žÞÎá®ã=-±l—ßýZÂIz=½¢%÷ÊúUò¤Õ¨êk=%Š`ûZOU–ïWö`¶ÔÖéî€x%DBt^98å“R™k±6u H¼4ì=ÔìËŸ‰$Îõ.­LZ˜e2§úQ¼2:âå•gG;Jü;ÔÏ#ÿùìýžñn¼2A^yÏqeOñ¿‚žùBë_�<‹Wâ•IÃ?Çx‡#¼:®»D—¥ãºëé¼/F©Li¯Tæ@CµüôÖ×+�÷´ß+¥TfoÚ꾕åûå)MËy� òʇ8�W¶ö¸äKýÒ°W»C¿gQŠçÁ†öD{eŠ–¿â•1¯l¾~2’òž�ìg”WŠg�h¯ì=yzÍ3_h}ã§»žT÷Ê¿í(Î2™ïS `dÖôÊQ�·¹ÃQüÖË18ßikîphSüVEñ[þ{ý°F òv‹Ñ+e/aP¡;ÞÓR²ÿíí…;äqÊ«ßÓîÖãî),-.,->ÞÓ"7Š-ªÅ5Íuâ8rr K‹O;Û•�RXZ,;O·î÷5šWöµž’R¹äv‡ÚmÉí¶l+{V–ïFG»šŽv5 úˆ#ç:Å­r‹jÿ…ÑQO�£«éèÇWaŽ#"vPâ.¹Ýâ•åûËŠm]MG==Žè&2È+âHt^y¨Ù!^çûªí¡öépNæÚŠJ+š:”Bz¨ÙJÅM­=.¥9*÷¿4ìGÛmûke¥ØM)¹ƒS¾Ö×Á†ö¢RÿsÜWm?ÔìßyÚïY³5u „߹߳(ZRTZaÛ_+zpʇW&“ؽR)•ïzÿìH‡ó›¾áïoôÓwnä܇ö�s·çËêÎ4dˆW>H‚WÖU¾üqûÄg �®]_¸3þëøÄ·C·¾>ÙþÁÞ—_Û¶m{íÇ—j™’^)Nå•ÌÛ`4üGg3?,‡Ê‰³ŽH~Š” s(ƒ¼ÝbôÊ�'×¥6*]Ï9å,Ùÿv¨ó£*š :o�|èPÃ<w{Ö4×ÝÁh^)mqͱ“³ƒCõª<=¹eºÏæ¾eÅ�rÁ ûw5•çäVG`hg‘ug¨‡Öî0;8$¯L˜^W¼2£ˆÎ+6ÖÎ/´­K¦ä4;AoÕµJ�í÷,æZ¬ò,·«¢4ÐPÃ?CõŸv8'UwÙ˜“×áœÔîÙÔ1ôàù…¶èŠ~ñÊèˆÑ+O\o¸ 9¯œí:oÏÍç×ó‹ åŸxpæZ&xeÏ™“‰öʺÕÒŸ �·gð|·<óGšS×+‡nŒã•)^‹WÊŽÂw�²·QöŠÕIN;ÛkšëÄÔ:J+ lwù‹eûñž– ÕòrrÅÔ¯�Ã]5Íu²åÕï‰%Q å•Ò×ÂwV†JÔ^ÙR[§³9Ý甆´·QVêöµž[<=/_ü–meŶÊòýJÍ9׉Wf8Ñy¥,@]ïØÆ¨½R5ñlk�«¨´Bš¦è-*­�}�r€g~¡m_µ}_µ]i‚Z[lêtÐäZ¬ûªí²'T<´Ò�¥SËÇµí¯•�nª"¼2:bñJÇ“—�ï_ 3¬PË�9¯Ø>(wÜëÖzåõÉ+ §vî)ye{þ+ÛóËÞ/?|ê‹Ñ'ý¡¼rØsµ©íð›¶’-¯æoy5—­ä³Æš+7.h½òXkã±ÖơѯžÌŒ¸ïöoùòo¯ÛJ뿨uö_”^yÝy±¡¡v«%ÿï…Eûöï»ùuP¯œ¾³íxÓ»ÿÙgÝQ´ÕRPZb;u¬i|°Wé•÷o\=s숭$ðö9{ôˆˆðÊ»½Ãn¼pþÏ�©þ¾svûç?ºv¦ýüûù#öÞ¶¶P^9r®óBÓÑ MÇ~ûíÞøð¹—¿9¿s…™öPåÇb7[q™Ê+Ÿß¾wöH‹­¸,oÛkÙ›¶Øv¿e?Ô8ú•3F¯t]¿}Ò~z÷îoµüÕjýǾw*[Žžytçq¯ì8séı³'Ž�=~ìì‡Ö=ò<“^é¹;sìXGù¾�ÄÃU~Tôع£ÇÎ ¯ìê°;o?v^ë•_]u×Ô·¾Y²ocÎÖ×vì~³dß—Ç/ �M«¼rôþÜá]‡O\¹?÷ÑϽC�¾8ѽ³tÿÆœ­;K÷¿[Õ4úp¯ˆœ0^9½’ß.Þºï�<Ó«w ƒ¼ÝbôÊw�@í·îP­ú~­W TÖdžê!•&kÌñ•²Ó°¬Ø¶^©ŒÅ+…T*Õ¯¥¶NeŽÊH •ò+²ÈºSn\r»å3²l+À+3œ¨çƒUjÚ¾j{„2µWí ”·ªÆxJIT–éNù”ݬÊýåvÕþ²µ²‹³ß³¨|Örç~Ï¢TÑ0µÁxe|‰Å+ ô—–íŽe�‘ãÝ/«JTé¸zJë•­ŽoÌy%èþŸ5Ö¨¼2ðòû¸òÒWg´û÷¯¨å¾ýïhoºqí¢Ê+‡úºÍ!÷ô±&é•gŽ º�ðJñïí¶Mõ÷ɛαo[½Ö¼ ê•âò”½i‹è¯,[�¨§®²:ü:#?ݹÿUÛÙ¹ÛwUã+mÚÕ¾ßFÖÌß{�Wž´ïiÞ´uàÊ�Ö+ŸÜÿæï;þ©ÝyøÆ=á•7W{*U 3oÏýóµõ-Aïµ1gë¹î›J¯ìš75Ÿí;|â¢ö.¹ëMÏx%@„¯ŒDーÝbñÊ^O¯´¹òê÷ävY«òÁP·†÷Jå‘EÊ«ßÓîŸ*^Ý,¯Q{¥˜uV¹óÂè¨ôDÕqdפ×)—DQJ¥VQ×Õei�W>Ä‘8®3²1'϶¿V97l|½RÛÉÊ+mûk‹J+6æä©Ùþ ã(e¿§rª"¼2qÄâ•òµ*ׯ\¯WŽ<�>øníÊñ•Í�‰›^y5_zå]ï Ü¿óÊiåøÊ‘ûWåM÷¨¼R¨åµþ.9¾²ØV*o*¶•Þs;ÅàÊé©[/, \ \Né•%¥� Í'üîÁˆ_yo°W*ä·w‡åøJY«_©|�}ªMޝüáv ©Û¶h½RΔþ|ðæï÷ÆŸ¬^ã¶m{M®_¹.¯ÌÛöš8ÂõÎåøÊ'Ã.©–ߺ<ëòʧî‡ò©]¹Ð«_ÙrôŒ°Å¿[ÿ!½òá�'b£yÓÖ;#äøÊGžo¥Z^ëã+�ë¼Øþ8¾Rë•·FŸJ©›Vޝ<×’óŠÅªõJ¡–½C�äøÊ‹}ãòPx%@„øjw<Õ¨_Ð\îwowü³¬B¦îhûñvÇÄ7‹!å¼2| K‹{=½Ê;JÙ XÙÞ+µr´#5½½2üÝ¥WÊöH¯ Z¤*g¦U•ÂÊ*#í‘å:›ÊH¯\Wq¯A^ùGbñJ¥`lhW®Y)£’µ¨½2èd;kzåà”ONî*"½RÞE$”ÏKø¦*òPë]÷¯ŒŽ¨½R9¸2j¯<¶Z»çýrí¼=Ÿ4}è]ê=-¼²µë¸ØòÁ§´óöœºp"ð[Ÿ¿ËRí•—¾:£œ·çDË—ò¦{w®)çí©^íµ¼rù¬ðJÙYYRjÓÎÛs­; xe†¯Tz\‡sR©o*ÉŠÚ+ƒšc˜[/ {•mÐFë•kvz*ËhïLQ{åÏê•è­ÝA½òÊ£¯.�w_ïîQæ^·rÞž½_.rqøœÖ+/ �·¾Ws@xå§«¦ùÕ`§Ö+ïNºPÿa+Ñz¥gò†Ò+oÝúJl7ç¼¢š¶¥9 œ­'¾^yòD“ØÒv¢Ië•ßÜ·ÚJl‘{¥è¬Tzå]G@èê*?Rz¥‘që\§ðÊ MÇV÷¬ŽÂ+;Žªž:/k½ò™ë~àéì~k]^Y²ºeâÖ¸Ö+¿îº¸Èm^)*`³Læ»þÎÊ?xå#ϳGžgÊù`#÷Ê×vì[Æ|¯õJÙeÙx¼Kë•Úù`w–dÿë›�ñJ€H^ùäûå0¹Ôÿr ï0ùgYEøãÈäíû|°xe$‘óÁF7oO|½RYS$GMÊ"ØÙÁ!Uf$Á+3™øz¥L¿gQ9Ej’½R9›k®Å*—˜ Ú_)‡L®é•WÜó¾§lûkñÊ$µW^}ЄÜüü ^YT¶;ÔWzeÑžÀ>ÕG>i8Ý W~qú‹Ã§¿8|ê Ù_ùÆ¿J„W¾ù¯À�·aÏՠ댈[ÿúúëÚñ•ªuF¤W¾³ÿ•WŽ ­òÊÆúÏÄ–Oª¶­Œ¬|™cM§�¬3ÏR¹Wλni׃.³7mQz¥¼`ýêvÇ¥¿òý½��<œCA×·foÚ².¯Üjù«ØrÒ~ú¤ýt«ý´_ÙâÏ™ê‰[>?*¼RžŠHÖ‰Ü+W?3·]gäÚà¤ØáÓú“*¯,ûÏ'Z¯¬®?…W¬‹5½ÒóÍ¢yõë͇‡ì—ú]7ǽS³¾'ß/»Íß÷Öm—]™í—‚d^ƒ¼Ýâî•Ê%Bb¯ƒ ï•)4¾RøTä댨F>ÆÝ+åÏ¿rà¤PHÕd>òÈJÙŒ1yåCI�W*Ç-*3†ñJÙ£WÊ)[7æäiK[e´ý•A—ª j¾JSŽKðÊèˆË¼=Q{e¨i]U‘^ùZÑëbK¨õ+å]T^ù[i(¯<Ñòåš^)W®™È½2èú•�«³÷ Ÿï^ùëj�ÍÊŒ=�õ+å¼=Ñy¥­¸LÜýùí{A½R޾\—WFxŠvï.O‚Wî*y'¼W¾Qò•W>qQë• 'ºñJ€uðJ�úÉo_ýâát…Úgê¹ïoEþOÑ-Û­�ç—׌AÞn‰ðÊ8ÎÛ³½pGÚx¥üÅuÍRØ…ÑÑìM[,Û ¤ô…÷JÙ«¹WÊ{‰)wd¬jÄ¥lóºž)^™iDç•ýžÅÖך|rÄ¥T¶0óÞ´ö¸ââ•ò8á§l•w‘“¾FR¼*;añJ#‹W¾¸îô}ÛIl~Q¡Ê+¥Yìܳ{%%"oì)yã_/óiÓ§Â+·¼š¯¯WZw•”ØJƒÅ¶’½òÅêì=•{÷ ¯¼µú+ètŸSzåo÷^.½‹W¾¸;Ô+wXߌÅ+Kvÿ»d÷¿w‡HBû+ïÜ{†WèK–É|¬ÝÆ~æÿ­üƒÚðª84øj‘á^ßuFÒÆ+e)løî¿%·[Žj”f†yÓz½R¾.¹ÝÊ+÷‰qº!¼2CˆÂ+eG¤v!e¤¯mÌÉ“ënÈ Umç ¬G�Ñ+Ã<„l’ò.²ŸTµ¨¥H®Åš_h+*­OAÛ݉WêH\Ö¯¬=[ɼ=²S[;öl@;¾òÞJ”ëWÊ:X×£ëa¼rË«ùñõÊ�«sÎܺ¢_ùýJäú•±x¥O1{Ï/w\¿�ÊfÄtJ¯”ëWÞs|½¦WzoŽÙ£WJíÕ>„rÆZ¥uJmíq)ï¢íúTvªj©‹fÚö׆Ñm¼2ŽÄâ•rêž 9¯ ÌõÇâ•Wî^ŠÄ+å¼=ý·{´^91=´j‘êy{bôJ9oÏÕK‰öÊáó�Ê«'Û~ \ƒD-�Ò+åÔ=+K�„óÊŸîÜ׸Ï*?ùñ®G9oÏmGŸÖ+çïÌ+êy{ž¸§"ñʆÏ¿ÜNÞ}G¯”óöõÊž«�ºbí¼=x%@\È2™�¶;Í/‡ŠôÊ0ûˆÞõãÞHö4ÂÛ-^©ì=Ü^¸ãxOK¯§·s¸ëpÇ‘ 9¹Ú®Ì¸xåáŽ#«×÷ܚ溚æ:Õê'FðÊ…ÑQ˶ùÔÊŠm]MGå²}­§ä­Úa˜ò¦Êòýb}É‘s�–Õ)¢ðJyLywíJ—*o­?P%ìratT.V¢ô_¼23‰®V.Ô(ºù6´w8'…g‰å6d¿žrp¥ªó`C{¿g±ß³(z*ãå•R{s-V¹½Ã9)ò‰Ö+Ýßܸ1Ñ«ôJ¹ÎHÍ—Ÿj½²ëÊiqkyÅÞ¸xeçÙᕽ—Rt�‘ïºÆ{ã啾ñ»«ãý‹úN.4âÒ£ôÊßîÝ·¬Ž‚ìŒz�‘¯®ºµ^ùþG‡Å­-íWñJ€DÄ+çþ�òjE¬j»*ƒ÷ß+&¿ó…ßóÑœQÞn òJç”Sª¥6ª.Ÿx¥ì •QÄÁ+E�¤´*Ù›¶h eåL;ªT–ï—ÕªëõÊ–Ú:僆j°œ½Gxe¦õ¼=Jµ a^AJ›x�¯ÔÎ+ÿ-¦ñÑn ÿtTžxÅ=¯<ÂÆœÄ‘X惽âžoêP—*mNöå©28åS©e~¡M  A‹Ý+û=‹Ú•öWTZ!²Ã9)MP©½­=.¥!ªz$UOA©®òYlh�B*ñʨ‰Ñ+o¼h¾~RùG|½l÷Á£·öŸlí?ùy{CQÙnÙMéíÙ=8sMzåíÙ¡ê#ŸÈ[wî)iï;uûÛ—nž¯X‘ÊÿþMßz¯\öWÞ6üå©ÃRE¿ìt?¸?=40æ�R¹Ë_{+î^)»,Wä(¿¯»c~Êuo°÷˺Àò;vÍyF¥WÚW·çY  \}0p5r¯|16¢<¥²–Få•¿Ý»_WY-wÛ¶íµ{ß=äÄ]Gï•“íÇ?k�¿‚foÚòÓªT®äáÙÕRØìM[®wö|w{üû»“žþ›R*W‹`×á•Ï'f>>ø™lÏîÝÿ¾=àòÞŸ¸2¸ï�ÀÕªÉþJïƒg'޾ü1ª¸¤üÖ�»—/:÷îûPlùðÃ:YÛ}±?ðwß´upðþà çÁÄlP¯|ðð…ÜøÚŽÝýƒî=øÞ5þÜqÕ-¤2P;µ€W$á•apìáüËoöö±‡ó*£¼xÍ%¤ÒÿÃÞž^ǨJRu‰¡¼RivÓ}Αs�Ó}NíÆPû÷µžŠãÂQ´6’¦â•™C\Öé÷,^ö*‰“^öþWåÖ;q½æ+ t#.ÎÉHf»•Ç_ïCà•ñ"v¯|qÃñø«ü�…¡z«¥Ú/�óç¥WŽ>x·öƒP÷z­èõ;ßÜPzå=ïàûŸµÿ.[É݇‰ðÊçŠQ–AýöÞ°²v¬÷²jŸÈ½Ò7~Wþô*fì 啾ñû÷_‡_j9{ÓïÍå|°‹÷.ÜøYå'¡î²Ãúæ3—' ¯üvüÉÞ© uØ¿[ÿ¡¬ƒõ>xöäþ7}øy¨ý=w§¥WÞ¿«^ÇdpÐÊ+ÝãÏä(Km>­?éï¬Ä+Ú^9µÚeùÇkDž\³Ræ¯E¶ßùðJƘ^™�1È+âHâÖ¯$xe¢‰‹WŠõ+¿ì±—ø·\LD&¿¨ðóö†ïµÑùA­WºVr¦¯mçžÝŠ/¯”½WÞ|ñ˜û›Êñ•÷Ÿ {ž {¾>yáø›¶’?|ýxýuûÉý·ú¥2>^)çíy¾š;CWJJlÙŠe7KKl§�5}soX5¾òÇIw×¹ìM[l»m"ëòÊ«'ÛÄnÍŠZš ^é¿ÿbÌuⳆ=ÅÿR f¡õ�ÁóÝÚuF„W.Ü8ÐyYÎ +�òŒ½õ…çñ‹€T®Ï+ŸOÌ|7á½pêbÉJÕ«ÈVË_÷½sðüéîéû3*¯œyðÝ̃ïêëŽýmÇ?•ÍØ»ïÉ€T¼òñäÜÐàý�›¶þ£dïJÞ}Ê+L½¸ÿ`¾¦¾Ue—o–ìë¹ê¾?µ0.‚W$€,“Ù~Æñpn9|ìµTÿN¸§âîÌâšÇñgÖ(o7¼2:ðJ¼$x¥‚WFG½R9oÏ•G_]¿84{]9l¯tωy{n=íxÐj>Xé•rýÊ[ž«·î_•ëŒh½òñjT^9ýÔŸ™•¨¼òÛ'cß>{¶•WÎ>º-æíùîÁÈÔØõ0óÁþ8éþñ�û§•(ÇW.NÜùyâÎÏ«R¹fåOŠò˜P^©œváÎøÔµ�…;ãaÖ¯”^¹pÿ¡\ùÝíñ'7]r�­WŠ©^971=71=ȼR®3â¹ÿøÎ£PóÁJ¯”ëŒÜºqwâîÓ óÁúópþÑjäøÊ‡þüð0 •/½òÁÔ 9¬sð�kü¹gJÎQô¯¹ûèg•Wºýêz^  ~¯<íx8»¼fîN/¨µïÚS!{*7æäíÚSñï÷koÜõFrƒ¼ÝðÊèÀ+ñJ�à•F^ òÊ ëŒDâ•á×Ñz¥jýʤyåšëŒÄâ•�¯]_±ÊŠm¿+.‘xeÐõ+×ôJÕú•ñòÊðëŒh½2Ì:#±x¥r>X¼ Ñ„òÊÉDÆ o7¼2:ðJ¼$x¥‚WF^i4¯ünhpÛêºZ÷¼¯H-²Læ#§ µH¼R÷à•‰A^ùGðJ#¯Œ¼Ò ^ùÃí‘Ï+?R�¼z²í÷ñ{x%^ �Z¨¼ÒóÌ7p×;p×{gzQl¹3½(¶D­E>ÐÄ o7¼2:ðJ¼$x¥‚WF^i¯|伦œ°¢®ò£ßÆïâ•x%@Ê!¼Rßõ»^ñ±&79½ÆŒ=ªgí BeUíÆœ<ÝÅ*Ó_hÛS^¡÷k!õÀ+ñJ¼¯ˆ#Âï·¬Ê5·Wäý{–Éü~�]nÑFì#¢=”6y»-ù|Y&sÉþ·u÷¾D§¼ú½ø‰Yò­–mº›Zj¥¥Öo÷³sóqüC€îô9²Læç¤în•±œò’×7Úõ~-¤#c®,“ùÌà x%^‰WÆÑ+¯{ òE É„òÊu­-"³1'/…¼r¥¯¡fCN®sÊ©»ú%.½žÞ¸éjik÷+Òà�î²–B±l+°ä[ãøW#°°àÿþ°¯Ú®»^elš:üj?2æÒûµ�zˆâ“ϯ4á•x%^G¯<眤< 2“P^ùæ¿*6æä­×+û\ÞñgËkÆ8^é™ð¿÷·îHWµtN9·îˆûç›ø.mÙV°ävëîk)‘úU|õMWÊÊý“Æ´ö¸t7¬ Ì÷üÆœ¼müb-Y&ó?¾�Wâ•xe½òÆö8>H!²LæÆSŽP8öxñ½•×7þUÑxÊ&—‡&ïx}‘H¥¡¼R0)¯~OwŒ{zÜ=B*[ÚÚã~ÞDU‘u'j>KnwY±-Ëd®¬ªá*“–,ù|¯¿i£6ùiíñ eoΣ¼å(£y¥0˜½y«,è-,-NÝÈgñú®ÒD—÷wu;”ç­Èº³¬ØFÊŠmÙ›¶ˆsbÉ·Rþš ÌÎÍ‹‚X‘\‹µ¨´‚Ä=¹«<É•UµÔÄŽ²9ûÙÉ x%^‰WFí•WÝsB*�ö i¬é•æÆÄ¼(—MQ¯?Ûö9ºº•Uµe{+R7•Uµ}Î�……Ť�º‘1WW·£¾Ñ¾fÛJöìÕýü$-]Ý~±Ì4fçæ»º-míñz•ìÙk{k¿î/fC¥¾Ñ>2æÂ(ãHŸs@üBøvÝ{G[.Îôà•x%^¡Wö¹fÛ.�}ÔpFüÞeÀï·IÃï•mŽ{ß.«r7X®ÞöÍá6ÇkEþŸhÞ°U½£*¼ï2–¢]6¾ DNÝá#mg:ôn¤? ‹eåïF7µ�_ñJ‘¶¯\#¼UFze¨”Á+3„ðE°”Âh S+ò¿þOï6@2øŸÿw�O½ð²LæÏ[#ÓË¡òy‹Cù!öŸ�íAwëYõÊЇ’Á+3„ðE°"[·ÿMïf…5‹`E&>Ò»¥�XžNϬùQ@),н2×b•«ŠÙ*n>öEâ•·B¯Ì")‚™�›×»±†`Í"XJa2„·Þ©Xó£€RX0Â+C à­U¯,²U\°˜ÿºM|”åZ¬½wç•»]^õÊ0‡Â+3ŠHŠ`EZÚÚõn,€!X³VÄ´a“Þ-€Ä²f,¥°`4"÷Ê[ÓËC�}¶wkÅGÙÆœ¼sý“x%DÎôŒ—?=ÀºÈÙòjΖWõn$•HŠ`Eb£.½  Ëd>Ôâž^•C«^©Ú""ï{iÕ+_Þ÷iÈ ™ ^ °^ðJ€ äXsÛŸ6æ(cÚ�ó?Ê6mÈQm¯®ù\ïÆ¸ah|镊�­—n¹¯Ú>øÈwéÖªW†>^™áà•므åååËŽ+Y&óeǽ’è¼røéò•;ó¹«pÉüB[‹#0˜îæÓå5ƒ\d&x%ÀzÁ+¯€” Ëdþ¬ÅÆ?[ñÊ×mÚ›n<òåÚT¥þx%„¯X/x%à•�Äâ•"ïTÛñJˆá•#cL2)x%à•�¯zºìÏ“ ù¬yÅ+K+‚Þ*ÒÜórE‰0»Éà•™‰ðÊé¯Þ HðJHo¯œžñ’TÉ¢ޯ04~¯lvD"ƒásqØûY³#ÂCá•™ ^ °^ðJHK¯sUVÕfoÞáŠ*Ä8©¬ªá»%r¯Œ_ðÊ̯X/x%¤™W.ù|õ‡C¨Jö¿}¸ãHçp1~N;Ûkšëʫ߻–¶v½_J`8²LæÚf‡4¾ëS¾®ao×°·Ï³(¶ôyÅ–ƒWB(’㕳só]ÝŽúF{ÙÞ bü´´µwu;<“ }U¤.‰óÊÙ¹ù>çï’Þ©o´‹O˜%Ÿ/‘6^¹äóíòOùX^ýžsÊ9ðä:I¹ôzz·î`Æ Ð¢òÊ®áÀ2”rcíÊøÊÈR'¿ ^™™$Ú+GÆ\–|«îõ!$ºXò­}Î�½6R—DxåȘkï’aÉÞœ×ÒÖžºv™6^ùú®Ò,“¹¦¹Nw9"±Ä9åjI(ñ¿»O8n<^¹p3à•rc͉õy¥Š)×C¯ÌXŠvÙ,Ö8Pô�ŽœëÔ]ˆH¼bÙV`É�ç‹$¥‰—WÎÎÍg™ÌÚuÿbOˆ¾Õ°)W�Wcf{Ꮂ½z¿²À(d™ÌŸžpHã»|{~GiE, £“x%ˆšÕ8±ôLLúØçÔ݆H¼ÒR[—e2ÏÎÍÇëE’ÒÄË+Å/0—†½º«'Dßt8'Sq7^IŒ™ÂÒb¼$*¯ìòÆ8•7^ aXXXÌÞœ—½9/^Ö DuatTw"ñÊtŸ“©Ë%ñòJñNaXB§|©ø%¯$Æ ^ J²LæON8ú-‹œ�Ù+å¡Â$?Ò!^ˆÆ¢]¶¸¬#&¾-ë®B$ŽÁ+•Ä×+uÿJOˆ’Š_BðÊ$ç@Cuaiqaiq�»'üž=î±çñž–ä·óxOK„íLPðJP¢òÊä$?Ò!Žˆy)-Ö®nGŒƒ\ðÊô ^©¯$$îIÅ/!ë•ÒÚ K‹w‰Ü³bT­ÂÒbÑ]Ò9Ü~ÏÎá®ÀÊ¦l†HÉþ·kšëD:‡»z=½qѺšæºÛ‰WBð{åqGÿÔrÔq®æÜ ÷ܠשØ*©ø‘ñÅ31i)°ÊnnK�µloEw×]…HƒW*Á+ ‰{RñKHÆz¥´¶,“yCNîšûÿŲ]î‹jõÊ^OoMs�ª_2¨WJÝ “òê÷b·Ëxy¥^¼bDxe$2>_�û—�xu‡ ¯„ÈñLLvu;ZÚÚ£“Ê$xeY±Mwu�šîsN÷91ŒTHœÿ-ÙtTÇç¨m^)Ho¯¼4yq¨ÙÅÝ5;b¹{Œ)* |þ$h6¤HŽÅ=iØ{iØÛïYLþßN¶0×bMþù�%©ø%¯9íl³³XN1q^y¼§%ËdŽd N©{±lWöZ*µWÄ zÊó†WBŒÄÅ+Ï zÿý‘âî%x%$“õJßz5JG¯\­?P•½i‹öGβb[¼–VÁ+ Ž.^)uO›¢ÒŠ¢ÒŠ}Õö¸ˆ ^Ýñû=‹ÿýlÌÉ újíq%ú¹‹U •�›üóKRñK^)ûøÂì\^ý^B½ò@Cõz½2èóíî’ÇÏ2™#©ïMhwÁ+!.d™Ìw\›Z{·ËZR±fŸ¾µ¤bÍC]Ã+!~¬w|åz5jä\gWÓÑä;×ȹÎ5ßnEÖ�Kn·êŽ•åûËŠm‘?ÐÂè¨x‚ÆY«¯Tb4¯Tƶ¿6F¥Â+£8~k�kÍ?M~¡mpÊ—¸ç.Ï|®Åº¯Ú®Ëù�%©ø%¯,Ùÿ¶ø‡sÊjç 9¹Y&óö òJ±1v¯–*ú4CíÓëéíîŠ}Nç”3Ìq¤�ã•#‘xå{õí‘|Çø‹Åz²wòÚÃå5“Šé`L핺dvpH)�}­§„ô-ŒŽŽœë¬?P¥ì¸TÞqÉíÖ«w¯LY&ó¶|kìljÎ+s-ÖCÍŽCÍŽç¤øÇ¡f‡ô‘çdÔ_ïñÊõ_©üE¥MâÖ~Ïbk�k_µ]ykž{SÇ@òÏ|ìIÅ/!Â+›ŽµèÝ�˜ˆÅ+E ªøGÐ=å²÷M«„¡ÔIܤF•W*»eÄs ?¾2ÌóUVíjuRz´ÌöÂÚ2`íøJU{4TKÑÖv�}^ë*ÍÅ+A‰ß+�9Â8 ãÞ¢òŶaSÞ_,Va‘Ö’Š ›•0ïÕµ÷=\Ž0©ø‘Æ$-½Ršcö¦-ÚÉå{÷úZOÉ·¤²ŸÑÓãÀ+ÓŒÿžŠ¿îx3öãDç•¡ÜäŠ{>.cëâå•I¨üÔF¯´í¯7æäí‘lê�‰[®4ÑÏ=ÑIÅ/!ƒÃ#Y&󾊃z7$&bñÊÎá.¡Z¡¬G(Ò_,Û•w1²WÊÇÍ2™•=‰Ç{ZDÇkÐh¨ŽÜ+U…Á2ÒÍñJˆ/Y&sõ1G|¯.ÐYY}ÌḷØ÷p¹ú˜Cy¯#Ý.ašGº]x%$™D{¥œ3GnY[¤ñM÷9»šŽV–ïïj:fØã’Û-ö¬?PÕR['{!µ)²î� s´úU–meÅ6O�C¶J ©h¡<¾ø÷ìà�|R#ç:Å­¢UªI�´û÷µžª,ßßR[×Õt4¨ê*OEWÓQѪ GÃ+×…¾ý•aú¼®¸çÃøËà”ïÒ°÷P³c_µý`Cû¡fÇ¥a¯ÖƒT^)g¡ UÃ){iØ+Qz¥´›çäÁ†vQ™ƪú=‹¢y¶ýµÚ[{\áýHî,žH(·’̓OÅ›:TcQÅÑ6´•Vˆ.à ƒUƒº[®Åºf7±mm®ÅZTZ¡ÜGyÞB�Ue3Tû_qÏ‹³$’_h“Í[TlêgLü-Öù§¿4ì ¿³h‰è7=éQ õMÅ/!·FoûÛÿó+z7$&bôJÙ#©�Fµ×Ó+µ+^ÙãÝ^¸£s¸K®{¥rž[ç”SJeyõ{Â7�SÎÓÎv¹]ÙcÆ+Åþrrkšëz=½Ç{ZdÇ¥¬¼U>/q�õ–Ýâ• dM¯Ã*7lÊ“[T^Ù·Ò§):.[{'הʫx%Ä�D{¥vÞy„é>gÐQ�•åûƒú©e[�vç"ëN­pÉ=[jë"|^]MGƒþ&)nÿ.+¶-ŒŽÊ›ÄzBäþKn·”\˶m›g‡´S õµž’G‹¼ƒ¯T²!;WÇñ•ák)C9οê�R&×bUy�Ê+6´‡ï¾”�qb¥Wu´J3TóB�IT—*UZë}ʧ#Û¦Oidªì«¶«=¼W®·5Ì4h¯±Ü¿ßó²fIù¤TÑþ�ÖüëËh[TZôo!_!ª¬·¿;¿„¯LõÏÆ½RŽ ÔNt#õJ HŒ»W†Ú-¯”ã+•“ÉFí EÒC•ã1Ãx¥”ªŽ*oRʣܸ®? ^ Z„!^]ѽ ^©ÜGz¥r·#Ýþkú[ÙÃJ&?ÒÁ˜èè••åû…IeoÚ"wQõ3ÊòT!eeŶ²b›´°ìM[TšÖR[êP¡2r®SyLñrô¥Ü¨›¹¦Wþ×y¥TYw*µQ5®sºÏ)oµl+}©â¿òñÊèØby-Ëd^òùbø““>ÝG-©Õ§[ý~Õû‡™V«uºiµúÕçÛæÍs×ÉÖ½’ª& ÛŽ2�r•WJr¡§OWŸH›ªë•ôY¯4܈aE*¼ØE šýž&qÀ×>·çBwdö{Ú� •G‡Õ�ýókø~^¤Õ–tþñþ¯ËðJàj½RT<ªš¤:>1�„²ÐÈ®byÒ‰ûbßF憋S³†[«ë•TŸhÑ+I)Ô‘“Ö§]7Îï>¼²9Æ^�dU–ÃWc­lÇ.¯ÌU’™C¾u(ï\’ÚF±w¤™Ñ°ê'Qg˜|ñËùYÅ�£j,‹Å-’ÖG†á«k ½²¡�RI£øã su9¹cØO³«'r}.n(˜M{¥¡ƒ›ÕW6tFQCb±ÀÛ…2ˆý¥È‡b†Û'ëôƒWV«Õ‡‡—£â à‰´î•ÌŒh¬è†LÓÐ+™�:ï•5ðÌÐèŸñ¹×o¬ÜÜØÛ+ 7Åç½Ìšnx%pu½òý_ÿ©»ÕZ²Qz.tG^»¹öƒŸ_»¹ÖûÉU�*1·¤ñâ%¸…^©k¼ª[Ÿ¼’–R ÓJ‘KÍYIv¦L�]šy%ù©8ÞŽÜ+uµ¨†»O¦iØ^WôPxeCŒ½:9öêäâíšw,ÞŽŸž–›ÛNs^Y7ºª7ùí=m–TÅÐhÈïxÝ ³àkBåõ�¢ûð &ň³aÊwG2nOݹWØ€´l¸!~JP‹^IYNî��ñ;вåMx¥¡ƒ[ñJþÀÒ±å `]y-5üÛÉŸtžW2Nž–Ò™�ÍÚôì<»P¸+¯¯$6œÖ^YÞ+‰³J¥¡ÊÊã'Åæ¼R>ψ™WŽôb½¾’Ñ…uu¤Lݘ-bËU¹û4ê×òõõJ’eqxUÃiÎ+ù7’†Ó4,mÃO—¿�”–�Íkx0ùXï¤iXÂVâÅ›x%ïA¤“×&^f¯ò³r¾…ÖdcÆò¡&²½’ÍfÒ&¯”ø/MßÉï/¼¸ŠV¼²éxñ’܉û½’–ˆ}Írzp ÷•…•/›½^iq}òJq�þUë²ðJC¯l‚vÌ_)Q'ùfÅz4�/Є ÌŒX#X~z‰ŽI´E^'FÞ�^½R˜”ŸdDÜ”u¯dÚHªŒy‹�Úð*5Èð# _•ŒÃcxFÑçŠÃ"™½½¡I*%ñâM¼’÷ ¾æŽÄÊßB=ùy=ñ۱蕺…öz%m홡çtûPQùÞ—¶x%™µ(ÝðJÐu½òË_¯ýRD¿:iøê�›Š/éÀ�¸ß+©™¨Åi(i ò >C_Sâ•ò¡‡h€\xesxË+I7 ¦RIùx°¢t0ƒ3œ¹£!¯l´ÐÊdšòiS(’95xE•{%i»áFÄÃÂ[˜¤î•t»E¯”|„á¸=âÄ1üáe hÙ#:ÚuD²/Þ„À+u^I�"E2| u]$5ã5Í¢WÒB6ÊëÔÒœí^¹óÑÏžzŽ>ejiîÝÔê�•›´ðBO_9k‹WÒ¸ÐÓÇ­…W‚æCߌk?þ°j–oÆk?Ï~uR²N£ñâ%¸×z% §CëÎ_¹¹|—ÍBJݘղÊJj^Ëëªhµx%ÍÚîî×í ß^ÙÞòJ²'±^){T!{¢ú)‰ˆñM7Íd°Q¯¤â™UÛõ D¯ÏÅ©x¼ ™U•ZôJÉL†=" ½’_St122Z‡·{±v•%™9¤õ[ôJÒ^]ýãv¡Ì�&ÄŸtLto¡§ ´›ô‰â\¢¬v{p(f½•¬oBà•:¯¤Z¶ =}ºz=Cu2›S’U ZôJ^fi}Û½2s”ákQu¥å¥Òpg wG~pÞˬQ [x%hŽº^ùîOÙ”"ïÿs^ ÜFÓ^ÉTÎ,d…M{¥áÂpwÿæò]&_gù”_ŸJ¨k+.l(ìƒXQ‡FG ÷ÔlgÅÝ©{pRùíWC#x%àa^©}X5Ëf¾ÜóÉÙ³_�Lþ²$YÓz¼xIî¤i¯”‡¼¬i¯ä{Sždw©9(S-ÞÃÝýº®—gù<¿­¦[2pé²nþÊBJ?j"«¸l·WždwÅâQ %‡ ^YÏyåý¢nÔS~Ö ]Í”\ĨzѰ–ª9¯Ô¯«'¢+ž®^R7-­<8£î„Çíám´o ÊoJ7ÿSoÊZÞÐù½Ð-! 6tdÝ{©`-z%Õ?ÒA �ØÊ—x1$ç5ÜQØY¨57~Çùª^x¥ki®þqsà•€§®WjVþsåê×Ï@{¢ó÷wîý¬hx%p×z¥®%êY>O•z¼*N�OðPòëï¯o,NÍšùšYoÍÅ©Yç½’©åØHŒJ;péòâÔìIv󌴈缒)Œ¡,Ì,­é¬Mî•4z?áH‹^)N‡A¦c8#§¨–dÇôé½2{TYXÑx�euŽTgÊ™¤7hö¨’Håø©*u;bVm§›è„íÈý¢á_¡ ¯dAºMûB†ËvùŸ£«'b¸ºÇ´�ŽëÅ›x%âÎÀ+O]¯dý+­'U¨Ö�/éÀ�4ê•gù¼¤ù«Ø–™/‰´Ãñ]i}³Ñ\�Ó™tâ~:qßP' SHiûë|ñêz™îÓŽ�ïŽäƒä»Ï>‹‰Æ²8l¼R‡¯ÌU˜nzVCYXÑ©œÙ89ôA†#‚’j™�º](KÞÎêÈ作Üá›’JÂö…‹•>�oîkå¸måKËÉ�ºÇ–Ê/ý5™9d‡—"ß&+3û£ˆÅæ�ƒüèÕ=¶ËÉ�ºãÖJÎùi/ú>^¼ �W"î ¼ðÔž!Ç5‰ÎÀ+�‹iÔ+‘6…ù¦¸œji­O³¯äQâ•.‰|tYi:^¼ �W"î ¼ðÔõÊ¿Û.ÎÄ5ë‘åûŸÄ‹—tàNà•nõDz—†£W¬o ^Éã[¯¤Æ™vM-� /Þ„À+w^ xjÓäŵ÷?5>gâÅK:p'ðJ7D77 k(K-`Á�n|!yà•<~óʇ{Å™¥5êžÉ†|Q^*¤ÃâÅ›x%âÎÀ+¼xx¥KBC‰±>à ¼’Ço^©;yÐiG¼x¯DÜx%à©yåíýßTßÿMõ¡…¬fŠ,Ów4+ëÆ‹—tàNà•îI!¥é¦G‰Y®‡¯äñ­WÅ •H›âÅ›x%âÎÀ+óʺ&¸ùëÊ›÷vz.Eù›Fz56_ÜÈÁ+�óÀ+;/ðJ¿y%‚8/Þ„À+wæBO¼V¼ró×�Qê¼’ý—ßÎi¼xIî^Ùy�WòÀ+Äöxñ&¤c¼r|îuå*„Ø/~›@ûCSw4¹~iäOsid26}>I4{uýŸÊºÏç)þνù¦à•À^à•�x%¼Al�oB:Ã+ÇÆ_»ÐÓ§\…»’ʧjãõevTŸYÀ-ÔõÊ;Ú!%[²’)ò^ÉÔòR´6jGl:^[òÏuâÅK:p'ìnù,ŸWnCˆ]a£ËÂ+öz¥ÙDöâŸlÊ^¼ é ¯LgvÁÐ{™5åB„Ø’ñ¹×kóSŸ–UŸYÀ-‚¡7îh?úçªY>~5 ]èŽ$—Ù’ïÿôÜ+ùÕnþ0÷ñ¯çRT²)Š/éÀ�ì?®�xM ƒ¸6l‚’³JEõÉå ìòÊã'µëv"•S~W� jæF-|xhÇÔ9:Ã+OOËáÞ‹zú2GåN„´˜�½ÍÚ}㯩>­€‹¨ë•_ü¤ì«o­ÑC¯üØ:χ…ÿT?á•ÀÎ*•ZßÞñ å6„Ø6e‰ê3Ë-Øå•Õj5܉MÌ+¿«GµYX©=-?yZ²åkå�á•ô4ø™¡ç –žÎ»©Õ@0î½è¹¯h+½’_‡¼róŸ«”�_UØÂïÿ´È/7 ¼ØÈôì�pwÿIvW¹!­ç$»[›òòv\õiålôÊÅÛµ®ñ[ù’ò{Q•ìQ¥«'ri0jËwÊI:Æ+©5ì3CϽ›ZUîGH£IåS¬ùëó/^ƒTÌ%ȼ26§%†^ɚ˂¡�_Uà•ÀIX¿áèô²ôzN²»áî~tÖà±Ñ+Ož–½‘®žHö¨¢üöAœOö¨28Tk±ÿ8gËwÊI:É+Y�ïpïEvßøÌÐsC£#ˆ'r¡§ï|~êñ×Ð]ˆœ{åU³¼±\ÆÏtGîeKlÉ÷ÓŸzå§ëlä+ŸùdHØÏtG$›¢À+�½°v5PKO§�ÒÂÝýáÞ‹^¼åk6z%}S‡bPKÄoÙÊ—˜T®Þ[³ë å$敬K:³³x;>6þÚß¼ò·HC!+w2C/^-�ÙÁ³_`F úƲöTÍr;u>ìgº#—-ýÃÕw?õJ¶ÂÚAytê|æ‘+ãó’MQà•ÀvVï­Õšúw÷¯ÎߨZ ¼´�“§¥ã'Åtfgó�f–™¹·$¯"ÇÓ7{í¦^ɰòM1ÌÛKËÊϱžÂ‡‡Ð ^ p?�`èõeÍŠ .¬çz.E ¥òõem=_1}ï¯õ�Wµ\øÜçÿå_U—€ú´Ï+›fàr5Ë8 ¼à~jVøŽ&ªŸ$ßKo½¸°žû^ºøƒý²õ7þðÓÀ+�B~wò´6Äñ×®«.õq›Wž<-ywä¼ ¼à~˜Wþ�“>¯ ¹yëN ú_>§º ÔÇm^Ɇýzášê‚à/à•÷¯~ãÂgÏg_BSXà~Üæ•C/\c_Œ3€“À+r]šûûåÉw´/|eò _™dSU‚¡‹Ñ[ÂG¾x%PkË‚¦°Àý¸Ê+OOËôõIgvT¯¸Ÿ@04ùަW¿_ýY&ßѬå­{¯aà•@¬,ËÿºÐ­º8ÔÁU^ÉÁ² ),N¯¸Ÿs¯4wÀï>nÏßí•ùåk-^ œGl‹¦°Àý¸Ä+÷ç ¿>SßzSuÑððJ€û C·5¹^|6†FÞˆ·â’ðJ ÃF°h \ŽK¼rê[oš}}Î*Õ¥ ó�WÜ�¯|ïqåùOF…íŽDGÞˆß|pøÞã ½úîÏJï<*Rà•À…˜5‚ESXàrÜà•f�`YöçÔ?¯¸æ•?ÈWÍ2qKkhþÊäªu¯cÖöÓ¦°ŸW]@ŒqƒWš5‚ESX^ p?5¯¼¥I^ :€�ËÏÉÏÛòý—ê2`€¼RÒMapx%ÀýÔõÊo¯å.yÒzÞËUë^ æÿúÂòã{?Hª.#(÷Jy#X4…Àà•÷†þö–fEm ¼8‰ö“¬{c|i0ªº˜ Ü+å�`Ñg€WÜ�c^yŸ ¼8ÉР׬4áFSXàB”{åô켕¯šÂÐVà•÷†®ßÒîÿSÕz¾¿[¾õ“â­Ÿzx%p’º�`Ѹå^i±g=šÂÐVà•÷cÝ+~t8øåIþF‚^úÊ7âñL ^ \Èá¿ükwß@¸÷"Ÿà…ž Ÿý<¿ä³}—Þ˜ùŽê G­Wž<-Å^þÛ‘Ø+|žùÂóÃWcü’k/½šÎì¨*$~^ p?Ì+ïýSU’Ä~¥ÿÙ˜AýΧ+üåç"�`hî9ùv(ðJ –@0‹ž@y}¥.à8¼à~¬xå—¿'—ü\$Jµ–ìÕ;™½úÖ�á•Àý8ì•ÇOŠt S‚o½òô´¬üœo='OKí>PÀ'À+î§®W¾õ£CæŒýÏÆîdJ÷W¿ûãâ¹W>®²Üùi‰UY~ùõøß=®Ö ¼¨Å¯<~R\¼÷^´ØCÍýŒ¦3;L'ñ›WžU*«÷Öž¿jÐBÆ»Y¼?=-·éˆŸÐ‘^yò´´zomlüµ±W&¤Õ¼:¹ù@;~RT}^ûš@0ôõïjüúw5ö˸üÓ[²ô©Wò«Íþ Çj3á•Àý8à•4;ÃØH,�¸œÎx:ûë›Ëw.]CÃWcPKǸõ�Wž<-…{k�(û¢3Kk÷Š^ÏŠ6÷µy]E¤¡W¾›-³…ïfËðJàrÚí•‹·ãì·ò,Ÿ¯~ðA'esùn šž½Ñ¾£xj�&üá•…ý‘®žH"•Ûû¨ÚIy¸Wìꉄ{#¸ÕMÓI^Éž»†»ûÓ‰û§Ê×�ŽÉY>¿¹|7ÜÝë­ÁЫßÕ�«f¼:©[gñS¯äW[ùeå¼ÁÏ�‹’­±À+�ZÚê•›4VMÙyRɲ85ËšöµéŸxåéiíÉdWOd+_R®�mRË@0ôü‹¨ëMÒ1^É~"‡£WN²»ÊÎ�ŽÌIv—ÕZâzë<½òêëq¹W¾þî[ø½l^ \Nû¼ò¬R ÷^Ž^Q~]mkÆFjÝßÐeÌ|â•¬Š¿S¥’%‘ªÕÑ`BÐ�á•ì RG6æA\•ýõ�Ú¯çøkªOyßQóÊ%-qP5Ë«Kµ'Kù¹È;?-±%‹Ú¹W®T)Ÿ‹DÅ…f�Wµ´Ï+Ó™Ú–ýõ åÕ¶¦�Òp‡ì >ñÊÚ­æè¤rõkwºz"Ï_�Ù{è€Oè ¯dO�PS‰8Ö¶ U–üRâ€ß|ï|ø‘¿ü\äöOK«Õ›‚W2÷ CѯÍÃ+�ûiŸW²>Ê/§$ÜÝ�^–௼XÄÐ+§îåèÔza2nX_ùVªH Ÿyñügzê^îî/«u¯jñ¢Wöé >Õ>(¤´éñ ú…•üÀ±¶=üšÃÑ+‹S³ uÞ‡W:¼Òa¯�\Nî°bóðJàüæ•T}fÖ�òôà@·¦® +”ÆìSŽÓV[GÂo„½}àÒeöûÈÖg%aÏcé¿ü¢u¯‹wzpÀ�¢s–ÏRÚêüÍÅ©Yù8ðì�›Ëw§Ç'Vçoî¯oðûexË!ÙÚpôÊÀ¥Ëc#1¶Û8õÇÔ7ñ¿ûëüùA�ÄãÆêIÇFb›ËwÓ‰ûfw ì�º¶Ç†x¥øøÎðk‹šÎûž›g§Ð•ɸî¥ùO½r>U¤…·Vf Ÿ›¿»W­x%PKçy¥®9E×1„ð(fàÒe³ß#x¥*à•Î{åÞGÕÁ¡ó›ÌdæP÷öìQ^ œÇo^yœÎ°‡ŸfëSåZ!¥‰º$‡$kè•ô_>¬$m·‡èÆð]ü5gÏ“ùGÄü³bQÓ,¶.èu¡ãFÿå[/³# ŽÛ÷“ì®XìáèQÅCîîgöjå€Ã+�§æ•75^úîdÏ4ÿúÅIQ çßÿÔ+ß/òËÿú“*Ë¿ü\^ ÜO zubª[Vâ•ì™* æ¶¿¾ÁZ‰{ù‹ÿâÔ,{ÜWHi´…pw¿ÅZKx¥3¸Ó+Wï­Ù¸AzåV¾ÄÖéˆf�*º-À+�ó0¯Lýø‘ê‚´DC^É*"Ím21™Ÿàßb—W®Îߤ%áî~6j Ó±v{%U¿†»ûùŸr±ž‘J<½Â É?(Öi? ¬Å6Ãûë|ë&öd¸üº^ɯOû¥k:¥ë×ÉK%kUE+ÓSx¥Û`^ß«Rn|jŽºåºWo¼_ä—uö¼—å­í²ø.]à•@-�`¨§ [V╆U�t�çŸLÒBÝÕû,Ÿ§«´Å'™ðJgp¡W\Ž\ŽÚ¸AzåÞGÕ™¥óµ™¥5x%Pο~ôÿ‚¡›·î¨.HK4ä•ôo±! ÕQòUW6z¥Ùjx%ûAß\¾Ëžñž�iò¯œåó$Yü:ëçbøCÏ{h¸»ßú”"f“6Åvœ(-ñJ*i/ï�¼ Óïtâ>í5?¾¼Ò…ˆþøÆ§�+g×­{åõøŽárx%p!ç?UOK¶oY•WŠƒ‹?s'Ù]zî'nŸúªÈÇI€W:Œ ½rõ^M¸NOËvmÐ�^™=ªô DÙšºé,á•ÀyØ×¤à ª Ò y%™…øǪÞX›ÎóJ�Góc‰ëN B‚ºH:)c{'ï¿Y×+ ë”å^)¶é¥Óúôè@¼'›ÝJJ¯tÑ+¿vóüO¹œ­ˆJ¸œ­¼ù~ñÍ÷‹ïd+wöª”7?õÍ7ß/òË ¯j9ô7;oû–Uy¥øà‘®ÉT~<Ã� gƒVʯtzåÉÓZÑÅÛq»6èN¯Üû¨šÌ²5uÓYÂ+�󰯉×ÏŸF½’ýÐð>ÅO[É~Ë:Ì+ ÛýŠw ´ÃQ¨ÕôQÒ‰ûºæµ$­¬wŒ•ÒêJ%~ŠÜ+Å;^:€´qãüí ¼ÒmÔ¾27µ;¿¨RÆ>õÊïfÊüry¾ñw絜oo•ê® ¯j©�ôøµ¯Û{oÌPå•’õ©<üÏë¡ 5ª±Rx¥3¸Ð+«Õêâí¸�½,]ë•{Ucç£ØñÓYÂ+�ó°¯IWw¸7rV©¨.N“4ê•Ô�†ï Aí9Ù:敆~Åõéן5Ö¥nyNØX¬¢`JºÕ˜ÝÈãíȽÒ쎂/°á0¿ô¯t-¢W~kýü 훋ֽ’úWZY^ ÔÂÎÀ±Wk·‘éÌŽ�[ö„WÖ�•ýðJgp§WV«Õá«1»¾>nöÊíBYœÎ^ œ‡}MR?~T;K¯Æ<ª–�z%I ßµ�U·Q½ž¡WÊ“ºÙ+ »=е“Í­”‡¦)áë.ù´u½Râ‰u�§Ù4ü‹4zÀá•Ά^º©-ÿ¢JYØ:O·\žÏ±v|þ‹1++Ã+�ZØxV©°{ã�ËÑÍÚþãÜñ“b‹ñ„W²þ’È'„â·¦ú/Ùù¸Ö+Ï*•�ËQ[¾>¿ýd@wzåÞGUq:Kx%pæ•ÇOŠéÌûÞí?Ω.TÃ4á•4¨ �c£kiè•òŸW7{¥¼%*M¯iÑ+y·ø³.î¼XÇÐÃkw á‹ÑÛ?¯XñÄo~ZÅù¥—æá•ÀýÐxV©ì?αÛc»âZ¯¤¶Cø¬ü©þKv>®õJöõÙ| Ùõõq­WŠÓYÂ+�ó�WV«ÕÍZ¸7ò§�W'=+?@¢$ÒÀ§L$里ž6ê•d¦^ôJ]ÙÌ&ai:ü ’OçË`8Ö¼Ò·zåKŸv±üâKóïü¢*Ïb¦üŸ;¿¾Í¬þÙ«»Æ�WµˆgàY¥Òze%ûÝw›WÒúuÇíi(ðJgp³W-~}Üé,á•Àyx¯dì?Îm>Цgç• c[½’ºÚ1aâÃWÃ5Ú¿’Ì´¼ÒâýËIv·î¹µS1ÉÛx%P‹?½’ÿɉé~ŒäƒÑ™ý ´ãx¥K¼’ŸÎ^ œ§¼²¹þ•¼1›ÐM;b¨0ôc§›¥‚æ(±î•º¶¦.ñJ²iÔ‹S³—./NÍRka¾ï¤Ùd~^HCI×�½Ð¯¤¿õ!¸t™~–ÏÓ`°ðJ†þæmí¶ ~·w«ßýsµ”dà…ÉùŸ” 7bx%P‹Û¼ÒpÖŠ�^yzp@OùØçRÚæò]úÕŽ^1¬Ê„Wª^é¯ä§³„Wçñ¹Wò*¡«q3TÒ®�K—Ó‰ûgùüéÁÁæòÝpw?ýÖõJZ“o>*÷J6¤YÈËZ÷J¾ ’ö‘ýÊócôþú³©*÷×7XyÎòy6$,¿Aþƒ¨†W÷ع^ɯO噟`áî¯oðOà•.Dâ•L-¿øÒ¼Ä(ãÓÉCëF ¯nÀm^)��^ÉžΉÌ.ÔVF‚…W: ¼Ò=^ÉOg ¯ãs¯¤~ü\r##+Ñ…”³®WòSoÐúr¯”G”FÜ‚®‚Uâ•Çé ÿ 8ÜÝÏï²ø”ø$»+~ $•º#I=Ru·íðJ^áO²»bñØ®aþJ×¼òÖnµ–¬qÞþiy|yçù‰øÀ “,³ Mÿýá�—ÌÞ"¼¨Å%^)¯¦ÔÕWždwÙù«îâÔ,¿ŽîD\Ÿÿ™`ï¥iG,öÑ€W: ¼Òz©Üðèäðèd"•“¬6³´ÆVÛÊ—Äå3Kk’÷nÊì½u?^ ìÅç^I#öˆ£�šy¥¨Q—.³D‹^©Û‚3^ix|Ìz8žÐKünò-`ùœåóûë:_æ}Íð†á,Ÿ×}Jû¼R|Î43ʳ|^>Ý'¼R!5¯\КÓæ¯jq‰Wz:ðJg€WvRà• i|╬Mæq:#öÈ8=8à›’ê–¾…m-�¸ŸNÜçßÈÖçë=O²»†9ËçuÕ£TB~ƒTyè-ôqâ }P\ßp7©ikÝœåó…”VHiT6ÝnŠ?]òFÃ?Š•õÍÊ’Ýå7EýgåņW:��^ù]Ë�WµÀ+[¼Òà•�x%hŸx%‚𽞅U^ëFp¯tž@0[Ь+¡-�WµÀ+[¼Òà•�x%hx%â«ð#÷êZçRSdñpùÀ+�Ç9¯üùŸ¯j�W¶x¥3À+;)ðJÐ4ðJÄoá{­¦÷YCY~dàºmwá•ÎüréçU'¯j�WÚuÁoÇ1<ðÊN ¼4 ¼ñ[Îòy³A}-žHðJç�W¯l=ðJg€WvRà• ià•ˆ?CsVR¦Ç'äÃÀRà•ÎÓ„W.¶x%P ¼²õÀ+�^ÙI�W‚¦�W"H£�W:óÊÖU^ <¼²õÀ+�^ÙI�W‚¦�W"H£�W:�Ì+wÚx%P ¼²õÀ+�^ÙI�W‚¦�W"H£�W:O }K»¹Su2ðJ xeë�W:¼²“¯M¯D�F¯tx%ð!ðÊÖ¯txe'^ š^‰ �^餭gàÀ`4ÜÝzp ü¢Ú¾L�O‚¡ÓÓr›Ž! |â•›jy‰TN¹úµ/¬s%~û@st†Wî?®5/¤4å¿bHLJ�áõ¯ŒçC_}K{ëgU'ƒßV –¶ž�…ÁÐpôÊY>¯üºÚŽ,NÍÖd�`Á'^yV©<ÿb¬ƒ{Y&R¹®žH¸7‚§1 9:Ã+OOËáÞ‹áî~?ôAæ8� w÷ãFÅyðÊmÛ¯ji÷ÈÉŽ�Ä:¬Öò,ŸŽ^©uX¸G1gð‰W²6äáÞHWO¤óÔr9Yëvî�œ<-©>ÌÀ«t†WÒŽtð£WDyö×7>¹ä^Ä%×yj^9¯µ®Šó�^ ÔâÀ¸x;†Ø›Ëw )í8�ñnÒ‰ûÌ(Ñ Þaüã•Ô=¹vÏ9:¹°¢%R¹‡{Eï&‘Ê]Ÿ‹wõDj{t5†G1 :Æ+éÑëÀ¥ËûëÊé¤RkR5üâ(¤R �`hd^kÈ [¼¨Å™3ðøIqlü5vŸÜ ÷^\¼á+¯dÍä6háÞˆòÞ®LÏÎï?ÎA*A‹t’W²±ÓýÏ\ºûkó "Hk w÷³3jlü5\rU¯>Äá3ðô´|ü¤èõ8v¸�ß¼’Gù9ßzpoì¢Ã¼’±ÿ8·ù@{urì• i)ã¯á!ž`^yc»êdà•@-8�Wð³WˆŽôJ@‡QóÊÚ�LÕÉநg ð ðJ¼à õÊ7íîê�Zp¯¯À+ž  }å†f‹-Â+�WÀ¼¼¯xx%ð!8�W€Wà•O†¾|CûN¦Úp~Ú|pWÔ‚3xx%^ ðç^Ù‚$Â+�çÀ¼¼¯xC¯üv›ƒ»z œ�À+À+ðJ€'`^Ùn‘„WW�3xx%^ ðíöÊ9£à®¨g ð ðJ¼à ÁÐÕ7µ¹tÕÉநg ð ðJ¼à à•À‡à ^^ €Wg ð 8WðJ€'C/|Gûæ?V� Zp¯€s¯xx%ð!8�WÀ¹ €W<Á¹W>ªZÉŒMÁ�P Î@àp®à•OÀ¼Ò.a„WO€3xœ«x%ÀÀ+�Á¼ÎU¼à ÁЕïhÓ�ªNwJ@-Nž�§§åtfgó�†x%ÇOЧ§egN�º´ï\=«Töç”íÎÎñ“âÉÓR;þ|ÀoÀ+î§-^¹U'ðJ gÎÀtfgøêh B¼˜ÅÛq7A;ÎÕã'ÅéÙyåGØ?Ÿ„€�WÜOÍ+¿­ñÒ7ÕþÀ+�Z8oÇÁÐÀ¥Ë«ó7�Ó™ê žÈIv·�Ò§fÁP¸÷¢rµ´ý\Ýœ C]=‘ësñD*—=ªì}TEÚ‘íBùá^qfi­«'†öçlü;¿¯¸Ÿ@04ümÍ—„W÷ÐÖ3ð¬R- M�OœåóÊE i.'ÙÝpw¸÷âY¥Ò¦SÅ öž««÷ÖÁÐàPl+_R®]þIö¨Ò7ýø×Vùc à]à•÷ÓV¯|Ã$ðJ –¶ž�¬¦rqjV¹!-f}£v…¼kÓ©bÖ"×–M±šÊÁ¡ê(�ÏV¾ÔÕ ÷FÜÓux‹ÎóÊÓÓòþãÚäû9—£cã“éÌŽÚç·ÀF˜Wš `›¯jißxzZ®u§‰)w"Ä–¤÷?þí+|xØŽ³Å —£c¯NÚ²©ç¯Æºz"�JUy¸Wó‚Õ{k¶ü5�ßè0¯d�¹X›üØÄüІø-3Kk㓬-G¸7‚ž�Á¹Wþ¤êdà•@-í;Ó™�š†¤4åB„Ø’Óƒk ›€=ÌoýYîÉÓR šYZS®W~Nß@ôy¥ÕßÀ»t’W²V=ƒC±dæPù·QžD*Ç:¡£§@PóÊ9í?©:x%PKûÎÀÍZ RnCˆ�Ž^ ÷^lÇÙböT¿õ¹ì¦ôá^Qù-„Ÿ3³Tëߊ¦°  :Æ+oÕ¤rxtm' õ€Zzx%ð!í;Ç^� w÷+W!ÄÆl.ß­=+PÄY¥Âúx¶XeÉjÒá•jÚÂv€çé ¯d{›˜WþeDÜvy|iÜž~@­{åë�^ ÔÒV¯DçÊ‹Z¯¤*ˇb5éÊï|x%hšÎðJVY¹](+ÿ2".Ìõ¹8Ztx�@0ôüœÖ„6�ë¯j�W"Ö£Ü+i~�ÅÛñ¦pá•n¼4Mgxå¥Áèðè¤òo"âÎ$3‡˜ê×ëœ{¥ ~m ¼¨^‰X�¼’Fº¨Í‹:;¿ù@KgvŽŸ­gcó}x¥òÀ+AÓt†Wbô0Dö§ú<ÍüròÇU'¯jñ�WŽ�ĘM(×+%qÃî»Ä+Ù�e‹s½)¿g³°¢±²ù¡ï'¼4MÇx劦ü›ˆ¸6ƒC1»¦ÖJ€W¢Ð+�Óv½¹|×+bÕb$š36‰-NÍî¯oœåóîÜ}÷x%OC••쎴!¯$Ý£tõD†G'Yf–Ö©œ-wðJ¬¯Dü�áÑIx¥§±î•¯Ùx%P‹‡¼ruþ&“/åzدäîîO'î»p÷Ýé•�ÒhÿJÑ+Åô D[·Kx%V€W"~¼Òë‚¡¡9M¯~Z{¯jñ�Wv@Øþ\º¼¹|W—Õù›—.óª"ª¥òøÜ+‡G'V4Êõ¹øðè$›Ãšep(ÖÊñJ²6‹âFžÕâÄz'tÃK_ J;¦S�tmgy»v^éiÁÐs³ÚÄ'ºçXà•@-òÊ“ìîq:sœÎÐ’³|ž-!ÿ:=8Ø_ߨ\¾»¿¾q’Ý•líôà �ÒX]!¿IiÓ‰ûl}³�SyNø%ôߺ^É F?ëüΊ»zpÐôîŸdwÓ‰û…”&Ù¼Rwï$¹ œYZ£*KñÕìQåá^1‘Ê-¬hËɳ»DÝMZÝ[DºíÔݳe�*ÉÌárrg+_¢…lM~‰®xËÉyñÄÚ�­|‰½+™9lô¾^ šÆ'^É·À·òÀŠo;ъδ蕤{†éê‰Ì,­Ù¢™ðJàrà•À‡‚¡Õ{kíØ²ãöÐŽÓ™“ì®®im׿oŠÛpôŠáÈ9†JUHiâ–Ùú:wã÷è8� w÷ëôЊWV?ø`z|Bl +î>³<¶ýãtF,¤á�M'îëV›Ÿ8Ëçù­Á+ ï�$·v[ù’ÙÍØrr‡¿ß£ˆS ènÒè]f÷`±‰yÝM]ö¨28Óuü\Nîн¢8_žYñÄ�åï⩜î]]=‘dæÐúQ…W‚¦ñ¡Wö Då_¨D*Ç[ÑÃ�°Âè üp¯È:ð×(¹WR®ÏÅ[´Kx%p9:¯ü[’‚WÅ \Ž_�µcËNzåôøIœN¯ö×7tJk’åÑ¿.]Ö©âY>ϯ?6ã·?pé2¯¢üñêÚ´Wò…—xe:qßl÷u’¸85Ëž 9½²:^i+^™=ªÞŒ]Ÿ‹ów†Ã£“}QZ¢«ÜÔy%Õ�šµ¿ÕÝpnʼTò}?éžSç•d¦†ÅÓ­LwqËÉrI�]Zïf¯MãC¯ C†� ¿ËíðJöõ·RmÊ_(t­a—“;ü5ªo ÚJÇLx%p95¯ü–ö·©ª“�Wµ¬Þ«Ý»žž–mß²“^ɲ85ËZœždwIÍ.]æ7BÚ5½BJx’Ý%ÚŸMJWõ¹¿¾Aëó…Ë£kYjÅ+ÍÚÁJ¼R²ûüîð[¦°bm,µÚ…W²XñJ7^™:1ÿâï ùZE~Y�WnÊ’ª úDVÉ;, ”=ª�œŠªhV¼­|‰Rñ.޽eaEcŸ’ÌÒîXï^ ¯Mã7¯dO{®ÏÅÍÖäŸ2µÉ+­ÁéBaÖ†ÿá^‘®0tùjN»à•ÀÍ´Ï+¯›^ Ôrò´Ö~oñvÜö-;앺zIÞ¡x¥’BªHbE‡Ð¡MñûÈ—g8zEÜ…º^yzp@UŠáî~ùîó^É÷”4Û}Z_<àä¡òù1á•fëPe¿Ýöˆ D©Ý,ïŒbg%Ú‚XUA/Q[2ºUÓU�Ÿê¼RrûgX<Þ+uaV* ¼4�ß¼’=êꉘ­IMè9’n; +šáDHÛ…2{•¿è¼raE£ÍÒ˜Øì²#o+éNÁÄ+Fö¨²œÜ™YZ£9‚Í Ï{%íˆd¾'ÖÃ]WZÖI<61›˜_Nî°— K£ÅcÇ^b}Þé]×çâVÆV‚Wz�@0ý–&qÀv^ ”3=[»%NgvìݬÃ^)z"UÃQ­Ù“ÎÂX¨ã¡•òœdwEû£…¢çò^9½Âê1)l8 ^îÄ-ȽRÜ}jKšL[‡ôáK¯4»»3¼ L¤r|ÛQ^©jÏp³TÇG7¢W’¯éª*Hc󼦙™�x'6£5+íÝʼnc‘‡Jn}u�W‚¦ñ›WÒ÷ÝLšØ%(61Ooá_•\èºÁ—Dç•ü¯…]£äãöHÔ)™94¼˜låKºâ”ØÄ¼îqï•Ù£ŠÙƒ5Ý�¿Fé:¥ÒÅÖð°°âñW{+Åcm} wªî”ÇðJ¯¯þä¬R¾³]-�ôJÃÊAZŸ¼’–6õ$·Zœš•”™b(bÑã_•gl$&vr”x¥®í®Ùî“iî½*HÖç^Éz Rtµ®žߦ‹îLHýÌ6+ñJª…ÔùUOPM(ݧÞ©Ò«toIŇb¡ * É©áGèîEá• }0¯´ýY¨ÃX÷JzÎcx1¡ï2« ³Ý+Ù\½´¾ÊÏ^¯ä[V ÅØðÔ3Kk¤rº‡`ºv°TH³ÚCÝ�ï¾Ê”œì�¶Ì–ºÅÓ92ÿ ŽŒ•ïÛÕ‘w/…Wzæ•_OUeyßæÀ+�8«T.×®�—£›´Â‡‡ÇOŠ-ÆI¯4Ü‚D¬êj�®œºáztÍÑlÇë~t¸»ßl؉WZÜ}ÃKÖ‡WŠ·f�Ô�mhöÄ[Ü,Ù¨áMùߘ–ݨ¶¡5ü8±6Sî¡üé&M>½&¼8I›ºo8IC^IZ$šù›K×v¯”\ÍšöJÇT´P×<ìCºÎ+©Õ„ádO$tt¡&ä·©kÒhñø«4ÿì‘ü–`MÞ½^éuνÒns„WOpV©l>н34·ye£Å>Ëçi”TþU–¦½R|•uÖ°�®�^iV6xeÝ»;zVOIfÍî�êöÊW0¼I›¼Ò¾ª±Q¯´«x’{Qyà• †¯ÆÂ½Õ¥h‰†¼’šqêL„Ú²ëƒ'¼’·‡šÙÓeͰ-½¼Ç7-!_§ô5{°&¾^’öW^<Ãn’Ž|ÏYÉ ¯ô:-zå«M^ ÜÆéi¹õÊJÖNÉm^ÉO() 5-¤Î/þáîþÍ建¦­6z¥î³ ÛÐÚ啺á€à•uceÜ‹7l†›•×Wò÷'¬ª‚Áò÷N¨¯¾"�©} öçT¤yòJª/ÓI Õc²š2Wy%›g„i›g$™9äkñ GÏ6öVêVôJ:ºrÒrñjfXc(¶ƒ¥ ¦™ ’)K6B‘X­®ðJOü²9=l:ðJЩ¸°¬¼¥ª¬L'î›I¢]^É+$ï/Ùôî˜ÂK7¼ÒðÞ©9¯l±¥xSÄžÉënHÌn¨Ìncêö¯´^<³{Q+Ç^ šãô´î�„{#'OKªËÒ$�z%}‹ÅÁW©ÍU^)ÏÌÒߦ——™qlÑ+©öÖ°'&ߟQ~5“´Ö0k¹ª{ú'Í[>Ì¿Mx¥§�W`#nöJÃÁZÅPŸJÑCiž½òôà@"wMï>ž&R‘� ¯¬{�a1ì]u\µ"nìfip(FíÁtcSÈ5–úµ2,¼¸Š“§%¦–g•Šê²4C£^I×z$6‰ßBW —xåàP,61/^ChSâ¬LºÍŠÓ0ñ«Q/HZ�Ž_*o¬+^óÅqÌš+žîxÂ+;›@0ôì7µñ‡U'¯�Š ½ÒpÒI^‡£W6—ïÖ±³|žÆÇ.¯äç:¸tY×¶éݧ%Týª[ÿ,Ÿç§8�WֽǰÉ­ ÝêÈ篤Ð] 3D±�y¢8²ÝXZŸ¿²ÑâÉëD ¯­³ÿ¸VMî�¬Þ[;~R<=-«.Q4á•ì:@ßJ±I¼ø¹Â8Ж"VÛÕÝQ Å�.wd‘t”ø4ê•â§×½ÚÃ+¼±î•‹S³Vz;¶.V|äÀ¥Ë|­%mŠïÞHÊÏA.¹¿¾Á—l$ÆÞغWš5IµE«§fùcK»³85kx¸à•­x%÷Ânl®ÏÅ͆­¨+nü ŸüoåK4v«Ô m¤'öºÛ]ñbóü§èV†W×rò´Tøðpó�æ•4ç•dIlÞ öªáÃñ»)Ÿ}C¹WÖIŒv‰¤[“.w‰TŽŽ’NWåž(Nƒ"ïÀÞPñà•þ! }雚½Ú¯¾Å=^©«€;=8àg ùÓ]tôŠØï’5ŽåWccÃê>‚>¥u¯äzå[ÃÚâ•|kXúVk¶>¼²¯äort·&7º±1¼?dÙÊ—èö†î[Ød(ì¿bE§]Å#™µxXà•Àç4ç•ì ÛÕa~,¹W^ô ¿ïJ¼R>û¤á4fâF�bót}Óõ åâ%‘ÿá÷ׯâÁ+ýCÃ^ù Õ¼ü^ :–º^y–ÏËçûеƒ=Éî²%â Çw¥õ §í8Éîî¯ol.ßÝ\¾[Hi†ëð+o.ßM'î‹uyT¶]™E•–¼jxd¨`Mï¾ÙéÞÈê.Íf!ñ³Wnʬ�nN4ëaÃìÓ¬—f›¢§>7*_þqüväu¶�zQY<&ðJàsšóJ’&æ>:-¢úG~¡8D˜Î­¬{¥•6 Íy¥|UÇ{qã;Ê#o‚üån»P¦c¨û8q(³¦‹¯ô 5¯œÑ^þD÷ ¼t*u½qO¨Å¯á'z¥Â?B7Ô:yꎉá|à•Àç4畼Äì�+íGáÞÁ+�oiz(°¦ÃºH×½Œ¸$L{›îÕ.Nüa=T/)QcV¼&z%4´ ðJOsî•?ªÚž1óÀ+A§¯tgN¨‚’2=>QW*ᕇ÷ʾ�¨Å»Aê9Å éÌÒZ[ïšÞ;x%ð-Î{¥Bí{%™eƒF5˜j÷^éu˜WJ°�W‚N^éþH†“5 ¼ÒÉа®ÍÕ/Ðð­ÊwÄ0ðJàsà•mÊv¡LÏÖ$@ZG×i�† ’ªã@à•^^ €�À+;/ðJÄ®À+�Ï�WÚ›­|ifi�o­±œÜ‘¬ÏwH�MÌ/¬hÉÌ!µžµÒï Ý�Wz�@0ô…í¥U� ¼t*ðÊÎ ¼±+ðJàsà•öF7–¬dèl M"¦î4Á^éuZõÊÍf¯�ÊØ«“—.+W!ÄÆt’W*íó°PðJà[à•ö&‘ÊÑì“òšJ>[ùRlb~xtrxt²«'Âz£7=X�½�Wz�šWNkÍéáK›Õ¿i*ðJЩ¬Þ«�¨f½ïâþŒ�ĽUŸY­rü¤è’ÇÑ~«\8=-«>P¼‘^éu˜W6§‡M^ :•‡µúˆýõ å6„Ø•�K—ÇÆ_S}fµÊY¥â†1|ÖMõ¹€2à•ˆ<ðJ¯¯À^½ÑŲc²¿¾†Ò™Õ§• LÏ΂!·M½áŸlÊ�`hñV\õ‰€2à•ˆ<ðJ¯Ã¼2¶Yu2ðJÐÁ°¦°‹S³Ê�i1'ÙÝpw¸÷âY¥¢ú´²V™>8ƒZ:ŸìQep(†Î•ÀçÀ+yà•^çÜ+ÿ¡êdà• ³™ž½Q«äJÜWnFHÓÙ_ß`RYøðPõ eû�kƒÌ�N*¿yðU¶ò%6¶FgT|Ð4ðJDx¥×�W`;g•ÊðÕZÝÄØH¬�ÒN²»Ê- ±˜³|~}cz|" …{/ž<-©>›lfñv­‹_ß@t9¹#™>±%ÉÌáõ¹8“ÊýÇ9Õ|¯Dä�Wz�@0t^ €ÝœU*‹·ãáÞ‹fE!.Ïôì|g4Ù| ]Œ:p –᫱Î{@@À+yºz"ðJOã°WŽ~x%ð g•Êñ“âæ q¦gç§gç?v®Njø*áøI1�Ùiâ@Ý{o]ùËåY¼{uró�¶ÿ8שO'h‚po£R#’@¼Nm‡imôSãk5–‚Ó<ÊðÕf`4F¥F$y¸W„ x�šWNi}Юà´/rzZÆø3€æ`C‡-'w”+ âÂÄ&j�ðÜÒÓð^yÍ©À+À‹¤3;�`hè…kª ðg• ëܽ•/)·ÄUYNÖ~\oc†_oüÒ1£„W€wyþÅQ6 )šàäi)Üéê‰@-Êõ¹8â Ò½N›¼ò«ÒÀ+Às°F°,h hŽã'µnt]=‘ësñ‡{Et·ôm¶ò¥åäÎàP¬³Ç`÷5¯|Cûê«N^ žƒõ�byiü5ÕÅx•ã'űñIås!nÈ¥Á(¤ c€W°ÂÔ·ÞäoðlÐ 'OKû�sÊ'Bsûv�`è™7´‘V� ¼¼ÅY¥¢{ȼÿ8§ºPp ðJuáÁ²L}ëMÕ…€[hÅ+¿R7ëÆ�W€·Ð5‚ESXð0¯4À6^ Bl‹¦°à�W�#6‚e™ž�W]4¸‚@0ô×oh_^¯:x%xˆÅÛq³!âU ®^ @NWw¿™W>Ü+nåKÊåÎ,Û…2+dö¨¯xå^I†e=V|* �N*÷G³,¬h¬�í³ox%À”{%–õÀ+á•÷Ðy^é‰v°ðJ@Ç Ü+ ÛÁ�Ϲ¼œÜi´¬'¯t ʽÒ0ã“íÖ.x%Ø‚G½2‘Ê-¬h +ÚÞGÕ­|i9¹3³´6³´Æ*@ÙK‰TN÷.öÒðè$«��WÓm?{TIf¯ÏÅû¢}ÑáÑÉåäŽa©¶ ååäNlb~xtòú\<™9dýò[«ë•[ùÒŠ›˜g›˜_XѶ ex%À�xÔ+i…ìQ¥«'ÂÔc6nÏv¡lÖasp(¦›ïƒß>5Êås}..ú •„ÒÕÙ.”iku½r9¹#n„ÅÐá•å0Lgvlߦ3^9³´†X5"«¯4óJz «L¤r´„-4\™þq}.>³´ÆK_¶íB™×Ûåä™ãàP¬o ª+�¡W&R9¾<¬Š“/$_ã ¯¸„³J% -ÞŽÛ¸M'½’_Ûhè•ÉÌaÝJL~#ºíóÍP¯ÏÅIii!Ó[]=æv¡L+[ñJ¦Ÿbeh"•cÒÚÕ�W\Èôì|¸7bãöJ]ßCC¯L¤r3Kkã“â©™+ÿm_T9ªUä·O••ºö´{UcóV¼’6««9Õy«õÖ°ðJ€c¤3;ö6…uÒ+E 3kkò>C¯ûQR')çV¾DM^Åíz¨è•T³™ÌšI¢õ�‚Wœä¬R¸\k�yò´dË�ôJ±þN®`÷Š4:+¸•ZŸz¥¡åQU©•O$ë”{%o²¬xºÀ+næäi)Ü ÷FlQK'½R\ÁÌò’™C³¡V%^iX3¯4WGlR+z%é­<ðJ€k9yz^­¶x;^øð°•™G\è•Ô?‘ ;³´Æ*—“;ÔµÝ^)Ÿg„NVÃÞ—ðJ€K8~R\¼·Rkf%®òJ²6±Ý¬áЬÍy¥ØS7ä¬äCé·ò¥¦�¼àNOËÇOŠéÌÎæ­¹¸Í+i‰á¸:òq{$^I[“÷¯¤)Nä^iX x%ÀŸ¸­,IœØN•¯Lä‡è±â•´ýìQE4G ?…¥Ä+i‰a¥gö¨Òh=&¼à]Üæ•fó€d�*ü<˜3KkÍy%_Û¸œÜá·O¶X×+³GÖX·«'"~(“Ó®žˆáø´ðJ@‡á€WJZ�¶JŠQ•åv¡¼]('R96+)ÞàPìá^1{TiÂ+i’Jæ§ÉÌ!mŸ>Z>,¿�½+‘Êe�*ÉÌ!ÕxZ ^ ð4x¥¡—I¼r9¹c8¸«£ä›ª²¶²�z¥nÈYJWO„šÚÊç¯dU–|ItŠ1ç…W:z%?çú\œÚš^Ÿ‹Óذۅ2MäÁ6á•ô}Ñ®žHlb~9¹³](®/)2sÈ·ÎÕm ^ ð­{e[c×D ù�®ÿ¦•lÊ­^ ð..÷Êvd»P~¸W\XÑD¤&¸Ö‡Ü±%ðJ€wñ¡WR»VÖ¡’—;6zO j¨w$¼àg|è•4K`gaE[XÑøAxøùGà• Ç‡^©«šÔåú\\Iyà•�âO¯dI¤r4´ìðèäõ¹¸ÃÃÁ+€Ÿ½Ò=�W¼ ¼Ò �W¼ ¼Ò �W¼ ¼Ò �W¼ ¼Ò �W¼ ¼Ò �W¼ ¼Ò a^YøðPõé sò´†–“;ÊÝÊÏI¤r�`èøIQõéÍpi0:8SîV~Îõ¹x :«TTŸ Ð «÷ÖÁÐV¾¤\¯ü™ìQ% ��Oª> INž–½‘®žÈv¡¬\²ü–ìQep(†F°¯Søð0 ŲGåªåŸlåK]=‘@0”Îì¨> Uö׆Žéê‰,¬h÷Ѝ»l_²G•D*›˜gR¹ÿ8§ú�ö°ÿ8÷üÕZ›LÄ™LÏΟ<-©þ³€Íœ<-><Ü| !íËþãF…Tþ§ò´üôßÿóߤõ<-?ýïÊ·ñ|ýŸÿ©þþ÷ÕÿóĆüþ÷Õ³³ö�­ücõ÷¨žü'‚Ø“?´ñlšçgøõ¿ýj磟!ˆ½)üî7öÛåÙYõ·¿­~ð‚Øœßþ¶úß6Ÿ®g•êoŸV÷>B›ó«bõ´��î€Fù�?ü‡rû@:8¿8þ…�jyzªÞ>�N¡`cÅåY¥úøX½€ œßÿÁ®³h‰ÿÏSîHÇçqñà�ü£ çëï¯Þ;�ŽO¡PkeÝ2§ÿ­^:�ŽÏããÚã @-•ÿ©(7Ä'ù—§ÿÒêùúÇ?ª7Ä'9>nýû«¢zé@ü�Ç6œ­@K_T®ˆÒj•%*+'ÓZ•åïÿ ^7ÿ-¨¥ð»ß(w Ä?ù�?üGKçëñ±z×@ü“ÓÓVÎÖ“ÿTïˆòÿý¾¥‹+Ð"�‹Ê]ñOþý?ÿ­¥ó^‰8™““VÎVŒ‹8™ÃßµtqZD¹h ¾Jáw¿ié|U.ˆ¯ÒZËÃß©w Ä?�WPK+Žð¨ðH‰›ÜX¹†ÁÐÆÞ¦rQòùn²�ŽX\߇^¹¹|—¥ãtFya|¾›¬„c#1«oQç•Û…²7YXÑØQZXÑ”‹’Ïwsxt’ÒâúðJjiÔ#RùÔÔÒÜÐèû½û«�gÆç^¿•¼Óœ�èòÌÐs×&^¾±ró½Ìš×…«õxb7=á•'ÙÝáèVÔV|D—á蕱‘ØæòÝBJóºpµOì¦Ë½2{TYXÑÈ&X®ÏÅ·ò¥æ|„Oß@txtraEK¤rÙ£Š§…«õxb7ᕼEC‘ʧ.ôôÞc�Ͻބ�Hr¡§oji.s”ßûnjuhtdht$•O)«öÅ»é~¯L'îóçU+>"I¸»qjö,Ÿß»¿¾16‰�dw•‹Uûâ‰Ýt³W&3‡]=ó««'"1A‰�H›˜7Üf"•��L¤rÊŪ}ñÄnÂ+x ëÁKåøÜëï¦V7ö6§–æþjà™&Ô’non¬Ü¤ð[£LCµD\7{åéÁÁØHLw;ÝŠ�‚¡Íå»”Õù›—.ëj0O”Ûb×zåV¾DRÙ7�YZ{¸WœYZ눲…3KkMøÈõ¹øÂŠÆ2³´68ôg_‡®žH£5¡ˆ“�WðÖ âÚÄËì7N×êõQáù¦õ—to#¾”ʧn%ï�`^èéss…�Ïãf¯ w÷³â-NÍ®Îß´Å+Å—NÒ‰û$˜áî~7WØù<®õÊØÄ<™ î%’AëH>òp¯¨{i»PN¤r´Í®žˆ›+ì|x%oaQ2G‰A¼›Ze¯¾›ZmÈG ½’>ñ™¡çH-ù>†� �6ö67ö6©*3s”aKHl™œ¾›ZUwco“U�Êû->*"yûY>O]8u} OŽÓ™ãt†ZÉžåól Un29Ý_ß«;�ÓV=*ï·È>…­YHifÕ¦ºÏ=Ëç )­îö©ÀéÄýt⾡8‹»Éç$»KTHi†[‹Åâ±í§÷ÙšéÄ}³•]ë•TY)׳œÜ1“ĺ>bö–ìQ…¯»Lfé¥íBùá^ñá^‘/ [BbËät9¹#ªîV¾´œÜYXÑî%mw³G•‡{EV‘šÌš)³îsYkaö.ùöÙ©ÜŠf¸qÃÝÔ½Ê>(‘Ê™F]ñ²G‹Å££$_^ À[XÔ2GÃ!zÈ:¯M¼l—WêÔ’od+h³±·I­j7ö6ÍÓÞX¹©ëzmâeÑÚÑÀDòF¹üçfŽ2⻆FGtoÉeÄb°�n¬Üä×4·'•OÑaÑOg—ºâ‰ï2ÜýT>¥;€TBq<%7{åØHŒ§Ý^©SËÅ©YZ.hsœÎP«Ú“ì®®1m¸»Ÿ;�¸OU®$D¢µ�åóbs_³F¹ì¥Õù›†ï·–Ïo.ßÕ# \º¼¹|—_ÓlÜÃÖÈl :»ä‹Åâ1£Ô@Ú¾8ž’;½’IÖrrǰêp»P¶Ý+ujÙ7¥å†ÚœŸQ£“Û…²YcÚD*G­vY‡b¢Óe�*×çââß˰Q.}îÞGUñ]†Û‹Á6®kHl6nOö¨BuǺ-ðö-O|—Ùîë dûðJÞ¢Ô›”LÄF¯ÜùègïeÖhM2 ‰WŽÏ½Î”íBOïnSKs¤Æ:§›ZšÓY•nÞu�rés¯M¼LÖ¦Ó7]·SþÕg†žá?Ž?¼†Çü½Ì¿>؇/¯~T¼©¥9ú\�3êdVW¡Ñ~ý =}ºz[7{¥¡õ´Ï+y3 C¢ÒŠ^¹:“)[¸»Ÿw·éñ‰ýõ öoÝK¼±2«Ý“–ˆ�rI9I�ùjVqûÓ㼩ñC¼¸zåq:ïÏö1Û–éñ ‹Åûøð+Œ�ÄxÇ4Û}·y¥<÷ŠíðJÞXù5å^É«¨N X•kWO„}ˆ9—Ī>vU~}�YÓ:$•:gÔmféO¿lü[~}~� ws»Pæ 38ÓO'¡�OgǃC1ÝÑЩ%¼€·°¨$/M¯ÐœW>*<�K╤r™£ kóÉ[Ø…ž>VsÇ* i¡áŽðµ“| &ïPºÏaEzTxDÛç�˜v篞á+ 7ö6Y9ùå†^i6JÒøÜë´å†Š§Ûý[É;l9_õ¼±·I»¯«’†Wò9ËçiMÒ+‰W’+±ŠÅýõ ^ ÃÝý¬æŽUÒr¾ÎŽ*õx‡â«.]6ܦW¬H¬.-盡~(É,¿ÜÐ+©:\œš‹w’Ý5+mœvvÄHEy?%æ—{Ô+©¬õ--zåÞGUò 2&‰W’+±’$3‡:-º>g/%R9Ò1¾ÎŽ6Î×Nò5˜º‘où�÷ D™uf�*fÛ§Ýáòu¬´Üp7©ƒC1¾‰TŽŠÑJñèAß@”¶³•/Q]'_q ¯à9l÷J‹Ã·ZôJÞ¤,z¥®­& 7$+DsTIÛ1‡–6%®/Ö{–œ¬MlNÌf™Zš£�‹»IU®†G:òâ‘qóÞj6dà•’P}ÕÄɽr}ÃP¸>¾�×Õµ‘£‰Û1,ˆÜŠ=^fuëSÅ­OÖ–NÜ×­\Hic#±Õù›VôÙÐã¨xü��,¿;¤áº¿ôцZí!¯ÌU˜+54Í¢u¯$£±è•f­Iź6r4ª‚ÌU¨NSl J›â«,iãƒC±º%ßÊ—Hou+oåK¬V‘ )î&ÕÞÎê"?,’â-'wÄ¿‹ØàÙÐ[ᕼ…]^IÎ% ¦ ¯Ç¡•{¥Îie¾"Ϭ̴²a7RÒ:¾®ÐÌgù:DÚß·î ·ânÒ ÇG‹ÇñïB»oq´%Ã?¼RCê~(÷J�ñõ’f[�Uô>¦~¢£™ù¬aÉåÞjv„i7i ^ñ³øâñUŠT<±k$Ïpg-þÉ<ç•ÌÎDm±Ë+I—ÈÅ䥓Gª€Ó ‘áv’™C3ïã­�o;Jµšªqik†Ízëî8m™6h8¥ mœÿ[ÐÇñò¨Û¾Å b¨F•/9¼€·°Ë+IyÚ畤?¯ÔÕ¦ñ=4Åé5ÅíÐnš Ð*j”dGhû|Fú6 ޤzWR<Ãw‰cöÒaÑ5v•O6œ, UeÂ+­x%é�Ä+uµiº>†f»@ÞgX#I¡V¬¼FÑŽˆàˆÛ×µ³-¤4ñ^Ív“Þk68­¤x’íëÆ Ò= ÕozÔ+³GÒŠFg™´î•¢LɽR'�d[ºœ¼rŠ5¡¢…±P+VñsÅ#@Ûç=”oO›Hå$-‡Åݤ%f�š¶6]<]¶ò%6¢ìý"¼@`—WÒ ¬ý$kÕ© ßÓºW6ÔVlíI/‰µrâv ÇY#z¥¡XŠ›®Ï#sá[É;â<&bñêޤ“kú,ëÅc#]›xÙpHØNõÊýõ 6¤ ŸÕù›Mx¥ØšTâ•bkO~LT³] c5gUŒ(n†be(nº® l �Í廢*J¼ÒìX‰rÝhñX¯Ìéñ Ã!a½ë•[ù Ã&£‰TnxtRL^I"F®'ñJÃjSö’X)z¥á0°†ÅMü\Cqã«,©Ì3Kk¢`Š»I-WÍšhy��:“ ¯àul÷J�³Èu¬®WR¿¦|ž3¯+RÅíX¼íákE›·�½MªÞåsmâeÞ.%Å“{%­Ð„WŠ8z,ÐÁõ•ü°0³â•´¦•ñ`Ey´â•´‰Lñá›Ô6!nÇéÌâÔ¬8ÕÈôøß8V,^݃&®ÐhñÄ?= {Î+“™CI?D]¯FC³î•b5™|ï{? ׯm®¬ø€õš+Óuzq¥§Ž¹Ásåúæ^n‹�x)Ô?üñÏË�;¥R%¸Ýh=ŽW[Íz?ã[¯¯[z™ß´�óÞ‰�gçæÍK|/¥—‡ú÷N|nEv÷½33›}�\ Àxé)WÆ3sù¨§PùÊ\™®nkÏŽ4W†«ÅV�9^œØ˜Váüñ´ÓF«QzòlŸ‘ô4Òp†Ò}6�Î/ŽC®Ò¼øüWš+¹æ8<†æÆÿ±�½+qþÉÉ•YàŠ»÷-Wf=ta¦a®UÅ¢‰`U:¿òÑú­nw2î%L4ïÙÆF®K74¯xÇzm^»±škÞÁCGÂB¾ñàä¬U‰óט+Cye %W¾33;;7ß­÷s¤¹2«Ó‹+ÅVMM+í)WfÁ0×!_u¼iK·E„Ö7÷JÏ05}¬xÇßKión´O>;7Ÿ¥ûÐ+Þ%W0^zÍ•!¬�]Z8»´p¥¹Òk¢ g(­nY2®µöZvpn íµo¯ƒUâ¥âyrñíJså•—™hv8é´Óì~8÷Qö}4ïbãRh^·ûV¥yÅó¯µ×¾¸úåÙ¥…Ò76Z�ð®êßÚ>çÊÜ8ØWnÀ‘®noï–%sÁ*;8«™ý¤¸Pjâ¥âyr¯¶«×Ï_¸~þB»±ZzL¸�Òf‡ó—.ßš úýôäÜ¥ù…ëç/ôÚ¼Gë·¾ûúZּᄒÖí¾õ×¼g7—/_?¡ô�Ù“�µªú·¶Ÿ¹r}s/½ïF¯ã`o´—¾½t7Ì\}Óþ=;8Jšx{·—ÂE冤ƟrniõÜÒêrãNé1ñ…$nZé{o´Ÿ¿ú�¿�ùêôâJ6´¸ÊeƯ^mþš×íÎ'¾—DóÖ7÷–wJ[–½+qùr%¯¡þr¥RýU]ëö(ÕOíûþ•Jõ]r%õª=h¨‰*¹R�SÉ•j|J® ^µ 5Q%Wªq*¹R�Oɕԫö ¡&ªäJ5N%Wªñ)¹€zÕ4ÔD•\©Æ©äJ5>%WP¯Úƒ†š¨’+Õ8•\©Æ§äJêU{ÐPUr¥§’+Õø”\ @½jj¢êÞ“{=¯ívýYCMNýôÓ O«\©ö³äJêõÏßמ5ÔäÔÃß ô¼nmÕŸ5ÔäÔ“'ƒ<­ÿ~RÖP“Sr%õºÿô~íYCMNýºýë@Ïë£Gõg 59õôé Oë³�ú³†šœúy §µ³·S{ÖP“S�Ng çuw·þ¬¡&§ž?äiítêÏjrj{w ¿\`p†Âªý©A'Wf …UûSþ´þü´þ¸¡&¡¾¿?„¿\`@�NG´T£®ùqÐÎÊÿ?¯/îÞ­?t¨7»¶¶^ åq}ñâî/õ‡õf׿¼Ø¨k†fgoçöÖíÚ£‡zSk8=•Áóç†U#¬aôT�ÎË_ûk�êM­þ3¬ÿ€áèt:{ ]ª!Öí­Û÷žÜÛÞÝÅóúr­NéR ±Úí—‰r{ø�k§óâéöË‘Šµgõ&ÕÝ_^>Wð:ÛÙÛÙÞÝVj�ÚÙÛÙ§çuw÷ÅÎŽRÕî>-z²÷üåú*J R»{ûó´ûç¿ø)Ü endstream endobj 35 0 obj <> /StructParent 100000>> endobj 36 0 obj <> /StructParent 100001>> endobj 37 0 obj <> /StructParent 100002>> endobj 38 0 obj <> stream xœí�]o·†ï÷WÌu€Rü’C@0 Y–Ñ‹p, ½ \'@;µãýùÅ®VÒŽ´ÏÌ9\îh•¦еØáá÷yùžÊæ?�íl÷7³óÏ\|÷áÓêËj]âc´]ð%™!ÇîëÇÕ�ßuŸW_VÁ87ß>üúðiåºõxÛÝþøúËêìmè~ù}uö�ß>¿ÿöõ�ߺóó³ï_ÿýª³Ý«W—W¯7b—:gcZKøyõnõnW¼·Å¬Û6ÌË7É•Ôíþïo»§|h×åÍêìý~ú|~~vñáÛ?ýzóñ¿ßºóë7××Þú«WÝ«Wݺ‘g×}ç|wóóÊÝŽ˜ëRv&ù’;_º›O«skmÿª»ù÷êÍ÷·�ºùWwnm¸ýc6ÑÆ!–þ¾ �Öö—Ööeó˜hÆëûfŒ…¼¹9¤ýÙ:“{gÃL\~¦ö9gúäò\ûb°¶¿x¦6úhúŠŸÃtà8>Úòi7?~xÛÝþج|WÖK?å®ôÅdk­ë>­|,;ÿþuõ~eüfÇôÉçÎ8òf3=ùcÍfr¡sƒIéц2n½Ïsçl0yH)å»AuûÕnþèœq%ä˜Ü}‰°¤Ç‡%‘JÜk*ñ×úo&Zðå\ l�ÇqóŠ%ÊØ.Ù§+O±>úÎü­N‚E†ÉÕ·çn)ièÝùëX(ØÖÿ´ÀÑþR+íðí"×ȸ ‚7Ú~lWñž/®© WW•ÕCB2¸ç4ì<$XÕU³! 8ƒ4ç4$!Ò£µë“ß¿®bÊûGw§ ÄBU9(p×P0Z»»Â½£‚žª¢V±Œ7ÔsìÇkmÏG2F× |$cÔ\ê Ž.WuEÂq¢hØC$4ì(ƒ1HZ%>ê¹hjG_ yç œZjn Aäž_P}ÁUyÉþ@á»=K²ª®©*š\pÛa�õU@„PbšB(¨ª1=¬ 5†:•ªJ‡ª’8ê7§V•¬À½ºç8º¨òõ­Â =0Äa¯h®3nž#niöÑaæ€:”�ÍK*¸ á ðøç£eà�´ë9kDîÓðè¢&ÁžtAÝS�Í.%2F=ǪpÎEW$CßÁÑ�<Â4¨Ž ´ñ¢Æ�CÂý©iöLNÉ÷3š=¨¯i¨{èÑ&-â GÂÑ(’±SÕÌ;A°Ó“äŠÕÚx�½™%³Sc±Qû”`«H¹†€ðHÏ$è=�ôn6í\yæxÏF,ft�‰©_—¶lyÌGÓ‘�‘ö‡_o¿öÜÝÙaÏþpwNðyH1Ý\^A~Ñ(¯é‹K*PÝ­½ÓÑ£±»Á'Ó;_ÂÜèÂUÊ®]Ä âþÔß„*|×Ô½/aÅŽ¾n·q[¬—>ybñqn½ðe‰Æ`Ž�q‡W´Þ„>ôýìáeáüˆTÐg*¸¦‚ wý…¶ª¾L·ê„ÏÁ˜£IÞ»¹sðò¼¼ÅX¬)}N{1Zõ¼æ¨¹¬øQ8aˆŠVùSß ÙZ3¤~pKî„& wɸ¡Ä¹†Ïbƒ··n‘Ñú“ÝÛІ„GÜw^-CµŠŸcCº� }úÝé�Ø‘šëø w‹Àª/!dŽ©]½9¦â4#ãÅf!cÓÚ×hî0;å+ÿž£«"¬ðˆÅc<œúaÖ‡Þ”âË0s–ÕÜìÕžè¼wôþgµ^û'Ÿ¢÷¦ÄÁǹ™©°DÒèM߬~ÈË­Z ÄD¿ŠaÍÚÙö™ó×Ç“ÙB;8ÜÛ:r¬aÄ6Í Ï>®I-ºzVÃP�/’Ûz3�ÚLjÃÅÕA§�à|,ÆùÞ»Ým°ÁY¼”áu¿ÔU©Ù¼uZÄ•ê›-P?î­�‡ßÐ_ð%9”b¬÷ÉͽáÊ¥-FC2eÈÃ0;3úc­óÈ�~] îâ/÷�pmxE…kÏb`0ºM„—›tðQÛKDê½NÕxTŸçYÝj1}¦ÂX¨cEéº_‹T»9Ë\ÛG¾~èi¬Fg7N½ÿ3�î÷²piQØ·Ì7K„Ë¢í©²l2"?ò¤�špAe?� 6çCí Ë^ÀúP:JeÃþèXº9)M…ÌÓŠÑc=�Õæ—¥<�cž„áìè§Ž·ÒÇBU@}ÔVjf²B¹>+nÒ§ÒÓ\í¢çõ¦f}{Ô<²;¼,˜#iôñ$ (pÌ£3 ’?’窈S’{ɰV% ˜‘ ‰:‰OEÈ;æ¢Ãªvˆ®Gz«ÒÃ<Ñ|È’¶KÃÄaÜ¢¤š²BLW“²'fý(Ð%Y“â(—GÖ0åÞÒªI¦øÓéáȹøZÂ=Ø;I¼U�4Û%S«Ð‹ê,k£ãöÀL)ÇO³Ø45’Kê;2 ×'LÇÝŠ~ þEŠEÀ/b9d‘ËX•>Ió% ¥ŽÆ­&ÊC#Ë¿-â�è‹fRÒ´AóD™TÇzÝ£÷×ûiëeè³7«5{#¤{\$Ý »!â|èÑD)ÙUX”,^–ëF�û—[…W/µÍŠ•+²ßzÜ„zNùqÖ4Ñ�TdM£æêg“4cAm€Ã®NæX‘÷WIìàµ)mšð ‹†ÕÝ'ÝMËù1by%V„¨P´ËÖÁñˆn~kX5–½ &[%ú4�œÔF’=ãvjÄÏ�êÞ¥GG×ïùeÎŒr{d“ÖÙçžž>O <}±ö=U]k¿ðôEP`—§_�çãØ)dÛ ÌXí^õlçz±„{G̓”jï –¡`íZuàËQ"ðÐ2—‚9=ùHÃ.#¢dž "oK™¡èª†·üü8*4~C§cQÂW4à!’ùEa†aF.‘7S¿ýÕЙ]�O[ˆ=eæڃ迲D¦dn.:è T•>T@ä”%ê�ÒÎbœ}˜ rRC&]jSij°À‘Iz/5õÀš]oòkYaÙ£!a�€ËG ¨~õ@NB±p Hh÷f1%2½/«žUjøÎ‚Þ¾¥fàZ‚˜óqÖõý‚ó'— Çg¹Õ^¼‹<$!š(‰ð‰‰"£Jâ¥NØg'÷“¬KC•ÿÒX—†©  1x²)ùaW¨RŒ:JÓtAnœþ“ò79Ì ŠUaò(ÊøN?1ÿ0˜`]Nõš[ÿàDC­ªV…|—Åd{ 3ß,ê_U¼ñÉæ~v.÷DîÏÞ";à6–ª [‹r›ñ}5®æz�¢v<«xôFËâŽ×7·á¦k7V覥/½š…”)M™ŽW[VÕfÄ絬"+Ì�„rbU$j—á ûÑpeù1ENz,ƒD¦|½ËÝȸ)ò)”�®:Õ,Co™uÙÁgú¶­ZØ£·sª)%™YVÆäéãŸó‘µŠd ˜‘�RÙÆg‰X”a�áÅš¨†iãÔ˺ý·S´ži o´'ù 9+sõC~-“âëYnçÝ-seþ ItS„Èq›!‰lŒÞ]º"e¨^¸þéÔò¢çUdŽâêhÒãæ ØÕceÚ'¯z:Uÿ$8ÊÐÞÓOÍy Ùø®¸i³d:-\ä�7z/ƒ�0j\AŽë ƒSÔ›YÔ+Ì4 äc—p5ìâ¤ïKä»B7)œs4´é=¦EÏÎË”ðzfy� û�èj.JƒÝòjþ¬ 6šeÈ HùT,ÑJ Ÿyxgùðµ�Ê`MðÖNÝ÷ï^ôµº7¹”Òàå²™>±5©l=,°”µ�[¥&]xù�ðê§k–9Ä&õóŒ&]ÅÌclJë¤!„ÎlsUŒþ¢JrÜü!”Êü!¤¯™ pê1 öhˆô0²UoV)D(ÖÈÀ[9õÇJÄ7t¤Ò§Öà›†z•pÏgn°M8¤w«w«/+Û[lçc´�·É 9v_?®~ü®û¼ú² Æù¸ÙÊ¿>|Ú“åìmè~ù]sf:1‚Œõ>»ÎYïL !H},7ô{�ꣂK(XÕàž \CÁŽ>|ÔÜ� ’ú n©*v,À±ÊT`ÕÍ¥äe �½ y´×¶-ø"Üi5}öÖ•õæK±t.:»O«”úíï_WïWƒíJ¾-}¿ý½.¸m—wÉø~­šý°ž¼‰ë.ÜþÚieò¦_oØt»YþùPE±fý¤äÔ)qöOo»«ß¶ÒûM¸•ºæb,&äØ Á¿+ü¾d#{[|ÿµëc0yNpw‚×3ó?䆃2 endstream endobj 40 0 obj <> stream xœí]‹SÉ×ýýé©�džITÐ]ÙÕ]e�dº§'„—(J@ž (b1™éž$òRß�|u{B@DDL2“dN�²¶Äb'=™3}oß{îÿþçÇ�ºG{ûÜÙŽGÑ®Q£�©ˆ˜J€Åbq|iËí«óáÇ烶„Ë‘ØJ{ûœ„A1dBÛŸ^»ÿêü@AÂV÷誄L·¯Ô‡^�¤gdݯ®E ™ ¡ ¡m½ù¾¹�yöyéiqéiqr彪Sø)¶Ü¾^>|¸ .YY7bIzFå¢q®×&Ó[wÍ�Žhd×èfXg²n…t_@|øhFˆ1*Å©Œ¨¢sÑÐ-…°hÂÆS/îd��2ïÛ_Tƒ…t+1³Q,Ýþ>|ø¨‚±¬¨™2¶LÅ•S IØñ‰çãËïŽ�ƒìŸÛÙKŸ¾tûÕʈؔ°)$4� n_‘5‚`DbËÄ–±Œe�F [!¬stóä¢QfºPlëËK˜vŽ(íö‡«.xù¥ð婢22¡²Ò!êôL×ã³W—ÚÛçܾ@>ª‚@‚‰%Âwž FAÖa›¡è´cdcäá›táë¯êF™�ß©„P:„WÜþ”UD(ÎB—6y™*˜F ö×Ъ¢Ó°Á$ÍjoŸ‹ÄVz¦7ÆÓ[~ç£1EyUc*f"QJØŠLÑé¿Ãë#ß<ü Ñ8ÈŽ‘ •PQÏ znãÅ.[Ò˜¤±Pœ)ýsàétæÃùþÂLæÃBîËÐÂë‹C«²NUN ŠÅb÷誈Leݾpo!ð/ _Z _ò7i^Gà_ì´„U0‹¢¼¤YÎNãÒõµ¡…׋¹ÊˆF™÷èg•0A§2i(õ(‹K/»Skb—­ª6tÿµó‘ÛúòSÊsÖ§ž;Ûg’98ÅÆ–ˆ²2¦ 2•x6ÜÝÈ[²“£¥Ó üKÛÛçÚºrµ—ù;4o¡b;Ú:�7D Y°¯ÆôâÐêÐÂë¹/•�ƒì½»6˜B˜ˆ˜ÛËPˆ:ë™Ù,‹²'×WG6îÛû x®77k~ú~&WÞÇÇŸñZ\[Æ4ܽ¢ SÀ™´Òðy¡ãÑÒi È4ŠPñ"Úºˆ¶| qå¢Ðsx!¨ï PúÇàÓþ¹�{{õ]Ueºðµ5™“ã9µcÝí%ù-4dPb1&´­¿0ùøý¡Ï{6™›³ŽP�½Õ(Ž.½íÙ€Äa"¶(-âL3'F¸t˜ÎJÈ’�%"ËÑ�v_C\ÔwSì8PŠi[¾ov¿(´f¼½üN!LíXWcy·æ”pB•αµ@‚ªDö/mê 12‰‘0a iêÄÈžt”DDTÄ” ¥} ©"¾/ U ;Ó¢q|QhÍx�~Vâ¦TWÍ/N¨"è4„ ЀPeåp¨rˆaÂN•GšÉ|@ÏýĈ# ¢x ãhHbjCÒêéËãqü°(tüŠBkÆž™mÕ`²N\Û�“‡*‡¨ö;Yè$F²Í–éൽXF³DN_C~PªCQ¨t (4b°øø3ŠF™ _Ï&s6C18÷q{�ƒ·z¦7öC•‘ãB•C”1­HµÌÁÄȈVªiªÄˆ¨™‰©õb±(i¥„*×Ó/›ùUˆ]¶Èç(T¼’¼E¡5ãèÒ[…0¨9éö¨zHör2¶¤¸¥¬­??ñÝ©Êñ”°u’-ÊÉé$FÎ&s �¶e'1ÂKGLeÜ^°ªÃÉ{ü׿EÌ`V€�ç¼n_ §EyAQ¨Œ(7î…^­Ñ8Ȇ×eÂBqÚâ½òqÝ@æ/…*ß«G•–îPbzj°Õ$‰‘@ Øra«åÂ7ÂKDøV¤SñUÅ¡¢PqO4ªTZ3ÎYŸdÂZ±‡ÔCF�;  ÿAXÇÈÆéŠa¾Ê˜Vu&F"M–q4DþÛæŽv  #qÓ�e@�Œ¶umˆñoŠBÛ¯U½(´f4î¼ [Ö™äqªPÍ–TµõåÇ1T9ÈÅüWE¯®z”ydb$6¶ &Nz#¿‹¹›î’Ó¼,áR>DDY …|n_`­Q. måE¡¢fª„)¸¦E¡5£“>•0 '¬ÖA7#wØið XU§ŠÎúfOªz¢Ã„Õx=çé§¾¹�Ö¾¼“Q@=?1âhˆÒ½ [/P^"¢3øSƒ´•ÛX ”ŠB÷œBÃ{E¡ ´¡Dã GÓ�>mÌD“î¼%¡òYPÀ¶ªœüTåÞ·¿DŒZ«G™G&FTÌTÁ¯+ë\mPº­HäIë`f/¡ ÒQ:ðmÐ|È÷E¡ª^. ýa—D#ñÒõ5UgŠaIM_�¾ÕPONà¥k*a­}ù‰Ç;æ¾G?G{lwöPbDÂ$Þ1màÄHë`&Ü“U0U;Ö%'‚,!ÎËE(Ò‚˜À†°·Ü+ =›´ Ï…ÖŒ³æ'YwŒ‰j§’f Äô­*ÄRtÖ{÷wC•Cœ§ŸÎôä\_[‡Nb¤}hU&M‘Q;Öåî¼çid�Šûù‹çCl·/ð”(…Ê:7È|j’g‹BkF}jK%TæÍÕ¾ 7„W $¢U^$S�Àð®ù©µ×+êQfS%F –ÑVBø‰œ|¼¯!º- B,X?ÜÑE¡ knÑ(s1ÿõL�-¢l´k¹z¾RN¨"Ây·©ªToñïš[{ó®/ì�‰‘Éï*F ;˜ÈúV«´þ®@N>–|:¨vМž;+ˆò!DLCÄ»ç2?+ uÿ[äÞ\|£ð•:wu©÷â¨P¥Š¥23™�çû½«¿i¥�ss+з*Öx‰HøhLBð–5$Ä‹d$d)^ªS ô­¶$r‚a* ­£JrWø÷õUY‘®ŒËUðvðŠnšŽy¨rùÆÚ<­z:z:óáBÁõ%=!lHŒ\º¾v¨•"š:­Œ‚€/k‡‘NÓ®‚¨„M¶£næT�¢P1FEÂ@Ã…æ}Ñø ïš�ɱœ‚*“ׂP%‘QV%ôl27ºô¶6ŸeråýŸƒO]_Ò_å¡Äˆ7Ác„gHÜ}¸*e”qV5²e Q�¬ ›-Īñð�ï‹B#¼ýüo.�QZ3¢É-^Ç~¿éi?TÁ–¢S2µU)ø“pbåýÅ:T�2�ÄHØ(%FT#«è •Q�¬¬gE”…ƒ §_›àâ‚K®DUý¿_Z‘Š£&äbþk4a ˆ†zÓ�Têt·F‰glªŸÚÄ …-9~Üý‚PC–UÔmUgg’¹Ñ´;¡Ê!Ž<|óÏÍu×/£Ú,'FäÆJŒÈv‡Bñl©á�tHÈŒô˜?êÿêxVé€é…†I³W’מr_" [ŽÓóhóG“€l*Þ |CH�i7C•C¼¹¸{åÖ†ë—Q3.æ¿/îJŒŒ§·ªü”W¡xús‘Ò­²†´f¤Þ¥–þ{å¬~¹(TAf¸{Å/ õ¯/¼V £3ñË#o®BÀ•]!0°»`¿Äá»WGšH=Êœ³>%$}ˆf%&ë{b ƒ�n üHWŽ—î¬@*%$WD='y¿(Ô›üóÚSY§­èé‘ã�TBϸwªr<¯/¼þ/µéúe¸Ån¬ó9,�ãÌ#Ç©ãâ~pP¦œ|V. ½|Ã/ õ§Ÿ|€Œî•°vD>_%l&ãÑÄõÐý×�£Í«]cÏ ­µ�ÔÃ�3(Ó± ‘¸uöå›k7ìú¢áMÆn?ƒŠd…â‡Û!Æ}ëáׯðHÞ{Õ=öÌõËp‹dzKÆTÆê>«  ÓuÃ:˜ßq}©}Ã…ÜÕ`¡8 ]Ú ¾IŸ*˜&ï¼tý �äÀü«ØíæU�þ¹�0´ÿ7¨zè,}@tÁöûP¼Îk÷^… Æ[¾IŸ Øìðjf²n'>þÜõËp‹7ìF,bx×=ãÔ€|iϲ„Y3ï-ë‹ç 2¦Á«k[ á<׫}³ÛÚÄ ×/Ã-Ž=zç Euó9¯Zà¬VÕÙtæƒëëìó$œ\�ô©3Ⱦ|�™jO\:5{înë“Í«ÓO>D,ìaç®S#Ô›°ùç@7P7!»Æ6UBE�–'t€+”N½Véá°gæ¥>½åúe¸Å{ô³ªSéêÚ¡TU½C‰óÙ„ÝXxíú"û<9lHŸÂPû© §Zá½Þ¬÷0f^M¬éBQÂæEþ¹ãö_I¨È„öm¼SÕìó„쟥V,'–¶¸;:• Ì}sý¾'™ÚJxõ<¨6Tt*…à?ÏÜ~â+è‰@`‹§š÷½P¿LŠçû 26»GW%0€ÿŸîÛ^,ÊÂS[ž=M® Ï&mÞ¯Ú8©ÇÿAÖ™ïÈQ§œ|ü^!¼�Ú¨Áhå�/𣉽³Û®_†‹¼0P€ÒnÔ8å¦`˜‰Í¿¯7²ñBó3µ& æ�`0ÕWk>lú$Ô&ž{3¤ª/7T« 8 êVØ`)oX@ø<ï³Ï a`>I˜ èè}ï•üÅo?˜kjõèÛl¤V™; F{l¿ã¾^˜.|�³>�/¿»ñ`·wv;6þüò�µ¶þ¼¬C£wÆf‘«àôêJ±ûö³ÁùW®_†‹l¤V—@‚Š|ãÑs§©£QorÁþ2¹ò~äá›ÁùWxêÅÕ[íCO£ [‚1|4’°£ [!TÔøÐUÍuÛñfQ öà=Ï=§]cÏ®yïªjÉR«‹Þê$P©¨èÔŸ•à�“†Ta^Û|P"ÚÛç"±'üG¬4¯™'â‚ÉtËÀì'1•0õ`MxçèæÐý¦.(ºñ`n\ý—›‹Åα5IgW¼ÚTÕ0\°¿Ìd>Œ.½œE¦¶:G7Û‡žžMÚ2¶¾•Óñ½£éŽuE³ù.œ�eL‰ˆt>>Ûñèø¡Ø0¸G³þò^¼#µÙäåˆc�ÞrWϺW�ÛK`Ъ/ÈõȃaLouŽm^Z=›´0版$ì°ÁJv¸DPZÔ³{Aegw�²RŒÉ1[í8¥…]›¶¹¬„íúšâÕ[Ë»®_†‹œ~òAå'b•~šk�ÄÌF›­½íÇô&ó_gÍO£Ko‡^÷ÜÙ.K„Ì#…@:"b0‰Oå'ûY9ùX!¦#*Ù—ˆZ âåJWüÎ^D/*ÊÈòš¹Ó•[ë7=ê\T:­.b�·ºÈ±œó&X“çÀ�äA‰HÞÙîÛüûúZ[o*²~ PäÉ´/0‡ 6y"'×òæ"TlÕ×›zâ­vé†×GÒM­�Ñê"k¶ËÉ:õR—9¼¸{®×–uKÆ4LX8ÁTƒ‰�p0% æà@ �³ßKD)ܨòŒà_\dÂs=�©ô[×'R¹Îzou ¤Rbâ±ìà�…×°¥äkx»1l̜ͤ+5Ô²-èI5�j@‚Ïb‘&nhõ,K­.z½¦>|# C¼¾ðÚé‘JÓm<´‹8ø¬ éâúÚú<Ä? |ªc½–›–Œ€}# ¢cô­˜H|ãáöÍ© ‚1+¤[g“9×—×ç!^¾ ­.B}«C„î=hê³3‡ó¯žáu`»}s*†ÿë²`À(¶üé]^c]·ºð\_Ö7âÒ±•Þ:ÌËÑ“•ê U v×ôèd¨¦%™Þ’•Pý«GQ^Á0×Û7JÞÝVmALà³æÝ¾3•‡JXÔÓ¡š–ýs;ªÅ�nA~Šæ3ۊ΂(¬ÕköûxÈP¼J“~ÿ£ÇX¿­. †fŠ&7"S[ ¡r,'jvåݾ'Õ‚„,›ÿ¥ü&&o±ÔêRoS]DæÄ©Ím„'·Â„ (ãzc9·ïI–§m^� Õ´œÎ|àÕ†u¦2a¢Î¢‰æ5ÒÆŸ©TúI:PÆíR]qÉ~Áõe÷y�÷èg¥ÞZ]Àˆ—X÷ÜmÒ@8>þ ‰(¯è9Á(¸}CªŽ@‚JÔcŽúæ-b¹ÕE¼P7­.Ab5³P÷Ø3Õ`�ÎŒ¤Ñhãæ:!Lh4Á¼9ª™©èð%.ÕG«‹c$c« �€Ò…bGjC%LN>p&ÐÙàËA¨:Œééon#bÒiu‘êdªËxºI�€@:F6TB(-�•wÊ»g2T—ß Ys>È}™£Ÿïd>N<~?ºôvxqwpþUòî¶>µ¿ 4 Ψ“’�žé Qk:# táë•› Q”—p¶^Úc+Q£!lzs2Tq!÷eÖú4�ù0¾ün$ýæÆÂk�‚;Ûxj+6öüjjãÒðÚÅÁBkoÎñ©–0˜<8& Î)¢ ûL�5lSA£"¢!ÂêB=B„I`Xa7•ÐÃÂ×ËÃka f;Æš'×q¢e-aON†òo.¾ÁS/ºÆž]¹µþ×õÕ?ŸžëÍG`'"Ë©sˆ nFÍÿ•�4 €,QQ‡¢e±ËF¨x¯*`ò@#ƾ€ðq] ¢qû òsH:\gS�tÜs­öö¹ðÕ•À¿u òÕ€Ë)¾± Þ› å)B×<#zÞýjr¯Ó9ht®„9:à¨GØ Ž=8Ëi–ÓiE�µjÏ.ƶª›ÓØcH¥„䲪[Ý·›%ø]Ìýkh5Lh • ë÷Ž·ox¨^ã�ß»~_¼ÌHÂc4D—œâ4SÀfP·þÏqûº†–þ=# �Y\V‰{ÒÁ©Tðúg:R3ÃñQlòLÇóaá«„­@*ÕÒwßíÛå-É´¨5‹ÐbîkûÐÓ°Á�b°“úÒáL†=9Ê;¼k~T “Ëþæ `¶"Än# …Ü— 8œ ƒgvë¨ ¸ªðìd(ïp4ý6lØu×xRmÈ02 )Œ€r_΃‹Eãº/û(M†2<7Ê;˜ßq°Ý¾WBÉH§ o´`ië+¨Eë�^‹¾tìó“¡¼C4ñBÆ`¤ïö½òšÄè>ûÜÚ—W �ñ+þëã0*¶ñÉPM’6?ÿ^‡²�F1Ä®# K ðÞ£ŸÏõæ&7)¾tüΡm3ä¾NǶޜ¬›"ö¿?%ˆq>Ò¨¡�€æ¬Ogzr΀i¥Þœšj gÆ®?êGTùp7ÑÏšîAF–7ب$ ‹¬GƒÙZzå°?êh.ä¾€¬ÎšÁòå$# Ý –lP# YóÓ™„-!°wów?E¨Û’âÖ¹^2Ôœ\y&õçX=”Œ€HcÝÉ~Œ&`‹¢S©AíÐ+‹àþd¨rxqú×üw‡c$aëê­4r¤Cáã0$ÿˆídp&C©„ú“¡¾gÏÝm§åÍí»ä L8F@�Ø5“ù&¥]‡R·#È]´Š'üÉPGæBbSÖý7 9½!#«µ¯ÑŒ€¦ž|ˆ&#ð]ñw¿ Ð[ƒ6jìwØ~mUÂLªÛ‰ö•…Ì'\_^»õðMÃÔ‰M®¼W °(Q0•ýýë±%jfGó¹Úþ”Ñ[FV¨Û�\þçî‹ØrÌÄî*v¾?ß9ºÙ?·3öè]=ºÄL<~§ž-|ZÜ^àºD[bçýÉP߆#è�Rvú¯¤ÿ•Þ2Ž­¢ÎDd:3"ÊJ°!�ÈW!póÇàÓøøóÁùWãËï<Þþp{ù�ʘ«¨ùµÄ§D‹îO†:‚³Ö'xL4Ú´îsÇ Ð™i‰eBñ¬„MpY„Ù@ŒÏo5%DÄ�s#¦Qþt}͘Þ^Ü�É|ðN�ÙØ#�Žæ»?`ù ”'CÍû“¡ðöò»z éäXNŠS)ÙUgwD‘ôŒÈ#Sá8ƒ¶õæ;F6úfwF—ÞºU4’J¿• iLÄ` îöÊÕ=øæ“�>jØÎ…SðÚ½W\=ü�Çiö}ó¡ÞEA_Œñ4 vd�… kªi°3’~cîãÜ»^ó_ €?ê{êS[2¦²ßW!8Ò†T¥`‡�)÷Ï‚�ŠK‡ªÃî÷ïle¹#ìO†ú†WF6d‰~o~Õp(؉Æ3íísÇ;÷~#Ø~°«@×ì…ü\GG4óâ ?jŸúó‚– ù_³Z¡½}îlÇÃH×ò¡`‡oZöNv0�ì;C ¯'WÞŸ0عñ`FqÁo6eÝ#T!�Q^5üÉPû„œ|üPí�¬¿Ú(ûäŒ�?‡‘µþ�‹'@ZWt3ÚÓø“¡ì/÷í/³æ§™ÌÇÉ•÷c�Þ�.½^ܺÿzpþUòîvÏÌËÖÞœ QÑ/(òáãø oyy2Ôƒ\é‘¿ÃùÛË¥Gþ:ä{g·{î¼ÄS/âãÏ»Ç6¯Žlü3¼~qhõ��§mýù3É\’TÒ-‘›ÀÈpü£:"†}&aGv”ÿ6X„@µ¨Q8ŒûÁ²?‡3*’`Ó-^Ì�§Ÿù‹þÃäÊûñåw#ßÀ‹~žú¾Ùcz žúÛÏ:Ç6¯ÜÚøûúZûÐÓ …¶Þü™;ÂÏàDä<õüПOÙˆ$ìˆQzä�Ôº¢ƒK‰¨AöF䥳’fñ*hÞ[¡g@ ºì@*%ô<7Âpÿ÷8mq2f’Ƥ8”¸}[|ø¨ðµ}íÞ«ç-Ÿýfc}¡ô–Oò·¼6ñÂyËÿë¼åá-vï-/ãÒó.󎆰ó�ö”ÞòÑÛùøgu2 "6Ÿ"xêQVЩ¨Ûb—­v¬Kqæ‚‚-P�½_È &P !KÔ8¹Úp11E- ê¡™Rœ†ŒG-½ �TÊí•öá£Ñà¸IC¿«üÝÛØÃ(yÞsêì hÿ‘—!ãJË�|å(- ŒcÙ¤ðƒ3§2p�ü D†î=ïf‰Î#�L[‚Ƥî¼ü_AíXw{m|øhvü?½Þu› endstream endobj 41 0 obj <> stream xœí�pgÇ7�” $P:’-M¡ENÀ4ÖA�ÅÂ1N;=ÆZ£u°‡ðÇíÐ4XM•›B˜ Z 8ˆIµvJ˜f §bÓŒq(´�˜bc$mlšòãÈîÞíîíý\g÷8r{·w·?žgwIùü�{ßïûd÷yßçyŸ÷]‚¸…�¼y2Ïj“Ÿ‚³dŒq[­c’“_ÙDQQAr¶ÕZ&3Ž=¤O2³ Ü~«ÕLZõCþ�0»ÜjE“’…Û>f‚‚ŒhÏ�Iš5½\@Hƒy ¸Ÿy¿ß\ ÜäõÄÜ Ý.ÝÌ"Þ›!;Êÿ ðm®ÈF¯ŠÝÇyFÙÌ⤸°«{{}R£4ûjå§Í-¹Ú³˜Yš—@õUÒÄÄ­†™Ñ_.‚jX‰B[½6…®?è¬f'Åw`:ËÛ@ñ²†ùÀŧo�i[�Ç?Ø0­qmL©<ÄÒ±ŒžÀÿDwåï)¼:LàXÕM­+ðå¿õ{l`ëüÊ&Z•™EÆf‘‹*7Žè²+��s[lëä0PlƒÁþò6P Èfì$—]Ùù~•u3¯£þÊÉe†‡õö™ÝqÈ¡ÙV'Âó—ç:û3m=÷‰Þ€ê1§q¹P_¯+Îær2"~ïn—�_uáÔjøf•(qçüºÍ,zêízº�­ÎqÈ]ö£f!Ô®µç{º ü{1\v�»¿£¸ÍSœ¯sªã“øÔÔõŒíŽCFÔçݽØ7y>9ZܦÖ0PCÓ4t®×qÈ@pÙÓ}'Ù9í²o®õ¶‚,%ïÜ6¨# TAøÏªúw�^è¤î²gÖŽ,3ØÆ‚šÞÔMW8«ÿÅ'¡‡ h—=§n¬é6ý?7ª` ×>°ã�ÁÞvO×oœ4cÕ�5Í×õK1 Ô—ÔÐ0Øg×àÁUàuÙó¼û>£õGÓ!Â@0¥YD,êÄ— ºl¸•í Þ}·jøûB×–B£DðpFÓwrhŽCÏ]|Z‹y²²`Ÿ·Aeù d¨&SšÛqÈ`ƒ]`.ûö¦ñ†ÜužbQ(iž™Eú§* ¹ë¸¾+@—½°i¤nVÖ¿¨h„UÀ<•.¤È,Ç!#ê»å²—®ÍøŽ8ê/#„�*ð§-k]ìB@]öÒƒ—k•¢þÏÖ#…�*¾&×Rö¶ÙŽC˜Ëþ\ëÇÕ)K·c†�*`V&‰)ªçÂj‘€rÙË[ª'ò•·`‡�¹‰]˜¨VyØ2Ç!#ÂÝ`i‚XyôiÆ7# T�sBY»¥Ž# úQKÇKÌfšªÀ—(‚¹lµ’ÜæTÏêÞ JŽL�W®ªê´ZI‚Øs`–&ÚÌ P²ÃÞõ¢mDýÌÐó-žåÄþ“/©Úh¨†’60Kï°ÁL˜³QRµÒ¤ÄVnz  =õŠÕCI�’`³¬\×Ë€²ô7í3Æ 4JºlóLÓP–î²z$i°RÕÄ?­–‘ ’cè»ìå¥E¢ïŠðﬖ‘ 0ÆÒû­J'eÁ¿ž ˆ'íòÐ0GùŠl³˜JF¼‘b5iµŠ«�0‰��v›%¸_Ä|Û<Ó0‰�óV�CnAØ"•–ø¨°IbIF�&C%ˆsVë¸ Lâã5Kv±” ûI&Êö�x¥Öí,›J°ZPˆÄG± |aÜÀƒ§›E'—ŒýÄ.Q"Dâc«uÎ#B“tH4p�ÇéP<Òì²K”�øÈûÄtÕ–¦CÜ`wËó§#ûE*‹ì²H|¬1m‰'8î>²Ë㪘©NÝ»ÄT‰�·Ð³íÂV§ã‰�R¼-€â»Zê6}}©þ»–ÚÐäiÃxâc;ÚÊ#F} à†Çí6Y‚N|àmDÉeÆíLßÉy»�9�_58´-€èøRCËmbiÊhâk 2 tå@¡åÅbqŒ&>!yéðˆÑCbׯQ¨•ØÏ� ã×8ËÕð°Ž› 2pE¡v^24Š"œ@<4hà(^*{lR]c,ñ± e> d;�¥»T×K|\À�ê½_À.Õ5D9†óà/m#_¥Ø&ySC‰Œ-þü8+KØdAm$ñ�±À�Í~L=ð*õ0ðýÞyzTfC5ð2¸J]H| lpg@/H�c�ê> ?ñá_â±�°íÄYcEuM„óQ4Œ©¡ÿžî8ü›çžú¾¾+$DÚ¡Cö˜Î‹³SjÂ3áü´� üøà¹wÚš÷þìÉï­[U^Vrç1ø)¶ é>wôã ä�'¾ûPå²;�¾™Q<æ ųõ —X1 ‘”K@o0Â24Ñ «4�0št‘GaçCæP)·µØûã#hÒENƒje^Å34~uÍ<íÐ[Ì˘¸£W×4#Š'@¾‘þ}˜RÑ«kÂ?EºÀ¼ˆ¨”À¯®¡¿�¨r €Ù‰(Tâ-8±JP_@Ô¸À>�¨3ÎÜê6¡.ã>8çÁ>ƒ'3Ác¸)ê¢ô°‡„ÝŠ(3Á \K÷ã)‡Û`·à©œ¹º¦Où3P΃݄'2™ ½ÊìEÓ�7$Ñ´³Ÿ¬÷C4Ýk�–xì·Ð$¦°³º†ÒöÑ -¼ £›ýšÂT6azò݃¦»jWçXpÜè|Î>„&0�/aæ˜Â(;EטUánìöñ´î”³UŸÔêšq3FPê¬>Üôû´»f�ú®�¹ ~Ï´QLuTí8>ÊSZÙì¦É“xÑÒ™¯qÇa¶èNü ©Æ�Ä|+U´ buM´Îä±ÄQåNbôÍÖµoÜ÷¸Ùƒ™  »;‰ù0³ŒÊ8ñªkȯ˜>šfWz»–LÍ9�~ÓÆmx7ªpúk“@)uÖé R_¿ˆ’+tày��uß OgZ¹{÷ßIþ +Q/ô×Õ�rzAbÐ’ñdeî[�ï‡;”¥‰×Ñ,mäSç“‘gÑ¢Ä&«‡f3Öae>‚5VÍf,Æ:ß0/#y}`¸º&Âs4MÓŒŸ Avlèßé8ÚÒø‹Zȳ““‚u ó,E‘$E±|LQ£ƒ}½'Ú�4ﯫ­ö¸]ÎÊ Gi jeéõO{ŠA¥'Ô/>¡!vìÒ‡ïwwü¥å¥jk<뫜÷W,)+Q¼ªì¹ÙbdžúzOw¼Ñ|`׳[=ë«Ö®ªXR6áÓ§‘ÿ49àh endstream endobj 42 0 obj <> stream xœíÝÙO]‡ñ?ß+ADMH ‰¯ ”}iÀR¡XÅR�²w£"JT `|ÓPl§ÓùÍ™3ó$Ÿ+(¥!ÏÕ9ßÒ{ÿmß\`%û pÞÔòIË@êið#B‰èfáI0×:˜Åó+Ù_t‡-¥.^D¾4’ƒóßâ™Kã‹t'�-5’ÏBŸÞížßü:‘ÄYÇh¶}$;“8ûû»ti‹»ç=ღ@jléè_�¡Cȉg.ç¿5ô%ŸÏ|~Ÿº¨ðH:„�ÐJþÁPºk"Ý(T}0Âvo¶ Ý“û-驸‰É¡CØ(–¾ì�;lèÝí�;\þ}&cÂ.SË'÷ûSÏBŸÞîœ×ú³tˆúEÖtŒíµ�dfÖN­=¢KÉ‹ç3ŸúŒËëÏC‡°&ž¹YüÞ(žÉ,U<“1ƒaAøÃiÛPæñxnný‡-OH‡¨ÉÂÎù³Ð§æþJ—#Ð!LŠ¥/û£_ú’½s‡±t g2fÐ!Ì(Vç·~J΄?è7XB‡N2Îd}v&c:Ã3ƒU!tè€â`u$ûx|oΗg2fС¨ÅÒ§Þ(ù«z¡C!^¬ ¡C ¬ ¡C{•«/ゟzã=thc°ÚHöG¿zx°*„mŒ7ûc°*„ëd Vúf°*„-{Wºi$G¿s9R':´àêL¦¯4XMr&c:¬Õôj¾mØ¿ƒU!thž1Xmñ÷`UšÁ`UVU¬.0XC‡« V�@‡wb°ê0:üÃÍÁê;«N¡Ã›fgí VU CƒUµè°|9ò"ò…Áª*>ï°t&S¬¾a°ª”o;d°ê*>ì�Áª ù­Ã±¥£¦¾$ƒU·ñO‡³‰³G£ÅÁê ƒU÷ñC‡ VÝÏÛ2XÕ…‡;¼¬Nä^o”¿TæÉ¶¬jÆc2XÕ”—:4«Ý“û Vµã�£WƒÕW Võ¤{‡ V½Aß�ÁjS_²'|À`Uwšv^=mÎtŽ1Xõí:d°êIu¸Ì`Õ»té°ü&b«žäþ£› V½ÏÍ2Xõ×vX¬r&ã.ìЬ¶�2XõWuh V›)«~ã’¬úœ: ­æ 1Xõ5µÎoº'÷[ÒSñå (¤ªÃ›ƒUÎd ¤C«øƒÃFÖtŽíµ�0XÅ-Žuh V¬â.tÈ`UIw8½zÚ6”á?¬¢2¹JƒÕæ~«¨N¢C«¨•í–«ó Vaš�F7 O‚¹ÖÁtˆÁ*jdK‡ïSÆ`µt&ÃåjV‡ VQ¿z:Œ$Î:F³ÅÁj‚Á*êb­Ã·;ç=áÞD »ÔÚ!ƒUH¨©Ãò`5Ê`¶2Ù!ƒUˆªÚ!ƒU8 r‡ VáŒuÈ`Nú»C«pÞÍo V9“�ƒÊ2X…BF‡ V¡–Ñ! Üÿ•Ph8 endstream endobj 43 0 obj <> stream xœí]S"Ký~:UO`êšv×Í»&˜D³‚FdÕfºg@PPT ÌW >ŸkF…A�S§¬ÚÕÒ¦çN‡ÎýßÿÞ"L�pó&f bŒ€³�`!ÎŒâ1³€Ñ£FC묰–M$Ñ@œ8 Œ”`¤Œà H2ÀTø±Z«H0ÀhAßÅ,Fñ¥4²Q‚ƒ0 ÐÛü5ÝK:·[í ÐPFèÜîºõ¶U¼`$$-˜:ÿ© �&«H²"΂ véË`Ô<±m›Ýí]Üö¥Ç׎g§^þl f—Åܲ”ûV~‡•U9�þ)ææ…3/Ÿ™úsâö ,t{SÌtò§+ö¾G®µŠ#¬µ‰È˜-n†:·Ûh_Ç`¤y#Ũ€Ús£áy` Dca™2ÚÖÑS6óLVH0�`Áǹk|»waòÏɲxnEÏËU9?Çg†}inf÷ûÐV½ ™Ÿ‰C¶�ÑÀ@pFÀ çÄNÔuGÔž0 ¥AGùÿ±lè©Íâ"f DŒ.<_4:¤Ž±í�¥ƒ9þ¬¦õú¤üøú±uv÷Ó@”dÉAœ…Åëº#¤`°ð5]AµgQÃ]йÝ5Î%ƒÝo¤‚:Êo°ðèQ2 Ö ÛǶGVÓeZ»žB¿¬LNís{{#8 ê¬è�¨é b4 (ˆ™!Þ%©=¯þ‚ÞÄ(Þ`[ӹݘ�,$hð¾'ì˜Û› fT·¨rEÊ ûÒíî8Á ‹F¼KÂ)`èjÚÝw ö4¿i�¿¶ð‰0‹8%èÍA’8›�ánojdU7ž',wy·ÿ¨Í'Ð%·°Ã~3ºÛêÍÚöZiÔP!#-â‰üµe´ð&˜X‘ñ$½‚j'±rpUί~ê� $Y 7qZ°OÇ&üIEQÔ~¯˜YÀit»¬¡B$ |Œºüi¿¬¾m”�^áŒñ$k9X[¸J(ŠbÝ2ÑbRû�¼NèÍ£!²4³P¼ÁuMl¿²¥ìnúeŵšné‘Ñ¡”uT¨–uv¾±WóÔ=0&€3´eâ@ 2Ð@OójÛBy�Q»×·¸?¶v¤b¯Ìe1çùs2°|Ðíݳ΢é²Îîv{Sƒ+‡žÍÓRÃIëǵVˆÓàÆ*?‚A­ôz� dl³»ß†¢&~è YÆ·vܾÄôúÞäï]×JÂ1ÿ1©·‰�©s,>¸|P�ø×ªœö¥ÍãÛÍÎP¿ †í3ñ‘åÄ„?9½¾7êK.îбÖ>¤¥ÿe0ÂÍ$=*á¾öògö¹½#[µlqJ�£Ñþy4]žõÝ©µ]—/Ñ=·ÝæŠ4ØÅwv±Ýë]ܯ@݇_VFýGÔÔ·^ÙÄÂ/aët|x)1^˜®±ÕäÐâë‰}@ßmí 3žÄøÚñÃ~sž`‘¥éÍW ô�N£(Õ½eÈ«r¾wa¿µ/Üè�†—ÁHúô,§Ü‰Ä~f‰ß·LlÕq°c,^&¿Êl0cžØ©³ÂwÔ»™Šï�Þ=ª³lÆŽFW“ï{B-=!‡w¯Ùï~Y\>ø2ygûæwþÈéãÓ{¦+•>ó�ΫãP>áØÃn©œYÆ“xg¿‡g6ö¢É“|þ®QårùÐöñäïÝÏýr“Câfvïݳ>õG 4o´\]Ù ]¼¾%�ßm«ÎùTƒ]´Œo�­£»Çv#Ò'ÙÙ?{�éÇÈÖ3šÜŸisÇêmâ¸7•>+yXŠ"ï[§ãõ6Ñ6»ûŒÂ­ýKÍÝ¡_®È9�Ë•<_'™Ü¿ÿ¡7ôy òŒ&·³]ãÛuV8¼”Hìg1]±½Ó^/ú ôTâŽ~²Ö¹]¯ Œ-‚ѺýÀ6±~ü¾Gî‹ÆvïY1îE6—_ î7ØEjjç‰;…/”·Î$ëm¢g}/sVºõÿ�äAÆê‰5wKO×?Ÿœ~ˆ|‡¶�Ÿ8ª|^Y“›»¥Ž±ø»júeÅéMÕÛD—/ytß{/޲ýó; v±ùàÆ?7¾~\ËBŒ½ªÐ l„ßÙÅþ¥›_�;èò§ëmâ"¿_ŽQ�drœ'ö±W.µkꪜosǾ†w³›ß 1~Üè�ì7­ wsêÏIƒ]œðï>£ý_ ›Ë.î4uK×üÍÎFñúK¹”“« EQp\1ÎE�ýÐ+-î”c„HdZœ’Ý[B“µþ僻Iœ”qXŠâYÛ»qo㊔û:å<±lédz‡ãð8ûe@¶Lî<\ÓxÔToùèQùF¥(Ê*Deòï}ªs<ŽY„Ë‚�¶©-¸’V´³-ÎÐdA¼Ü88Î~ê—íkê׿tÐÔ-=ï^p|à Á.Í= Y’/”ÿ<é›/ï‹YÄI&׿Š<°ÝÉèï£wv1¼SÞ³>ŠþÖås‘s!E²5!Â(ÁHÁËB>)ßÚ]MV`„Eg[œRÿ}U.ºÁ.îTÄÒŠXì7w‡îVpòËù#[Ž™xÅFuz–û:¾WÃóç¤Þ&>ý’òpÂéwvqŽ?ߊ®]óXTQ”sccPá¹ñ¤O²ÍNidõÖ‹ó’˜ktH›át%G¥(Ê"r×ÈÅëÕ²”à(ÊÄêîùU”…$WΛ ÷-îî—ϲ�º"þÈé¦néF×ͪœÿØž¤*?ª|^iwGm·,#£¿�šº¥2] îF$qòÎ.z…›wùÃ[®åDåG¥(Šc&Þ5~^ÃRk�]€›ŠŸGEYXk‹Q›˜­·‰;©ÊíSWÐ7¿sãiÄ6»KMl©5ªÃc4-×»? vu ÆÊ{ö¾ž5»>]K_ù œ oBæ,ßÒ*ziÞ÷Èz ê�‹rØìË4(FÚGã•<ª]Çq&×à¯Ä+çø³z›ø¸èÀsa1¸ÿu0rå™2žd%�jבËå[ûäaß_›é²”{g£ÉJŸ7.#I·8CÈäŠ-¼¡´2rܾ�ÓB±Gs£CRe½ŒaÿÛÐ_±ŒŽ±xeîÅw ŸW¾ È—ƒ h°ÂÃc6Ð˱£gèò‘’›I:ç¶ÕrÞŽoõ,¤¸™]ŒF²Ì(*ÊôŒÐà���+6·©Â¡è r¹|‹SšÜ8÷0Ï hY;Î<5¼òt¬‡?õ‡/ž)=•ZRçPt?G"Cÿ¹—Å\�ML¨vº@$qÒè�ú÷I5A.tÓà 4ÿe âÎÞÙÄŒÚËZ �T›û\@‰šJ¸}jîìÈ畽¡â[à“òµVø¼‘²G#I·þût{SÖi5wöËèpG¹™]'’cCõ¤”ÐæŽÛfwvÔÝ9N2¹:+\–r~9ß`+ãÂ}<ë»æ‰í¢oÙ2®Ú…å òy¥Ñqìhí“U¼°\ÁoñuUcÏs?Œ´` =™hé UÞ…uØ)”@èöýލ=–ÿ°tVg…~9ÿ}8ºþ¬™ OÄÈJ‚›IÎ2MÝ’JwÐ�ÉæëP¾®Ð@G) …DIF =Éw6Qí¡ý…UxÐîŽQS(—Uí±ü…¯òøú±‰…'UpŒ¼€?þ4vxS½óê_ .ƒžØÂ(@QÊG&eb�É*¶�nsž˜Úãú Gȵõ±OWÓz[\C:Ç· …ÕÈ_Èæòµü1]—ªh½UÅ»™BÍ—9¹‰ÞFŤü>¼å­‚{è49$‚jy&oÃ9ý¾GVÉ9~Ž Š�ý#5½‘×M¢ø,N FYZ-'~ꃭj9U^àçPøCoHíQ\ÅN*Óh—…²¤Ò=ŽÙ8ÉBµGq™³<Á#ƒZŒ 6ØÅ½òäû=–ñ-ËxTíQ\E6—¯·A1^¹TŠbh)ÑÚWu廉(õvˆ1‚ñ_c#Yxo‘TåAOnU>ùä!¨·ÁíÔSk1ž#+;¿Fªèæ~�=!#4R(*Zω-ì§«Â?y�\>ßîŽZ§ãUvdCû‚‰Īñeqz–³NouTŸ±e?ôHª¨ -|!yR at¥*õŠ¢�d[œ¢±0°Oý¡*‰k(Š"m×Y�‘0J`Æ«åþŒ¤k9ˆFE vU®Àµ’@6ôyÌ,>Ð"ë­°Jkÿüöå�M­í©=¢s´�D.F…Ó`ëÉ…�Ï‚oòŨH”©Ü¦Td²ùz+üï9Z„ËÏ´Î*VÉÉÍ9÷—±�û«eÉý9þÏØA®Hnÿ½ørÉØT2mþœžåj/ÅÓ?Šïiõ8Ÿ÷�² öóm´¥[ª_}0’6±çÛh›«Züº~ñ€<ß­ËXÝß{¼Ûø¿Û(ná I|4;CÓkÕʜ固¥:+T=¿î 6#é:«Øë­¢£Q±bèë€L0 JBDŽHâfh´ –ܵœØ>wùªË%žÍåM,¬«‚ìÄ+X¤¾ Dª'�ç-=¡U–MQ¬·j°‹z ÌB1\e�Ùý>X-›BÒöñ§þð/×ÖZ•û˜©˜s~¯Á^]y ©4J1¥¦v¦7ªå2UÄÐrÅFÍE…ÒÓ›§ýË&+$YPè.ºyQ¤\ܳ>÷Ë*&Ç‚­£&gèŠê£_V>÷‡}@Í·Õ<¾å¸&ê5±~ÜàU pl§NÑ+pMd©Í÷«é¥ïõnSS;…Šé]œA¡½Ëò þ6U«üü8“kqJnÿ JžžÍÓwvÕ|ààC¯ì¿©uB×øv¯WçL6—ÿ6›À@n7µòÀÖQƒý\ è—;f yÿz€$ MÜZU‹Å%U©=d&côä­wvïÞ÷¡p…•©ŠÒúõ6´#Ü8ª)×ÒòCVÝÁÅ�Ã7¨Ê9ä;|ߪüª{xœmtü§ý[–ÑÓ—ŒÍúŸdVQªÁQéþ1òSøîÆ+?F¶*ìãMŸdß÷„nÄ.r:€ö² W�- H¥ðeøßaÅ2¹Ó5VQá¸ÌYþûPØvéÈ]kkX��Ž� gNÚóWCÛ¾Åý§tP)y�ùÍT‹ó�Ç¢èÁ§þ°»RIž'$ðx›2ÛeºýGH³RRc› <ÞF¿¬üÙ²ÏT(Û9›Ëw�E».ÝV.ÄÇÖ’çÊ“4ÀhðùZ‡w¯¥'T�õÍ³Ž¤’½�®- *~,¿¬ô…Trñ”û®V@V%Áƒ‚t탺–øBùoå—•.f¯uŒFÛ\±Ë'ÛñµãZ«hÿOæÔ:72bwCOÛþ¥ý‡(•­’(›Ë÷/ì|è)M~YÊ}Œ°žXùR=c{§-=!Ûli"ð.?ZpÊçéÍç•Éß»�¥h˜Ÿ æ»bíîHùä1÷ϾÊ–‰«æÎùÉ‚ýOÀyâ÷Þ�ÒôE"¹i›8ùûù%ôw2߆¿ܱGôyñ…ò]ãÛzCå¸p-òûõ6ñò!öáœúsÒä .î<»›ëð8Û9ý2Y(½Ñá¿�SÊ"’¹!£fÎùÔõ¿Û>7Òw‹Ï™ÀiÇh¼Þ {½Û%EQ3gy¿xÐ5-¶ä»Û“P*ýr¾é Åú:({7S%eþ$ö3c«Éænéë`äÑýªn£—?+¶Ë´ÍÄ…R,fsùÍpš™ŒÕY!ãIÜݸmlíÕ¿3¨C÷c#¹ Á‚‡¼Ô~9?²šnsÇL,ü>vû’kÒáÖîéÑéa®³l~ÿè ÆŽƒ)ÛL¼Á!6;CÖ™äS¶§{¹PÙ½r½Md§bÞÍ”°u´wxv¹aßñi.¾wº:_MþrEL,ü1²5¸røŒ�¯M—2ºvÔ9¯åà—~yh9ᇑÄIú${1_Ù\þð8+Å�—ø}çÜv‹Sj°‹ôTbúš>ù3r f�ó©Oýá:ZÆ·f6ö‚‘tò syƒ8Éäû™ÍpÚ³¶Û9­åà×ÁHßâþCÞJëì.É‚¾Ú’ä‚$+�,,i­^•óckÇÖ™Ý¶ÑØÇ>¹ÖŠÄCH ¯ xg¿ EÌãÛ½‹ûéÈó¬V—X:°Lî|Ž6:$‹ ÊŠ_k­ð}O¨Íc§“£¿�Êgc7Y]~rãÄ>»×>oí ×ÙDœF75œA_ßÙÅ/ƒhºzæS³Ï±c–duC¾Cj*ñc8ÚÔ-ë�/¾6;C?][Œ'1²š.iåÿÔ1XNߨ¶˜8гð¤{Ñïú,gžgg9%?�¾PþÆ�«ê|b+ØbÛn’ ^¾Šþ·“Rȵûåöþ¶5>œÅ46‚EdzëÆf4Cc‡H0àîè¤F�!íIÌÍ{(2¶§P¥ÕèÚ3ß}4¾A6:$ƒ%¨·¯ÞhlÅ ©Ñ,kd©Qãm\YŒ:·ûçÂmÆf¤�e½MR}´_4{÷M¬h°­ëÜî[���D¡æ�5ÞÈ}ÈéAPâm–v¾“¼pô¥"�Kâ"Ìâ ¨£B„åc3Ò‚ž®ô‹×¨ñáì™O™8HÐàJ”ê:ô R“31pê¹Ã—ßß÷†Q… ¸ÛÒŠ i@ÒBÇh\õak|qœã3$t”ÿjã!ÆFPA‚ÕßÑXͤ¦&`tPGùfl€ ‘n[ÿâ ‰5ÞF¿œ'9$2y=Óã4Ó1Œâ[œ²êã×ø‚8ìK›¬ÈÒp3|€•�£•JR”B°ÐsKe®F�×ù©?‚Y„^ .@QJ½%‚Qà§+¦úGÐø"88% WƒËŸ’Œíÿû_M¯k |–J�¯ž?]1œ5ÌC¯—¡k-(w—º]|C£Æ"çŠ謠†+ájp8-`O°ð‰I›_=©©ÉB-è¬�4¶bÅŸ‰…\‰…áßa–`aMêƒö8K;_Ü(`줶¸i¼�–‰œ� ÔtÝ�þp»N’�ìt²ÃÖøâ¸X8­ÕP!}OŽÇƒ·âÉ�K¥KLh|õìßF5’4²·§Fñ$�NnWT‚5jôògÚ@øMõz�C--¢\8Ì”³@[ã‹ã·¡(FC‚å TiQƒ;PG…0ÛÁ€ÖþˆêPc•plíˆ`Aco ÖölËZúž%�Ûmâ ËŸVýcjT�~Yit„0˜¬|cï³-kEèÜnƒã7FÃz»¤U1kìžO¡&A ÄJÉ&z80ýr’…ŒGsƒ¼i.€,ÁòÖ¨R‰JA‚8£¥½i~Œâ40RÁ’òÖJ66 tŽF�´Ð씫SªHc¹9´rH²¥Q%§•Љߍ�‰…¶Ù«�œ4¾z.Â,êÁÍ=xD*Q©@Í@=±š.$Sy[‡�¯•_£�LÐÀ”å^p…ø>�SBƒCª¤r£FuÙS¸�ê(¿žÞ¬Œ¥�SHÈ”``§Ãzœ dHâ”`¬ÈzÕÞ z’®UÍÍûÊé å»C#´€?-iíq@©•…?M°°¤î6_ÛÝqäX³Š£‚¥�SN#±ëGÈ'i‡·×IÔŠ…ºîˆÞú IDO²7à +ÜÑeUãËåäÆ ÁÂ0ìM]cC1úN ûŽRÇ5ÏÛ+ã8«åÄB) O˜Ÿ9Úþ8è¾C'Ä»$’wvÖø‚¸"å»C¨�#0ꙓˆž¼KÂ)c &7nní§ñÑ/+_¢&+læ¶ÈÇ–‚–Àh³ ý´¬ ª4V€cq’ƒ¥|fvÕ¶¬›�¡FE€`„z«¸4ц—JÚ“,†ÚèE)j›Õ­ Ô(�`@½]º»? Æê¤}n�`�¾SÐ[Tˆ” ‚$‡$î!­´ùe±{>…bR]fFö¦¶)= M$YÐì”5{{)ìYØ/^öVáÖ/+SN­s»ï{Ã8�Êl1ZÀ»$¢�œ`4 Zô¼Ê¡s»kœK»Ÿ AÁω„k­ÈõÎ.uŒÆû—TÌ-Y‘r£kGÖ™ÝÖ¾ZÄŠj{PG…H-ј¾,õ E K£Páj#ƒ6Y#�”Pk Ô¾¼ï‘;Ƕ{ö'7ŽË£±*çgƒ™á•Cv:ùup«Þ&bŒPÇAœ†šGÆÀBû9HZÄ×Wåô6AQÊGz·‘в˜Ð[‡Â(;½–ƒµrÜá´ðÎ.}ˆv�o[gw{ö‡WÇ×�§§^þld—ÅÜò¿QZ_(�þ)ææø³9>3¹qâò§û—º½{Œ'ùÃké‘ɶh*ü~ŒŒ%ŠRéhQøš(„€Õž åŠòS"NênØÂ¥� ê(?ÊT· 0Òè?ë¬"2E+,ŠÎ ÕH FJ@‡«Âÿ 8Z�µ…&Yô]ª“åk¨�¢(æ±(ÉœA•³MT¬•JV³Â^Yñ¹¢Íà endstream endobj 44 0 obj <> stream xœÝ�‰oTEÀ¿ÒŠT9¤rÊé�ˆ"Œ�xÆT¬âF<ÐHÁ£%ž€�¢@N�¨MÄ*‹HTTLP°� Õâ@*”ÚîÛ7óöÞÑ×Ýîn÷zÇÎ{3ó~ÿÀ~¿¼}ß|óͼ‹èV\Z¾è½íû�ž”±‡�€‚›ë¿ß¼fÞ½WÌ·êG­ Çµï×cŸäò’4„ä8¾ãÕ;‡°T“‚KË·6{[Òz$YIn_íÒÒž¬#ÎÌ…Oþè•<Ú& N.ï±·ÆŸÆ:ðT:Þôv£Qi#ìöí®À:þD Jª�6ãEñì/?‹µE”ákåœ\"`ÏOwwb­§OÛ‡ü9»D@híp¦2ý–"™’K+\3>�•Lñzl(�éÂýϬB2£¿ÅAê2*rsù©vË\´E Y"£‚šgÙ*4 ['£"Ÿ˜lÛ;túËÈg©Œ Ú{‰=6÷4!ËeÔjAy¯·õ2g駱š³ás?`ñ?®Ã °ËF}…j†ZisÁA[þgq‚ø ËPÞ#Èš‘&ø{‹jÓž_ÚöÖ$�§XasU³õÙ9=¨²#u›§l~kQö÷£+S¸‘¡ !×u4mþ®°´Q3Â#ôlF7Ñš¡™­è@ɦ„ÂÜ™‚Ï6:Ÿ™¦4ôQöQ°y–iHÄÿGî5ésÜØâ?šk?nG6„Oœ›“Í2®l 5ÊÁfg6„ÌW¤OpgCHðo³ù`‡6„øëbÊæF.mñ|gf�k8“Ù�ðã6g5òPÙ¤Ï5jSø›�-£àRƒ:Uœj�‡²)ç4 ´:ÒՀ;Ÿ !Äû©~›î'YG« š¡[çcú«PôAè´¹Ÿó'B¸^_»ênÇÏöàezlòjìïÜš_¡Cgº ‡rD{ɱ¯›u�úÁ/iêlcÕ‰6ºPÃf‚85µ8¨ÉnÓñoÖC¾=«ÎÓB 9 œÌÖí)Ô_MÏÏ¢S©c×#g Ì��A¬—=Là]�Q§Šýº‡qpÿ 6ç øpñUfÐÙ$âÃ!D˜Öf°�‡ÿÚ´:kD*oQÎLcÓ•ûþ@&”yitæˆVÄq¥îXÎob”yÜSSt&H¬ƒÊ�ŸSt¶óÛ’Ö'Ï{úŠÐ‹Êˆy’Î|A�(î¤&Õ1Öå†ts;›‘âféVÂÕít‰Y®ÅQÚ}¸ðëprEš”`3Z æZ>KÐyAÔê3>%®s€u0¹#�‹Ù‰×ñH!°0¦3EüW‡�C1��¬C¡�7Ö¡:Á:ÄRuo¼:„„VEunyª§.ª³ÒÚïØìÂí¾ÿÂ::¸"#OžÐ3·8Jd_ÿ¹Â­‚dà�V�[]¬ã Ä�Hý)Ê>-<­ŸÉ}Î: Z ÁªÎ!ÖaТåUGð6A4 ºˆÞ&ˆZ#œQâ¨lV›Ó-¬£ F-<è˜w‡4¨=xÞ0m ü*XÂ:z„óÞg=‚g|Í:z„†ìfEFìe=²‚áûþ`=Âs Lä%ÞdÓ³�*‡�²Ž€*Gç8êÏ6êXÇ@�ð$G £Á‘Ž*r¼çT±‚þ"€Å¬ƒ G¨ÀSŽi}¦9gr}Lm}8¥Ei}\ìœÆTµ³Ú†/9ª©+? êÔ³ƒ‘–ûVÖaе:3ß)}ÃÈrU©S2umëb¢(ßXkò¶£âñÌÈ6‰ZÖ�Ð!ºM–;dKt³î­Î(sD·õrưØwÂï¢VqÝÒ¦óëPhàíÕ¦3Ù [[ëc[[»;àå ¼â¬mácã:Ï‹ÿxpÂt£„/ÛŸ@ ¬ÃÉé–D�…¢"Òþs¤‚7 › ‚�À’Œ4¡½Î<±?´”’>´ì#ôΟrØW"/*┓Ç‹\·íI¶ûÿ{Rt8:äÜ0ÍiŽì*¬ž�j°RÔ:Ÿ‘Ng  C�ïõt6Å\éÁŽßóÜïémÖ‹XW+/³ñíñ®Èdð¦xÉ e¹í·H¸JÍÉl0K´±ôxÖƒ[ þbŸ1d�CÝy½ü =¡]Ùm¶ˆ”¬Sç9Éô¨å†ž×²xHŸðŸ:Î ÏÛ%Êg±ørm€‚ >ø5=6S…Èn¡:½7)V‹Ð¥BºoVí&ÀY&èa½6—q_Z+Õ:4b”qþú„~7vãà¾=u¼ÿ­ÓAžw¹áñÆlø¾ì =cÔà"nGS¼Î¸ @ §¯�ç›|3:ð0—>¾ºÎ¦løœjû�˜¿tôEî|r¹`)g>¡Æô·ëeW“¹\¯OuÚå¶Orãã­ï¥#^-¦s’¯•=Ý)Ø\/óPï -…:bÕC1—ª¿–GÉ =ëù60ùÔ¦Ó¦ ;ðïš6ð8çìéCÙ`l«µ,´úñ¥Ûf&Èïšh�ŒÊtd¿í0_Akq~­Í!€*èåçT:”!;["ò�C,”Q´Ã¶ä•Ron¡Ï�'lI ae]l _@Ö¯8Ê5ŶȨôûP±6ÇÉ ·Ù&£2l“bÝ€RSY�ލ2â lM’s7ÍлE•!o`úëZò±ŠÔ‹µl¢ïDµõëÇ»o°rØÔä´ûöbZiÉ«µîÞµ�a«$)÷´€<»îÒ¾çÙò¯[/çd„=??j]¥i‚‚’Ê㲩j!$û~x,—N­U ­Øé‘ 5‚.ß‘5%´:4ôÉõè§MÞù;$¹}ûO(b±6EW?ön�ì—\i­‚îhøzÁCÍ­:1¢óÅuÝ—{7JX!$ à“ÇÝùÑës§ŽëgÝØò’R  endstream endobj 45 0 obj <> /StructParent 100003>> endobj 46 0 obj <> stream xœí][oܶ~ׯàs�Ãåpx ñe�>´@íká“8ˆÓ7úó íÅ»²÷“8Z®¬¸I�b#†rH¿¹p¨-çÕe”QÿÑ{�Ùª»ûæKÓ–Xï�b›ƒNÑ«‡Í/?¨ÏÍ—†5Y¿ª»ûuwß�jÿ{w£Ö?>6‹Vÿl?ÿñùýׇ¿î¾ª³³ÅO—?^)£ÎÏ/®.WdEƇ–ÂïÍÛæí>yk²nû–†éë@9¨ýÿ¿»QÏ?îúuqÛ,Þÿÿ·Ïgg‹7w_ÿúíÓ퇿¿ª³åõri�½:WççªíäbéYuû{CkŽ‘ ‘t°9*›Õí}sfŒqçêöÍõOëAÝþW�Ãë�Q{ã“Ïî±ÀycÜ…1.¯þAO7.»Ñ%r}{Lÿ£!¥ê‘v�âPÿ<ãÞ¼P­×Îs¶C< ÆP<¢�O¶DùŽ4«ïnÔúÇjåSn—~ˆ*»¬£1†Ô}c}Þûû§æ½|‹�SÄšíZ’t÷ЦöcT™5·–]t€]f»grÉÑnϰv‰ ®AÁ†ðóºDMeT‡4`¯ì*@,±@^‰Y‚‰#–ȹ‹‰C–¼A-8+¦Qoäí’Í`‡† vWì�Çx˜ø~]¡¦(èlƒNS¨ 3À� àÈqw êÕ5*¸M1ì.j Ç3¸D,¥Áh¢0¯QÁ%"žÅLbAº|ŽänŠ`ù”Ѱ%+nÎqÄ+ÜÔ5…öLjU‚ö‡|×vFÞ)¸(yg€ {(F„%�‡ZЈÁÆb°ƒÎö 5ND¶°è®�Ovt†âSWŽ´ Ñq 1&>ÀÞÀ½‚p�|6«‰a¯â&9<‚Û`Ÿ»e˜Çø—¢öààc+PE§•C6†•îåú¤Áåa8Zýò•ùêu¹"…w1lP�€ÄáaSµêã´Ÿã4>{‹äð¿Iõâ2¨_¤HÁ¦`w1ÛK +gIÑ|tš*šs¨BÎFY“kÕx1@Õ Í ï7Õ�úEÛ Hk€5F/¸9üÙ÷* rj0‹å)!ñÏò3¢Ôz–PxáÙƒñ††C,ÀÒ^�€`bxÅ'{E} .8¹µµLÜwö@)_ÖT‰ævÔ+[[;ëêHû¢!G(ò‘c,�4B�W|êâu—�•6%G(Ô9Ù¡=6U4vˆ£ù¨oNž!H`â^�ð:4׿™GÁI&À…\`ž‘òŽGXâÄ'äˆÅ�pTM—ù†) _�Šžql2•ãÁz~¼'Q�,ÒLÊÌEˆ¥Lê!¯2³BEزKXrtŽ�‘Æ´‘‘Ú®Âî\°Qi"Ž«ˆ¼g>J¤)+ @ІD:ef*0rgL»,Ÿmƒ \ ‚(¥±Yp’^-AÁFúÍàóÚÝ|AV÷Ü‹äVç^ÿŒy©¨a>†5 gS.䡜…Ð+?÷Ä,1â¦äl�‘ã¹IEŽ*àÈaSpjÅ&.HëÄPÏ+²]ÏÙÀÉÑës¦"‚c àž„«Õèz…ËÔ’ä«F!ßarm®e±¤¨¸ïGè8P~A¿1lJÌ],¿äÄ!t. 6+³fÖ 6“ÇCb÷WE_Ïu=„ÜŠÂVÊ¥®p ¬Mj�2Ñdmü£]€7Û¼ºý!r¿H6Fº mLmµ ˆkdYSŒ) ² :AF+@Iº|îÀ5E‘4ù”Ýs&¹jq" yÜ¡÷†Ünô²^Áïælv,sÖ&·2|HÎÉaüé54kg¶Å‘6ÁQÜâ3PxçõµqÖ ríõ ­zQòƒôEƒ8&5ô!ù�ËŠÕÜöïXöýæÊãEëeîß4©¸qÌXÅ0q¹ä’êè#®¹à‚ŠNÐYš�a Fî-¬¼'ToŠUŒ¢�&QT7%¿ß µâ�á!{†`›‰ªb ÖÆ“Ò>¸¨4›œV.§ßd~'!XbmØÇŽçC"|»JØÆ|x,ð¨ÀET°D£o¤M¹Üß«Â|Z{�g'óúà4Ù4áq ��Š¡“„ËŒ[5N#Ì«edŽH/ä^MM~3­^$�|ö±³Bìrœ!�pûWT,ÅAçrÕ$¨x‚›ÎeÞJè :ò:YeoÌѶÆHÚÄöë�𘜟�Èu”µ dÜ×jF´Y7æÃœ�åp`IU”ߊmߓׯ®|¥ýÌù7:ã¼÷Ú˜Èvp[ òüM1«;–Œ)ˆüîh8èŸ.bÞwƒà0©¨l¦ê2qwÅaV#œï¯ qŒ9RÊ|LE¦6F—É …³ Ÿ66j6±�;¼S&¿¤¨§G¿’ÇËMpeŠÈXÑŒ_ïö5Ü0âGlKÂ,§þÁÝ­—k`nAo6±D½0»,Jý¸³hD¶&ñ²`h}ªè «çÞ�Šfi¼Ä«dŠ0ï)lóâœE5݉bUåÔÆ²¬M ‰†¤Ê·y}6ÒÛ9n}ªÞ ðy„ymHñ™�¿Ckí[ U*°‰ ÖpÉË!Ž8j[žpn ÈǤsŽ)L¹­s&Ñÿù­¢ÓÙç<4e…áKßOœa}�c/Ÿ+fŒ�?/!à/yÅù…�ërå¶¢±öJòå¹f£ÒÂOðCLš¢‹6©¢ŽÔÎþ&ÃÏú`®¾¶²)È´ˆSþU4GOp9iDÌ7DP�%0º¨JÜ ]%Çòg¤ˆvŒÇdŠKo0·4hTËÌ;‰Å¦ ×MüÞ^Owå2T¼JŽhàç. DD3Xó¢T=ûdÙ ×½r[6Ž¢—¡:¡\E8{„êMkEÛ ¸¾Üë’ aŠd4[czS¯nMQ¯�noιS¢í˜[ÎĤròÚçœÓ¸‹%ÕÜKzgñû¼ŒŒ‚cj€S75â8­èû�‰oSTÌq(�–‘ Ñ(‹êÈÜ"„Ñy;W¬u�Zºµ(¥U“nÚ„Ð&> stream xœí}YoY–^ý¡©nLu£1ðŒ§ÆžÛcŒáyðƒ�~³aÀ~± vºÉŒ5“”HQ¥RIbqɸq#2“ûžÜ7q™ÜÄŒ¸7rã&.Z(.î©R©µ22"2ï‡�^P-1ï¹çžå;ß|Cñ 4VÒxYç!âä "" bŸŠ+‚†_Å¢Bþ#'뜬ó ò?‰*ö±1+k^Y+oŠñ².@ÄCä½·Uvsßã1íþá(þUíë¾�&ªÑuyS¬“_Y÷©Ø4|AìS°± #è$¿¢‚|ªQ"Fç¬ß /@ž–4§‚Œ832fÔ¤Ý?ŧá¹�Êê5o£ž9žÜà �Ç,oŠqrŒ:+iÑ/”5‹:4Ï}òßó2b%� hL@³û¢ 0Ms8ºßdDÌj¹q_Ð$Ȩº5ñ o+8µß³ðrhåhôÉÉ#ýõœñf!yM™óñ³GèõDìddõ¸?zØòè apûf[RT1‘_%®ž…Øã1Ù¾ æ ŪÚ×íþ‰KŒšd¡Á+ØÔ«Ú×Yñ2-KU�ÚÎt`x§mæydéÕèÚñdìt½žOœ-¥Í…Äù,~óH;}r<´rÔ9ÿŽïÝïÙ¼Þç¡N.qˆYIcÔ$¯`žœz�žq‡€ gù^âŠAŒȧZ±¬ûU|£5q·{ã§Èv`ä)Û•-‚ѧ C;ú¶j;S×› ê‚’ùG0'ãZAšÎÉ ´?8y»ÊRDySŒZã@Ú4Mh>Hâ.QÁû¶:æžO鯗ÒfΜ3Þô.¼lÚ¹"š_Å NCTµÐøæðÒ®iÒÈüêà‰DÊ[g™æ(IœLNn�ܳ5­ ylopùh!yž³­£)slý$€íþ%Ï}T^¯³MäÍ]PÉ÷‡Œú�íÞÅ—óñ‚}2vÚ<ýŒ\Ü2¹¸ÉS$™$Ù¼ÙýŠ,ˆñVbÓ+áÌqnÚ];¾ ×ý1§Ñëðäþµ°!*˜•uˆz½<÷´¤íþ0E¶Áàˆ‘I]C´â±š¶Dûìóžâ/9ó”Yzõ �äèD…8pb^Á,¤žü²@,.a¦ yî#NÒý )TÉ£»±ÓKµõBò¼wñðn÷OÊ%ØK*hÈʧÑK!ÁX•J�Ô¡b¢Š+ÃFçü‹|^ÐùphõèNWšm™TÄÊ›×ÊÛæ<‘ˆÝ©H@.Gy�‘4¶Á°®lüÓÀö¤v¹ùsœ�Ÿ'öIí;h°0S$¥1y�Á‡Wyu�”ŸÞV²ît¦{^F¯ö€Ïà×êÄ~I³`ëÑGæ¬D=y¾ð5®ù¤˜ kŒ¬û¬´I÷ü‹hʆãüGŸßëÙ …Tˆ=‘ŽÒ‹;p2bäuˆ’D(ÄõÛ�ò+m„ Éóæég~Õð©À¢døšbݦÝ_Ëõ ­& ˆ‘4âÆe”¹¯ó,fåÉhÊì]<¬jNø‚¤Ì-�7 ÎÉ1»?•[AªÉ Fܸ‚üA£ë±#¼÷ûœˆ�Ôv¦}�\ܤ?MBÞFÝîÏæJðMq"éü$鋺þ-'xï÷¹˜"žœ¤g$Öm �8iâ4w0RÌÛdµšÈH„èaÿÖ”nÏkëcFSf÷ÂËká¸ÕÊãéEôÔÓ¶´,À+뢢ùTd5¡†ÁíÇ—PÃ*û£‡•!ñ·Q'�©€¾µ³É@Ì7Åý*¾Š,¿²Ý¦Ÿã\ü¬~p;3> BÌK˜m0ìþ~.ƒ§%í ÇY3iKø±g㲓޹1š2;ç_�÷—‚<õ댤ӣ}AX£:¯¬ûUt£%9úäRN Ëlj3itWPˆ÷‘?¬Ñfò‹ÀÓ’fB >·êX™Ø_LÙSæÈŠC«G×›>± +a†í ƒ•4¯‚=-i1Hzû{_ÚnÍ/s>~Þ­£-(¯Æé Ø`šæèÒ~ÓÀ+i"DÁÉ}§%O¾Ì‘µãÊ�ÁC\Õ¾îj¤ò/A€«ž–´OÁUÍ » —¹q1uÞ4ü”ôÌ<ØðÖìÑyÞ/Ã4Í‘åý¦ArºÕõo_M—QA8´rTŠûUƒ šÉ†—Öµ?>¼žÚ0M“ôÛ«ØÉê/p>~v¿wS$Q¥&È:hzüÓ°o]€¤ëûadk!á‚ðûcöGI›«¬{<&wo‡‰|ätO’ÓÍ+DøÂ�§{!y.�ìŠ ò0ÐŒn÷Gu|�k\ç뢊o·§fðÛM–[gHñ‹ÌšQ7þ)ð ѫɤ”ÛfžÛn¯|8�^ßlO‰*ª ¿§nüc0�ƒ1rº|Óå§ûÝ­Í+šW~Bý2ðw§ù×D7 îDÝ�ý*‡W�ˆô ÐE⩨ÿ‚5ñÊ+D¨dôÉ�h]*Sçuý[>… kó—+ÔÜ¿À+aV"ò¢‚ê¶]Qïø2'µÓëÍqQÁ-“W© Ѧð*XP°<úÔvÒÖ±ÓÊ !B¢Ìã£#~DKFR€¨"d¸+þU*ã{‚‚Ê�‘h³Ê7Ölµ¥)‘ñ¨Ž¹¶Û¨Pœ�Ÿýн‘q㜬•òã«\!º Ô| ?:°Ý4ç ~]Õ’ðAì·NíþÞ6Ã#Màךã3ØYíßaó£gÄ–Ôf›¨¹‰œÑVð  à_eÓÐŽ¨’Ç—OÒ}�kvo@¤b¡^®èÄísîNŠ~�ó‰³êÖä[å�v㬥Agi'ç gD¿ÌÎù‚B8�PÂêI‚UõdMTñðU‰]=¥‘§D—¾qMè|SÜî¯~¥ðÜGL–Üòè™í¶¸TÎo®5Çyk­4ËÙ‚LÆ–Yˆ*Ãñ"và¶Zãœ@%;d�-ë 5ë+S¥³‹ÐÊ¡ñMq&€Jg–Óã1Ëj·=÷Ih Š+þ9Îà×D�œ¨"³%æÆù€¥#*k~;gžúR©Œï}˃ -•šk &p€˜û’¡ßq>~6²zÜ>÷<4¹/�í6íÔE¶ë·¥‘§Êø^xê wñpJ?½ì1ub_P°§~½,´X"æ.·œ‰*~пeûq»2NÆNE•èÖr�L¡Úm„+‚¨ÆÈÍ c˜cEÑ…rA6 íøTä‰D¼ísváê`-gÑ3�—�Ïà7�s/êú·®‡ã¾ þ¡w[žxžyÕ6ܱpÚ=íX{VΆö®7Ç{ £ 8¼Jò¥@áñ­"[žÎ6�ý¬¬ÊÊ®æÐêi¯ Áâ,núCD}WPpo¡ó¢ndmgZ�u&¸\”ƒ?侯8HÌ]�¾£žÇ/+CFhúeÏezï?òäËg·:Óû· Òø Ç÷Detí6N!‘é•!*ú~Ñ ²~`Û’ ‰± Ø6=‘ª–¢ñ2º×»aûwv§ôS² Öü±Û8…G¥¥–/*˜Ô›�Ÿ=èߺݑîY>»ïý~ž<<}X2zó–4�¦ÎkÚ’¼‚I.±Xã,ļL–Ñ7 ,WævÎÇÏH 1ˆÝ�·(®7ÐË›b<‰ÊJ:‹ò>Õ‰}Q%+•‹¬GÅ �¨ê>ˆï÷næù‰&b'UÍ uêE×U…ß³wùìF[ŽïåÙR>¥¿¬ÝÊ¡bɨð f-Up©¾_;ç_�)'`Ö‚=»MT0xe�ƒº¨`ubßö/ì.¦Î¯…㌄n€í¢¹²MÓ Žo[n<ߣݻxX4:OíòÞ¿äUV̇‘�{7óü‰Úçž‹*&•%ןîÌÚŸŠÛg‹V%gÞlOñ@¯|P<[`8¨{e­"_(ùªÇX~å+®+û]/J[~G»}öyUK²÷Êó'Ÿcײ©L>¿Ù–—°O4eÞhIò²V?�tû0/#VÒ®‡ãîZ¬veçZT‘ÇczoCùƒ˜‡È§àîÇÅ#4Z@ÞêHñ²VW¶§%]?´%@TÝœÈçh·Ï>¯iMõ®œÛîºÿÈ�/™Í³‡Õ­‰|ÆX†×ŽH†A¼n!}’ùT£‹êÏ�ëö”‘×Ò°Û\ù‚ƒd¿dEÈ(ŽEç»+»¬ÆõWvy(áiI ^Í}æ±uæYM[ª{ÙYü›g^ÝhMä�×E¶30æÞÍ ‚LôŽ*‚í'üì¹^z%*™síî'6©\“ªÊóe]ܼٖbbîmÛm®¼À‡WÙ âUü°/wÉ£Þ…—Õ­I§Eà0œ¨ýÀ',Ôä„Ïàו!£{é�í.úBn|ټ߿£Lä¨ù3‹ßð$ǸÎÉ.ë7M³q Íɺ4R áùp!y.@TÞc$—Yù¸Æqã2š-I)³¬šÚÌ(†§%m·ÝrAf°ñXNòàDâ¯;Ý:wd»s¾8{–Íê–DÎj‡ C;"D*«wM`öx"6¸"BœÌEH¡kþÅ�};¶»âüÜø›­‰ÜÆü!ȱ.Ù Žoy¡^¦‰”,8°ôª"ˆ`ˆu›v0 x<&ûpÃ4èlfV¬iK² æmrljΠ¼mΉ=ʾ¥p!y~=ïvÌ@}Îüi`·u&—fi0¶'ȸ1⎚§ ¢†Âmô(.$Ï9‘„ÝÌeÖ„)¯”èr½œ Ç÷ ÐM>œi^²3¥røyC�ÀøsÛ=pþìY>¯9¤ Ç×OD…Ô¼†¯‚€Y7*‚´Â•5oµ'3¹e»m˜¼÷¶Xˆiñ:[®ùɰ�î‰é̃‹Œìe…Z²�†ó'z.Ȧáý¶œBñª–8#ëAÇ×¼jÁ&¯ ÙB,Å()'÷É"'W¥Äyˆ8Yo¤ÊðYr1u.(dy.+¹£ÈõûäÁÅÁ\FÚçž7�ìÛî{ Åžå³ë-¹(}'ÈçÀ«Á&´ë4ž=–^ùƒdÚÑnfQÁ$Nß\Ù³¦-ÁH®ì*¿»å àkáx?iuk¢{Éõ™ð÷ù ²“CžaxõȧbNAž £Ý8tVÖìÉw¯G ò‘þZT0cnÀ¬†>Õ§“\Ùó§þmènÁæä\#kǵ]›¶{ݲ+zúcö«‹2�/O•;»ÂCÄËŽç(/PÊŒ¦L^Ö= Z&­ØmÆ áŽ´Kòf@§�á90Åàeämtô‰þæ›on�ýL‘+[¯M�W„�nûVd^åñg9T6C“û¢êô~$QÁ>Õ ûës£O5H2JйB©’µÒ¹µ�9Jg”8û£‡œåÀÇw‰W�-/@9$×�î÷mÛîo/ƒ]Koîvgý›?¼zäW±è`9qkÊ~ƒƒhŽ®?Ξєé#ë°‰Ô0\Ю`É Ó¦”œØg�ÎIˆ h¿²IÞh?öe�V&öšg_Ùîo/…Ëfe(‘m13¢KÚÏ€CÝøèü Ó49€èöÌ8¶~"@Ä’¢°ÆHÛàtM$Ž”äôœ¥•Kœ·;RÄÖ€ˆK3Îî0äeÒ¨ d_äªíLYGÊû¬ÚËA�–,ˆû”ÿÕwù­Å?ùÍ÷ßþæ¯ì0õ7áá§–Ž´nûq#Õ‰=ëP[l0˜€Coêw .È(<{Âñ½5 42ïœÛ+nùpÃáâfÿõz¿û³¿!>üÏÿM8²lûßç“o.+×¼òš¯loYöêÏ~ àAÿV×âë+õá�O~÷—ñ�ÿÛ/]ö׳rÆ]TðãÄE_(‹©ów94æ�åÎ~ýÝß~÷ÝßÿÉŸ’¿ü¯‰'nÜsôrE¯Pi.%kÞjO~èÃ%+Zp¨­Ïšè˜wt>|:vøßÿ—ðÿñ?ߪï´ý/“áèÚ±O5>07“¹²�7Þå•tײW@ªíL÷\¹`x�4ñ/ÿþÿñ¿üŸŽÅ7—ýgÁ‰™û÷â%¡îÇ/H“O¦‰d-~ Å¿ûîïý§û«ïþúÛï¾ÿ•åÆm1wY(Jž]0ëgW‰3š:ÿ¥Káýs-£ �€C«]•Å–é\t8K™Ÿzs‘g+¡²¦˜Ó´11ÝhMdûcÖ´&{‹EoöÓ÷EG:c»›mÉ ~“Ú_rhÄ�{�§xVÖœ“Ixn›¹J™·ÚÉAö�Ì,™ôùùÊöÜGåõÎ*d“ßFI»Ý™õꇪæx¯;×_ˆÑS¾ÍŠT†Œé ì�œ‹ŸU¾—Cc€^!¥pÖZO$„V¨R¶”ÇvEñ½Àð.Ñ”Z%H`r’ÎAÄÊÎ:Ôï�ùU£»¶@1š$âu7ÛSƒ+¯2— Õ¢ {ÉõMÅ�èÃþ!û&:Ðè+RÞ»lÞíÚxç�9 Ã±¯Ÿ‚ðÔoEeï|8æ-ี>‚BúÃsظWÊìœ>¥Ÿ.¥Íû6­½Ä¸µÒ^5Ø"³�N•¶#}ìzØï”†=Wp>qÖSJ™Ñ-¬P ŸãW~°’ÎIú�ì}øµp¼XãðöǧïGÔ™ÌØ—g &µÓŠÐ‡…l rçIå�ùkˆZÑùë\˜Ñÿ½äÄ>á�Q.“IRZÂÎ�áGD?ÜÉv°’ÆI¨¶+ë|xM[²oµ8ÅR~ìúqUº.ò¥iãð'þ2Êç¼nÒÌc°~`Ûö3â:>B.Ûãã "NA"Dt©}ü)²ÍÊ:çl)éŒgAìv{Ö>ü‡î�ž¥Koð»zv/ŸW~"¢Ö¯…ãÑÏÔß—ÇľkZˆ 8î€ è^ ßn¿h³ å;,»oŸ¦"¿Š³7¦´²£IFÖËÎÊ~ FÒ8 Õ\¸}îw:Nlw¹ghú•ÑÝî­Àè�/hH#OìÙ¼Þô¹=GËG¼‚kÚ’ÁÉýÖÙ碂Rexëüí¶ð‡ð6Y{RùÙ¬©N¸o¯½(#Ä­´EûܧbAAÄ�0pâ»›‡˜Wp3-kfÃ…ä¹Q_opèdý'ÁÊ£&ESt" ªã{Ä®xs1Áu>¼ÊËYW®gñ›Š ÑYŒË43ìX<Í¡ð§Lî“:ˆóÂï÷á%Ëhð�,å¼Jœ+¯|AC†X·i·³£&y²�¬Ò ªYðf[’:£8wïÃ;5N~›4ÈŠÕ-‰ž"m/$k‘'žµÏf-T?¸M¤†%Ç¥ÁßG$-g<ÌÅè%K8¾ÇËä£Ùm½¬!ÈH�1�¸¿8’ç0´§%]®º#oF^ˆÍfß}~Úvµò³WÉš¶Ô¤vší7¹ÓµÁID¾Àn«~ ž bÒ®0°B'}.Êkaƒ�(8­¯‚ G9 Õ´eÝ{V²ì^xI„qìiIÛm½ A´v±åPáZ)Ú½ö½Ëç×¹ˆlW�œXµäôç6u¢/7½S¾ãÈÚ±¨`Ó4‡–öí6]Ö(o�óD"D�²�IJ“$špA"%ƒŒï]ÌzÙ‡¥”ntcJ<WËN“+ü XçdݧâÎyG/[t£ÉsQÁe3­Iu x™ çV :ðU6“{C�ÜT¼æˆ ïäðóެ×vnØîu ËÞ•7Õ-¹Èuοð«†�ØOø1*Ö ÝÊ~D·ÔØ»xèñð2§ê„$3‘¨Ð�ͯ³ª9Á‚sÏM…�^¸œ§nµ'»£E5tÛÏ­wºa�¼¸yÙ'½òáRmí´ÑDŒ¦I¿Ä›m)NÒkd7ê�!Hq¢û}›¶O's`ù•¨ �Ç,«qz:ô}”ßÝbä�•ÛOÝ»ðò~ÿŽíŽ·Pì[=÷«x>žK–øZ˜“VIÛv›ôB¨­�ö×Ç8?裕ÍÏrhåHPpF-Ün‹å¡)!ÖmŠ�ÓùÜÏóvgŠ“õòÝãqz:ô}”ÝØóxL^Fó9•·¢)"�ݽT$†êÄ3ù>æ\üŒ—Ùû ¹¦u�oLŠu›D9tQ–ït¥y W‚¤ók_1tS‚‡:½²?G«ûy"‘ò¶Y»Í•<“{¸áƒ+9æÊº¿xпÓe·ûÍŸ½+çþ ‘C«|F)ŧâ*74ßA¬Ûd›0/ÓU/ŸæØú‰¨`ˆ–Çm3Ï™P\Pè•ýiÞíÙàeÍ«,{"»m•5È~.çÖš’ Å«[ÝÑ×¶;á< F”‰û¯‡2ÉpGOh~Œò&ÍS¿ÎCLÏõ'uWš”›VÜ"þed®lÐ+ûY; µò¸ÁeG8’�lù<²WŽª[“=+öûáœÙ³ü¦2Ï­_:š2ý*fAÌi»ö¾ Oýz¹ºÌɘJÛ}À¾è¡Qmíôõº%»­T0x­+[P•OyŸ$!ÜBRêûÒžû®ì õB­\!ÝÂù|‡†�eê¹í®87v-™·:6rtÊphõȧ`ê,pºÚðÇ(o#s|¢Š?'�^‚\Hž[Ëõb +µµÓv›¨`ðÔ¯gVT5'>·Ó¤Ù6û\„dw$êÖÊu¹¢ó T<˽f=?« ½+®ì3 MÖ澞,0¼#*®DúÆšãcš£Ð|¹6äáø^Æ n¼”¿ h"ÔE•Š¿å|üLT1ÐCc[nœÃ}"AAyîûèœq«#íºŒJ÷ÒÙµp"·¶œ·s|AÌ@ĹӇ¿=×2œÛ¨W‘qJ? . Vv�bFVdM¬ žF¯mÿÚ¶³~`›¬P”tÎy›³‚W5 ×væ«)]?¸Ý4¼×å•îe2ÄñnOìYxéW1ÙÝãZN/ÊFH ʹ=©8¸˜:¯nMòPgeâÆí6Ë¥@¬³Ò¢Œj;Ó%>}ß»ø’´Õ¯{¿7ó«(SãžR…Ÿ3òZ�½�<¿Õžl›;´Ý9_„]KæÃÈNžZ@·ÚS Ð+Ví¶a^¨ `¯„ýA\ÊkÐ¥‘§>ÅUƒwüBó|à­Ù÷xLâRšÁ¯EóÄ\°sí«ð´¤‹ª‘Ãâƒø½®ý+No5ìZ2áij}›ù„"±SA!Ý •]ß½à•0ópƒ‡øvGª4WwE–^‰ ¶v߸F³.7x<&û㖨ƈ#K¥(#M�ßlO‰*jØà.~A¿�ŠÆUFÖ ¢ß=¬ ÇûW=¼Ù6÷êf[r!‘—³ªëßä—V‹£{¡ü& Ï| –GK.<#Q™‚)ÆBâÆí6Å¥CTc<Ô@¶�Ìà’KŒË£¤lmšæè²k«¿ŠÊºhmí4Ñ”^€q�öÙçU-‰ÈšC—µu-_ yÖt&b'"D|xUºþ!–�Çc2÷6‰´¸‚»—P«á|üìz )ð²ÎHÅÖ‹ò90€D¡"Ä7Ú’%¥$ß>ÿ\„ˆë¡ñMW÷¢|"‚Ô´&@Ô8”{—Ýûl™~v£5YuœïZ<© ù‹ÿÜëÞ`,†b|ØÝÉð÷Á€uhÞ@LPP‰¼²Sçµ�ibþ'2Šn·®£Kû¦iŠ ©o.”FÇxd镈¦:Š$úzAѬY¾•Íw„c{·;ÓýŽŠÆW†âù�–¯‹2®j_÷…]_ÑþÞ@Œ•u†,ÁëÅߦR׿%¨Øã1½7‹çY}A˜¦©v½$õMÝëÞ(ú:ÈØ“cbNŽñ²Æƒ",[.k• ŸN åâ`âdBQÅ#kE(¯M™õ‘mr¨�æ ç]|Ax@´ ¬7®àŸ¶Š2];&�„$FÕ¹¢n%ýÿòº ¢º�BŠ›uÍ¿¨}65v/›õƒ»w:Ó³…È�“R&á`qÎñ½G”IæPTp>cPäbêü~ï¦`IË2òzßÅqãªîiI‹ ®íLY‰sÐÚåÁËd�—‹ßÖ^¸æQ’ -hô5°ôÊ4:]±Òxßêù­öt`øiA¢‹Ç ÒÀÀÄ‚¢�ã{¼µªÏÊ�£ügÂlj³;�i’Ñ2yµ8¤eó‡§%]Ö¶â‰DßhM$àq- J²ÒšsϪÄ<‘‰Lˆ®7' [ªžÔNkÚ’�‘½ž«ÆïZ<­Å å|¢)Ò‹âS¯h¬k·œg ’:ÐDˆä±=·?´'µÓëÍ ŸB–.]—ÓÔ�¿O$¢Ì’®iAF•¡øx"xN`4eª“û‚Š,]hÒ o÷¾:�ÞEœ�šß'¹�<—FžÞlOõ®\nz¼{ŔƞÝhMŒ>)ØkBÛß¾¾‹a±ËÅÁ4^&=K>ßlO¹w$¤g�ècp ªV6ïÊû.Zºte ¬Kû�Á ê"ÄmùéàÙȹøÙÝ® QÁ|SœE(AùUxå'V�uÍ¿(øçíœ{Q4Úæ�/Ë�/½®jIÈc»‹… [§Ÿ‰ ö5®±ÒZ o¢kž ✼ŒE÷¸Ml<š:—GŸfƒyˆ¸ëϤyãçÇ×½ž ׉�>9© bF£þ ßTäâ Ÿ„m>±Ô†ñÈZᛄ§ôÓ»Ýéú¶{— ÙvؽlJc×›ã…mlnž~&BÄ6!! ùK+‡L„Ö8�æd2DÐ8¼ã–£=²v\ÕBò'ž b ^”�ÁqàV묠àŠ�1°ìŽ�¯…ä9y/CRÁ¬ ¬Wý´T:¹�'묬 ½œî²Ž¹çþ�ž9Ì¿ÐÙµd¶ÌU†âêÄ~aÓø¡ÉAÁåM16 ³M¥¿qrŒ“t¶Á!ò)¸óžiä|ü¬ixG´ºx1*qãvB× ª}½"¬ù‚:#‘€ü~ï¦ÃÓh˯*ÃqŸ‚½ æ,7n÷'´¬Lz)9kñÇØåÌzÌâ7uý[Õ­ÉÎ…“Μj�]¤vùº¦=]Ù.¬¬ýBò¼ap[°Rj¬„Ê›J.¥öI° À¼„Ø€&(øV{Ê™s@=�_úUCT0ù K%ÑTv`$ÍÛ¨{î#꼂CSÜã6c¹QÅŒ¤ñ â,7n÷—s ,NZéˆ{/+ :²v|·;]ÛµÙÍf›Û²Ù±øº¶kóvGºà Ÿ)ý´º%!@«ˆ b¥™RûØ€æýaËã!r¢}[Îñ佋/«šÖ‰Žññqãv0Ãsyt6  �u¿•Zi›yæ}•ü&0¼#@$*H¬Ûä#ÑËúC°s2f!&Y#»—·ûc`ùÕ­öä=Û]Ñ×_ŽÉ»—ÍŽÇ'7ÚÒ?to zõL4e¶Ï='á7 <´Ly×n#8�Y^³_þ éQbâº7ìÝ™Þ=¼ÑJ¼7+ë¦i†Æ·JG‡ð²!ÖER C,$umQ%+$l¬‰Ìâ7’U§&ËO›âB .6%ĺM»¿“CÁBÌ)£&E×´' ذ÷1{ït¥o´¥Ûæ�?è$ïZ2{WÎB�^^ Çôm^F–~díøFK2³&•—õâÞçRx@´\~ÂÉÙæ&“¡Î›©ŽùçWyº¡×Á‰ýŠ á#àš¨ ÐÄÖðÒ^1)‹:,Ä`4uÞ=ü¡gƒ‡HP‘¥ò„€éKù«`ÔdhbÇê.#S{õÛs—yHÇ×Ow|*–Æö{–^÷¯š Çw{6+Cqe|ï‘^øÚÊØúÉÃþ­LûY&„sûšÔ«DHø®l\¯­�f$ä ’¹æ}[‘¥W—7ô8qÖõøEmgZ€Ø¯`ÄȵK4ÀékúrÁtÁ’Ó)³éÄ×ÂFhòàR‹žãë'`tWT°_5X™,PceMPÉä‚ÝßÃ5ø¥» �P‡'bã;“±¨H}Á¯Ö´%Y g(�²å;ÃhŠŒ~ÜjK‘ç!Ôùðjã`j$JC¸\�YKWѰÆYÛpˆÖ C?to´L?+ÈÜ_4u>¼z¤LìßlOò2òÉq&"Àª&Èz Žr؈2€½7 l˜¦I|QD׉ÀðN_ôp¾¢+3øMçü‹ºþ-¿ŠEKÙš8CŒ¤—5ÅŠ`¦-à€Æ[ý*^Ëé �ÈwÌ?/Ô.ݹøYôŽïU·Äyˆ}Vn“`NF–Z ºÓµzt0²zœO€7Ÿ8ë^xIoåíá‰DØæ%A]/¦�v�Q“,48ˆÒÔDÚE‰ ØîtmH#»í³Ï‡VŽ."Ê1�^,¿j™~Ö0¸}»3ÉCäâÌsÉÊÞ`_H÷…b¥,¢1…n´Æëú·BSû½‹/'b§_ À’çcë'Ý�_Àñ½{7+CGÌmpD 9&X½ý™á#»èb€Õ�‰9æQXÞUFU-q0¶Û³ðr|ýä‚óbê|R;�,½j�yö°«2ld‚+AÑY·D-6Hò Xzdà:#“W@æµ~³-ùÓÀvxê wñp"v:?ûdÉõqâ,ã šÔlßhM¤½ÙÈt r²Î4GËÚf=‘ˆÝßµØ@ö6Êš5âueÝúÚˆ‘‘/høƒäWˆ‡$…^4ª[â7Û“·;Ó7Z“UáxE[ËÑHâ.Ó"ÈÉäû×DòˆD€E€+J@yÌ-À¼-íUK[<ÐYË303@¡nEјHPÈé¾ÖlÜhMÜîLÝêHU7'*Æ…ˆ“uI•�vÎJ¹“õÍdU·Î�>².–òð#¯_—70ùâ­óHNÔ+CÆíöÔÝ®�‡}[ ƒÛ`l70´S?°ýcïæ�®�›íIë†%•‘Š )Ž0@÷b�É=ÜàT-oÝ{ï‹Zb¬¬ñŠÎˈm0¬UdzšsˆIk¨•͸… Õòìâ .(Èú‹Y NR,±’î h´ñûjPÞc$Í2¬ÆVÅDïT�±Ðð0™’42FÐYHjèV’D·xrðRL¬—쨬‹`y†'ådµŸNÞbq7ˆCn0¬%hÐXIóÊÄ33­$> stream xœí�ytTÕÀï$a1,�¨hŒ‚ÄJ¡,Yª`pC)‹(n@…Æ ÅOQ ".€VYd)çTåX©  ‚ÈZа)¢€d!Û¼™÷ÞÌ›õëy3!!!“ÌÜûÝo2v~ÿä¯�ßùî}wùîÆ˜}úô¬nëÒ4Ú:Õ¸jÜgV·¢úà|VݹsZ÷„hËUÐä–Ws=ªbTsôÚlž_—ý©u´åªh:ðù ¿zt«¢9Ýàw:mV›§hëëc3¢-fbé·¬À¡Bœvmãˆ&Ñvd­ŸÜe(žŽ~›ëøœËNSwŠ«EŸ]+^9üâèÚ¥Í,°yCtš¾²�%ŠŽIƒ?]+p9r¿$ŠŽŒ±ë”iÎ:ý6×þ‡.ŠšÞ€Ýκì*ñÚó'4Ž’c«lÅæGRs®¹>JŽŒ5»O¯íƒ®�ª/ë¿�9ö°‚´,›�QPJ¶ª‡íèunêGÆRæjö0=Zî`r¿þûÕðKÚDS¦&;6Ÿ£9"rôéÛè¿í/FP@?’Iê×æÃˆô‚hyýH%‡–DVÒ&>Çüf¤’M§Û"¥žÓ‡Np”V?}¡ä'—’9¶û7Gu4Ë&sd¬ïi�Ãѯ/oIãwåÞú†µ!qÙï¥qd“47¯¤¶)…H2y¾YGX‰a% d¦•;Šæg³˜bº�ü1wu4kdñMŽŒeñ5=Á@®•ž²Ìð 8þÔQ¶#ëx"òžºÎÙòó}–Yb‘t�í!W°ÅVžþ¥>u�\G6¬Fº–í Ùi‹Eš¿6A¦`›#|ƒ²êèÊtdã[žŽƒróh'"©­’—¢º<Ïà~ôliŠŒ=-Üòp�J—(9@nzLô=Í% v, µ~)Ú;’{ §¨¼e�¤IÞ�Ñô˜Gä4?ée(u1€6WŠ"cs±ŠÀ_zµ$É»±ŠÀø±�Á‹ó°¾jmºEÆ&áEÀ›™ÉÑ‚³„j¸OµClº§¯>‡.c‰øÁ˜¸OÈȪ F–ÌÃΡ%lÀ¬Œ&úmÈŠŒõÆkÀƒ{ñ×kº£KîD–œ…m`»W‘¥–¡;jó‘YZgZ44ú*TÃþ¸íNϸ³CËÜ^&€6 Õ‘µDõT ¿€h˜RŒ/ ¿‹¨ÈØßð›°_ƒé(¥>èx,[ÂØ ã8M‘±Þšs0~³7|JJ}PÐf $Bi ,EÖ$_’£6 Í‘ý^N}poGÚ¾™b“dŽ…8†Œ±™¢K !ÑÑR*MŽãe£j =ƒ£¸cÁ£vôpYš¬/À½É‘½#Oô.†Ý%ú�&b(2¶QdE=`�Å»I $ø`´âÑ'„ç¡â¬oÞ*kDà J…´ì“Ö‚›¨ˆ+fJëœFÙ²_f}D #ccäÊÄ×7÷J #¨cÂx“ÔϧB&—ÊuÇ¢Š7ÊìdLN!Äq»ÜúöÑâŽÙ² ÑÝ[¤v2f‡ ‡Qæè1ÈÏÂŽ-$·àæ„a‰˜âµØË[²K8Žkd×G° ï"~Vz}p´Rœ-%[ §è ÍäÍÿÏá]JjŒ¿w!ÎWE-E†3ãø`¸§Ð�™Ž“ß„›]‘œs_‚0B¾``�£]lº`9Eà Mp\Qß­ ¨7 ű�ü&v 9ö¦øfÄÆ�E×KBqÌ"õB÷-–°C¡6´ÎÜŠ ©ŽDÂȾ qT (&I[)¬�›?Ÿ2EþŒËÄ%r¾=�dÔ^‘íwR•5”p�}¶Ò*· ı;Q� 8~*9¯W…­?§b"IOà] Çi$C3ƒÿ~±¢8Š„² UÓ³—;ŒŒ}Iä¨ôåVìAÖ„üÈé8’ʱ”;ŒŒ�&rÔÆs+R5=&F+>Ç™D3pó/½&JÜ�R ?Gó ‘¢‰Â¹}x-• ÊeWša8æU¤öð½Å'ù• woÙ] •¤Ÿ÷®n„Ý5÷|�®>*Ü«qOÐõ…Ë8ï'J�qr9Z¤/ Wâ�3Žì:É3œr�¢¹ˆÍu¤Õ°ÇÜÑÅ{Òy�£�óüÙz:E°Þ|îÿ0庰/#SøÞæ‹#[AçÈ[!O*hYÿí8Õ¥†]Ø)û™SœóÂÿ:zæñZg×fw˜_ñÿîp‡}­Ù׌#çÚQÊ>ÈIž})ò·qUÃ[1¬˜ï5ì»+:“ÎNñåShV4+ððlèJ#ËTP±§+ùß=¶d:©¤{GûˆÒ‘«Bv"ýd8“>)´ÍI®+@ß#ut¿¹a/+©"ÀYŽÍ)ItóÂ’C‡Nê\ûI_&s„C‡Žå[#ߊ”I]Ö°”#ŽdókïóŒ%™Ã¡Èž%“ô˜7².ˆü˜ó½”CÜ?sœ+-¡’³ß¹\“ *Š8 ‡S÷×`㸵›bãu…ÿÚóÞd_ÍvNÃ!äß5lŒÜ’lÜ#°~ÝJÎM½~};y §#�ç_h¶‘”q†Ñ„ª…ä¾… qYû\àŒÜu•å·œa49Hä¨ðîÐìG\Ö'G¬)ø>bËK‰&Ø^®J ŒA�žÐ¬¡‹43(“)6�—’弘r…â67“Ýø¨‰è%P¶áN�pÊŽ£Ê¬¹Š’+äY±÷]~�kW�Ý"¢3åžþ(Åx¤«™ÜS jVu°Tª]5œBï”¶”ÚÛhO‹…±‚¿K­�åBw›1ö(]‡­ófR‚Hí±O5 c-e® ¿S‘NµçCdv 鄼9¶&2—9Ÿûå}:>ñWSnð bˆæ¥úI«–îÏD£XÉ7ÒîvÑ» Ë­¤ºßLÿ�¨êjY“í á0ž£ƒ¬㽸TK]û„U/‘ÔjOˆ‡±’™r†þ„§Ä“‰:lûq×R>c“¸Y »¤,¶ë½1äÖÒ4âVŒ‘n¶Œ¡OIk³*$ß¹ºQÊ-�½µ½P÷»ªj€ËúÝ¢Çú6€(9µ}�?föéÚ¾u´›íÐ$¤\Õ©gæ­7d\A“Á«�F×e;qúäÇF¾åšºZåäÔöé)Q˜Ëĉ'Nœ8qâĉ'Nœ8qâĉóÛ"5ƒv,N´tÀûyûhkD›¦7f½û>æÁ< 4µ|GÞž×óþþnŸç£9; è*\­XãŽÀR"Ê}ÒHr €kßï“ ` c–Åð ¶Yl1ü솗77ð²nä\Ò3‘¥.O'®ß? ;Í?­tÿ•Øj1…¹røN/kKpï›eð=rô/˜ø»þŒê‹4ô²>Ç‹œÏè†;_…·p…b�X)ë…ð×ï¬|ëÙÿ÷;vʺ]9ð� pCÇÀßñð²Rìe�ð5p> ä‚à-´a®R e=Žr�+…àNÏÃǸJ1HL”õl8�ÎùÓ¸'ð÷Mx U)‰…²~Îtàýí2Þ¿o=‹Qb ¬§ÀY¾<ŠÉPÈ5·™§y\”ç & ¿¬Ÿ‚âÎü¿NÌ…Y–ü% Ütë4ø²žà· �xìfƒ£ë‹à݉ÄIbNNN1ääl�¶IhÚù¡0'ÀûœÿBûUÆñW$ß¹ÐàI:wÎm“ФWžÔã«�ÿ>q*ˆ endstream endobj 51 0 obj <> /StructParent 100004>> endobj 52 0 obj <> /StructParent 100005>> endobj 53 0 obj <> /StructParent 100006>> endobj 54 0 obj <> /StructParent 100007>> endobj 55 0 obj <> /StructParent 100008>> endobj 56 0 obj <> /StructParent 100009>> endobj 57 0 obj <> /StructParent 100010>> endobj 58 0 obj <> stream xœí]mo7þ>¿b>8™õ âØîCHc ýZäÚ‡&½¤)p?ÿ0»k{ƻό¨ÕÎÎn¶ZÇÌè…’(Š|H*ÃiõOK-µÿP½?†dÚŸš/MG1ÎQË&yƒk¿þÖüüCû¹ùÒ°ÒÆ­¾}þéçF·Ý¿?½m×?|ýØ\½åöã_ÍÕ¿þüüþÛ׿?|k¯¯¯~|óÏÛ–ÚW¯nn߬º‰Ú·šœïzø½y×¼ëwo(©nlqºåuòmÿ¿?½m·ù<®›‡æêýý|}}õú÷¿ýãá·ÿ}k¯ïïîï ™ÛWí«Wm7È«{ÛjÓ>üÞè5ÇtëƒVޤКÔ>|j®‰È¾jþÓÜý¸žÔÿÛk"^ÿ2(G.ºdŸÖÙ"›Vadož†1ìäîaŸñÒ*XM<1}¬ñi­¬×aj|މìë#�Ñ8e'3ÅCO¤Ãc|q$òO$­~øém»þaµóuê¶¾mbV�ˆtû©1.õþüGó^~DØ´š›µ$éó)i¥»_v]*îþñ�ìâmvédóY926˜'f÷š¼{h9Ý*çmhSŠ+‰ðòw_? ¦©š¦ÖN2OÒ¼‘ lBôÎ?ˆ׈`!!Â}>/·¿òr{3 ¸f!×\R‘½ö~›kz›kÌw›©¦ä£ÕÏuó·· ÌkD°ˆ�áäÃ}ƒšºEª×G6Ò¦2ñN²'ÁœÄÒ»Ó1vï@ÖI…À¤³6 ^Q¼k""ÜH—a³Ôsóž^öAg)óðn81óðsn&ÝÝíg}'�Ï�ô£yy 8D°îÝ_—«pµXÉ+œMýµªsú‚ÑÝ�E¼ê�üû^.àåÜh–”ÕÑÛ‰�t¹Ë\K^qòÎMr 2?xà~FG7…NTÝ ú€‹<ßI^Ì~ql[yj¿Ì¡ÑÃ/ ÔÏÑâÇÁ’Õ:¦sWëFgH$ÖŰ…AíÅŠàm½Q™Rëž×ª’Zˆ\ìBq›‚‚ºâ¨àÝõ}«u£é¢Öµn‚kÕ:x4Xzü  otØ9TÒÀñclÃ=¦gÐÅ(*v†yr‘Ñ~Æâ&±*ØP6¡µÄz(JQçsloÜâ.^((Ãä�Ï÷ÎYÌêë”6Žž!ùKš†àákÆ�Ÿò§£ÝŠGÝ#P{[ËäºÐqÏ)”7h˜% °.HfžeÖ4þùÁ8�æÎ‡Ý}ô a×ojðEŸ0Ø»ƒÎèc0Ü6E¨ó{é/˜A�*!•E} áÂ…2°©„fwSF“ =ŒÑÄŸ;>c|†Çõ…],6G·Øf¥µ�¦¿QÎÀw1}Oæ"«ƒ"ktœØÅsÑ€k�¢i®Õ3ÉáXF'�Åþb¢J)¤4ɵzO¼è„G /N& Ôe�saje.v®º’”%ïÍ”\[nŒ€áxîWúè O.ôó¢Ot‰ÖJ³6Ü_Ý3ðQŸØ½÷=:–9hE>’›Øz—›ràX6�;Þ%?ɵ8–k<ä.ÒGÊ„Ói1«ï¬W)ÅÉÅ?}éàBT)æìó‹tèå“3^%ïSœºÎ ^` ˆ1_ ŸûZ±Gª,Y®IÖ F9@ƒ´&sTð5,”‰YÈŠ½<à }‚Ø«‹â" :/4a¿>Ž<?rz2Ànëó‡CˆÑØýŽš*è\ #À:,>Y£Ê› •¸)|pÄlß4µH…õáè0¹4—»Æå5„xSÛÁÃ…†y¬þIEá>9£b±"‹¿8"aO±"�lÌŠÖ;�&‚ápâ°J\›zDVlŽŽ8ò �‚–É­R‹Ž£¨=ÚgõLÓrhO�.5fÄ ã‘< õìˆò Ãrq[íT .7ßâ>²âU¤ñâ(vØ|�@‰'2ÃÇL^„yÖ+2‘Ñ}"G8ç=ò¸›•‡ ë^Ä}À»7ë9º_˜¾E=Ø/v$ôÑÎõÍ람J1Ú¼kñbcï³Î‘J>Y“Å»xùa+Þw.Öœ·ôß#º.�WÉÎcѱV8Gç5ãÚ®8-˜<î¶àí-Ƌà l!òÀb0�ª6eV©¬7¡UZsXaÁ¶~)C q«£ê°woª ÕD¦â5w;hQâà¼~¦8DÙ‡ì ÜÚm>#wuYzò¸Õˆ9–‚wnJ8%å;Ìõ¶@Ý&ôņ3;šº—~aÐ,À-n=dña l=æ[Êxâ»j'¿¸àÐ$&�Þ�:Ô°ÄþÊ9A8h"šªŽüœJkLPš}äí�º3ç6D•B<-ü"Š›gp‚°Y‚Y¢ÄÐ\L@óx‚­î1>a”oW_‰Ø—'"¡hÁ±yHg“‡¨VÌ ‹U³…Áú¬sŠˆœÉ\ŸzfFùs[ÅËP`±D3/H�:Cù5‰Y¹[l.�‘ÆÐC%h­!=¹{¤I˜K²dÀ ¼E¬©ùæo­ŠéÙå–D º€7«›X³s¹OsÂ’XMCèŽfŠs J“3¾µ1©°Á[óæ˜U\9Ís!ŽäޱÌ9±,sg(ñôÏQµjn&f…ïãhDä…/ȳæÈëßȳ&d¥SÈ‹r…ˆ…£bà<²23ÀTÈݼ’@7» f!¯ðfph¸0I‹w;."”•UjPDH\™|pœMeAdªÄOú£Âõº á8qÊ9 ë2Š0¹†2GZqõ< ;Ÿ�\’ " M°À¾ŠóÈ"r×F™ê|?2uðÁÜÙ7�ýÔuè"线ÜqwMsºC¬iÝÿ;»ÍŸ_oþŽYÿ=çó¹5¦î‰žHyïý(ì^‹Mòø�šÞ÷£[‰óÍW„cɯ¡Ë ÜÉ^¯†|¸³g*Ì“¹DŸu?å=OÐm“—X·JiÙJøï¹œ%A‘ ÑçIÅUnÄ-…µÎ] 35iEl\Êcê2§.ØAõž�ÇÌŠy]å<ùc‰¹c Ò·â{[ž¨úƒæèé ºrЧ xTÏ©|‘�ûLG_0ìcî {j†õÄæ,%£Î>›$JÉ ­ÿy®‡ý¼Jð ì¿ÉJ‘š—êÇ¡£ %·ÆlG¯X‹aŽJr?ÔàÔî0Óo}Á(ø`¥U`zòœáf¾ÎnÈ+±+hÏQA^íð*-¦nEOuáÑx–YpW3¢À´2ó›TDjÉÑTÌÍ“3Óœ·Ì²®x—›ýr³WºÙsšbÄv†„£Âx´K LW$�›A¾}úL\®PÉÂ:åi(âË�g>Qïe�Xï AæË¼ÙgÈ®Tµ ¹+·1¯ÔqmAËñ�ÀúûåcZè�eÒ›4t8ŠË$æÝ=Y¼‚…µj"LêÊìhÍÊï8ŠÂ›#¹6¡>Ä 1C´9B¼›\A ñnõÊ}Où% Ç,Ì�zUŽŠÄ�ÃG§<-KFfÅ ä¡åóúȪ1(ÇZçÕÌRÜó„òbÀÕ^X—7ru� çR†&ë£Z¦GžÛ(€àÔ éb˜ÓlzŠ×PÄðs Àkôr³x�Qõ\ÒW¬ÄT°’Ô™r›¼Ø _`ÇmäÙE ñkfóe 3+öqOOß"µ 9!.fš/eg†,º2ã V ?Ìr-ç…¢Í0�탦Pœè¡ öæ5…:gd{1HuÉ‹È< ëw µk=ˆC—`­X S»¤’w:¹ò¥‘×÷g»(ðŠÀŬ·Ê³dʬ—y SM§AÅz«ré±_Hõ~–þÓ2§”ä`”’ظç»~¿Ì ˱Uy”T« µ�ÒIÛ tw`t« ;e`“Öi½ë«i¼rÁÅØ¿E¨g쯙M¡^e6yÚ½‚¼r#ÛD±Wɨ*†iÈøR�/~ºD«"Û Ũ\ ÊçÌÆ=ìÈH4¿ 9i™¼UlˆÆ È�¢:kÔV…”’Eƒž+¾7¤Ž{!¶É'åRJqìR€¥¨+ªú[q`C, %sH~ñÈ‹ˆVt@^É‹-ˆ‘Øø ñ{© ˆ¼+4^A)‹D#6¶Ë¡F0´ ‚Å ˆ—gqƒFQ±}•äÜ�!1sáX,Ñ�Öª9ç‰tX1`‘”·ÉÃfÅq:5 œÎ�öt 1÷­}¢óÅäõè©‹ÑehSrˆ´ü:”—熷·Xo�W®À)W0ñ+WÎ’Ò,ƒ ΚbLPš}䬽Z"waª~±*]2÷ª8�Á,™qê¼QmÌx£rµ7j�møüþtœ¡¬ˆkÔ,Î2×›\w5}ºqøL®È¯sq‘/xWA8<\+¬–ˆõGŒ¿ƒ2¾^´34†ûëìÒwÍ»æKC-S¢Ö8G­!¯bpí×ßšŸh?7_VÚ¸Õv{þéç7ÍÕ[n?þ%9é!¢¨È˜ [MF«ÄÌ£‘~=öF{B¨ÇÞ„@`ØÔ-"À/ "0"ÜBoc½nD/þ±vN¨)ÌvH€¼ ˆ@âá¢Äa}–�yqÖ6�MÊ> stream xœí�ûSÓXÇýÓ3Ó\Û‚‹ØuD¤ÍIiaÁÝ"È¡Üln½PŠ(Ѝëë-ï¤)I€ª)ç4y¾óýággÞ�“~Nž“ç{Î¥K‰G ‡©lRã�Ê!•éS#w·ÚzÖb±yÜWý² ØX{Ïì´¢"'šO5/©†a¤&w™„Žûê@¿ j°J噤Æ#…•T P5Kj,6íÝ`E÷e‚@¿ &¡§&w Ãà%íØ#�T&¡sH$%’’q_&èçâE•IêÔ`™5ߣÌ 'µþ©ý›£{LYQ±Ì$`LA¤‹M•ØdžEºÅ"Ë]Ã¥�™7­åkÿ"ª‘”î—£i¹}8‡û’AõÅ$tVÔXQåEgй9Z™S>¯mkÛÆØÚ‡Î¿K®ÙGæ²�ÈEû¶p_;TG±Ø|ÛíµH_ŽM•¸£Š %¥ÎdKæ#½Rø–šÞì7+QiÎ…S '©¸¯tLß›hÆ7þ³èd;[ú6¼ð6šÎÛÿY´o늸C¯2pÿ �#NTZz7b±yÕÄKšøäårá뉧zVùtûÑ®{AÊrôÓ‰¦®—ó_Å'/­ÿžE*�4„Œq—5Üt‰MÔÖ"8Ñüîc=ÕÝvžæ>}ï‘6Ë„u§Là¡L CgŸhêz&÷©{tÇž}øj�È -„à �¨´êWIaŠýdv ÿ;?Ë# e9ò6ÑÔõ¿«ïÛïì1 !�M*|*' lâþ+AEtç~èv™JkœT{¤£ýúÀÌ›ÕÒ·_z¤¡LÀ«ßœhêzµômpî ’Ôír^ؼû¸4±¶o0û€.NÒèî]Š2ø£õ ^R{Ç^,é_EA™p¢ã2S]}jÐDS×÷—[] �a¤±q5Ô«R·€T ßU5Ò²çq…,WTk�Æ©éý•â9Tu½ }éßã\± Š2˜î /A‚wY -it\¶olÛÀùO4u]ëŽK:ÝqÔ-�îS¡;ô;â�œžª†áÆÅíG»sêç xª'7?^)»4äj•BÇ�T¿&,M]ŸîŽ;ê?�¸è×Äô묤±æóã̹]ÃÛ§:�íÑ•wmÎ"—é>Ê„³ë{Íü…L4uýxýCç�¢ÑŽvT�YÁ(ÐÏuÔiüœéwr—Óùá…·?è4n¨ë– LŸ¹Ì‹ûn-r&šÓ¶ºãZ\‹T,Ê1é5zh‰Êdpß9¹âEµ¥w³N§qþL�Æ õ¼úùÄ·ls/#Ie’@ª“"p¢©k«;ÎyØ�Fe2Ì@–— ?tRBuM€^TÙ£g¦rÿåNã†úD™À$UÊ„ã"y¢©ëùÓ wwœ¤óæs(‡0¦ SÜÝ<—Ð8QÌ'D±;�3ÙØŸÞº†2á{b“šµáM]W»ãŠNB"Ç&äP\¦z�TÁ•ÕiÌÜÜ11u´ ­…Ü/ôs�C™à–5јÛ=™«vM0ÑÔuÖêŽëwºã¨Þ\èæ6tÇSŒ¨Ó×�w#­o|oñ¼;�j(¨L&4´È¤6šq¢©ëÝìŽã�wÇÑ×+¬='A‘Õï*#: ª×ÿ)OçØiÜP¶Là�L¬R™ŒCé&œhêzrëcì¾ÓÇŠ²µ'tRù[‘žŠp·ÀÅñt7ÔA+‰oþlew_Áõvšw¢©ëÝq$T;�Ÿ�mó|ŸyA;Y&†‘žÜ%¿L€‰æ{^.|•¦^Yç ñæì£Q(Ë ç~Zxô«„„n\þýsëf,hÍ�<#r—líŸP5¹cdEû¶„DŽO(BBg�F­c¨8ÖT�Æ uý2á¯ubC4ö8Ö¶í üDS×�Ì“hœî¸j3¼M‘(ëp:góütþïÀWu] ÑHÇB4ôà"î¬#ë ;ÿ®s@0ØíÕÒ·�Ù7Nw0ŠHñ ¹)Bî„Ø} ŸP™ô*î¬#ëò`¢9£ï/ÚoS¸‡TGöè '¯°?-Íbk…Ê\›"rýÜPìw©Y Œ"\öèH“À¨³å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'£0ʃ�Q~20Šp£<å'ÛŒJ�ʆaà=ÐI£<ØfG0£– _±ß¨¦ðÃå‰öžôŸ#†aTÒi™ãp è˜X¤X�tßã=ìOK³Øb‹4FÒBé5XÆ=ŒÇd hK:?¼ð6[»ˆõÒÆÁÓ›)…ãU޳,sœÂ²*˪ ƒ{A5Ñ«6¦nŒîÌÈŸ°?9ä»k¸T{ÿ”Tj°|çqebmŸœ2AHèìÑëqÇPq,ûû#ÍÙÂçéäØópTå8MvúúôÖÖ©x^eEäh4×ÞŽ{0A—BC‹T&cW|<ÒúÆ÷–ô/ØŸ"’½ }é{áÜ4I5 #5µË"÷xšâD�U^Tù£+¼9Z™U>c¿o„øéØæ³ËW-"•º»fgßmlf³»é´*Ö¿+—koWÂaJ?Ü¢2™ÐÐ"—ÞhEENª=ÒÑ”>8weÂ�=¹ù16²m“ŠEzòji¸Gõ/ªŒøœBYiÖå ’&>yù,Ø‹TóK»sWïXÊwt¼{·±áöÁüüvO�]úY°Rx^áyÜCtµ¢b邨A™ð«¾¿|ØšÎÛ¤ #��«¡^•º…™TÊÒh‹e!^°/ïò_]¤z&¿Ÿê‘yó5I‹F_Ü»w¸¶vP¶÷ÇÇ ��vé§ð¼Ìó9AØŠFñŽ)HHèP&xðJá[jz_HÖÞX8Q¡nitŸ¹Z…{H/ ñŸÐ9ó¤b“ªkd{bó#öûv1οMý=·nµ€Sîí}»¼ü=:Ù>\_ßÑ[Z쪭ht�e—h:CQ¸G5è‚2Á›g•O·íÚ° g)¸‡ô—PÒ“Ã0ø£«â�Ú;öbQóùÂãÌDnùò5 2Åë×ß<}úS:#ÕÊÊB_ýðDzÏg(*KÓ,Rá” žýxýCçÐÑW?¤ñæ7S…E2‹rxÇÔ0Œ‰µý¾G•HO…kïTá~-5½¿Rü†ý¾�»³¯fº¥ÚÒS[ÛË~‰NÇ©fgK7oÚ/TÚ‘ó@*Ü:^&hv™ðdó?ìO ÉΖ¾ /¼mq-R±(Ǥ×è¡%*“Á;¦‘žŠp·ÀÇ5Éöåµß+Ž®¼Ã~ßÎË«Úÿ¦â£9Þü$§†Ã»éôa6ëP¶_e2ùöv›TyŽSF…rPúáVµLØ5 ƒs• ·íΫ°Hõ#/翊O^Zõ2[mê 2z ËðÕ¯ (¥j‡T×ÿÙ™Îýû}ûMOÿ³¼ÖR#ÉvOÏÁÂÂïÓÉ)ýÖÖö††´hÔ&UŽ¢¶C¡ýPÈRaUÐÊ„sôŒüéÆè޳He"Kã$�Kæq�ªI*z`õtwÜbsvÇÍÎä;nÔ–žºº^?yrŽtrûíÒÒN<®òNwºAQš–¡?·ì2!œÈÙOõ• ò¿«ï¯ÜsVö¸džÕP\¦z1/RYÝqLjƒ»›?Õ×4³ÏÒÆ›é[i+Ò¢_¾¼72òn}½A€²ýzzº‹Õ0Ų2Ï+GÍTxÇNäxQæDÙeBC½Zú68wé×�Mo.ts;Ô¹OQ˜C4& +j¬Ù>Q{Oî,fˆïŽË¿L¥&j‘žßAèpe¥Ñt:¶Hõða¾­Íiøäy…aÔPHƒÒ·|V&\˜ô/}ã{îŠ2èëV”qé%6©±Õ ãE3.mwÇÍ)„F8Ÿ>Ìf£µ¥§[·æç/’N¶O‡h4ŠRF…*ÜòG™€ÅS[c÷ËGŸüTÖ|/5W°Iè¤âEµ¥w3›·»ãøjwÜrž î¸ùÅÊÜÕZb%ÿÇû§"-ïƒÅÅro¯¢±J?Ø?�5o™€Ý£+ïÚ ®Q…‰+$„hb±ù¶Ûk‘¾çŒ]™"õ2;½<˽ŸîTªëÕZ4º74tØø¥§³ûõøxáêU»î3÷O`Y™es,‹wLAMW&â•b� Ógn¤€{H/1ý:+iÕð¦³ðØ5¼=±�§;.[ø250½Y�´˜KOñøY"-¼¾þòÁg§ŽË±lŽa¶B¡,,RáVS” z^ý|b§³5]R˜$~RqHNOU°wÇ=ßzv¹ËÞMåÍÌ ~ýЇ++•dÒ^¤Ò8.KQÏiZ�*Ü"¹L Ü�×ÿ³C4fÝ—T9I’J$…y9Ýꎻó¸B –�î¸äuÇ-¬ìÍÆµ¥§ööWbçÏÙ}07·í јËSÕ—@]ðŽ)ˆ´2¡Yœ-™;½¸C4‘”ô ‰[ÊâSj°JåiI£ãΘ¶ î/6èn¬ª ‰´\¼÷ÇÇóüa“JB4dè{e„h~èåüWiê• Ù‹TšñŸ³"þ¯~t\f +*œ}yHýó~yúù9wÇ™‘–h-ÒrÆÝTH¶¹ÓËéMkëþµkB¸G5ÐÂ[&4µgäO7G+N*YTØê÷¢‘4º{—¢œ�^xÉÜéå\¶˜ž�ÖÛ»k‘–k×^ONb'Ìyùí³g;¹7ù4ªtt@k:vYe“Ô„~'Dsù¯– ¾ñØÚ‡?†Š®ýòL‚Œ eÐ�û¡Ûe*­qRmö‰öë3oV½vÇ-­cˆ´\¼ßLOÿüÓéKçy«�J¥i¼c ús¼$›ÏsƒËŸ9[/DӚ؎¡×aÑPi-Ô¯2’ºvïé,þ›}ÿKãjá³i"µSZ:\]Å“†Ú Ñ\¹â¼SÑ´¹–[[ñŽ)¨¡e‚�½¤Ÿ¼t'�2:P…„Öt6Q­CEÅê–·®°ûÁÎÓÜ™ºãÌHK þHËÅûtˆ¦ØÚº�ïOL�sZ0Õˆ2! žÜúŸ¢á«Ù)Œ¤ÒýtR‰JKïF�î¸ïo1½°X™ë¼íDZ?ÆÎ�‹÷é�a&»`‘ ·Ž— ªç2!€6wzq…hè~•–r!´‰½?á¨;.ǦJöÇÜ–zç Õ"-œiñåÒÓÙýzbÂÑØ‡Ñ˜ç�F"xÇT-ÏeB`½Rü60ó&’´© eïdŠ$—̦Jl2Ï"�I8}¼]Ã¥ñjw\�H˳gØA„­�ë$9Q"ŽK&@Êpõ¸ä“!ë¸dÜãiŠIè©êÓ‰÷0“Ù—.ܽ5–éì³2w?8 ìöN_Ÿµ1$‘I“¢©þâî/£ÎäåÂWei5ÚnRP¸zûo¿Yl}UF©À(òdÆÝLõ«&–Q& €QÀ(É®õ€QÀ¨`E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QÀ¨€E¸€QþdTg'öß~³¸‚0Šd£~ÕÙ¹ŒZe‹Q*Ç•nÜ8˜�ÅN’}¸²²ƒP펱¬Ìó¸TGR¬_\¤_˜}³Zú†${|ã¿Î¿KÄ2j‘¦3¥aJåù„WV°Ó€8¯¯ï ë--Ö�R8n+Í îÕQ•Q²ý6Õ~¯øhõ=vè9åóíG»ö�b‰dT†¢–hzƒãŠ­­5Lqœ�î ®¯ã'~=1Q¸zÕ¾?*ÏË<Ÿ„­h÷‚ê¨ (å©®ÿ³3�ûv,â•â·Ôô¾�Ôj÷GTZQQ@î¡û®Š­­z8¬ñ¼Æ²ö/1ÿÇûccØù€×‹‹åÞ^7�ìÿ�{Ð@?‡dz`•ÊdlLñHëß[Ô¿`G^�®¼»2P°o ÝoÞ™°¨·¢"îAû‰´ê"ð±_"Çmߺu0?��ïÃlv7�VÁ.î4ŠR«Ëw¸ tVQ™Lhh‘Ko´¢"'Õ~’Ñ”>8w� ä"ÕäÖÇØý² Ú ‹F21…{¬~A*Ï?g˜¬{‘J‚¶HõêáÃ|[› j…ç†QC!�¢p�è—ÕŠŠa¤óHcíÒ©ƒÅLövh\˜ô/}ã{ü¨9¤R”ÁtWx¤à/ÊRÔMË,[8z‹P9N¿|yodä�ß©^OOÿüÓþ«e–Uª/Q ¼>5¹Ø¤ÆV¡¼èüNoŽVæ”ÏØÒPgKßç"ýzí¯–Tª7º¹êܧ(÷°ü– ‚ W»§AÐŽ~³Å®®ýÉIì$i„ß.-íÄãî:× ¨J•Õ¸‡tnâE•ŸS(Ë£Ú;• iâ“—Ëù¯ØaÒÿ»úþʽ¢Íäp"Ç&äP\¦zs¸‡âܤÂn:m†³nÌqÛ==‹‹Ø©r^>\_ßÒ¢QûÌQÔv(´ PÜùNÊÒh‹A2c¿Z õr:?¼ð6[ÂO•óòŒüéÆè޳ô$鼨ð¢Nø‡N¶ ÃØŸ˜¨ôõU"Å&U8¼›Nf³Ø ó›~•ÉäÛÛ:…Ã2ËÊ¡Pèäk1ý:+iœ¤ IÅþ!_ÞžØø;^~ÓËù¯â“—ö‹"�4*“a²¼¤ã¾ë�U%)T‹>™¦�þ„¶¶—`çŒ7ÌΖnÞtÜx^±ŸÂaÜ7tA’JzºbçZL¾ýhw^mÊEªlɸ¿|ؒλÚ2sLz�Z¢2Ü7û‚$Ó´ù…‹at†±ÝÅîî7OŸbgÎÙmEZì—Ïg(*Ë0:,ŒO†aL¬íßy\¡ËœX{§ 'µÔôþJ±™ú¯ÿ×9T²› ˜¤Êš­2‹|XÜýT:ÃìÒ´AQîžÆroïÛåeìüù �Ö×÷FFìH‹YܱìÃ,U3A¸ï+›¨Ár(•§%�Ž;­ém…ûËM�JžW?÷޽p-=©RXÉÄîûŠSEíÓôÃ䫟æíÍ‹{÷×Ö°³¨®÷ÇÇ ��µKµºžªÝ9ørªŠŽËLBaÌoÎrúõÊĆhV '#-Ô-�é31…û^’¢|õÇnõyÚý ùŽŽW„…hæç·{zjtrå} ë tZŒ¨Ó×w)ʰ;yIí{±DXˆftå]›+ÒbÖwq%Ô«R·È�Ýá’©}Š«?¡ÔÝMÂN/õ#-ÕeÜ· D®(Ê ;÷™›;ÜÝ<')vˆf`†ˆ�^¦¶>^)Û›ðR-CݤMã&…ã6ZZæc1÷Z4Þ͉H‹¹àOÓi�Q& 'ª‚IÍÑü›Å¶ÓË‚fFZ¸ã‘º»ÂK2î»Õš�ÅÖÚÚ6[Z¶\ý�zKËÞÐЇh^OMc1çªqi…adšÆ}“@M&Á,£TNT«_ýjïTÝvžæ>]$�V­HKÒ‰´›Ìí’"-/kó7…ãÜý …®®×Ož\�êFZviZ‡…qÐoˆ•–Þ�XlÞé�´B4…‹ÑT#-ÎÒ—ÌsI…Oå„�MÜ7¦‰eö'¤RuB4 ¢ÓáÚši‰Dìÿ»MA(1 DZ@ç¢Xl¾íöZ¤/ǦJvµÕRÛé¥QtšÉ}êvGZDͬ:%�Kæqß?¨¢¹s§LQ�Ñœˆ´è¡�²9žß„í|Aç*6Ub“yéLÂéOè.�{ˆÆŠ´X0d«‘„Œq—á³Ý9«LQùPHc˜œk§—üåËç¢1#-7n8ó¼Ê²Ãè¡î?ä[1 �5V<µÓËy„h²¥oà o£®HK´o늸C¯‚¥§F)'rµgÒlO:Z,*^¿þ;!šÚ)-�XVãy¡ÝŽ ºž@"s§—¤^ ÑhvˆFšzõì7©ÆÖ?ا´ðHe2—�…D.Ú·…ûÏ „4–=—ÍéHËV4º}åÊëXÌ@÷_ �ª!š“Ô„þœ³ÓË_^B4³Ê'÷)-œ¤²¢ÂŠ “€¾‚ •¢)W›”¼…hܑ󈆑9Nia”П3)%Žñµáí'[ÏB§Z¤Er"-íùpJá Ò‚Of³w(¤0Œâ>‰¦£ãU&ó£¥'W¤¥Ö7β ËÊ ƒû�Ìíˆéî:!šEíG!šûˇ­®¥§0ÒÂI%š–Û‡ƒ¸_i²£T÷ ·ã~¥îî7§B4§#-¹öv%†H ˆ(Y!šÐí2•ÖœMýͤiÙ¶#-BBãEs *Lð9wÁ”Âq›?Ѭ¯¿|ð@wQª2Œ"r4škoÇ}í PQi-Ô¯²I%ìÚä³ýž¢™×¾¸vSQxI5 #=¹+$€N„Ê ÑlE£²«Som}qï^¡«Ëù†Q­C¡¸¯pRáÍW)sÝÛÝŸÐ?µ>Z¶b‘B –ï<®L¬íô�.9QªÕœ;Dc¿Y†±›Jé@'PS‰•h5Dã›t’¬Ý2µP*O –q_&èd‡h´£¥§2EUîÜy=1 ¨e†hzÖ¢ñ­HJ¶–ÓYÉ|ƒ"p7•ÿȦÅÍ endstream endobj 61 0 obj <> stream xœí�KlTeÇ;…‚1<Ê3ÂC†‡)1µš(&m‘�ËI¹ ¹³ì¸¦à|C%ÉKÓ"!G“Ü0L­ïRLº 鬟ÈpƒP–yàPñõ4\Lß"!m™áp9Õ­nG–@½ÜZ$äâf¨†ù_¹ Î-Ò8ça\]g¤‚aÃ`A„ yR÷ Æ Biú¯È· †AÔ ¹Å¾ ¹³þ¬�‚ýƒáÛ£·HHó›žÝ0(n³Eð< 6øi‘§äføtƒ0Zw›-‚Ça0§Á£W7þ±HªæºçŠ›×xóÛ"!„›�;ËOø/8ß03²—ÿ 9ºÔ˹ùgšëm¶‘‡Á @‹„teö\Q#2Ã*¾å«5T‹„ÜÛ9Âç1ú ú ²`÷a€l‘�_Þñ|–ÑXø º`Ça°õªàߎÌ�¹þ�Ô‘Š½žóàô±Á«›,âX�ø˜T±Ãœ"™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHf–…’™e!€dfY ™YHfM‰Y+ÍÊb­^�ñǽ»9¾ q°|H*øÑîr­þ�Þ‡t}6s¸J†o¿CªØaÇ|õ¯$·öÚ‘˜ãU2¾Ž5 ô;æ 0B’²Vš6 ṽ7ÃôâpBÖJ‡�zÒŠ“$·Îú Ìé¾à“ñ‚%y¤Ò�Üî¢×JçdKYxÃ@¿c²aoP.¾ívÈBrApnƒä…Àõi}qX+=×÷æÉ‚4Îv:e=¿%}>KðJØZÁ8 ƒ çHnÀµÒ9Å;$yxÜT\„›°µÒÏn²]µÞ×ÐD? Ñ|2I¥éÛ$·[Û‡¹__äŸ `:o¼¦u»§ƒäöã÷|Žø3óÂ$yÌû’ä–o˜í»³ððmoÜɨ‡ÁÆó$·‡µ£"ž£è;Ö¢$y”eî“ÜnèŸ+‚0ï ©à Q= &О+úÎáaT¼a°çe­[UÉÍá&!Éà õþ ’Û½�ÉxÈ�8 ^׺•ï~Lrûs¸jh‹äôno“Ô>B¬ ©/HëÕ–’Ì“E ë®7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,PèÍ, z3Ë…Þ̲@¡7³,Pè͆gÚ^¹½ˆcubîBÁÁÕ­.nãñ›d�&dF~Ǽû:œ_CÅô;2Ñ€×JG[U}&æ°;–r4G\Ÿ6´I´`ݨaà°`}Ó›d›Õ»Æ‰ †�¯u›ËOxóÑ"HüƒÆ9¾Üü®•ö¶‘ˆßµÒ-›}º�ö·IÖ_‹@YîmR[ôý˜ýð´Vú¢×Aâite'äÖŸ�,æ¿E�øX+­ßl/£4í&ÔY�h$Q‡ò6;.Ê&Ù#‹qb0¢ ƒvðmv¾ëZéÖ¨ çµÒŒÛìÆ bèAâ6 N¯f¸•©oBù†J† ý0¸I»ÍVè6ÉžZEò¡[+ÝQ7†èVu,�-‚D³Vºq6×-Us-�-‚DºVúÂ&¾[yí#A‹Ìâ‹Á� ƒ»™a±¸MÏæ“×"Pª‹ ƒÎúø¾¾_ûS[IùΆ¨øð¢8ÝJÓ&°E�—c¿ÍŽÝó8y-eå÷ƒÜ^;2n±’’’y�Ä.ÅÞ"Hù씸­B6þœÀAÒüðFÜF/è}êÊNŽ[‡À«½†ÁïéTÜ:}˜´/ü‚øXUÜ*$¶´<-øÑ®ò¸UPÕÔýåɶdµ’²ÝÃ`"ŸóJ½×R›¼A2éÓæ·ô?õŸÆ endstream endobj 62 0 obj <> stream xœí]ùWI×öOï󥻫;D\£ˆ/ Iº: ›è¸AÁ1l¦»ª³— ÂÌ;3ïŒý�ªJbKI*�zÎýÁsÏ$}ož®{ïso]¸ÀÒ@Ò´”�  ÒˆÙÀ@ „Á`ŠÇ'(AÍybi%‚õH@ RÃX…¶ -&y:�\×�Z*Þ{¶. $‡0g“Ú`J‰®ÈcóR<Îû“ ´#4)aGÍ‘h„»L…I=luÄìžqÁ'œBvìeÞu]­ì¦Ë£™g‰ß_¬ýyc|�: iKñ¸2œóþ¼m%ä¨V ¤¥\ÏHæñâÎôÚŸ7äH¸¸g<é�Zªióþ¼m =˜ÖB!²‡tD�á×ß>d,­»Kën"ë>\ØîŠ¥ÊLÌÄ ,’�ÆB�fÕpJ…ŽrXpz#8:S¬çÒºûxq§{8M‚ÓDªihÓÒÂâpÒ¼Êû{œCøý³ÝýK¾@R�f+éÌÀħ9¼Op.¦DgŠÞp)8µpPJÑ 8Ÿ4š�¼î‚`”žÿ͇¹™ä_{ÝTm¯­¿ûçK‡éëJÖsµ(I.ï/$p~ »s`ÅïŸÕ`)8¯�¯O­þyxp΢ÿ L|ªTö4hwÜnB(‚³!ÐCa�ª¬³{8ýpaûp7UÛÄÒWƲ%—A$I®Ò›×L‹÷78óPC¶j†Í‚³k(u¬à|¾üßk÷³å¶#†Ðí�ÕD¼¿Ù¹Ig £X9*Ë:Ã$ë\Ìü8º§ÊÅ“£o·|‘Röª™–jØJÈ–ƒ‚ON)†=¤˜¶Z®×éalN}Ÿþ÷øÁI*{�åÊžj"•ÈŠNÁ¯BŠÇ=cs ¶BÒ1éZ˜Eÿ;®›ªm>õ¯ñâK¥Ý#-9`{�tG¸Là¨�$W¾Zôôç¤fé(Ò÷8ÿÆþ¥à\ Áù³²ÄŠ‘ôÀU &xã³ Å´åáRIYf¯™ï'$À Z±i2‘AÅ?Eï\‚ÓO+{äegØTfo‹Êƒ 3 tTˆõ2ßÖˆÞ›o52{Ít„̾=ÑXÓCIÍ( ˜ï+zo¾UdöeeT»Ëì™è]3R2ÌT‹Þç™uÝÞ§ÿ�ΫeöŠ�9�Éþp[1�b8ZY~Ð Ñ{ómbé�ËcçAf/Á„ÇXUa²"z×͆‹Þ›oÕ2{’é„‘XÞú`¢wÙÄrÐÚ5‘qJ"G·šz³‡÷ìl3–¯åÿd$˜Ø-z?cYçÑ­"³¯, W`Òc¬‰1ðVC�è�Õ»zm¼j=ùÁi“ÙW*{^ˆ½‘3#³gY'ûðW8‰Þ›o/×þ¼þ $³–`âÿàŠ “–ÂT¢ÈDè�Kpú«hôŒ'µðÐX27uF�û³[ ®ºâ&["ëŽÏ}/í¼2 ™Î$¥þËe±nb=Œ½&Ò¡]k&b¦Õ)DÑÙåª{T訨@J}~6›.°gä‹8#oyNdp±ßæ·»‡Xp�¥" ”ô`Z X0‰a)ŒdB&aÁ¹‡IÂÈ{ÜàŒ Ù˜<,Lr“øgý+�t%'Xøú´žbö$ÛOWÒj†]?!m&9œI$Wê-(l%ÏÜ—ßœñÜ ië$‰Šó &9„Iú—ºý³~hkã™�óTfgÅÚš5±ÎæãC–è_LÂì&¹RôH®dbý~æjzg¹qÁ‰¾/�¾ ΃ßt‚Ib’ÁøØAŽ ¬lN7”I2;+/ Qˆµ�¥¶hâ\LÂì &� éNÆÃd銓�ÎWŸFL¤…l0��4](˜ä & a2¹m-žl´§2;+©íÄPªÛ¤ÄebQ-LâÆ$k°H{²þŸ&gz{i4Ýc"ÝuÝDqr_ &Ù—I ŒÒž<ÝÚšk‚³2;+ _Ÿ0 "ån÷ް`’ƒ˜$’ÔáÇ’N2¹5ÛœàLŸ³Iµgë÷’û§`’ý™Ä&ÊM¤ÍbÍñ³™›&Òî`iµ{GX0ÉAL¶5B&¶6•7›œ�ÖûL¤ $¥ µOp &ÙË$†£ÐËçµ!Ò\K4ÓY¿½a•™’�8ïp^!˜d_& c•ÝMu|x{±™Á™$}²ÄȰˆô &©aÚ\“)™€¹/�šé)fÏ7BÐÖ"H·÷0Ž`’½LâºîL!Æ$µyûy¼ùÁù²¦ÃÙdô¬Æ_‚Ij˜¤Ô\³õ±tc›kÞ^Œ:&�w€m<Œ#˜d/“,mN¹®kb}$Ý“ÞæœÎö‡!ç"]¦Õ¨(“T3ÉðªÞŸ-�ý.m¾h¾§˜Í~§KÓÕá„�·iéU0I “ÜÁÒÓÜ=ÖÝûPœàœs_‘à´µ¨íOöTü%˜¤šI"Imx•lox’»ËËSlÞa,}-Œõx\º?צ¥WÁ$5L2€ä;X2‘ö0ÛË183;+³7É\|²'fwTü%˜¤Â$úøiþâ¦6ײ¥Í¤êkƒhB ¬uú›;ŸLRÍ$=c³!²PŸ<•µo¯ùçê·W&Ò ÂÈL—J¯‚I*LÒýl,hÉÐÖ^äÃ|=ÅìY´ÀZG0Y['o&©f’kOžE-Ÿ‰õçAî‘™ÙY™È‰ð)­N©Z"˜¤Â$×gB&Ò¢©N§¹ÍµƒÌþ>v|dr|O©üÜC0I5“ôNG´!çdVê �“ Ù‚/˜¤šIBd­"ŸæÚAöª0Dµ%ÚËÂ�óç‚Iª™¤qrNlo?ß§×2kFþ2t¡`Æ$úðj룜škYz{i8u bÍuÝ¥Í)Þ?î¦B0I5“4tCÎ ƒsgy4}•´ƒ]‹7“0& ®úhsí9wÕØâ×glçi!p7ïãýûn“T˜d0q½ÑrNfË´/@âsã¢`’»ñOZ8 ±þh½�»köµGÙÛ&Öîæ}ƒ™6ª–&)1‰i›È;žm솜ÛÓõ»¤º˜U“Ü�º15±öqë w¿ìk·Þštÿ| %˜¤½,8ùùÚó‡&ÒV7g¸Çá¾fmÍÑ t€`’»†å{–»ÇÝ)Yzgy8ÝÃ6ªñþ}7‚I(“BÉÎÇëw¸á!v?sÚ‚IÈ™¤ov0‚}xû=w§ìko™x¾Í¶¼ &ag’Þ7FØñÙßç¹Çá¾6ÿå1�ìLB˜Ä[‚H›Ü0¸ûe¯9ÛbN'iÜS2áýûn“0&ñFWL¤O4eqßq�-úƒH3lQ')õn ËG²Ño¯¸{§Æ^äÃ&Ò‚˜ìpãýãn*“Tz7�µˆÀ2¿‘Òƒ¬¤w¢Ë‡“0&¹òä ¹1ëçî�j³¶fÉ]Ÿm%ˆ“´�1&醉0ÖsYsq�±�ó&RC!Á$�«AÈÌ}ÂÝG{º~b²ï.`·ÝD°`’je´ÈùwŸr�ÉŠMäM¤Ö:Bt.L0ÉϹ›Wdî&–jöÆÅƒŒ^¦H�,yöÝÁ{¾!˜¤šInMGL¬E�Ž cãÀ&aËÇfÕ“üœŽß9:Ä W¬žÀîÓ+Yãqi¬-W”&©f’«Ož²Aõ© È=2銒[&ÒÆ“=CViå…`’ “x<'·’øÕ-ÞûIØf*�ámº6M0I5“t�½!³r6€˜ÿ~’÷t‚: zmš`’v¦õsôm®]4éø§Ùf-› “ÔìL3/Ìt‘�iëËZ[_å)˜„Ù¾÷±:˜"7 +Ê“ìË$¤ ¬ù(ók+›ÓÍñÔÂ×'l1&ü¨ÀD;v~«!˜ä &L�¾ •]¡•ØœlNp&Š“¤“hƒÛyußÝ}‚Iöe’ .ô/]ôÏú¡­�§›±®Š4×Ò— �ù5Úo“ü^&9ˆI.\¸puS¦}m$u¹ }r•[æJé’+]-Lr“øgý+�¬#Ü„«Æ_1‘r£�ﮆ`’C˜„õLK£·!ÜotpV6äôæÉÝÿ´,˜ä &¹pá£H†q{ «4è]À!Giàïóì@0É!LB:¹ãÛD Úà¾@yC0öÜ*^ Á$‡0 ñáé7ôb¾É�ÄZÄQLq )C0ÉáLBú8¤Íç5±>‘ 4.8é†Jz ë°¤[0ÉáLN�ˆ£Ð{"ô�[o᩵­7´íKþGq )C0I}&Á^˜TéɤQ}kkÖD:ÄDøJzñ—`’ÙäÂ… Ñ´g4'™Øû[öV#œõ(ÛÆÚhNŠ¥Úqæ÷ &©Ë$„LVe˜ ¥×]cÁ6ä�ë±êÍ &©Ë$£9éy~€ÕLÞ�Ÿ®§¿N°…º“ù{£¹vïüVC0É‘˜$!Á�²iÓ%]§Ý¨lÈ1rÝuw &©Ë$.\H§\×%w~¦º_æÃ{‘?ßîkñÜÀÓõ»{íÉzÿ£loÅ¢¤–¥»®›h³Ë:ëB0ÉQ˜„”òlÕ°‰~>ætUçËãçÓÝÁK]$¥Åuý%˜ä(Lâº.�ÏUhtë&ö’äÑÞe&ÖÃŽ7ìxɆ¬W[˜ŒpêLJ´×B6˜Î·Ýâu!˜äˆLBšŒH ÙD«FÞ:Á‰÷'òœd)J�\ ^×_dòXæ-ú÷‡ÆÅfñ?×îgë2 ­n)¥+PÉ�c:Üë,ôÓ;µdBþ‰VZéPã)›X¨�.²9"ØÎ©ž‘ôûoîqÂÅæ�üsŒIÔ�}ȳ ÙªAå G Îj2AzùŸìœ%;’N’ýoGfŠ‹™ÜŸ^Ól1ó#özÓÁì Ôe�&£Â¼º‰Í—_Rÿr�™¦Ù‡ì�‘·ß|ÐW—r(ÉÛ!uÀ^ŠÌe]C©‡ ÛÜcìÙ‡ß/ §)‡`ÍD®ë†§×“´hLÚ€-U‡¨3ꌾÝJdùO£mbé�+cYÆ!ä'¹ÿ×{‚vçÀŠß?«ÁÒÛùúøúÔêŸÜŸgƒìµõ÷íÇ€½ï » f‚ñ�©¥¢(S´ ´äáR<Êç“ëãÙÉ•ÿr�¢Ægßã|éËšHHzúÖ=W‹’t6‚ÓïŸíî_ò’j4 Ê[™&>Íá¸?ÛS´…Ô¿Æ‹/ºY"L9B‚†Ó3¼= p ¤xÜ36b+]0èêQßãü9«ì-¤ÿ5§¿V‚„SŠ�˜A,K²X�ç¿àL°à,•D� v`öž£î̯€Œ’úÃ.™ýø»ïÍ/ž<ûð{ÏÈOÑ{iÜ(Ôv'F� ä ¥„l…ôw�«ÌžŠÞ3Õ¢w¹· B‡÷j9ð•Ù¿NþÝ[%zgY§Ö~Y§À¾P GJTËì¯ÝožÌ¾Fô®¯*ýÙ3$zo>¸Èìvg�rÉmŸu ì“Ù+Ñ0˜Ú%³ode¯$z/Ë<ÐQöMê뼟ÇÀA2ûSßQ°KôNñBô.p8�„00˜ÌÞnœÌž‰Þ;£$8ÉÅ�T(®@ìéÌ1Q-³gç“Ó•ÙOT‰ÞDTô^hŸF¼À¯ Zfè”ÜÅS] ñ|ù¿,8Ay"£4C’O¢dŽ0™=fçÉ[¿mÌüZ3®Fô. $»Bë7`QˆÞŽÍ@�«¬²Ç²ããë/Ö~©²W#zï¬]2ÖÅDÆ©€ÊìÓê™ýÜñeöLô^µÖC޲Ï訵@+ \Ùû¨”;³'®ì-f~Ndh)!K Yz(ÙXãý-ÏJ2{Ó®Œ�—eöG-žTF­IâI:Î$÷ÔC"ëøU(G51ÙÉ[^Èæ‹8ÇZ QÙ¹ÇDïL¡„„„©QPõ2û+£™x=™}Eô*¢wCˆÞNZ±é|µÌ¾g¤¾ÌþåÚ_þ*Ñ{ÏxÒµÛPôÞ|”döw2LTvÔŒ›Ý-z'£Ö†½ 4 Lfïyž-Ð8\f¿Wôî�Ø1«g\äÚ̓cU…Iox—̾²0¼4jfrb[ #µ F­Zl�†l(³¢÷Vƒ7lkdú�šÉv^¥~›ß~¼¸SÚôn •\Lh«&!ÞŸW �P–ÙÛŠik´ÈßM�Ï}J&22,цíºntZˆÞ[´ïÅi²c"_hmüzìáõHWh˜Dô~¹wZ5EID€Ó.m³7m_(9â}|Íì .ùÁh.2öa*!®!h`U��LùÑàÄŠÂûó¶)\I*Êò†¢¤˜#4-}íÚæôôÎÊJŶæærHU1¥bºnù|¼?»À9‡ëºÅ©©B �÷ùÈ9€ÔµkÅ—/«ƒóûüüF @ÆçÊBþ ëØëåýÙÛ 6Eq%‰�CpW×—G�ªÝTm›ÓÓ™70%Ëç³}>»£#ÙÓÃûKœO8Šò)u]—½à�Ï÷yllgyyßàü63“ñû+4‚TyGQ­¦®ßºµõæM]7UŒå§„ªòS$Š'¿ŒR® @¦«‹…VúæÍo¯_#8—–>��9,85ÍuÝ|,f‰à/^<$×®Ã'ïßç ƒ½à,Ú, Á)˼¿ây€%ˤù¢ª˜¦“…Xl;‘8™§~O*ù©¦!E!&òS�c"­ëÍ—±ª²F!ɵ?|øÅàÜzó&{ûvéÌ,ËIEYõx"8O –ur–e–�dûú¶Þ½ûE7Õæ§—.!‘Ÿ ,×Nvt¤u�‰CÖûú¶fgO18‹““NOÒu›*O2²\ôx\Á'ÇÒ4ÇëÍtu1)ˆÓÓS|þüÝôó<ÉòSÖܧùiahë:ï к°kríK—¾NL4$8——??x€;:Y¹’TP!‹:",E©hÉ*M´íšh§eßËù©­ë¸|^uDñD`7Xd2#¿n¯—äÚKK ÎíÅÅ ÙÏÁfJKUµDñäP°³œE›hD°|_Xh¨›ªíÛ«W¬xRjä &¨BRÓ¬Áêü|Ó‚“Oz{­’â¡ÎCÁ¨žVoÜØœ™iš›ªíëÓ§Èç �X𖤲W°Ú¼àœ˜p:;%4ÞÏ£¥AÎ�Š‚øõø¯XúêUDp¼Ÿ‡@ Á¢­C@3�"{��LDpÖí%LrÙj™äÚ5,œ%°¥òßçæ8gæÖ-ñš« ›öòg’ë×YÌð~-RÁ£Q±Å—Iz{±`’z(©qx3IæÆ 6ÚÃûy´c’S5ײ½½¶`’z`³ÿäy„¹§ÆYÚïGâL"°•×Üé*ÐŽkë·o3-%ïçÑÒ°é¸a’&6÷a’›7±`�ݰʯ9¾L’íë“§uakÆóe’Ì­[¶¨¸ ì†]îs>“ܹƒéÇàýLÆ$\‹Z¢Ñ&°X–3ŒIv_ÐÖl&g’º`û ¸3‰h´ ì…#ˬ±È—IÈÍT·Ïûy´4Py«÷ò¸`�TÚ›œÖU˜„íæýïç!ÐB(Äã®ë"zM¤ÓÓÓ [Å2r›ç­[ˆ®'µ|>K0É¡ˆKҜdzDG¥XÁ${ëVËü¼Ä™&5˜H2]]¼Ÿ‡@ ÁuÝâÔÔÆÀ™¾¡qB‚³ñ§íD¢04„é €½•Øöz-ñš;ÈÊô`€uݦ×ç‚ÁFÝ[±¼LÒ™Ž›Æ†ëº…¡!Q!8YvTÓë�Ø{‡\5Þ°æ_=Â4ׯšæJRAQ±€ë˜Àº^bçIâ2ŸïÓÈÈöÒÒ)ºisz:}ã[ °ªëÙ@ 85åº.ï¯.Ðê°(Äb¥à¤ ÇB,vºÁùmf&sý:¦™¾­i9UÝ”eW’xõ3 vž,yŸ��RœK—¾>yòënú>?O„¬ô¬èè:»€`UäžGF)Ù 3]]˜òIª»ûT‚s{q1oˆ¦36ÝÝÇ´ß¼¿ñ™GÞçKÓÓ]²¼Ü›ä§'Þ^^þ<6æø|$u¢}"LÉ„÷·8“Ètu¥¼^‡)*ip¦oÞ—É2ïï!p>�4í£¢$$‰¼é4͹xñË£GçÒɵ½^"<Ð4¶}Ôñxx‰6BN’ÒOJUKù©¦eöËO¿ÆãNw·M}—¤¥}ÞŸ]àœ#!Ik²l+ l“âÉõë{@Hp^ºÄÒ™dOòù‘ÎpËO‘¦Y´xR�Ÿn½}Ë4�äo}¾%U�—å¸81 4 YUM©ªk"U]ïïgW‘\»¯¯ÒA&J³ŽŽdOï�Üî°ÈÓâ Kv�×KJ"ìlIËV6óþ˜íö¦+‘­Ÿ¬÷÷c¦£¦ 7¬ëXLxµ \×ÝœšÚ¸wK’ÍøDU]×ý�:ŠÂûÓ ´;ˆ†�OlU-§$}‚ÕCñÿ ܨ‘ endstream endobj 63 0 obj <> stream xœÝ�{pwÇïMI ´„Ð�@ËûÕBd*´€µµÄZg2-ã4cuÀ™êGœ‰èèDÔÊ0Ú1ô1RœZEI­Ói €y– RÊ; ”Wäuw÷÷sî+÷µ�ßÙ=ç·wùüËÞð=ß{w÷w~�s|>QF×l{Xøbï1¬zÿL·5ôpïÊçJUžÛ:ˆÈYÞɹ¶ú~·u„ð—]áŒsÎo–÷r[ %ÍáðnUôv[ŠÏW¼�k<„Æ�?å¶tŠv‡½æœñ ]SPÑT;ÒeA¸äWi áÕMrQLvÅmžD ªŸ‹‚pÉ,¿•žRuŸ[jJÎr–,‡ñKK2܄˂czá]/¿Ç 1¶¤Š úïl7ô 3v£Qx _–.f@Â-I«)”.—þ+ÆáñÚ¥Šéµäšþ7¥½²�TA¸d”}a^犾òÔÌ?j.&øýŸ.•§™Ç�X‡w±Ì/G̘+1aAÛ½™Ì«fBá˜%ALne·µ–0jšd»r*;EÃÓª‹éIÓÅðZ2ï/m†„w§’4™ŸQ¼ßŽ?M©™i{ á�¤{; ­i‰òL2?ÐdPkQ2Ÿ]q,&D ê^A¸d–·Ù O©ê�¯F/MƒñËéŸÌ/øÔ~x7°“ùGwÙý�Ì�Ûä$<�7ÎA“o㉖ä7«Ž(—<“4]0<^û’˜àÄ£ƒo>JGš&óeW1Âë\�2Õ¼àb‚ßÿ…2 =È<ñ VxÉü˜Z1aAÿ~Ç"4 «1Ã;è,™ï+ž¦‹¡U§S2ŸSÙ…cÕƒm‹É€¥ébܬÈBuÌ>þÒóøáµÛNæs§C?š&vïÄ÷:´2o3—Ã×&~&þ �MM§Î¹ÐrñVˆ¶Û¡ØmÚ96›¹£%qÿÇK MM'Cá��…z€uŽ�íö v“ëÔ¿xÝíþ7Mnõ}Ùn¯QÍ.d¤»ï$¸ýªù£øI¹nO1W£4Pίл=Ê´>˜²Æ¡Ù¾zί,Ö=H~Êi�exJML‘š˜Û#-+Dt Ap›óCz ?än¶Ü2¥Œ’è¶åi ¶Ì©Ùa·¹^Yaúó’?µx–h¿‹“C¤&ÎíœS»µK9Xn󎔲Âông�6?Xžp”HMü9÷EæW>ïØì·9oIªD$áœûBó+fí‰ÔÄ»íßkò&Ñ lG«�ûƒ‰=‚dTÌØlÞ±„2‚Djê“L½y¥åB¨zÇ™¦¦Æ† »vn¯ R[SìÓÁ#ÞíIJÂ2Ü{-%¼Ý‘ð6Ö$$RÃÕeÿÀÙÿ}óG=ud¸ `+M) �Ž&>ðÜ~�&¼ývLz=HœŠI~W�qö$y î/ÍkÂÏIÿ�þ:Îè¨Ìvæ5˜x·wNMü·^KPÊ\ÆpZŽÙy ׌×45!æö�»j@•½]{á9/5^,¸n,æ0úÆI¢n·4M¿'<´žx% fú¸ÖrÊ8s�RrÃo¼€FF¸ÖNÍxVª‡¬ò”ævPpÛŸˆ5�1‚ñ:šM ϸÆQ°ÚÉÛ‰ µÏÜFû¥îO| Y ãÕ„¦l·Œ*㧃X6ï2¢ÕÕ:¹Æ+e‰Ø®¡KՒͬ1�!‰ E:“k£>´£ÐV5]4Ãwâ%Zûœñƒ_"Iæƒi:©| uýe´‰$óéÚ—Â @2/§²X2ÏX�ü4ƒ<¡d±çб&çÆbÌŠ´füGÖá}úU‰‚JΙ öÊr%MǢ䴹ßè½²,È1ë§x¢œ¦=âÔÕ¥€Ì1J毛 ] >C ’yÆ·Ñò5cæþÔlW㟹˜¦£2moêã„&MC'™w7MÇE'™·ß΃¤fOéÕªÉ9‰ÍžHÓt1b�ÌÒ° ™sbɹ•Jd Ec{¦ |€’Œ²që9Šö–WjÄð—]‹Û¬°u®Ž‹%%“�;nÿ‘)Ú¯%f7�.÷¦ì‡¬a©›ÁÕséð|Ã`ÀkZê:¬rÙy¯e;d–·ë ÓØ./­E‘QÖª»æ­±Ã³å«™÷™á!…­¥íz*�¹Ç ¨ì’W¥ ×›nv tzpI2Ž‚u:ÏÈÝ][8IÈ®ì¶ÚYâÖó ƒÌò«ðWÈ—Û£”´–ÑØ!g½ä]c�ù)Ç0Œ5JYx�¼‹‰í˜SØ_Ÿ›–ÏØ­Ll½Ê6’«™¡ŠoOSÐkf“3I„WE.g¾°λ~K.›€ðº_#—)RÚEPë–˜b@x�×ÉåX¶Žw{…ÀL/¦AÜ~“\ΈÛ+Éå`ó( <åOärÈé&ìXMĈÛo‘Ë™ qûUr9Ø< Oý3¹œY·‰j‚2 âöÛär@C¤Uär°™O{‡\Ît€ C$lÆAÜ®&—Sq›~ˆ„Í@xl¹œ©9†HØŒ„ÇדËyâ6ý ›‡ nÿ�\Îd€ C$lF@Ü~�\ÎDˆÛôC$l !nÿ“\Îx€ C$l†BÜþ€\ÎXˆÛôC$l†@Ü®%—3 F ›A·7‘Ë ‘C?DÂæ~Hx[Èå<‘C?DÂÔž÷_är†CäБ°Éƒ„·�\Î0ˆú!6÷AÂÛA.§"‡~ˆ„M?Hx»Éå †È¡"a“ ½ w  —öGär°é ¯ž\䥭xï·�/°‡\N¯•ËN¯µ7�ËÁÆ¿¼Kp³”ÂÞ–qì¥ð]‘�rŒíóæ¦ù¡z'.RÃÓŽÈ:<ë�fU{I¹êÝÅÅõ–…=­å²v«\6ýþ»U)®¨ð—¶˜Þ½Š¶JnUÚ\“ óßáõz0Ùú‡Šxøà¤üs¡ÃŒNK(Íwáà‚5:'ÊB‘ÏÝ)rXœ|œ0ôqñH!.Eë tËmÈ�tºZT*´}¡á©ÂÖÞ]%"L¨  UÙ»n• ã¾Eáì Óž²i˳g./u´¦Ï²Ó/z6u´&ëÇg,[/8æÿIEáv endstream endobj 64 0 obj <> stream xœí][k9~ï_¡ç�•uW ŒÁwöa’1̾ÞL`Ùd6ž ìÏ_ºÛIWÅýU�O¥®n‡8$tú¸t+�‹¾s‘v¾l~”QFýM÷þ›‹S�VŸVkŠ‹Ñ(ïJÒ]ŽêéÝêןÔÇÕ§•×ÖÅͳ»O�VV­ÿ¼½WÛOïWg÷^½ÿsuö�?>þòùé¯ÇÏêüüìçë¿ß(£..®n®7Ýt6)kbZ÷ðûêÍêM¿{gŠ^�­›î_'[’êÿûö^½ür7®«‡ÕÙ/ÿýíãùùÙåãç¿~ûÏûÿ}Vçw·wwθ› uq¡Öƒ<» Ê:õðûÊnW̪”­N®dåŠzø°:7Æ„ õðïÕíÏÛI=üK�ã·_fMìb _ !®Œ eó #øþ:Œa'·sÆŸ�Õ9Xã'&`/�4>kuH6O�/zc±Æè¢Ñ7µ†É›gŒñ–�s¤Ù|x{¯¶jv¾ ÊzíÝV@ Y@Ûõ—Y¯ýú'}Y»oâ3+”’º`w¬à<"@xnõaÒ~‚÷·€à2jê@Sx¸pæö=Áö128ª;D@3‡Oày4Ú%ëm¼ŸÐµZÝ‘ ôšÇ —Üþ™ýíSÞiƒ ö›B�ûçÕÉ-Ø,-jmPÝ@Öø\´É©³ªë´‰Þû<"k¾lzѨƒÎ¥”ÐdÐ@Rúbu—} Ê€…äq G<Úlž­˜› ÿ!ÇLy< Iˆÿ �c5;¿"ûðPò`�æè¥Z+(’øW‹G…–ÝÃ>àêö yØŸà@ìÝ ­ jʱ‚²ÿt{™³³ÎìÚlÅv™G; ï{Z·ñM9vß/#Òøµj' 7BD}À¦*6Ãâ¦EÚö ÂvYA} 5˜‡LÖA‘fá45X’Á]»%Éì’`Ú³‹èÑáZá]rM*%¨ßîvW�êÐøL�v"¿$n꾑Ðev·7\’~ç¸)(Kàpš \8ܲ¿)ïp²éáoÚ¦ñf̦qPåC…�llo@ÒV?⤄8nÃWKƒ{š�z¸X´uÁYe]ÐÙ­›E=¶_~ h|Ù�§‚†¸œÖ“)n‚‹k€ÀzÞ!üí3ï@ç#˜ à°‘>ÀqwŽ'HÏ£¥üú� ½ ÔbCË À¦1�lšÔµÐí±Þ´°ðý$c|•ÉÉ0JÏ* ݨ´™WodOò,ĆH¶a,î{Þg ›jçF†[O¸–g!Ö\a¡%8þ@š\|@4æ!4è|ÐÔÛÈð&ó‰P„›yKËÓFž‹ái'D«M育ÁÍ8ì0³Yà°’Ñ)t®›P'gþõ´Z.[¯õ±£{<"ðŠÊ Þ­Š;‡KB#¼ËÄ󇸆Z¤�ŽÆoðG0|�º ºeà¡ zÃxÈwãêØAW·6æaÍÃCwFŸÕd.è3…N¯ôÁ¿AÙZÉæ�v"^+4<óÓuä”Ñ#s…¦x¨Ã}Ð§ï£Æn` C™ùáòÊ!ÖÐt©0Úº°hÛ ýѦæ�6,#Pì>QΓÙ3ãCP(3.ÿq(dÆC»I$þ¡»^fµ3¨ÚÙfÞGveʼàYÜîÀHûŸðjFPç¢PÙn‡�Cv¾D£Ÿ�ÕMÁ8ÄQ<:µ”éâìx¾¢Á>QO ÀCŽQZ³Ôm¹a¼_¬�YQ> #|DÈŽD¤žBÛ}meE¬|LŸL�C#¡²€ÛA(%Ð xI :ž›cwe*_”ˆ1èC„›‰<±ñ)ÂÍ$} %µhûÀ÷aDqœ3Mb%öß¹ ß ¡<*hoðá³·lçÕ"ƒ0]ö,èaLFQ¨ŽÑ‘§‡ÐÜïáÆXJM j;|£"ºTÐÞ@„ Ã��si×d�›BT¬0�ø— 3£ DA2�ñn“ЏІ¾'ÞØ�N�y‰³ Öv¬ ƹ.15P“"ÃÃÀ5QýÐñǶE3D� žç�@è€P¤‹pæ–xÂU¬çOÕbÙtnè¤m˜|Î+3¼ Äá¨ßéTòŠ´$aØŽ?P@ˆÌG c;‹šªH¢Ÿ°±OÑNéÆ-^ë"5ÆgÝb šÏ‚i¸$ÀÞhê”ã½*p­ø¦ÚÅKÌ›‡RH�UW¡¶Ð5UQSoXÑŒ3;´‰Vé˜BVÚ›Òmjë~ûÝÓ{F„G˜4Ñym|Ìî÷ˆð¯®ïr—búJànÁ_£'®ÁB$2ô_>Ý[šÛ‡=5_›dǤKçÔRåÓ$z§ùr¼û½õ¦ã±îD™—ÎÞoA—ðÃÎÏ ¦=#<ˆÍèÍh±<øføL݆ Ñ0±¸¥—„®nÌóVÃdxÀ8¢]µÎK.3l‡µÁPAlR‰ ¨YØŽ0øb0\Qüƒ,•j^l¼`芸Q²�̾F›AfâÎ,Ô ßìƒ}Èç®°úaé;Ûñ!:üf ç1Ѓ2€ ."D¼T$Žwã…ìø¨\áPað�óö�ß m`>7©"�·ae¸%OÔÎZmƒ·¡¿á~œ¨�y¢v]Ô¦˜\&eoе ºÃ6.ϸ§é¦³?§NµLç4€“#kqê6²Ìmî× Ée¥­õy#Ì^|I±NèÔ:Ãf¿ÚŒIÇ4&È\6&\Óó_gL¸3&–çï-qÔR¡7Å®è´þY(ʆOçiÈž¼4iéõbý}A¿Á´¤v ÇIF°|%�rVYM4ÈV°tÑ«¯ Y›®„(äûv¾k¾:N4ã•ì];Ô¤\—ËÚÄÜ%Ùk¨p@È?+bÅ©$†“y Ñdm\r�ì5àj˜´ÈoiÜѬÈüø >T…÷ªÁ'èÕ­ˆA}x¤P,-}2Œ´3'ƒ/´>4C`yçv'Ã%ÊÃòÛ¢e…9ú²¶%²®ø,ïŠÜ<ºSË{£æ­Ÿ#“`”� ûÀÅ|èXq¾ÂÌÀ‘Žñ1ï3 íÐE‰ð.áïñbïtòÐ݆3ÉùsTV—Jâ³ùà«…uh Ç‹ðækVø^EQÙ¢äz,}P~ûTS'ÇÜøYZ´éB"°FLÍ �?ò€ånR\Ú†ÐÊÎ÷5±‘ø@Ÿ×@ØÝ15±8' ¶ÛÏ'z¤à…”z°�¼�¯—ÔäS%q�þ ò9é¢2U3/ ixÓƒh3ÌC£`ç°ŠÓ@Âõû@w«Ÿpe¢�•‰ �zß0ªÐóÚÚƒðàÍÚÎñL.÷ÊEãQñáppuù°¾œP»«‹+"ïé«‘dµÿçU©©ðëˆ`vY�!ÐTEq %¬Ž–62.*Ê-þ}´¬~„GÅ{´DšÍsø`#,D—Å÷VÐ%©§.ÿ8E㢌#?ίbݳ|É{øØÙ†øŸ·Ç‡S-ðÎFÐXhVÀóèBš“ÑÓ€9Êð¸MWl†7DÀ”X�ñ™ìG½˜c ŒL`m¨§ù[¯fQcÇŠÀŒ™7D ÚÈ85üdo‹Šv´°Ìi†Ž"­ëù¢�Kù‰²3hìòxœ�UáLá#_ÛÕnæó*"ƒèáò¾Û–( ?�<ãKÔèä½EXRˆ<9¢ÓòTq—JêeTè2÷ 9xÞ!�ËjJMÓ7_àQÖ˜ç~ÁÛZw<MÑpyÓî$:5Èà™y§‘;Œ¿ç…�]nx×Rö`ö¥î ®vz¡¡ª¬ˆFä!XÈ¢])Ë ?›•4r¿9ñ7qІvòáÒô‘EE/Ó 0 �•u§\<àÍêÍêÓÊ(oŠQ.F£œIºËQ=½[ýú“ú¸ú´òÚº¸!»O�öT 9»÷êýŸŒ¤Ê° �é´q.[e�³ºxïã¨W}·¼�íÂ^Ùü á {Úí�‹*¸þt7_m{sQ=?�K·}`¢+÷¥«õZÿÉ}¤û endstream endobj 66 0 obj <> stream xœí] [ÉÚ½?½ï¥WÀ%f“Äɪ@W³Ä%f›„$n“ÄDGQ¶®®FP131³g&“¤¿¯ª¡ii Aê<çñÉ8ŠE¿Å©ªw«ÿü§_1 ^EóÅTNÑD  @ã�€1ÝÅùÄ88ÀdM SNš† H² äcE·GGÑYx�> €„Z…XyFÁž¤@·HqÞ )p쑥͚oåõŽ�y%ïö):f2LJ5@»õ-J ÕŠ6CPR`ý|ÔÙöÐYwná Cf2רúx顚CÑ~Ômªkg��Ûc¤è؈ÆG/g}M šCÑn`7Î1Sޏò¬¢¹=FŠŽ@*Õ„¹üI@†¼ ¹°êö`)ΰ»&’'§'tÌÙJcH8C ²s¾ÀEu^A㣧6¹°*„U)œó3nœ¢_¬ŽÞÞòs|¬((§L9ëèÑþ‡#A†*Õ-ÇòÞˆ.EªK�7¢_œ-úãÕŸñ3|l‹�[c ·ßEŸA�áÐd*Xµ¶7¢¢�Üó®°ˆ ]œ)X‘SâØ�™Ï6ÿ¼PÝ÷jB$ÏÉš'¤2“tßKqL"á™{ÇÅRXv*žLŸ}ók²N^Nà+õó�'¥£á �ˆt±ëQ˜^»¡©,N3®5ýÔÆb²ømöͯ>ˤhÌdn8¼kæ±»ýv)zœÙéM&‘°e\ àËŸÞé_Z˜r[»Æó­¿.ÍlG-óØE3ÇzÄk—V«¦W°é×Z5½Å·ú—àËŸìQŒ‹ DçÀ€Ã�"Î.†œ-ÇxâÑþJî‡S®~±®ž€�t±ëðah&Õ¯²¼v?86½�K™÷ŽäŽÊšÖ„u/�ôÈi休ªÚŒÍžlüÑÆ)·F"öí^ìäQ¦™<®�‰#OTãȇ«¦oèµk‰“g§ºç !bib0ŒÁ^>ôÜ,0 IÖ8< |=¶rXïn —³ÿ\{d[ìd�—5 ÐÝ~ƒ…²éoï1q$Tv¶þ¨>ýê—™ÞâFáÛô«_|V¢…‚;ÜM¶ ƒî{Ï3øb'Æ­>E›|þþrz~of±³-v óUŒe¥é´ÛOe ÀÉ:{½�é�»nšç*ú2ùü}e@QÑ Ãˆ/HazÔ:‡�¢9QQò¶<Òë�ö–³í<¿7³Øym‹�4�æn=—†.v�R¹0äp¦Ÿn7½s¯]k\Êüx°[‰/hR‰2N óÒÂófvÏËs$E«íFîí<\ÿÝ•)÷‘ˆ†­˜‚a n¢$*´B°ÍðÝ)IS;B±¡jÁÔè´k¦·óáúïö-ù¦�ö„é-nì|‹­V ¸dÈÜDl� ÷+¤Œ¯” ðï(n?=x£Õæ±»È'ŒNW�<"€\ÒÅÎ!„0Œ/Õš¾;^»ø~¾ýôÀ^,Ì�W4.B•§o …vD\8£I¶8ø•ùÝ…Ô'×'X=7 ;.ˆ=œn?Èþ Ðy ¶8øÕ» é¿]7ôÉ|±ýéò\ѪÕâ"ÄÝ�¾=q÷4̼¬J¡›ë&?ÿö·ÖòØ»ÆUí_[D ŽÙ%L Såi ¸`J΋²Î‚‚Ýô½àºi’É"vòØ‹…}1Ü € ÷,ŽkAðãÎW×§S“|™útå~±ªlO†ž¿Î„J×ý,ö |šÀ>´#�C»Ñ‚ ×xB¯oâJÕËQ"Èý;åð»#¡:ì¦#ï Ž+µrÐ2}âŒ�CÏk:cx€~ãÉ®a6)Ö‰ÏÏ·�ÙÀ¹¸€„¼É�Qœ\qÚËiZiAëF ‚dƒ^ßfsŒ°.*º�)Ñ\|›½ß» è•eº|5<ùŠH}®f™þ¬=cÏ7ëœ<¶ù€�~æul"À ´Û&íu�[ÌÌ  «ŽÓò¿+IÅåî]lAЃ¬éõ-–KŠ�õUTiò¼æ¶IÏs™nt›²zÆv³ûD/³¾Xø(¡éˆpÛ¤½¼�ÆêmÓœrf”Õ‚  �CÏk#uOŒÈ3¥õQ— \_sï¸{á}Q}¥‹�Gú…‹©Oµ–#*M5çð$¥á”�ö`­oòØ»Æ5ýËè½|cÙQ°à°W>¸mÕfñÿòÈ0Æq ·¤ ןvò5ü×~µèÑ� þ¾ÛVíuد±«[æÐ‹íAôžÊ‘ã4hR4Ç]?pÛªÍïsní÷^¼ª9 ø~®JÔouhçíÓ`¦Y§9ýž]Ü!ŽÜÛi<åd$Låû«ß»HªLÜqÝg¢zcÇÍgž9yª9N@5§RÍÙNâ\;QLý¸çº9ÎÄÔf §(K^')‹Tsœ€jN ¤š£Þ8ô™wÝ-0™Çƒ¿«´ü Tsœ€jN pÍI­"÷µ«5D—¹ ÿÔüÃØõ¶ö Tsœ€jN <š€‡Ã x6Í)|…W¯ãøø“W®¢efÿ€�QW®m¿¶ðë–æp!Í3…˜›}< º NÖy€¨æœ•¦æ âeMkB¨ÿ¦“HŒNk’MÍŽë÷ßþ¶yZîJæû×8ôsiÜõ.ëŽXø/ˆr¾>Ó/¾�ÿÞø¾$*åÍ!¯`Á‰¼<0 Ãm“öDyYãdÝ|z’‚ä…ïP?O¤Îs£ðMY:”"ˆ<4ò5„Ä0’B;nÛólðÌ­1‰„X9X™ôFôË÷‹;ÇÊÎ6údÖ�§^«®ÛÂ!Ó¯r冥ðÏ&å-úâ�é’R}b"ÞîBÃ0¶>ºmÒ^‡͉Š*XþàT¦œ7ª/gÿq}>ô,¯=ÚóFªOLP ¨hRhGën›ôl`§“vÓ[”"(¼ðóqo?y€�$·B®¢-ÌÝ‘qÜ<ú°ÉŸŸx´/E<4QAñ•·MÚë•‘�Ú§'(Ú…é�dÑýùЃ¼ÿö7_£)Ǔݎ0•wÛªg€iëú÷‚—ž(jøöSÉe–¶·~rÝmajûgM”pÏÒ�ýSx=ÿUl¤Òæ)[Ô™| D  ²Ú@sðn-¦]hïÖû¼|¿ØxÊÉš0•ƒý´Õ¾Âõ|ÏjîÆÞÜûÞuC´‘ÙéïñÎí»»§þä+õsÃMŽy¢šs*°àØðú¢ú£µß]Ÿ =Èáx¾ñ”S�ÖEݶê@¤²ñ­~£›^NáøøÈWÚ�vŽÛè“6rÇÍ—S'ÿ$Þç³3¨æ4¼Ìɰá‰^TгͲW-¹k<ßúköͯñWçV]Î8ªRéw^š;fŸ£@i:-ET·­z•Wt¼CkôŽÆçwí¶®TGfk®[¡íÌ$Ö°3yìò •ª/¶?]9f—Ë+X¥ãËÔŸs ùãE{ä^þáúï?î|�ý^›�|1{ýþìõûÓ¡¥{ÏwŸlôe˜C®¢/“$%ãX*ª4�vÛªg€Ã:â£�5ý'Þ QÑ&Ÿ¿7ã˜Ù‹íêÑ‹,~ƒÇ7/]Õþ­š¾^¢É³"q«C·MÚëàm*±‡·:JÝV§¢ESS?ÌfgÇgÊ ÌÎ^»?ýý� ÀÖFáÛô«_|ýÁá‚î³­5ˆÝP2mFgAÁw§d»|}îy¡Ç[�:gµy©í²ã�·ØÊaÕ‡#Cæ&QÖËÏGÑ$€?G ÉCšŸÓ ÌeéŒyVe,Ú¢¢]šúqÆ.8'<|çÂ%ÔÝáJ!5ƒn*š/ŠFžäçm¾¿0½ci Å!*ɶƉ²Ž'aqÁ>Ó¼Õ™Ê !�‹¦˜D‚9$Y  ¡‚ÚCHªù6Ÿ_Ä®ã�[­W'õËÍKåó?Ÿlü1j3½ ‚B A]’Í3)4½Çõä4 ¼!LÆ—DYõ3¾;%1¬Ç—âË/¢ 6œñ™Ùk÷ç¾o±J¥ÇùXŸ•³c·Ön_ÿ!r}%rëÝ�©ÔEßô¦9åx9…Þ«;$Ý'ç‡AÁmc¶&‘ð̽ýßôš¤�4¿)5>ñl:ð`þj BNôŽ7'í¯œß-îvöWs;·ºÇìÙÜ›*‘Ø_1‚œIóNÉüNZ‚’÷8Íyø`ËõÒv®2ÁÔx`q:°8Sát`qúÎÆ5†1ü‘�A›r‡�Á0Ïk‚°|áVe¹GÁ—?½ÓÏi²úÌ ¬9#+¤Ë07Q•~Šô) ¹ú0q9T¯93�ÙÄ÷i÷§G»9§�À’]p0Çg¯¯ÄoÃÑKóÏܶIW‘–¤"Ç™Ó BÉçñJe–?¦Ï¾ù5yŽüɦ×nH�IŽ›Ï_�KÓ髞ˇ C5Ýäy•ã²’þj|v|Úœ¹ñéÇW?ÈN>¿v¾»©ƒõšƒ¹4}}%x­¸m“®"'ŠiIÒ*š“œšÝXdÓ—Uö©^œ-Ÿù°{ahh5è–HòÖÞRt–ݳI�æb74•k±ó÷öb÷Jý|ãIÉV)CüŠ*Fr ÉŸH2¤*(HŠf/=}zm%vwóša�So»nw°Æ² †±¶¸P’tŽ;ùW°à˜µr5s鯓Òkø¯ëæ>Éôx¯nv—­í@¢ú|9žG$I‡Î�­‘‘N>õ�†.I¨âÃ)ûÐNÛXƒ‚è’Œ «yËÉ3WxžüËõifçúÎWeùƒh~:°#‘´Û,¯”8R2óáî}åc©› P©°Ÿ–‚wJ¾®XÀM†‡S‚€Èñ|nlLõû›ü]QÖ¼2® äòq[Š eùÃ�=°ï]ÏcÓKV��iz9ËËÇ&\e<ždE{ϧýþLÓ�‚âL@¢¨W"¤š(BQlò¥°Ž'iƒ/Ø»7=°Ø%‹ÆÃõ߇l®_LåAÎ#g¬´[ cx®þäŸÜONÈZYDï”|Á‚ÔþÇÝcнÞÂðpÕú^onl¬ù_Ç«�œ—dwM´ Ï¿ýÍ­}¯éµ³›ž9Nnlz;’ “eY­²ÕÉøýªtþ'@÷a=aSÛ±K§iÍ1�ÛàËY$­ˆ†d:y5€ê_l²m‰ŠaüUŠ@_ì”ÌÒK‡Æ`Ì€ d]ˆj¬³ÜÓÈ‘€Ð²9«õMH¡1¬ã¾ôájˆáêƒÝîw�{±ý×åª×‘ÔbȼÜ4óFœ(NF»„�X2P¹hÕ¯8wa±;Ò‚€tfdÜ2Hl®œ1˜‰‹;F“ˆjlD;ųÑ×PqQU9p âì,G1b! ãKø*{ûÓÛOVµnì{_ÃÏ·ŸÔ÷I8kõJËÛ~ŠfÐÞ,Õy‘“‰j™þêüîBª‹ÝÆNƒ\ËΙޅ¢’ò¾j—^ÖÎç¬ÓH"йâ@WOsŸ ³¥ÌÝ%fvÏêŒá�¢ØÊáF¡Sy¤eÓW]7pl>ç�Aጦ7Ñ‚{“¢ItÈQ�k“—Kõ‹Ý›N.v5-¸¨Î†4ϤÖÚ­gŠ*Fs’åL¾~À1Fã(^ÿ1Œfmqy¾Èózû>YÌìž'–gĆª«ÏèôÎÃõ67¿5½vöæ±\P“è�«cóM¦?œ¦Ã¸gBçŽ.våÕÇÛ™ˆÆRúïÀƒ]›·_È+ˆ‹¶Þ�Ždµ f æò¡§-O¦w ±,–3\%i–-¶;ù– ©\˜ä‘ÚÄ]{¸·Ò¦[�3�ÛL/…‘Æ]Ôœ75j�®æ9o ûèBâ%Yìv¸’¢9[D£m‹ÝÑÆ¡øÂ)Ã0bËâ8êØqÃ0âñî˜X·øUûì'Ïbºõ¾îf ¯•«@$ï& [më Ã2ªnuHÊêù™r:ÇX¶ü�’¤$Ç%:yv`ƒ½|è¹½ÇÄQµ3FKŵ=ce8 ¡Ä~MoÂ^~h9vÚøúƒ†Ã…….ÒJwÈ7ÛŸ:\ìžmþya¦êºB§^€ôÉ©-À~% ©ÎÁ )Ûû'\�ns♥UZW²P˜8òD5>½‘ê“›)4ßÞÿÉÆ5=cE€¼¤Ol'ŒÇ:‡äÃÒ‰?tîQÞ…¬³*ìV4ÐtòŸ–콾͈F“‹ÝRæŸk÷¬(¯�Û ÂXv:4fÙ‹ŠpS‡ý¡®Á`˜–Õ+%ÝãAŽcUg‚7E³öĦé�÷-'ÏJö°ôáæ÷ÊÒ‡¥Ì?ÓÿxXí>Á˪Ù3–�v¶)±©3Ö'¥Äqu&Ÿö¼SÈó»Ý=¨ú©#½¾k»wú—é׿Üzz0ùüýÓÊ}[kú—úc Ä· m¸¨èH’µ èý-;öÖ£‰ÎènxG²÷6™DÂnÓàËŸ"K¼ ’3³”Ü¢¾øsðåOö[íðIíz‰—»Ñ8Š"²¯ †ùH�Ég„ZñZÏðЕ)Ê ®íÊsýÑþƒµß¼Qä�X¡.}âñ>¿ÛZ0“¹áð®Ù‚  CU S}–àL¦‡«ýZn\n=j&ä�Ö£÷rûIøwBî.uËôž»]nºãñìY9l‚°ëñäèVç,€§ZÎCž/±¬‹{E¨ìô‘Å®žö˵½áV=!•™l=õâ¬À‚“ã­"¬ÀjàÎV¿–g�¶-ƒ%ŸËE¬f±ð­'»¤H¡ñµà@ {ä\—Mob�aJwïZ+uŽa Ýê4 ÕÌ;µùÄ4·û¡YìHŸ�† %·~Ȫ7Üí)‡�ÉH2•Ìd>˜õäíþ0"ozAëZ�ö*w®§9’ÿ�Øskxö˜ .Ââ8èí¿ Ð} SbYµ¢9=ûÃ÷ÓáùvÜ”ƒ¸E‡]7' N–U`¥iòöc5„=·V“¤ƒ£­GÝ…aS‰ý“4çeºv38Î-‰Åªqs¯Òzó&ð‘£z6lj'—Î{Â’vóž),8˜fJN­j¯(v3€¶°¯Ù*§;ññæAòÕkލ îæž»—¿˜qsh õ¢^úøô r ³ëñ Îå<Ðøã–¹Étùn;Eã#¨2@UX.õÐ>ádœ©õ¨[ÂH!áÈ}©–CGÜ ¾‰I«‹`‡v¥.ß´YóÃyž×­«9ÍOGïyrú eÁ1÷�—²™Ñ�¿Év¼“­a¤R†aÀJ[s<Ãü�º¾:›­GË99¢˜ãy•N9g¸òÑs»ÈÉ�;š³FRª à ßñ»­�8WGù*m’G@®öÕj�‹x>oÏŽ ¡ÇPÍ> ¶L§j¶Ëj�w”™ÉBÈv˳µ¦ô‚Û¤¦õh†4twHýŽrô Öû¹E‘!)^ìoZ‡»Ý“Ÿ–¤œ$©Vg${GqI¢šã�œìV³ív`Ý÷ÛÎâÍ›Çþ_Q<ˆÇ»ü@ Ãø¸°p@zPr¶¬ zGX[@Òˆxù˜äµN Ž|¤»�ì IJK"}‘m*†‡ó=–�Ó§€Ä;Š}ä!Ézê´æhvËÖ�¡ëþºò¾Ë¶ñ3ÿ¡‹bÖï§éÎaºMޝs—bÉçƒõS‘´;¦šÓÔïpzй±±njŽÊó»““�eP÷FG º6˜ó Y«)<=êÕ96y¿m$%Ç @Ã{ûÆK°(îOM¹î`<8a§�êœ<â JR75qcE€ãã]ÌyŽMŽ\ÐÝУ†‘Ø›ê æàÈ8©©?aáûTOš¨†aü¾´äöóë{œ¤äS¶72ÒiÍA�>ã–C©›O'8„*Ï—z81£_0÷ŽM$ëŠÃHãòAÇsŸdÈ…T¶Ü.µ*8".) Ÿ0QK>ß§tº£c˜{‰zµÑÌÊÙ‹;}šÐaG’|Òy^%.ýë5ÐŽÙWW•�­#‘`f6ÿG Þo”K>…Êí{Ýh˜RYYãqÇT|=)éñI²tð¥.Hl¸š’îsÚÕïÏ��Y‰OˆD ‘$iä"æNÿõIB¤ò Uþzù.ŽÓHw¬NÀíhƒ”#›1²;èîxÎ+∉hâÛgpõ¡Z>é(¨KÉ–¤c*ÖœôÊ:BB˜hNò Ò6*ù$EêÏipýÈÐж(&F÷xrf~ (¢nyé5�F$4 ‰bÑ,4àùî—ÑA"³ çi+×¶¢*8ª;}-"ÐkшUä1 –›ò "8iIÊÒ䜶_ ößÿnz<�e]I{ñHAØ!_Û~b“0Y RŽ:ºÝmCJÑ@QÌ��™É9¨¢9%ŸÏÌÛq{t稢0¨r΂VUHo—YQ´ÿ"?A0 endstream endobj 67 0 obj <> stream xœí�{tÕÇwC/IÂû!øà-U €òP¢´µ–¨ŠV9¾´¥ÆC ´ÇöÓàlzNЋ§)X�ÈËðP‚!á•D ’”„@²;û˜ÝýõÌÎ,ÉæîÌÜ;÷ÎL칟ÿ’Ì�ýÞofgîýýæÞŸÃAGßu��ê¥�(ÏÒ�èôëê@ãÚîvËÀ ¥Îîmvë`Çv7WRíÖ¡ÏfH ìŠîp‡|[í¢KOdÊíVŠ2¥Câmv+Ñc”G‘Zo·VÔ)ÆØ­D�ä "õ¼ÝJXQ©t(Ø×n%:L,…%÷Ø-†©y‘‹ ¾™g·-Ü þ‚Þv ¢%!ëF›Áþqv R#1ë&DÓ˜o·(*f}Ù®CbA»5Å$ý< œ}ÔnYƹ3F‡®¯H´[ÂèÝ1„Jßi·4c$牱;Tù˜ÝÒ¢IÉ ¨XàËëi·¿ß6­X . ‘uèJfœ-B‡:¡Âþ¶hÅ¢k¶@Þ£cS­Ú-Ûƒ¡ Å•ÝÅz±88ç]4Ô¡PÑíV ½dH(tØpà÷î�ÛÒËiÒÃB%öÏB­X Œ Às)Ã*¡ƒHŸHÁ•‡HÌj¦ì¼× ¡I+¨…v°p`Ì,)ÁÂ~æ ý–�P‰ÊŸ˜®‹û>aÔ¡¦�M:á#¡%cMÕŠEªF–˜¯MEôf)´#„Û¥é1+G�€¤é±7ˆ€%E4%G�~޹P‰™ ‹‘™Ò!†9ê~¯æ.êpŒÚeŠP�Ã�Χ>رʢéabFNÎt‡#9×gV‡¤õ„¿íYO›³XæÀã]®–»d‚/¿Ô àó¾ÌÈ]M¦_k ŠÂ¶çI°Ä¯ñ (l¥úÌ‘£K´s)=äó{'³³X�-áÏ¢šÅb#¼A#µÊ� Á-ìL©µûûI]ÊÈ\=â^´¨C»éÃ%¯Y$u!g1oQ‡6ÒKåÞ„{�½GàÞ£pï ½GáÞ#pïQ¸÷áÞ£pï¸÷(Ü{ƒpïQ¸÷Ü{î½A¸÷(Ü{î= ÷Þ Ü{î=÷…{oî= ÷�‘÷#t—²pïy¿Xw) ÷�•÷º;ÛpïØyP4Tãî=KïAøc7Õ#¸÷L½×ÚÙ†{�ÀØ{€ã*osï˜{¯¶³ ÷�½÷*;ÛpïT¼Ÿ±‰ŒãÑg½0—{¯�Š÷”§½Ž¬[çÞ#¨x?ìgd¬‹:i`-º½÷ÁŒûý�X›ƒqïØ{¯²‹÷�µ÷ª›ArïØz*¢v÷�©÷ŸMR?‚{�ÀÐûËóµ6½æÞ#0ó^x£«æÜ{VÞëîJϽG`ä½þ•Ü{þž ÷Þ Ü{î=÷…{oî= ÷áÿÎû÷i…vú…FME¦+­©’V†!†Át¥ìâ÷¹-R ²¢ôØR�e{~ŠMi”>kå–†îÅì,Vc°•;~ú>¦‘zÖB¥§Ùy¬FŽ¥»­hö&m²R)Ô34Y…�–vHM!»¦%Ž14Y…w¬ÜèDšÝVW[¸/,¸-¨Ð5Ã@ÉBÃø¶ÓHíq^2ßßbî@óJƒäˆ»ÈŠqÎúðÀÍgîƒÌ])uH¸HWò*y�W·ê†WËØ˜Ðì.I«ë„³‹˜ù«…3³V U<èÌÐ.±NC¨h¨cQ¥P»:‰Vl|Ÿp¶»õkxjqL‡£wx]DžYw~3j³/1C¨å_eÌÚçù[ª Ç}Ŭoûv•=–XægÜ…€ ßã硦ãÂD;í+÷ípÜcR�%ßÓÌ¥ö¸ ÏH¹v2yêm-©ê„ü0þæ0Wº ŽÈCÀY_2‘xâAç!XÉ\&>ià» Þ#S#Š™tH� J„®ÞÇZé]Þ`ä5;Ë¿Ç}#XëĦÓ)xÍ‘$?nÔ5ôŒú*üñýµ;k©;àÝÖh �Fêwþ¨&~T¼ Õ­¯¯%dRŽö¥r°é%Ò´mì•>ÍÚþ<þS¡c”³ô½�²VŠIò5ˆZ‰•Bs9UÍ–Náœú»œ#p’õä<¾–µûUúƒB+k=Érø*�±TLþÚýfôƒjºUþ;.µ-<ÅXiœCÞµ3V·<ºNyb¼ÂX*£ý´¸»¡ºåíÊÞÿ.«ï&`„”H�ñë�¤Ór± Oô)‡ëfÔÚÕe7¬�ñÛDòêÈÚý ãŽÃëL•¾ %±ÿ0é3"¡ûÇ!gˆm‚Ù¨þË�]N1VtM Z›˜�2VÕÊp;çUc ý&V%õ˜_~³ÑºÕMį6{E×&ú—CÚð1¼¥þÇ®ÙxéWv췳чžùh>â�ó.bu(T8 fûÁ.ÐÞ;‰„ŸBcªÖ߇ê¿u,TK#´ìY€ÞжëŠ}ë�©Žã³á«a— ð’Î!3Oé=z¿zã¨IŽ%èOéë]N5êÃø¤‹ð#¥¿‡/tËnÇeh%Õ/kU&÷V‚ʘü� ¹šqƒgX µÀ0ë•«–Ttgë¤ÎÒÀmeê 3„ç̨U³¾Xï]¿Oa5©`3Þ�Ãc&CšÛÆÉl�ÒëÄf>îU©’£.Ÿ¡Ûr|À7’�ÒB½u{·˜U�-›†ÑîvwÈ„§ IÕðî±1rÔ×ôvß ³ŠéT:äDaþÑñíÂ�W1S‚‚rËr‡9DŸõðé¨ùózb5ë{~l\¢ÂsPCžHÉo õa u8ºVóÆô3ÄÒ¿g´!>³MŽºø.Üf¿�³´AÂWaa“q‘7—]Ø÷*‡c!ÔáþŸ()‚ „-RŽE]óñ%V«¤ÒÚ‘IâãŒÄÁC‰GG•ŸIµbZH SíW:ÔüA£Ùp³?éEq§78™¸Q$Ä ¹…Oú†9qeðâF‘tnó�HZí‚wˆ?©-Û`=y£Ýò_QˆÇ0wx>.ÜMÔªßM º¬ ѳbÅRuèt2ü‰;“¬Ù8l<}–i7£ÖÕÜRŸFØê·¤ß‚R#vô+õ67 /65ö�Vx%F¢‹„‡Î$ö1± ~eèÓð1~»0�|õŽ¡œLJ3•¡ì�óUçVa]_Îù‡Î—."œ φ¦>‡±#?ü˜8›¢¤s³ $ä+?ŽE4»j*k$©žzŒl§óCièáþˆèÌ`ºCÆ9çݪèby(%<)ÿ¸òLWÅDyb Õ?ôEYªû—$çg0Í'ãßJÚ=0w–‘—,+=^ox ã»Â’õÊ„X\2O�Ejæ©�OíEá-"ô’y1ðw /Ô‚ëšIZö|B.0ÇaùáïI�] ‹}ŠÈà‘öE2”7VÊË ½æ´4lRJŠôˆÄJ=xgž¦„9jqBïìX¨DkôK{å50žD‚¦n+–\¶òC7¶Cåå þ-xg~W¹ñºq9숯?l½)×!.é 4¦ÜÚ¾‚í‹…º”Hß·�CêÀFÉ|_“ê–ÇÑlUúsÓø<Ó½þ%º|3q_ékö—�pD^ j±öºwt^íñ´Þ&i¥ß΀+°7Ø´F¹G¹§Ð $綉ØQ­áiR>Kþò{ò1Z°%þìÉOê½øC�‘ò@;TmߢF\º”‡WØWÚ¹�-oJò¹4öï0tξ¬]nñÝÞTæž[Þ£ÛAËþbÈ`Š endstream endobj 68 0 obj <> stream xœí�‰SÉÇ÷OŸ2™™ž™ ÈEPäÈtB"‚ˆ¢†…¨�9zB� {°÷þöp�_õL2!ºK:ß§^Qþ¬_Õ¶óšo¿~ýúõW_‰Éó¦ DQS]33E‘õè€2®q8ÏÏìIª%b‚°!`ƒþa”pcäëÑõ`Ûöq:mò¼'ž’¸ &@³™ÒCTL Q5Eì7GLX�¨‡“åeÛ¶]Å0ÏE"¬Ç�„NÒ äc¡†’&¬\ HÂá³âʈ% $@s™×bÓ†tFCʦš0ß:š$‘¤šJâë1�b^‹Ík±O) 6ëõ@Á …L„jjˆ��J4•JL‚j+‰JÒ‘çàÆ¨�8òJ4— á’&�M!Y+ I°»é<Üó_Ó ‡s¬ÇØâ[ññœì—ZÔª )­ã¯÷†“o9œszDÖºÀLÛ6SI¨Œð¼ÿN =ð•¤\Çk=Ÿê»áN9çÂjžõ›¶ñxq(¾÷÷P !¡ó¬‡ÖBi]šÖ>åVÁY&X�±ùèŠB�z�˜Ä½—WŒF о½Ñzº?iµ· ”°Ä„ÉzŒM†–»ÿ:BVþ¡XÝËz¬‡ÖÂS:Ÿ2¹Ù£O¹Õ“¶X¶ih‚ #¤+ ©ÈÈ¡ $ däPÆJÒÄ�˜¨±µñz F&�PÂ’ÁOF*[:”2$ZЦw|\vè OéŸ 5 aKH(„¤:•AÐ|Åð‡‚p ‡Ð‹µÅpœî?®•”±’¨ŸÜPÓÕÚ ùÕtož°x£T£‘J¿‘„ФŒÎNÇÙ¶½úúdòaÙ¡åÌê4‘RÔæ8Uº€¡¤Ù•.ÈÞ£é}"§HÏL¡ª*S„WµÞëÜl5ñ�c¨ÖCk1adÖK¶m‹¾ØøÒ7/ÈûmëýȃJ”¤2‚×¾Û)~xNÞO®|ëÿ?Ó•e¸„’:ëʹ!GÂá‚sFS.‘e]’ö#ÖC 2Ò´†’:µJš·¶÷Çîá‡äú‰œ¢SNL’k÷KÏÉû�⇙'?ú–0š€½™-®¾>é¸V0œÍ]ýµÇ—qªX1a=´ú ã"�-§ü¥UÞ}·º÷Çëw¶gT=¬÷¹Ãþ¿ÜØÿcèî‘—6AÉJª¨s’±Þ}^/±xž8bÂzh�…›= ¥øñ§ô»o,¼üÅ?»r‡tÊí?šr[äýøÒ7ÕޤiÛ6-ˆíœ|�mÛ ¿¤8›ór�ªSß¹U¬Q\”ÕR­0.úZ8åеÅ�_{fü›YZÞñöËÉ�ï_üóß§ÜúÞñ»ï|ÉË™x¦ŒÛ}ÊÙ¶}ðëÛ¶iBȾÓGQíØ&�jJ*‰â¢çPéüõG,éÍ“j:E5¸QróÁQ;Gžî+TL*é*#@ùYk±žÙ8½ƒ¾ñðø™ùwSîõ;{áå/ÑL5y"c"L™í¼„92òÖ¶m/ÅêÙ¸3£>A÷2‚j"ß ïÈbé™Q§C={NþöEž¦yfÖ�QûÕ”¥€�ákã\ ‡ ‚2Ò øiKHº¿<ÕÁÁùw«oÿ×à”Û9¨±„ñ“tî±þGŸÆ¶í¢�x›‹ÇDHv`Û"!}(¤ ¶ø„åsèáJÃõÛò›ÿ Ü9¬êIÂã'ÛŹ%E9”¤’¢œz|³³ZРU©xŸÇ:?]�rÝ™ÂüóŸs‡M›r[æé%L¤çÅŸj—)çmj’•Û'IƒÇ&¯Z¶�ŽÇ·zn¼V&5!}èÅ–‘LaöÙOMt¨g¹ÃÓ‘'?I¯êD2Flžñ%¬#Ž;tº‹TS¬¡q²¬l<�jòjžÃ¹ÊErzž«®}÷²PÏú¿,aýs‡Õd]ŠþºJ)CI³?OÌ�¬:шP �WêX�ë|ˆªÑ5þ6ßòŠZéPÏ^üC#Og+ˆœ':bóšœ6Dv‘çÇ/]:òŸÔ„B$¶BÐÑ®™H ©ô1§¦ï ÿËÖå[”´.`-¤²¼ú‡‰�=šP+M�;5TLX�§„qz^¥YÅ¡µÔ¡~{jüuãáqµ¦ˆÖ(‚jð‰‹^)<ñÒ#Q$<2ÒDè� ¶$•H¾tß\q)÷û…M¹—ÿ$7¾—¼;Å*ápŽÇy&Å I÷ŽZ%ÅJŵ£îÔˆ1AŸæh2ª,#}³Åì:ÔoKo~ï÷%Oø„.&t)¡E&÷/惣ÑQ<â8ïÙMM–M§]ÀÅ ð¸;讉<=ôvÐi«E;èµ'ú_#‹%qýEHê(uqûk÷Œ:YíÌÑI¾\6š{Á§ßR19íÐàÁOYîðÃüóŸ#¾È32¹/¤_‡ç¶¹l¶¥ßD‹ÅÌ®®b4ê5Q´$‰¾SågMÂÛAûÒždråÛmë=Ã)G—°×¿_žóåÿSÚ…OžzÙ\Ë~˜}öSdºzS a£Åñ·ªØIu# ïÀ×ÙÝ$ID#rŠ61£›“>‡Þûz³mê·'ú_׿öI6íÕ‰T]N49òô8ûeÄ„\Ík.CBÓ&Ÿ4ß=‹¾Ùâ£ÜoÌ'ØYs—0ïwa‚±Ý§#µùK˜s:SUV7QÛ¾üŒÃ¹�º'`MNU»]\Üù•¹û>o�vë½]-Ô—š�ÐCSMë"~VF4gw2Ò n€Ð�#.CÄÊÊ™¶fžü¸Ëtý¯öDûkØ·„Ñ&Lh¥iªÐ¬�£Òdˆ¯e©sdÓæÑHÙ¡£E§çjÙ¡JÊJož´¹C=s#OÅyrãZ4ñnŸ4ynÅã9EñˈÎó´ jkŸ¶?b’„Ïô_ú†yJä¿›³„UoŠÑÇíšÔf»[½jùYt?Rµú‚tŒC=Û¶ÞÓÈÓ—Ÿ¢‘'.Õ�³1>ڊǽ_ËiͪÃÕ¼ �ôœ¬ˆèkÚ|õÞÑf¾wП·Ý3KXãmvÜ*lT|iª¤�û�¸�Ĥ!¤>rèF:Ôoëû^Y8òÎì�ÓN¼ŽîXN ™ãòkàé¢h Ü𭛚�ôzfN÷è8«ÝfçjIPÏ]ìäÜ+ª¹·³]|�Æ…mìÐÑv:òílgÛì ­Ï&t%¡)ª!9?Q9¹êó–'&©ñL•ß¡­nìÐ)æõ(P‡óRµ[‘—_ÝŒÝØ‰ôAۢϣ`Ë •�&Û£þ¬O½Øò";tŠ-½ù}OŽž’GIÐzÏõgÝWYû³Ý‘±…’&ª5åDlÞzò㸃þ¼=5þÛÃ^·"ŸMîõ�½¼ÛÚûìÿ‘šuw_�R÷~‘ör÷;Ig•ÄÅ7JÏËH?k¶;îö°æ”S¦ÉòX¼jX"ßý‰_S4x7;ôp޵W)Ÿ| ”¤–½xó£.¢šJòZé~écíÏv§f\Q ”¤¦}RI 1¾ŠÛFIj¯—çŠÌ?`{Ú¥û¬ŒèHzÒ=ü$z…µ?Û4uà¼6U{Cýò NìƦ^OÕT’ɽÞ¯®ÄW1k¯~å¾ASÓ§¬š%¶¿=½óD;“qÕ%åaïÍÕžQÖþlwÐä¡2VjM¹äú sç¶§­›ïTãtÆUÕ¥k[S7v†Y»´Œ¨Ù9‰óŠaä¹ûügæ_¯�m+õHG’á$L4$½Uº—z'G¯>ì½ÉÚŸí½D“(Ðw|a‰”"S+ßB®õ3ö0ÿVÕ•„®¨NbU—¯?{uõÚÖk—–‘+þnÂäʽ¯[ý„D0,·÷Ãvß5S7zG÷$i;ry©w‚µ3;>e†±Æáœà´ˆÞ*@¥Á±�w¤^l®Þé_Z¼‘‹ßÌ ^>ÆÚ™ÅE ·ÙHbõ;æ_¬SìñHÚÅý‰õÞ‘=¨�?ô�¼¤æD&fÿÜ!sWvŠ-lÿâFq½÷×näâ¬ÝXzÄJrNó”äA‚µ;>e‚’œ×<%q»¼z P’: ”¤@Iê0P’@(I#€’Ôa $�4P’F%©Ã@Ii $�JR‡�’Ò@I”¤% ¤�’4(IJH%iP’: ”$�JÒ $u(I ”¤@Iê0P’@(I#€’Ôa $�4P’F%©Ã@Ii $�JR‡�’Ò@I”¤% ¤�’4(IJH%iP’: ”$�JÒ $u(I ”¤@Iê0P’@(I#€’Ôa $�4P’F%©Ã@Ii $�JR‡�’Ò@I”¤% ¤�’4(IJH%iP’: ”$�JÒ $u(I ”¤@Iê0P’@(I#€’Ôa $�4P’F%©Ã@Ii $�JR‡�’Ò@I”¤% ¤�’4(IJH%iP’: ”$�JÒ $u(I ”¤@Iê0P’@(I#€’Ôa $�4P’F%©Ã@Ii $�JR‡�’Ò@I”¤% ¤�’4(IJH%iP’: ”$�JÒ $u(I ”¤@Iê0P’@(I#€’Ôa $�4P’F%©Ã@Ii $�JR‡�’Ò@I”¤% ¤�’4(IÖæJ"8%9¯yJ2erT½Íe³¬=Ù1 „)`P’s›§$6x¬ XcíÉ*5䌰ûVáÞö/¹Cö­�m—üùüÊ”�$Só’’½<Áe³ë«ë¶m³ög@×,ÕD‰òÚ*§È­Ç'/ ÿ0wk;[îðÃÌ“ºÒ–óÑ >i X¦8Q`íÏ2®Œˆ>“Sd`þÝÎÁæ_¯=íÕþOš¤˜¢è·%fÛöÁã—¬ýÙîÐù� 7®N¹iÉXOô¿˜;·mmäAINÿG£KÿDAHÖ.-#â�†çš”"S+ß2ÿzíi¹Þø)qm=vƒÌÞcíÏvGtbrQ==å6/Ï™;·=máå/òt�ßS� ²!Íì±öêWŽg ”¬1H9Er‡–œ¶ý·š2bŠâ¾¤ì*½¬ýÙpf¾9SÎZÛÿƒ¹‹ÛÐúïžý\åEfOLåY{•"ªFí&É3óoæß°Ýlû ù”’¢¨!‰µ?Û:»Î$®)ÓÖÂË_˜»¸ -š.|BIˆ�0PzŸµW¿r”¤¶[&¯ vÚvw¿ù¤’ i_аög»Cs­IKÄ5Ö/)EîþÊÜÅmh±ÛÅö�I>jŠØ¾ÿõfþO柱}lkûxkàæ§”äU¤ÿ•ÒÇڟ펓ԃElöÝ.>ÊýÆÜÑíc/ ÿ¨kßÕLfR5NBRk“< Õ4wTÞU"ÐÿIœ"2¹òí¶õžù'ek¯´ß6Çf „豯9-#HÚˆ?ëbíÏvGT >󆦿’g~5Tâ-a�µ/} Ë~˜þs$SÝ×gô$<¥óªÎÚ¥eÄ”&`MpVŠr‰šj lDqÑóu$mÍ>ûéËLÀæÞoÌlîÉÝÎþ­÷^Ÿ�Ͼîê«#'×Ù É;¨{#:ÌÚŸ@øÎ6—Í )"¨åœ‰@sþV<¾…0Aå:I¢®}÷òKÝ_/½þÝŸeE)�ãl¡ª½ôÓqÂFxª]”Ä‘=œÐ¹q�O™‘É}”Ðe•HÔ§Dða÷ͳ¹ß™ä‹´ÇË{¯ºÝÀc«ûÊÝ¡ôjll-6ö¬ûª&GH$¢ Ò~$²'Êoe7$³vfgÀe³¡;Û¡LŽÃ9”ÒÂÓô432¾ß5¾ß5¡ù—°®òÆ~&\˜=5þºñðØwÎkÐ:´áRøZ)<|Ìc�Ã9^ÕÂI3”¢bÂÚ™§áƵK �ŸÒ�ªE&Ë©`ºj$Ý(¥Y�,–žÁ?ÓÙzõÍÓxÂÕ�]%¶Ø¯nöŒ,÷�ßJ»‡D"†$ë²’—äý$ZÏ ‡sáäÛpr_Héáéò-’(.ÊØ’T"%,/}7pçpùÍÿ˜O‰VÛ˃’ß»%ÈÙëÅæ59­ IÃÿÑ\cåµF@ªÙ5¾çFžÞ1�<ZÞ¼kþ¹1µ¨;•ðšYŽÝœŸ_˜XìWY»âKAJX4g¢Ò%Ì[�GKOº„åiíYÔ—QÒº2mD2Fl¾�nÖ4N<¾Õsãµ2™ç§-ïÛ�)Ì?ÿ9H‘g®øaãγ·Š“ÑFÏÈÜ`z¹|ñjj~|žµ¾8�jòjžî€>^ÂVœ°òö¥D&†”2”t»$@š?m I"`Â'ªz28ÿnõm"ϧ›Ö‹Þ«îvf;:xo0½Ö{ýaßäÜ`šõ‡ÿr¡; ¼/¨º4uP]Ând Û2ÿ_ú¦ª!ÎÅF÷n#ëð KPiêøTäÙ¹±/Þœ<NºòFéy4€mÛ~;¿|4¤=�¦PÂBª)¥ªµ �¼„í?¤7O$ï8C5¸QÂOR1aý±/y¦,nöÈ«�S$¹ñ}gEž»„¦D4$Ó*$/Çn. /ìd˜OsРÝ�RFf³dÛ¶¿åÆÃã­N[Âw~황†Xü”7¹Ñ¶;ˆ¹¸Ù£Pú œ*„qÑytÊÕ‰Í{/_wÅÜPäqÏð\ÿ­åØÄƒÁé…áÖŸ¨�mÛ«¯On.—œ%Ìð–°ôæÉN±Š�Ö÷þº{äÛÎèNE(-ßbýiÙÆE[&’¯ônpþÝÚ^û^ê|ú¤ð¢ïš«!/»úRk=£�b“sý·XNàßq–°Ÿ"Ò´Ö)KØsò~rå[4Åq6?\BÉÀ¦UëCÂffãØ¶m›ñ¥o^�ö*³ß~ûãæhÆp Sß(Ýû§²\vEÁ )ÖŸ8Ò´F×ô¤á/ž¼zïh£ÍnŠí?Ì<ùQNU)’´�ã0ÔÂq°ƒ®�yN>,)c¥jä9Ý.‘çîÁßéÕ¼D¯ÌèHZ�ݘÄË]S�äÙ,ýW;!EÂÃÇW]ÂP²�–°G»¿ÅnWS"!l )¥ómrç®�QÆJÒÄš""Ö½»]\Üay[üñƒÜnWŸ»�yÚ}õþ•Û«±‹—'f1ë4 ÇÙáþ“Ðh‘Ã9o SRVzód—ÝM±�üŸWîùR"ª)¨&�I[¬?X'áȈá˜î‹<¿Þ¼ð žÏ_”žõß(·Z�ôݘÞì½¾ryòþ•Û¬?ÐL8œ ©{ÖdßI1“%l»Ü Úçc»O=FêwÂÛ,D¬‡‡KEž˜ö(xq!= Ê}œ”ÈžÔ•½<•ù§ñ™ûÓ¬? Ð*ä”�Ü+oɪž ß» 6;¹Ã³Ï~R¼:ð$=áíÁGqüÆ�i7òäG¾' bŹ‘´5óäÇÖEž¹¢Û 꽯ÆnL_žÞ˜~2ú0×™WŸ€sÁ'�ðÌ.—ÍúƒV·ÙYzýûå¹j9„€ÝK4pÂÛL¨Œ$è…,ÿIqßlKºc=^ÚÛ‰¸Û™gÑø�¡ôRï�…¾©éËŠ|AÐÆs/ÄÌÛ h³óDÿkd±TÕÕœ»ón——h†T¾+m8i1Ã׫9¯œlm?/÷ˆÄîà�ž‘¥¾›w† èý ÅíQPi³c4½ÍÎËí yO3¨„^Ró‚ qHËU£kü­¿GAãݱ^é¿mŒßuûìË]Ë}¸?Œ�Ý€£à3mvê_ÂÜÖˆ]µFÔxU ©ûÚ<¤©ô(ЄôaƒÝ±Ê}*)‘�ž‘ù‘[�.ß¼sy ÷ƒŒUζÙAõ¶ÙY~ó{ÿœ×€ ç˜Rh³Wz¿„ô¡�*IKLU{ Ü9\ùÏݱž,ç_v¹Û™çÑø|ÿôjìú£Á©ù(zjà.a]ã{‘Éýjò$SøïKةֈbõP¶3Œ¡2â¶›SËOœŸêŽõ"ÿëÊí§K‰ìòÌÓgo~.ÿeîûS}6{®-÷ޜ*ð/D&÷¥„&&Œ�Ûì®Tzì�¿Öî¾X�¼¿œZÝØ*•ÿòÀéPM‰NkDCüòú´35ºc9= ϬëHÎKІ¤¼É#9;óìT€Lwf¹çæ#H‰çáSmvÖV�=9š—Iý)/]Ÿ»»ý³¿5¢Œ‰œ2"=`­ƒÁÙîX7GV\Ũi½£·ã Ùž‰…5Ó�a=| #¡Ý“TBOŠ�6;½“¹|ùñ‘ªi’œ¾2ïäTM)AÜàYÆ_h/‘NÁíŽ5z}KJ�×JoM ÙC‘‡É»ýÓú“·ãÐKhzR¬�JÂSúƒU—j,^y$Ëãû¶mgÖ�¥hHÇð¼kÔæ¸OE#yIáÆµ¡‘mÖÂCxJ¿×�w"±šSN—”ÔÐ�{w^A'½ÎâŽ#g|ZI”± �f²ÝÕ¿«ÔV’<’o]]H]}ÈzŒÀù ÷Ew"}g}jˆèI÷Õ»ý·”±ëa�âY$þ´gØ­o<›*Á£O§¯-³#pn¶ºâÝ£Ú·jtu¸ó ?Áz€@ÐØŒ ¯I×òg’ü’]žZŒ?£OY�87Ý£Ï#�»‡ „܇¼5IÑ$e±¯ÄnÞºz‡õ� ±&]{¦ ®÷\÷ŽoòHÖE´Ö;б=7ºËz€@�¬ŠÑ]Q6%yXìSg&¯ ¨‹}P:´„õžëo¥(q¦Ük¹{96‘ž}48÷Ú64é\¶Ãálå§oÆÆæ‡f&³X²÷†çMA0E‘Ð+C ƒ©Ìð,ëq ±ËóD*çIˆ ÃaÖ#ÎóPÈ[¼ˆ,„X�hÎI�{^C�õp€à³ëN@bTÄ„õˆ€FÉqœV‰3M„ A`=" øÎd+×À” {ápÎ+su$…õˆ€€ã.^¤"#:lmAžç+ç¿"�Lxžõˆ€€³ y‹×~$¢IëM Z*/�@>&înš¾Òˆö#Ö#…pœY‰I,Q4 ÎZ�)å ?B�áäÒ%â‹3uˆ3�SŒ– ÒÊa0(I á°ÅóåSˆ3�ÖcIR1u•¤àÔ/±ÐÌÊvÕM¤³|B†»xUÄ„õˆ€F9â8Ëó)Bpj\Feñ2añ áð‘W±Ìq&É-¦\éL9Ë NX�hž7+×mLž'ÇzD@ÀñW’hgÀâ¼ôˆ{ Ìz8@ðÉWJ[é¬ãy ¯ÎÇg§@ˆõˆ€àã-[�á {¾8sO’4P Å¸uhåÝ´$ x)äÃa/‹®;bÂzD@À1*‰)Š%E)B'�@P½Ö-p­¸ çæ¯wpSRÖ#Åg¢X€­ Ðzü=Ià®h08gÀÖh1ôºM¥äÀây ¯@`T.OAœ \ Yö®Û£QH·/&1 Î.K’¬Jñq.ñ±Ð(þ8“6œ�:C õ¸}´¼ÔëáMÀòÅ™„ãH(ÄzD@ÀÑœóA³“è°›D’ŒÊ‹EpݸtAÐ*J¢ÅbzWëMÀ 2Mè}\ÕN‚`H’‹±Ð(º¢Ð”—[Ú*yH’­Çâ{'‹õp€&`H’®”ˆÏqÜ$I€cyﲉ"‘¤=ØÚ/ 1Aãù$I€c ‚ךo+ÝÛËzD@0+Yt¸Ö \ tÊU: ì+ÊV<ÎzD@£øãLS’rÐûh=Õ®­pW4(øãÌ,ǽ€t+Ðbt§y…›nÕE±§6�À{ûÌÅ7<Ÿ…$ Ðbèâá°;ålŒ¿b="  Àµnà‚¡I¹Ê”;êî¶1f=" Qü=I,ž?†8h=F¥†„ÀÃ�AÁkÆk"dcüÃà ë§à{!ËDèòr�Àÿ&ÅQOÄ™@«!‚à‰‰Íq' $�À[ˆ“we= ø_'�#ž·!Ãßùh²\mÜ q&p!¾»¢¯@ #¤É2Ä™À…a8uhîúU„o2Ö#š€áK|Aœ \¦ïM Û¶\Ya="  |t­Úz­‡fä¼J’‰ Û¶Y�h”CY&•c}K’Ž!ÎZ 5»ºÊ~x¿¾Ã!g†B´¿"B‡^’ĶaÇ ´â>€‰P1q3üpVØÉä8N»t‰pÜGòNuë×ããEȸ-ÀëP½r.І$ÐO¾cÙ…rçw¨w\ ‡ ôš�)IôFB5f�(æ¡­Vg’w.`’�êžÝè‚`9ï ±#(hè[yGé쬣­>/]b=FàÜÔvhŊѨÏ)M¥öÊå¥JxÚ�w"ŸW3¶ «ÐTþeÊÁ“(�Ég|j8Oï™jMÅtZ‘µ¦qï÷õ±#pnŽ3ÿ‘ÍGæ”1ÃÓ{@s¡JÂóggq.ÝØŸ@/èäduÕ¶íS[W·FÈ}<‹õ� aúû�û65&B– |‹A#‹N„ÊH*•u‚IåY âìkhkMxâhÕ Ä¿Íqt /×Dþî$kd endstream endobj 69 0 obj <> stream xœí�ytTÕÇßdƒ$ÈED‹ ‹Ô¨—Vl©PÛ�ÚÔj+dž*6Õ#=‘£ˆm]ÀºDí)Dlµ.QŒFve“@Xd“@„�Y˜Ìd&3ï×3K†$3wæÝû~ïþž9÷ó�þï|~_ß›åýÞ»?M³!ç½]ëÚt'µ"§ýcŸçÛ'ºSkÄ$ûd+¸^¤ö@£çw   ;ÆíØã‡îë¨M°xÅ,È5‹Z$çz‚nàŸGm‚űPA°›Z$74…åVQ› ÑMÔBmƒÁ-!7ýej,êÂi雷EMÈÍõ3j,JB·ëij‘\Ò»æùÔ"XôÞ,ȵ#“Ú$šì:(/kôíºßAm‚D¯ °wa­^óœ ÃV KºiZ2µ½Ö÷lZÐÐ#ði7j Lz®ƒêQK0zÊìø‹K˜Ì•ð�]Ãr>ëRag,‡ïSK0¸ð”§SK`’± œG-Áà‚XeÃÏmq2–ÂÁó©%œ»V÷ –À$ý 82ŒZ‚Á }ðe— »Û'P;Üü2)�U5n»/ Ãè«à«Óp—4Œã·•�ûg÷Ä]4­Ž^d~™ô-Í�Öïb(E¸ÖP…­Íä®B}ý´�àè„uæ5‡®±`¶²ÎÙ }×ãb’+Ô½X€¸fÚ‡pìÇë„/öÃv„ÅÂôÛ›²ð–ãd]¸ V¼��Ô îbŒ…Îñ†å1V ÒïØL¶V.È…ð™"yÔ�DY)Ö;Œ²œ¦ign‡Í§c-&ÀîpAþ3�LþÔ�BYi` ´QŠó›´ï6¨$ ;³¨µ­ ŠŸ ¬˜ü4\ޱPf‘Nᙋð1Þw+lÅ:¨øIÊ?Ò® (E¸‚”ü&4ŒFPs䀎šbökwŸ Øy‚›£×v*È5ÇìGer 4^� vùˆæë«L­Ù{#ìê�à&Ä9%ztA5ù¦šFI ÀùSójb©Z㋉/Ú{ì>Û¼›…'c®_Ôñ*8¯5­–^Ø[-ð³²Hôšt¯õ°‡(lG^5³ ½Dô½Íñ24›¿Å+w?S-À±³¯×º`ËŽ‚‘«ãä;€/AóX³j9«âªX~ ÿ²™«¨Zvý‹ý‰ :�Ï¿¬ãŸàgRíô¹¾„aøKúq®hÙ‘t‘Ò  ˲9×ũ–Í©¥4Q€úB®f9YË.·Ê`Aþ’3¹~<7™S¿Ã Z€=yƦjÙ ÿ”£ …iÆW~<¹¦Ô†-áP Pnô*#QË.Ëлb;v>ZŸÏD3j}æ¶ðéHk±¡_áé_ t‘8I�Rg „N”ë < ÞI&ÔR¦3àÍñ‚”„kwûjºHœŒß&T�wn¯ÄkÏï-&ÔÆmR °sB‚µ‘Zv| ).èû‚Dwñ�ïvqµ  «(�û–ŒÕ²ã¡÷œ3íøyÜÕßÂj=ŠL©Ï>v«eÇARþQ“Aiœ/P3À'ܤMʯ5ðê‰8<…qö¥¾'rDÝĸ®¡ öÅü‡Àw—¨Úë ¼´*®‰µ|ò±ZvFi×m2ãbþŸÀ/ð+?HÌK¾¢Äè„àµì Ò±Ûd’¯¯Ž~�é OSË(rá©®Åvî„$/DjÙÄ‘÷jAúâs;½Â]¿_P�}ÉW”Ž�¬–�Q.ÿ ½ æ¢÷<ß§ë©�ü]-Àú1‘WHBjÙäìÄ×UE8Øîº×¯OãrʼkÆÔ~–©µuBòÊ7-\ŒÒ²KDÒMÓ FÄï6™dÅ¥š6ê½ÊÇÞã×är»½ñd‹³åÆ.ù â|b{è_ºH ÉÞçt¹Zþ5iŸ…ùKÿ©ÃŸ¹Ü®r‡ÿ3)Z–q„¬ÁsÔªµ|r_JÊ9Ä«2>Åã¸ßªàã““êÆ+'Â2©__µ^ª[«e!GøHjAÀw/Mg/öCyÈ)³ /Ÿ\âïÚ„èæîb3Dæq™ŸD39í&»Ì^]5Œï7%Ü�ìšfYA1·]Ö[’Ô6JzŠ)mº¤‚¶ŠÜù $9̇ˆâ’-© 9•¶ *mM¥B¥­©´ÅQik*í*mM¥-ŽJ[Si‡Pik*mqTÚšJ;„J[Si‹£ÒÖTÚ!TÚšJ[•¶¦Ò¡ÒÖTÚ⨴5•v¤´%Ü¡[¥�—ö=m=£ÒFL`åeqÿB¥�š6ø_‹·sˆJ7m€†‡Ù;‡¨´±ÓŽ·õŒJ?m€/OË«´­H›µõŒJÛ’´[Ϩ´Ùiç¼ÄG§k¶\¯ÒŽ#íÉ&—uGÅ­Òf§}Á4>v\õ�觺TÚ½oÇÜ�H¥mIÚÇcﮥҶ mïÜÞ±ÿB¥�Ÿ6{WD•6vÚ;Áþ •6nÚõÓSãü…J3mß«ñ÷ŠUi#¦�p{•6^Ú‰·°Ui«ž{•¶ *mM¥B¥­©´ÅQik*í*mMÓ&î‘$§—%_�Á%ŸI*Èóz_^·7$îØdjr£Aò[$ís Ðr„s*úy[^ÀVE|о27�s¿Í'·Zê΢~«2>Åc2Ó†V¾�ÉjdºXr„Rëqá’‹?¥ݲ�#¼&õdå<¶Ÿ’zâí²,äãeîÜúŸÜiû=�÷SÏ K­ÂÇ›?˪ŒÛñ^ðsßcí[¤÷pàUÜÇrÊõ}ÃÛ쫸8K`Þžav Ë ü?­—2â0å/�.Ïá[S ,Ü~¹|DÒŒ:hžÏhúÇ£gv°ñ4ŒgÌ%Ço .‹¡Qˆ¤�ŽIáž%i”Ý7‡^Æœeî^ Լϡ$(Äð2 âÈË&}V…¾‚=N†g…wVp\ú£ž}U’gíEcp¾µQD©Ç#'þXyNÞƒ«&â ‘ï‰ÈÅùÅã+Ž9±Ž€Q8CªœEÝ­°Ë(‡_S+àò8¼H­À$Í©w©�HM[ ·Q+0¹¶Q+à’Ö¬K{J…›™0�Z—k¡’Z�Í2¸•Z—"xžZ�Iw—ß¾ç�+a"µ“±°™Z—ôçÆ™„ÏäYÁ8ØH­Àf5äR+àò$ü�Z�IF‹ï‡ÞùíĈ³»417Àj\zx[íÛò› ÏP+à2ÖR+°Y ¨pyfS+0éáåÜnÆöl€¨˜Ük¨péåóØ÷Þ�¿ÃSÔ ¸Ü «©Øl„ñÔ ¸< ³¨˜Øú¼bŒ¥V`2VR+à’åw'œOÆóPD­€Ë­°ŒZ�M%ØúY_~æÁLj&Y~·%;¢Ð± ®¡V`r,¥VÀ¥¯Þl›?¢x§VÀ%>§V`³®¦VÀåex”Z�É™zóaßv‚íž´‰0ʨpéMñF'Òò*R+àr|B­Àf7Øõ&gA^‡Ô LúC“=÷çf/Œ¤V`r'|L­€Ë@h°éÓ�Ñ8ð0µ.ùð!µ›*èOZ·çß0�Z�É ¨·ïy'Ä~@Þà‘»á}j\΃ïí²�r4 à�Ô ¸Ü ïR+°©l„ÉB?Î|¾�Ï;!jÀ¾býÞ¡VÀeµß~$m¼P+à2Q+°©�áÔ ¸,‚©Ô L.µóy'B÷#À7®PÝçÔT÷§Ö@äîjÏ(j‹˜¤}˜ñà«ë:;7<(HwÛò.»GBýœSpíËèðŒ‚:;6þv…÷6²ñM\|¼Þúä8j“´íOìý�ìgž�ÒpAMŒÂ2ÍŽ°\kW¹QêÙð±í”8‚Â0ÓBïÛž.ó¾� ¢²ã%dÇ»Á)¸G+33ø%Ëu%µGLRfT·ÖÌîJO¥NÚäm˜?Tö«þ9¨ÔO endstream endobj 70 0 obj <> stream xœí�]o[7†ïõ+x½@i~ó0 D¶ìEhj {[dÛÅ&ÝfS`þâHrtŽ­çˆCKr‘�É!‡äÌ;¤µóeýGeÔwzðß\œzÿqñÇ¢§¸�ò®$Ýå¨>ÿ²øéoêÓâ�…×ÖÅuÛݧ÷Võß½U›Ÿ?,®Þzõá¿‹«üþéÇ/Ÿÿ|ÿE]__}û÷;eÔÍÍòîvͦ³IYSÏá×Å‹†ì�)º[w˜¿N¶$5ü÷Ý[õüËݸ–‹«ÿóó§ëë«7ï¿üùó¿~ùßu½º_­œqw7êæFõƒ¼Ze�zøua7³*e«“+Y¹¢>.®�1áF=ü¶¸ÿ~3©‡©kcüæË¬£‰],á+!DcÂÒ˜PÖ?01ŒÛ¯Ã3¹8füÙX�ƒ5þÀìòLã³V‡dó¡ñEoLxs¦1º¨CôÅ’a2Ææ#ÆøäHÔŸH³þðî­Ú|hÙù6(ëµw1>Úö_fU¼öýŸô(»O Ýö(”’º`wGÁy"" l?'Ø[i U ‚›o‚wâ ®ÄÃÅõ‹ÝÝ‹™¿‘òÀtY¼´ÄÜ’Ø]”ÊÊ¢Hh¡FÃuÉíî�à‡-bÊûG5"Ü� „‘ØG]-‰p]áG<ªZàpG²ŽÊ»Y�º"Yñ#s\Dê¤+î ñÆ‘x|؋䠇=âyôàÍdàã›k^m*_�k^7*\(;® AI"Np)](9Þh@Zrƒ�Œ*-_¥‡Ø.ÂÐhš· J»u¾"$—•¶Öçu*ãÙ—Ÿ?HT™W6� 1ë®x&Ùf3�L�Çží’=„ŽK"d)�íq–Œj„-¦©ZÁç­Ç+ø<ô>¯Ñ ŬƒîÓ+†ÊQ’F¥B-X?‘ÖôÈõ“x¸ úI¬äyærí�àA ‡ ¥+y.vî �•x=<ò¨ ³¢'ˆ®ÕkßïuE1w–U•W€ºˆu-­£ ¶‘œÙ—¯røŽ‹{̙˩rŽñàTã� Êâ�ï¨M´JDzÒÞ”n�Ìž~'3÷Í}ìtIÉÅçæÞï1÷æq¯x—»ÓWB0DÀŽw@ð·ÔbI„(ÀaÏ[DsM™LÈ-¾Ø=•ǰÙ–C2Ó xê"£Þr$É££näá1Á„D±¸n€ÇáÛ²{œû¯âQg¦  ª€®<F6ºbðP‡o« ;× �ªÐÊqp™Sø¦%Ú„Òó¨[ÁÖÁQ·‚8ó* E+èGp¼*§À„u+˜!ˆ.O‚Tæòx¿¸¤P½÷òŠ„‹ˆ–DnŽÅÙ9 :HàQÉíôŒ�¶sU(y†u¡„[±¿:ßÑç¢MN�jŸo^ã ¼ÆDK¢×Æ…:T!?à5 ¶ï 2£Q ÅkcºtÐ(Ê­žzF¸ªÑ¦þ†’³WUž‹Gå*ÏäžGj¸b ºtƹRk@ ñ±eÿ[ìÊËË'x#‰³, Å)ļaH yxq ñËîâÄqòì‹¡˜î±q�—©¼.<ÛPñ|‚úeÎG¢×s‚lïYÖx>E–TZÒ3kÄ,)Æ„ªÂdU�œSD'g¬Üf!ÊÖâûRòš\L†RÅóclëãN9­³†vÊ4‚2Éë 3ª©ã"C,y¤nƲ¢WføiæXùf aWâ‹  Pé`Iêa¼r‰Ìd¢N¬Ø¼#ÅVì£bK¦+¶=�-[¡N›h\&&|ÛðY/[qü{# bÜUWèVçÌW"€æ‚–ù ÕQ•˵PCq„¸²²!tÎJ׳^å[GCBUÂ_~©Ág¨RåuµUW·ª¬B:'ü9»-¿=/w¼h3PõæÄ¾š¯Ô¡á• jÁÕ›tÕ”g.w9_×kóß’¼˜× †è¢5³‚a×ùÂOrã#¿pÏ^µ˜óá(Ä.8*5lDåÕ™Ey²B¥]W<0›Òn©u@«$6‰ z¡^ÅD” ¾óÎ¥nbÔÖp¡á"cÃ,ËU�„*#Í0zoÐ\XLuh]§3}†"Oß¼]�n¾HowÆ>Ö`Wlàä![9p˜´<œŠõÉèíbàÔã™´GUà2ùײÜ�|¯S!ßSgÍZPe•üü1œŠDŽ Ñe›1Œ„Pí‘E;ë;lr±¿Ô˽åMÝskU]ÉßäbH*~ ÍÒÌÒd†UwùÿTBEþ?ͧBÄšAñŒÕ„¤)JKg,ûä®Ð.Šg>gÍik­¦DAŸ"$êJþÚT•V•‡Ÿ_è͆†²1Œˆoó5<+Rå'ÔÕcˆ�€øê–ˆŒÜ(ÏW”'�wzieä £>vÆ0#--æ†xÓ~BË;ââ·±åuŠœ˜¢GEX/Àd;ítÊÃ]ó•µüU°€¼NO Oò`Ø9çÑ�'ïÄ#ŸZ©K?‰�kÛ„i¬.èì Õ\•F«r:¿ª³ª†*²¡GeF%'T¤rd™®`ÝÃgò›óU Ý*TßÁ}5š Š™‹nƒÃœ^ÓL‡cÎ{KXœX”_ùàpŒ8޶ÇÐ>ù•yÞ”¯¿Hò„¿4/ã« ¦Óƹl•5Îê⽟Î&ï„ÕÙ.ì=ŽOK xìêŽØÂÁa„�öx2ÜŽIÜ‚D‚Ì uÅbGÊ*Áˆ‡K+È¡zÜ;�ÑYs6iú_ÔêºõqJNÇþG7Ÿç.9úƒ‘6‡b÷ß]ÅèþÕË©ÓxõOgÔÝï[î��ë!lJEÛé•÷yÝ} `KZsßÑ»èLÖÅöéÎiö) ØÇ¤û¦ÙëlòªóYG¢°Ý|·æÚ¶m¬w��ðëùõrÿ?Qjä endstream endobj 73 0 obj <> /StructParent 100011>> endobj 74 0 obj <> /StructParent 100012>> endobj 75 0 obj <> stream xœí�ÝoÜ8ÀßýWèy�sôaI6È×÷°´ °ûºÈu 6Ýk¶ ÜŸðÌ´c'ósD�Æ3N§ 7ŒEŠ¢HФèÒºfùGi¥Õ?ÊÎccÕÃcñ¥h!Ö{­œmBYG¯ž>¿ü¤>_ Wë—ïnž £Ú¿ïïÔêáéSqvçÔ§¿Š³ýùùÃ×§¿¾ªó󳟯ÿy£´º¸¸º¹^¢©MPFûÐbø½xW¼ë¢·º)[Úê×ñ—Á4Auÿ}§^þpC×Õ}qöá¿¿}>??»|øú÷oÜüßWu¾¸],¬¶7êâBµDž-*e¬ºÿ½0+Ž¢)ƒm¢²�º,εÖÕ…ºÿOqûójR÷ÿVçZ»Õc鵯}S}T^ëêJëªYþÂ×ßÉè#¹½ß…þ¨M+£Ý+0עϘ² &¾FŸwZW—¢Ñú²ò®±¯ñ0hmâ4>Ûé;²´K±¯‚�ª4ÆÅåŽxñÃ1;Â8eê2„g»¢4íf�ÊhWÆ:„¿qÆlãÌj𯔦qÑó ⬈6† ö!‘ Ž(ÐÖŽÀÓD#Õi[ï=Ñ|,ÎÇ,äïX|gÍ·$yfv¬å»Ô­œ”Î9§Êz)£ýŸ<}Hf´Ê¸ÒÙ•Iñtõ7¹t[wìZm;ëàÃwÀÕ ŒÀZ9mDøŠÞ°b êZ Ðׄã–XBÈE,©ˆ%n€†—:]p·pÁuåV/ëý�Z=ˆ¤ÔT$¥Öš2úÊø®”nÕžßæØ4¡®Ìƹ°—иÀñ–7¹“"gÀ F1€†r–ިЀ†Â™Z9wy¨ gŽNVìw9Ôç�ù®ÏC³4n@«›F`³êR{m«haëçØèÆx¤ë~GÆm}#Þ½$Ü,FuJM{QŒ'È[y%Ö[L.jÔ)ây°¦“S…*PªüÝzi�QuÔ~®JcCù6u¡ÅVGn$põ£n~Þf4AäÎÃ�ºp¸•å>³]êc�¡ åŠЇ"�É\w6l6­ëåCܾ´]@yg(gP餡ºC1U=^õ ª@Ïú'±¤·9{,[‚.!û´V›™Z‚åoÀ «ÙÛ±)ŒsâãëŽz¤§AÅ&‚Y‚–µ4\Z±ëÏë�þ¡|愃£^<èªíÖ€T+™ˆ“^ß¿^7q®zÝ ¦ONz}öz]:ó‘¶´´¨Z™\’«“^?éõ½éõÙ†{íp Wc4"Ÿ––GgsªïŒáNq¦„É� ÄÚ c­ÙâëÎc ­ ÉÕñœT’Ô^oÍÓT«*ü¯zÒëë齑d;ÒbVHU µ®"–â®C3tE€Hä§0Ð=–ô�[ñ ’ÉöÝí\ÇYØòª™«-ßPžéŒ&ö×QQ²�Ekƒ8Ä1üÓqO`ÑéØ�¨tÿ0òî©nÇcàÓípz=Ì5»Þ¡ü¤×÷£×�UK²´1_Úýˆ¢ÀIúÐâ†#p€÷íøüD1DFŽ–Ài]ÁÀY˜ŽxÅÈñ(vIÈpµ}¨Y46 ›«¶©–¥šÕ`©&Ūå•e{¤ Y·dŒ|M¡<߈%eÿZ^:+_s±sÏyŸ¤ZÔ4¥“¤ “\uÆÚhGE€††'’8‹…T‰³XX —6Á ¦¡0Ž•DnÚ bMž©’NziÎEÒ¹­ëuÈ/TLunsÖõ­ÜÌNo/èÏs†3ùn$½‘3\Ö\ÞAK10‘(ÏÆâP˜àNÙŽ§>4”išîh#TÎÍ5óС\¤ÝP¦0wË2•/qüFJÓNÚí@Úm·Š‹ý¸ŒÚ-½gG¶f®®Ê¶·IÞFkÝ'k 1¢…Ç@«n ��: ޶Ö*" Ö»KFÛ˜F§–$y[’ì§µÃf˵íFÙnydHžA–‡×Ä—ÃG¸ânl ñú$’ûVÎ}bwF¾P�*?ÔÄÄ¡“‚Li)t(Äõcx,r0%_ÆÄ¸fpŠ´“¸.ѯF1¼†¥ˆ|‚Päˆüà‘ì$ß‘wjÇ0qAC‘øŒÈA¢´‹‹€L’PïVOÄñõH¼Â²¡E¾³FfŸføVÈnNâËþ#zEÈ»»d/—ËÒ%o=g0Mi|ÝT¯­·ÜËÒ˜"–‡€Ä]pF¸Fò âüˆ+Ö(…¯¸‘Y¤p?ç¦6›£›™›àn‡Ò�ÁâÎ/òydyØQ~Ø‘‡�9JŠ=§Ò®.ÉR†”"qÁŒEÉ‹@ÄûEî—äàvJ†§j¬sÙ/èß*-o$B1"W n6ÂÂ-·�8ÔÛý�.âr7¼òÏë‘$>)%Á‘–¤ðHZð‰×|ZM:I&Uþލ.Æ(HRŒ))”´cLc7¶§Å4’b3Ú;ÚRoæzYÇ¿’N!=òæÛg½™Récl¨�ó¸9E}]Zûž4£BªÕ‰#Ïx#ž p¿�žÚ#�¿0Â2×R&²³BÜe«)ï�DY,ž ‡Ë˜ò,iÀ¯Í˜f�ÎIZQ RpxV Ã'ÌŸ×ñ¦4Up‰,ö‹ãT,ÁâXXÆÂŸ¡{JÜ_ŽÑW«Ž2ž²2†9ñs=òSÖn§E,éHò¾¸ð}©W µ:g˹#£ÎñÑ”Ú4MHT:TéÍ,0 _Ñɹf®Ý¥;”gÊ(åSj‡•[qŒ�'˜1Ø4AÝÁa+¼ódÔ #²V¸‚ò|V—г$“DV&èa‰È5Fºì!l{Š%³MŸ„áôÉ‘Z‚£l¦xÒÒûÔÒS\1•—ŽrJ ©¡ðŽ]€å§#JYs€_<.ž8™Q™íG¸òð�Dº¼ÍÔñ_<—+˜$1"¦˜±’MÜŒLþ½ë‘Nù÷Ð>¡”`-²8§éΠ}èüÍq)1ãšïºÀæ¹âõ‘i±à¶P¾U‹a…¢¼z;ߥÑY yˆýYùPò¯‘g> stream xœíÝùwTç�çñ‹1pˆ7�X  ‘²@F@P�ÀÅ"•ªêÞZ…ŽdAŒXȬb1WKÕ-I6vHÛm:îÄö8N›t»ÝñØ�¤gB;݉Ç&¶™Ø,’;ÓãùafþM£§¸*,>°í�ÚÛ_Þ¼yôm·¹»2é*�ÇSñàƒ÷Ošô“ææËŽs)‘èM&ÿùõÄ…“W~5{çÃg )5÷·ß<Ü›L-ê“g�>ò°ê‰ôu|ßæOžŠ‹DüúÙvÕã¤üê‰'Ä/_¯ãüÃ�ªÇ¹" ½wuª ñøé�;UGB_ÿpð ûË×ç8ᅵpÿç§Ï8ÑHHõ€šzíéƒ=i᪫­Q=‘¾þë_w�êwÏ$®~?Už•ùK˜æ/�s§zíñÇ3ÁÌ…C¡Z[Ý©þ¦¹YuJõõúþý=iáú—¿ïºôTêž;Õ¾=\º”oS‡:~pû›ožþøyçÒ“É '�s/'¾u`#?„û¥âÑí5—»S¿!~|ªcçZ+ï},˲m»¡¡Aîÿ}Þ¼y†a4­ZõÞÑ£âñ³û÷Ϙ8Qùe–i~?‘èK$®|íã8½Éä‰ÎÇS]íx<ž¥¥¥Sî¾û­Ý»?‰Ç/Äã=Éä™ÎCÿô×ö{Ïv|øíDY ÿÍõõ½ùæéŸ¿Þuö¬ÝѲíø�-/Ûsîå„ê¡´ö›—âçNÅÏ=¯¬˜ŸáK‰ëµdøR»b±¦�7/[–áëdËÿûÅ/úûû»¶n=µ}{Ÿmÿ¾£ã� ÞÕ—Ê?~WmíãuuÝÔÔ¼µ^FãÚ ê¹´vö¬}hƒØUÝÆ˜êqtWgV‰]eþRY —x©Š²²Ì§ÊŠþþþ¤m‹©Úú´ù! =Í/.ß4Ø�¦¿S=—îÒß¾ªžEwî¿CÌüç³.÷'¦´:uîº?€Ê½Ýw…ËâoˆÙ WúÏcd8Rñ¨pbK ×Íâ®pYÜU¶Â¥ç/ŸžSé‰á’Ã]á.�žSé‰á’Ã]á.�žSé‰á’Ã]á�]Mž<ÙçóíØ±cø"�ájll\¸pá´iÓ2éÖÓs*=1\r¸+¸«X,fÛv]]] þ¥† W04M³¦¦¦±±1ó‘n1=§ÒÃ%‡»Â ¿«ÜÜ\Ã0Æ�_Uuåǽ�@(ú·ˆ óRÄË4Í`0hYV0œ0aÂm·Ý&^ÿ¦FREÏ©ôÄpÉá®pÃïjáÂ…¡PèþûïŸ0a‚ßï·,+‹E£Ña^jøp‰{ž6mÚôéÓMÓ\¸páÍŽ¤ŠžSé‰á’Ã]á†ßUyy¹išË—/=z´ûãU†kõêÕcÇŽ-++³,«¼¼üfGREÏ©ôÄpÉá®pÃïjÊ”)wß}÷˜1c/^lYV(Ú¸qã—m —ø6×Ê•+Ç�7qâÄ©S§ÞìHªè9•ž.9ÜÙÕ�wÞ)îжí­[·ÿRÃs^„Ë4Í3fd2Ò­§çTzb¸äpW8dWS¦LY²dI]]]ccã0?êpÃp‰7]¦iVTTLŸ>=“‘n==§ÒÃ%‡»ÂeqWH¸nñHY¤çTzb¸äpW8† ¤çTzb¸äpW8† ¤çTzb¸äpW8wQükm†Ç£Â1\r¸+œ»¨ ÿ"ÁÓ;v쪭áJ¶´dòRóæÎ#­«û׌ÿ®ÑÜÜÜÅ‹×××oÛ¶-“¢ò¨p —î t1íS 3y�ìÛ÷ÃNïØñĦM§›š^lk{{ïÞ‰wÜ!ñ)®îKEÊÊ~sìØ§ñx�ãô ¼!ÌäsÙ²e¡Pˆáº•.9Üâ‹îîß'—ÚÚÞ:t裶¶ _ûZ†/xª©©~ݺL¾îÚS[»³¶öÒ©S—»»{’ÉL^ê�ˆF£>ŸOüU`үãÂ1\r¸+Ð¥¶¶®«%¼Þß0ƒûê}÷…*+Å�C,Ëì¨KŠŠÄH‡7mºtêT&/eFQQ‘x‚|>_&¯Ã£Â1\r¸+œ»¨,þjCCC&¯Ã@é.9Ü.‹»rÃÅ?òóÃ%‡»Â1\ =§ÒÃ%‡»Â1\ =§ÒÃ%‡»Â!»š6mÚÒ¥KçÌ™ƒ¼Ô ÃUPP°bÅŠ™3gf2Ò­§çTzb¸äpW8dWS¦L …BÁ`p̘17|©áÃ5jÔ(ŸÏgšfQQQ&#ÝzzN¥'†Kw…~W3gÎ,**?~|QQÑÔ©SÅÇ Nž\Ó¦M›0a‚ Æ�7wîÜë¾ïÒó—OÏ©ôÄpÉá®pÃïjÕªU¦iVVVÞyç�3f̃±X¬¸¸x˜—&\%%%âïÏÉÍÍ]±bE(Z¹råÍŽ¤ŠžSé‰á’Ã]á†ßU8®©©±,«ººZa&ŸdíþÑ!4àfGREÏ©ôÄpÉá®pÃ益¦&‡B!Ó4Eg†Yé Ç£Ñhú=3\ÿ.1\r¸+Ü w•þ6éËÞ#¥¿Ô0áŠF£âÕÜ“–I =§ÒÃ%‡»ÂeqW7 ×­)‹ôœJO —î Çp�ôœJO —î §s¸2ÿsßYÄ£Â1\r¸+œÎáÊðƒ‡²‹G…c¸äpW8�Õá<ÙÅ£Â1\r¸+œ†áòz½–eUVVf8Ovñ¨pš‡kúôéË—/�Åb7nÌÊ_Ø›-îJ   TÏr ­Âõ|SÓwwî||íZñçŒ2œ'»4<ª@  ׬Y3{à£åô¡y¸f̘!~¶§±±±¶¶Võ8ƒtÛ•û+ …ªªªT�s }Âuª©é•ææç›š^ݱ#¹nݪ¥K×-[X¼8é²E·£ŠF£–eÓ4Ëˡÿóï·˜¶áÊËË+))©ø;Æ…††† ¿@È"­v%æ¿‚�@`Ò¤I999ª'de›mÛ›6m’øܺa馦wŽŸ:ôîñãÏîØ±}ƬO˜!éÏ Ê.ñÇÜ©‚Á ø3ìªç2tתU«†üjfþ��,ÒjWbñãEEES¦L1MSŸ/³þ\ù‰7¥ù‘G.|€u¯ã\ŒÇ|ýëY- 2ù€³ì ‡Ã郉?–µ`ÁÕs:‡«°°PüMî„6l`¸¾ŒßïwåñxÆ�·dÉ’üü|ÕC¥üùŸõ›P¿nÝ­­©w\--�\=~Mè®ôw\>ŸÏï÷3\ˆ²²21�ø&¡êqé¶+ŸÏ'þM™eYK–,5j”ê‰ýùk„ª ‡�Ç{uïÞ_?þ«ãÇ·]ý4±›ý`Ù?1§&áðÓ�í¾ûî3 C“ïB¸‹Ò3\†a,\¸Ð4Í`0TÏ2H·]y½ÞªªªêêêÊÊJ}Þk ZíêÕ½{ß>xðdcã0[­%¸Õ*))Q=Ë5ô—ž¸+œ†»rž?9?B1\r¸+œ†»ržVq„b¸äpW8 w•~ðªg¤á¢´ÅpÉá®pîŠáé.9ÜNÃ]1\#Ã%‡»Âi¸+†k¤c¸äpW8 wÅp�t —î §á®®‘Žá’Ã]á4ÜÃ5Ò1\r¸+œ†»b¸F:†Kw…ÓpW ×HÇpÉá®pîŠáé.9ÜNÃ]1\#Ã%‡»Âi¸+†k¤c¸äpW8 wÅp�t —î §á®®‘Žá’Ã]á4ÜÃ5Ò1\r¸+œ†»b¸F:†Kw…ËÖ®b±ØÚ555Ž”Åpåää,X°Àï÷gþW‹ó¨p —î —•]™¦‡c±XMMM$‰F£±X,“WËâ;.Q­Ì_�G…c¸äpW¸l…Ë4Mñ‰Š¡P(‹E£Ñ _-+¿|cÆŒÉÏÏw?ê1“èáQá.9Ü.[á²,«ªªjîܹâ¥Âáp&¯–•påææ®Y³æöÛo/--Íü#yT8†Kw…ËÊ®Š‹‹ƒÁà½÷Þ;~üø¼¼<ñ™ÝÒ¯–Åw\Ó§OÏÍÍõûý|Çu+1\r¸+\¶v5a„I“&UWWçääŒ;6“—Êb¸îºë®@ �þI¿� ÇpÉá®pYÜÕÊ•+MÓ,--Íðu²ûÍyñR~¿? 2\·Ã%‡»ÂeqW÷ßÿŠ+òòò2|�,†+77wáÂ…Á~¿?“—âQá.9ÜNÃ]ñPG:†Kw…ÓpW ×HÇpÉá®pîŠáé.9ÜNÃ]1\#Ã%‡»Âi¸+†k¤c¸äpW8 wÅp�t —î §á®®‘Žá’Ã]á4ÜÃ5Ò1\r¸+œ†»b¸F:†Kw…ÓpW ×HÇpÉá®pîŠáé.9ÜNÃ]1\#Ã%‡»Âi¸+†k¤c¸äpW8 wÅp�t —î §á®®‘Žá’Ã]á4Ü•ÇãïñxTÏ2HÃEiëºáÒêWSO¼1œÇãÑí® ÅÁªže� 'ŽJ„«ëÈN±´‡ý«TÏ¥µÞ®®§¶n»zjÛ¶ O>©z"£¿¿ÿ¿÷ËÏôúùgçOv|ÜÝ~Þ¶U•2¯$õ¹<‹ÎS=Ë .ÕS ú¢»»k˱¨dcãç'OªžHkÑŠ ®S[·þò­§>ø«ø{ÏvüM÷^Õséë³®®¾d²·«ëìÑ£¿8vì“Oþ¯7ÞèïïW;ÕçÞéïï?ÿ—Îïþ"ññsÎyÛ>ÿd»Ú‘ÒÞ³éûÏ·¨žbÐí·Ýöfsó™={<_ýªaå³g«žÈø,™ü¢»ûÕææï57~òdŸã\Òæ· �\¿þçÇŽ�³í?&?Ÿèuœ^ǹødâÍç®¬ß  t­›7ÖÕÕ“Híª7‘èïï?ÚÒ¢vª—O&>üngOwRLuþ´óÂþ&µ#y<ž²K&N¼ë�§Ÿ¸Ôí\zÊùar¿asç¹_<Þz�ça¯÷o·o¿�÷:ÎÿhkûC2¹;U5�P¿ºwoO"Ñ3ðË'ªu¼¾^íTòx<ëV¬øÑîÝç[[Å©÷8Î'§œÔÃè8?ùÖjÏ^gOmÝê.ê\këúHDõDW¼ûmƒS}«Cõ8)‰Ã[/w¦¦úädbSýêoÿŠwŽwwõwû÷«犺µk?lksÆ ª'Ò×kÍÍî/_o2yþyÇ}ÇõÆó‡#t=«W¯~hîÜ�Nœ»z·¥E|¼rÿôâ‰ËÝgŸtÞýv›êqRÞüŽí†ëÂ3ÉoÆwWiàÓ�·["ïŸ8¡zœ+JfÏþÅÁƒbª�lûŸ�QýÕ˜¾^ß¾ýCÛî½úîôç?lÿÛW¾ÇõBë6ñPTTTQQ¡:Z¨¨¨Hÿèäßµ¶þìÈ‘Ÿ;V:sæÀ—?s+**””ÁlÜø±o¿tì½Óñw_é˜>#×ýåS2•ðìÓÉþþþÿ*qáÉ+_*þö%çÅ{}d­ÚD|³±ñ󮮞�j]vœ~Û~nófUÃ,Z´èþûïGõ݆†�ÛÚÞ·m;R”„ãD(ôߎùï¶Ý“LvµlïÄbÕ+UÏ¥»ºÕ«uû×R†a<®´,+‰¨$¥¿¿ÿ…“�‘H¤yç£?~µýµøþß¾ä¨Êø¼«ë÷Éd_2yÙq¾èèø?ííýz|üᇠêAF€Ð²eâß*>³m›û%¤>?o£-÷'µúA ñMïH$’þæP-ñ~Õ²,¯×»mózÕãhÍýwZ•žÒŽ+ýÛ_ªçÒ�»1­"/~íĶªgII—×ëU=ŽÖøÎ'Åpݬô�©že�.}¾Zd¸p|q —† Äpáøâ.9 ˆáÂñÄ1\r.Ã…ãˆc¸ä0\ † ÇÇpÉa¸@ Ž Žá’Ãp�.@Ã%‡á1\8>€8†KÃb¸p|q —† Äpáøâ.9 ˆáÂñÄ1\r.Ã…ãˆc¸ä0\ † ÇÇpÉa¸@ Ž Žá’Ãp�.@Ã%‡á1\8>€8†KNÕ——çõz 2Ÿ*»á÷ …2y5† ÇÇpÉÉb¸JJJ,˪®®Î|ª,†kôèÑ~¿_¼Zh€Üë0\8>€8†KNVÂ5kÖ¬E‹UWW[– -Z4kÖ¬L¦Êb¸–-[&þEµ¤ÿ1.@Ã%'+᪬¬´®µfÍšL¦Êb¸ÒïAüÃʽÃ…ãˆc¸äd%\~¿_¼™IOD&Se+\ùùùâ}  ÷R Ž Žá’“•pù|>¯×›þK I¸ Ø8qbuuµøg4M“áºøâ.9Y —×ë­ªª}Ð-\â㹃Á`†Ÿ{Ëpáøâ.9ü9.Ã…ãˆc¸ä0\ † ÇÇpÉa¸@ Ž Žá’Ãp�.@Ã%‡á1\8>€8†KÃb¸p|q —† Äpáøâ.9 ˆáÂñÄ1\r.Ã…ãˆc¸ä0\ † ÇÇpÉa¸@ Ž Žá’Ãp�.@Ã%‡á1\8>€8†KÃb¸p|q —† Äpáøâ.9 ˆáÂñÄ1\r4WEE…êYR.@Ã%Góp©ž%…áÂñÄ鮲²²ââbÕS ¥[¸ÎÚöOŽýæöí"\ªÇ¤[¸ÜO[+--U=ËPz>€†a<øàƒ%%%ª§¸†æá*++³,+ää䨞åîÆÄI(÷ĦMgmûíC‡~uüøÏ�-ÍÏ7 £   ¼¼\í`"¤š„«¦¦&t•išYùôð,Òð4 £¸¸XùŒ3 ÃÈÍÍU=‘¡s¸ ü~¿¸|˲|>ßÒ¥K•_¾ËݘÚ,¤{e÷îKñx¯ãô:ÎÙ#GT�3H,J‡p…Ãášš÷Ô«««C¡Paa¡Ú©\Z=€†aÌ™3'‰ˆ4Ï eYeeeªç2tW 2’=@õ\)CfÓÁßíÛ'ªÕë8ï?®zœAâK3ÂõðËkƒ‰ÿR^^®v*WúÒTÏb\÷ÈÅ{ Õs:‡KüfíÎcšæ#�<¢U¸´jWKCËûö}ÔÖÖë8‰WvíZ¿r¥ÇãQ=וjéó¥bmmmcc£;ÛC=t×]wM™2EíT®ô½©žÅÏ ûvK<ƒ�@Àï÷«žËÐ<\î7‘,ËŠÅbZ}ÏY·oο¸oß|gçÎ3�?þݦ¦1·ß®z¢­¾9ßØØ¸nÝ:ñ¢išwÜq‡Úy†ÐꟴžþVUUiR-�Ã%fƒ…Ãáh4‹ÅTO4H·p†ñ��;×Õñß*O<‰¦i~ík_›€8†KÃb¸p|q —† Äpáøâ.9 ˆáÂñÄ1\r.Ã…ãˆc¸ä0\ † ÇÇpÉa¸@ Ž Žá’Ãp�.@Ã%‡á1\8>€8†KN¶Âå÷û�€û÷ g8UÕ——·jÕªÌÿ.@Ã%'+áŠD"¦iúý~3M&Se1\<ð€øX±Ìÿ.@Ã%'+ár?º+ýW!“©²®éÓ§Ïœ9³²²ÒýHÄL¦b¸p|q —œ¬„+ýÃIÅÏðÓ6³®ŠŠŠ!S1\·@Ã%'+á***Jßy0,..Îdª¬„kîܹCŽ! I¿Ã…ãˆc¸ädë›ó_ùÊWV®\iY–ÏçËÍÍÍpª¬„Ë0Œ»ï¾ÛýÎüÚµk3y5† ÇÇpÉÉî�CøýþÆÆÆÌ_'[áÂá°×ë k×®•~† ÇÇpÉÉb¸rrr–˜6mZ†/•Åpåææ–––ú|¾ kÃpáøâ.9üTÃ…ãˆc¸ä0\ † ÇÇpÉa¸@ Ž Žá’Ãp�.@Ã%‡á1\8>€8†KÃb¸p|q —† Äpáøâ.9 ˆáÂñÄ1\r.Ã…ãˆc¸ä0\ † ÇÇpÉa¸@ Ž Žá’Ãp�.@Ã%‡á1\8>€8†KÃb¸p|q —† Äpá<@Ã%ÇݘÇãQ=Ë qù‘H¤¢¢Bõ,) ®°°� ˆá’ød1Ë²Š‹ŠTÏ2¨hή¹ÚLÅpÝñô�Þµëƒöö³¶­z}1\7ë¼mÚÞþ½={¶mØðØúõªÇjcMÍÆšÕS b¸p÷ŒÿÓÇ}âD�㜵íÚÛUO¤¯ë†kHÄ(]Û¦Mçm»'‘ø¤£ã£ööƒ~¿as Ó¿Aq+y<žÂÂBÃ0&ßu×O÷ïÿ°½ýƒ'ž(›9S|é¡j*—ûÙ‘^¯×çó©F[�§~Íš_:Ôë8Wþ“Hô&ÏïÚ¥z.Ý¥‡‹Õº¡víJ˜ãü¶µu]8¬z¢+~xà€;ÕÏŽU=Î ÷SeU¢»÷mÛý|çøqÕãŒCÂEÃ{~çΞDBع�p©žèŠ·Ý߯ç—ÇŽ©ç¼+ęݻ/Æã½Žs!¡©Iõ8º»î—ŠôeZÎüÎx1?ßÖÖ»_**œª{Ë–¾«-íK$ú’É“[·*œg÷KEÕƒèÈýbÿ¶Q£ÎìÝûÓ#Gz‰ï777>ü°êÑ´ÆoÎß”ó¶ý?Ÿy¦ÿÌ™–G=XW§zœ”¾D¢Çq.uvötv~ÚÝ}9™ìK&U•".ŠßœGˆ]=ÕØØ“H¨žEkú¥"ÃuCýgÎtlÛ&5oî\Õã¤\êì¼ÜÙy±³óbW×§ÝݪÇÄp�øs\8†KŽ»(­~UO ˆ?9�c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Âé®`0(‹Åbµµµ���ª'¤Û®„3fx½Þúúú­[·Ú¶­zœ­ÂÄ]•——O™2Eõ8×Ðð¨Ü>„ÃáH$‹ÅTO”¢m¸¢Ñh( ƒ¡PÈ4ÍÆÆÆÚÚZÕC ÒjW®ÂÂB˲B¡�mÛÿÖ.Õã¤è.¯×ëóù�€éî»ïV;Ϻ•xÝDÄb±Å‹«*EÛp…Ãá!{{ôÑGu{¡É® ÃÈËË›7o^UU•W(ª¯¯W=TŠ>áòù|^¯×=õ•+WÞsÏ=S§NU;•K·£Ï ;’iš†a¨žËÐ9\n²\öÕs¥hµ+Ã0V®\iý ÕC¥è.¿ß‡ÓŸD˲–,Y¢v*—n¿vCÎ) MÞti®ÂÂB±(1�Ïç[ºt©òËwiµ+ñû ßïO¿1MÓ*\⽨»¥êêj¿ß¯É[ �ª°°0 ¦?ƒú|µ¨m¸„ ˜¦rrrTÏr w5jÔ¨òòrñK)žPÕ¥è®H$"FÊÏÏW;ϕȗišÁ`ðÞ{ï5 còäɪ'2ô—hWqq±ê)†ÒsW†a,Z´HüR2\׉DD¾æÏŸ¯z–¡´=ªÒÒÒx@õ×Ð?\zâ®pZ…Kg<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%‡»Â1\ Žá’Ã]á.� ÇpÉá®p ˆG…c¸äpW8† Ä£Â1\r¸+ÃâQá.9ÜŽáñ¨p —î Çp�xT8†Kw…c¸@<*Ã%Ç]”ÇãQ=‹î.@ÜuÃŇñ†<�ØUaa¡êYtÇp�Ü£âxCbW"\‡ŸÙ.ö¶&²Lõ\º[±`g¼¡³¶ýA{ûs;wŠp=·sgÿ™3ª‡ÒײÒÒTä.T=‹î¢"\§¶oõ“/�³Ÿýé‘í]kUÏ¥»âiÓÞØ¿ÿÔ¦MãÆŒQ=‹¾>ho?kÛ½ŽóãC‡.ÆãýgÎüßÓ§U¥¯œ;îxûðá7XVP zÝ=½~ýÏŽ;×ÚúùÉ“?èKžéuÎô:/~t¢ãµÆªèr÷½+ �gyYYÍÂ…g÷ïïuœË‰ÄïÚÚ¾QUµ|Ù2Õ£éè¹�;{‰^ÇIý'™|yÿ~ÕCiÇãñÌ�3Ç0Œ7›šz’É^Çùéþý‹òó—”–òÂãñ¬[±â­¦¦�[[ÅQõ$gz®3½Nâ{ͪgÔWü±Çz®>Œ¶µm¬©Q=‘¾~ÒÒâ†ëV=޾êÖ®ý°­-õ0:Î ª'Ò×kÍÍ鿾֓zÇõZoâå�Úýô%>hksßHô8NçæÍª'Ò×¥x¼wà]D_"Ñ“HÄèKü‹m‹·[â?çãqÕéëÓŽwW}Žó½?8¯õ%D¸ž~ë`ãÁ¯«¾zøú×ß:xð÷©¿²º®®ÿ¼gO}4ªz.uoÙrÖ¶{‰ÞDâr"ÑæÌKª¾zýÆ7ÞniéëêJ=Œ‰Ä�[ZNlÙ¢z.Ù�=våm|"Ñ“Lö9NO2ùÿÉM˜ endstream endobj 78 0 obj <> stream xœíÝy|TÕù?ð3Œ ’X’¨I°&­lÖ*‚V@–ö§l¢Ö iP[k-‚XÛ* ¸Ô TT4Š`]Q�}ß·�„„„$d�$*¶VHr¾¯Ùïr–ç¹÷œ¾ú›ÌçÈÌ\NàMfî=÷œç!½ŽéωãúÇ 1’~„\º«�öÌ»[ÿôT¢;csµA6ùIvêgîDýcÄIP‰“€'A%N‚Kœ•8 8qTâ$¸ÄIP‰“€'A%N‚Kœ•8 8qTâ$¸ÄIP‰“€'A%N‚Kœ•8 8qTâ$¸ÄIP‰“€'A%N‚Kœ•8 8qTâ$¸ÄIP‰“€'A%N‚Kœ•8 8qTâ$¸ÄIP‰“€'A%N‚Kœ•8 8qTâ$¸ÄIP‰“€'A%N‚Kœ•8 8qTâ$¸ÄIP‰“€'A%N‚K+&y&oû¥Øq°$mÞÌߨ9’äÎ}û&!GÀ“ü%oÏõÈC�ÜøJ÷"‡A“L9NéFä8’³ª)­ê€KrÑW”–$áŽq@ò$¥´¬ n4É{”ÒÈ1p$ý›)ýûÓŽ%¹¥…Òú,Ü1Hœ¤-µ‰¸aÐ$ši‹VïGßRz,9–¤ËqJÿuî¼äsäG)’¤gÝýïüeÇs¸10$ÞËÏzö™‡ÊÎÁ �$ÉÈjΣs7ÿuš$óàTÿßhþòv¨qp$½ê®!„¤l5‚ÄóÚªÀ‹ï*ÿjIFþßüc½„3Á’d<øÕ›»õóˆ" Š M$Ïl }÷wVœ‡E’‘ÿ÷À¯ž—6·G†$I?ð·ÐïÚÌÛˆ±Ç�„EIÝñ b 8Éã{Ò¿½½æçˆ!0$þú�çEŒ Ž$u׌Èï=/î<>‚$*â7y>˜dzÞÑ/F×ü>‚$ãÀC‘ß{^Ü7A‘¤˜þÓzfï>Cðbsà$FBRwÂM $÷›.GFÖ_Nb!ÄóÜC’¼a¶ù�G÷ž Lbñ›<Hr{EGóWû~ L’nñ›ìJã¾ØIÒº×=–‡fžJbÁ˜ÀHn=b;ñ½Ê×8”$=ïaË#žç¡&p’vkÞ´_²O;øSØ8@»!i»þDrcmwûƒC HbA˜€I—½ÍšD¹¿6]#a‰ÀM $×6\Ìzx ï Ð0’ô¼'�zžß:‚’$.ýðæ÷•Ÿ DÂñ›< @r%Ÿo0dIzûÛõÌÞ 1’$|¼ˆ-BȤ È0„„'Âûog�œ¤o}ÞS—Öý0„„'5�‘xßû¼-÷É 5çËÇ�ðEØoζHI.«|dôª½A>€Dø#ý8ÀDâ�¿Bô·½¥úé8r‘ÌDFraÝÕ¢§{ÔýV:„œDòÁ0��x^[)žcUs¡l)‰XÄ~¢Ïˆ„¤KõÍâã»WÝ*BJ"=y|�Ì@âyy“l†qD½ì^�ŒD&b½fELò³Ê1’ãI·Êq’WÈHQ�í‘ÌyÈIá»|(áÉn^D$§F Kÿ$|^Lœ�›%6‘’ÌÚ ›ï"¾’ÀD·„¸�œ™ÿ h’S"|¡��t(}d‰H7„&’ûŠàËj„À’> PB2E&\’¤ σG ™—¥Ôí¶G&b’{g¹DpÌ'ÁˆøMøo,<’vkÞ´Na‹’±Ÿ­Ç'ÁÝ™Iþh½³ ‰à˜K‚špH?{·ê,mû3e'q#BHv©ÝÄFò§CÐ4¬$|ô¹íž„�¤ýÖW�‹0M˜$ý긅yl#éÓèFÄoòGëCV’ñÈË*k¼ï¬µ~ÙHÚo�ëF„�é­&,’¾õ¿r5 !¶{åV’>�Ã]Ža7±�ü®´PCï[,÷%¬$®E& ’ÞõÿÏå(„¤í°Ü8°�¸!$§ÔrsÃLrkÁ2ž9›ÌëF-$Éë]‹ø×™ß^í$ûÜÿk’ºíÓ7k&Q!BHÎa³‰‰dˆÏé)£1ÖµWf’äõ¯¹±™ØH.ª»VÁ(„¤l™k¼6‘¨ñ›˜®�Œ$WHo=Ãâyv�ñ<ÕD’¼N‰ˆÕÄJÒ­F²fœä5oLŒ$ªDü&¿7|e éãòÅ�™†÷z#‰2B¦L,$]ªnQ4 !I+F/€ $êDéh4‰’\ìªlÓºgIòÚ×±Ûšù¹ß`b&9¯òwÊF!¤ÝŠ÷#ÀQ’¾ EéX5‰�üBºÜ•iEg‡%Q*â7‰¸›HrÊÔ–ÕHüøÓð,l„D­ˆßä®ðoÃ$�«G)‚L‰lü��$¯}C¥!S#&F’lÓ;³Š$.^úg “¨1š„HrÊoW<™Þø&IR-b01�·O«�÷Ý/‚“!õ"„t* •B ’dFWF‘gBE° Kˆ$i�rB¦M¢$áíÓjã}{]`R"H¢C„�󪂒ŒBõÿ±¢ƒ$Ikæ©!dJÐ$BÝ>­6Þ7“="„t® €ûIR÷ˆ–¹È¨ÀÆß‰&‘°I˜$u÷ À1NâyÉ?)á'Ñ%BHçÊÛ‚$íw¢Ö‰`2Òñé'IZ­I„�ûŠÏŽ�¤à–¼ ˜”˜;Q£HÈ„žš´þmCÖ=�Í%I«{6UÅo$i¿m6àõNãyvOÆê§uŠøï/ßJhÚš·P×Ó™—¢ & óõ÷®V¿I§¼›YxòÇUM °óD3m9©SÄoòýöc/æ�q•ßçebòï¯ÿSÿ–NBþþcËWSnk¡ôÇiZ³�RÚ2CïK(¥M˜Ég?|ŒRzø#Dý@iËGkÍ&JiÁJió3OêÌ^ÿ/hâÉZJ)md†óðIJé×ùˆœ ”®œ¡5ë)¥ùw¶Pz\ë#Iú¶¥e›Þ!¼(÷¯ÑÂ|¯ñlú‘~·µ2·‰:_`ÊCÇš|w‘OšêJ%œÜ攕 �ëÎã]ðÅfúý×#™O²Iž]wmóO>ù€±4ˆÏê†T§ß!,Ófí¹*pœQÀ[h«(šë{~~*¡½/¬cžC0Iþ–—Ö»‰$.f, âç­CοGHü7gÂ—Š™ï×:–^’€¡½ÉeÌ•,’[KÏ"½›°%5“ÌòßÂŒL¨d•2ŽªŠV’ ˆŸ„\^ßÏþ<ƒäÚÚ®$@B¼o­‡—ßÓJ*p�vÌ)Ó0ƒ‰NïÂ`í ? TßËö;ÉÀúž$Dšñ�E'‰ç…`@ÃäüyUô�§‘$RM$@B®«µÕ±‘ü¢~‰�Ïì]ÐÓ(�$ž9ƒÿ3Œ·°:WI7ë;Ž>’h}— ù­mI�•äÜê�_C$þmjé°Áô‘D—ñ™nôvU}‡4m$ ‹—…o&‡HÈ8ëÂS IzQh�d„\êMIø¾’m9Ä…ŠqÙ£‹Ä !!÷:ËkT0‘$´ß¾‹’�i°RoºH"w_틆zˆ‹ñ8�&£H”„<üÍ‘ƒ££¯2�ô?PÑ07ü…�„ü¡ ² PIâ¢eÑ«#ëҺˇiT‰IÄ@rÃIJ‹¢³Â’]”¶DnŸIÈÄ @¿=$‰K–þ¶¨}DeÄœG IÂ’ÏŒ[C£$“)¥Ѷ!’Jéëá/L$äöyY1-$mͳ:öeÚn7—°£ƒÄ"b ÚDü0ú„�äÙÿЦȦ:3 Us‘lH$Öm‘ŒÍ Wֻقʼn«H”d ï¦ic éÆ�÷«¦Œl:¶��õ’V:H’V-4ÏF³¶ü v±Q‘õ$‰V‘ÉÐFËËIp¤ê–•„ —ÕpVO’l[ÆÜ7Ì×SõÈÊI—,²N«‡H®¶ý»Z/ÃU·l$dˆUÓå$)[lEØÛGop¸é�Õ$ ‘ÉHûû®mB%TuËNBˆë«&±îŒ"üMÖ#•†D1IâÇv‘ É-ÕöÞöiÇ`Õ- ¹¼AT/X1Ik­¯Ám•ø*¢¨%aŠHîd-fLÎ6³HH¯Úù«%IßÇ*—Ê-Ø1ÞÞÀÀM”’$~üëö,íM~Ïìmź…寺Å$!=êøµi•’Ø÷=Â/ksGy'…ë$áˆÚ{Zq6ãñÁ-,§´Okfv¡ìVyûà+Ø«µT’d泫Q Š?ý U²N…$‰Ÿ°EzÐÊ ÖwüI3=ÁºúM-þž2ßž»ÿxòØRæØ I²qÖÅ‹J¤M.ÆöKåG O¤]¥GyÐÿ⫯�?XE)}�õGõ>Né×ÝXϨ#aVš DXHðáfcRe$‚‚Äâr›�îC4…F W„$¢ôãt«Û·Môë®ajÑ÷´€õÿ§²EÕ•ì‚NªH:•ñËvKŠÒº‹"¾!Óm¯Øozôª×¾%az‰­£eÆÞ53j zçäe‘38ÿ‘t­ì ••nþÇV\ƒY^Ô�$~Âé5íML; l¸!p|wµ¥~G‡O0O‚“>]%X¯¢†¤[`‡/2Ïi[P”�$~* \*ÞRÓÃøÐÕ W†®K®o0Í”t,™Â¼T<}ÓÛ¢©JHºW « HkÎ{^Ý�¬àÛPA" N¨\S×7úȘ`ÈÀ¥âÀzÃZ�®•÷0'TÎ)z^¸ÓF ¿ro0òÎ mæ餆¨% H?ý@¼Ì=8íøëèÄáB퇂Wï??Ùë{~Uà–‰�äÒÚ»ˆ0 HzÖ]/~ ¥ŒwáøJ»Ö¸'‘Š„'çû5„jzO;:Ÿ M¨ütÿóÁßôªµ¬ã e°´Ð‡{Qø` �—¼ÿ\ŒYñÏŒk’Ä¥2‘È-¬žuþOOÏ3»3BO„ç¸Ò6Ì÷ÿEú7\üÚB2Î×—HâšäòiyP{²É›8 nI"ѽÝ*_]þáÂõ)á'"ÓŽm?\÷Ί§}ƒB_šH<Ów‘~nIúGÆæÖÄ/ñ³÷Q3íqI’¸ô}ùŠèrˆ!M”�îQˆÎ{�PÚÙ¶a$9åµD—$}€�ÀV—íV»ÜÈꎤ-DÄ@òJiUôäÝ09_H)�þÂ@rÚ²å� 0w$C!uL¡ a“Ö¾áj¶+˜ˆ�¤g¥»¢OHVSú¯á/¢$vϽ5»"‘õ Ü69Ó)Ç7$@ ¹míg†ÉnˆÖF��œwh:ì[qC2\ÖU/xsq‡íBqAÒö3˜ˆ‘ÄööÑ(Iï:èÎ$7A €ÂIHê.@Ó@^œ“€E“\ß^íœd¤¼Ck(r¦¬×¤ ŽIÚ~ÆìZÁŠC’{ªá«Ö“Œ®±/œáCâf+¶S„ˆ3ÏôDez§$¡ k  H\lÅvHÒn%\ÄIâ‚­˜;§I&TØn×ðƒ#q¾Û JÄ IêÚň]ïNI&1—2ñ‚$q¼ÛI»•ïa&r�ì}wìˆdr9jI–ÄéVl'$H<É-x9‰’©°m�‘ IHçªûsÿŽžF“ôž?)‚%9¿¼©ùMáI:ÎÛxèlÀë Á“�ÁM´écÜ(x’~u´ù0rªGÒþ8¥{KrÆ!Jw"g¢�vÃ/tÕP,ºÈVB"¨Ê¤®†ŠÐDLÒ¥z4ï)dTU™ðHy·˜$䬂‡Úò ‘©ª4$2’t®’œ€À£¬—À„C2¸¨ns ó6 É<òuí:f‰Auõ¸&"’œò;}*«ÖñM8$;)¥Ï2Ÿá�ø·ý6³¯²ÕU­ã›H² O>pQXÛ‘kÂ!ÙG)Íe>Ã!ñ~K)ew)WXÛ1#]ÛñìÒ)ʆW[•gÂ&ñî9Nø€¹`–Mâ�_z´…³nEmT¶ —$£àu£+®<„mÂ$ióΗ½Æœ½zË„Iâ]ðÅ©=Gsʤ)­Ì1ᑤçÿUáફi³MX$ž¹�rbIÌ�,’c$[ÔVÓÎ,`™pHRwc7ÃH¢¸æüÖ¶~‰çå�Áå²í¾dl±c�Ø[p˜¢¸æ<Ó„M’Â*Oï*ª;3°Lì$ž—6‡—˶ýÔÞ³ÚN"*çI4tfÈ,°¿1IÚo›­vd ýK&vãfFYt ËÍåýK&,’¤u¯»*aÊú.?vÉ»� ˜íïIVæ»›)ê»üØM$íÖ¼é®Ð+zaÙL¬$�í5WûMXô¹ù“ÛBÂ>0EC/,›‰�$qÙÛêE´tŒj1±�aŒh高Yð ñK+IÂÇ‹tˆhê>j61‘L)bÍæzs×ö�I’×Úú„1¢§û¨ÙÄB¢¤-+šzôšLŒ$¼EþmÞÜ= 3�¤l� y»ÖÔ£×db&i3…‚2ͬèêd=Ôíg ¹—»Èß3gSd²$JÂêÜÆŠ®NÖ™…Q‰gîJT‘D´õ{7˜DIî±v|7Äóâæ°I„$u;ðÒX[¿÷Q#‰çe5%ÿYÑFb0‰�ÜQ!ºåëy~Wèä8L’¶Z�O éP®uf$yj‹šÆ¬è#‰š„IÆ9Wx€ç¹ÝÁÓãIú~ðNB}$QɪÚǰ¢‘$b"{Dº÷pVp»{�„ÓK��$“(‰º&K¬è$!Â&A’›!�SgîK“dBV³‡£“$l!a]Y)ŒV’�I€dl#L �Ÿ¤C¦†¨V’�I˜d2óÊJ]ô’Mü$7B7ÂL;øS?I‡BÔ­:½$$«ä� ÿ<^Q4“Lè9äúZpí×û‹Ïî\’]‚«éª™$`²©éâkÚQŽ(Ìê$ý+¶ãÞ=5lE�‘óý’Þ> ³5iJñìïª¹Ý ™IÞ{Y‚›¬’ÏþµöŒ£”RÕ7-ùY5¥ÛQ÷`Þk¡´5Æ5Í´å$jkÒ¶úï~¨16QzPÐONE&5SºÚß05žÿ¥~C)ýGªÎœ±ò8¥ßœß‘ý”Òo1t’RÚôëlDvPzbæ€IM”ïÙFkÆ5SºìœÚ“{´ž{~~×uù˜&]«�´Ô×¢V[¶ùš6ãªAvÞ˜�º[wSýGޝ—p›¬’EG—¥øÏ¸t^'&,ZÖ–ç¦í†@êRõ[RÑ©Óa~#[F:QÛÅøQ{!›+[Ãâ.¡3®Àu‰²f¼¶$,ö¯B(Î%éyÒͬ¡t®ú!�HÇRÑök:QM7‚éï­06Wº®ÈMŒ×%„<¥¨¯5¡u!Źþ”œ…É–t´°õÑÉ)¹>’^’›kü× cs™«�% %QՌגð÷ï'!æ›ÌœœW¸¬ Ô5Ê.�_\k%ìvá'Ñf1L;zæ®Rÿ*òS !™…òµßC�‚¥¦SP:IÆ…fÎ$$ñãELB"ÆÉy5ÍxM‰¾ïIHi”œ²P›ÜPõ¯Ì|èD­F’ñá¹Ì I\¢Þ$,bº…¥|-„¡­nˆ„d•þQxHNdŸQ¸ øv†>’;Ž„;„Hd«¹$«„uW‘xßwߌ×có½0 É>,jJcx6R#zÓOÉ„ŠÈ=±0 IPl±¬P‘uTGÅ´Â6BBróxg~†¢e �·Æu‘܉’(61ˆX×q¹oƉ¹!L”$òùÍøÆJ Ÿ4†J’© ½šH&•îäGIB×[jb±­vtÝŒ7Ëšg 9¯Š½S8«dšá+cqOÐ2+=$6uM2��„ÅË™˜Dìk‚Ý6ã ÿ1«ÌËï�$Á«s[,gȦz«)[_•~WZH&—™Ê¾I‚3E ba¬œwÙŒ7˜$ë~MI`ËËbe3 9m�tÉ®’)Åæ[V&â}ïs&Öþ’”ì�ûˆ$¯±î 5“�®Õ·Xɰn³°T%–/l×@2Õ"b!ñÏq»6±Š0wa¹jÆK«Ðmÿ|Ò­z”ékûÆ|k¡héöõ$ÓŠ¬+,$~—ƒFW9†ÃÜ«xæØü 'Ék_·ý‡¶’� k¯3|•noÿk«Ý-Û$¥œÄ¿ˆÅ+ ñ.pgbáìèuÑŒ—�dÖÛ¾�„\Twmä÷¬ºörêí¾ö´VM2ý }?„�$P¹Àù Þ¾wçÍxý;5'GvÒ#R}�yw‹Qá^¼áV1ÉŒBÆÊ6;‰+–·:DV©Ãš6œÓU éYwuà×Ô]ÿ`Áj: œWKòÈ>Ö½o‰¤Ã�™"ü*›ñ¦p.êX$¤w£¿ndêΧYG0û@ˆ¦û”’pú–±H›°E•†Î«º?JêöçØ—tLÒ§~ê‚{8³%ìÖ ‹–?ôfæ*IÛÃn0Å$!Þw—;š#"ªÇÕ­fóqAÒvñ&£Ø$äÁfÚ¼‹}§[Š·²…Vue=£ŽÄóÜnÎê6 ñÎÇ›ðD„Uë.¨½7Ê黹4’�)¥;ØGpH<¥”Rf=e$ÑmZ¶pH˜pEĵ/4œ§"šDç�<ÙLéì#x=…J)ýžù㫊ÄóÂNîj ñÎ_�ºMΑT@í:'%m'ëÄ)É©ÿÌ_ËYøÌ!¹æ«üì"ŠH:žW¼Çv7Ÿw$§ÌÿB~*㊸È@BÚäòN¤A"ð½d—¸Ê.�•¦wE’¸ø3À¿¶è– ñ¼Ê6�‰ :Y3 Hd—÷ò»!IZþ>äßË x³ˆ„x^a™E0ýÞï³—YÉo&tA’¼jhí¸s’¶K?®N‡‘0M "2#Ïr«-G²YÄç$)›!¥IÝ�7]H$!žW6ZLÀ"(2Ë\žº#b´c’´ís€k”�’ŠhG%±M_ÂEp$æÂv…›w,qJ’±\RÎ!IÒª…ð=5`‹ ìJ!‰ç¥hùÇNe˜eEI:äËü9#±-(Nbºñ‚A’ФâD’ä”Ü?À ¨¬y4ƒ JKB<¯K w®äoocÅÉ9Âæ¬Ö8!a-_C1Á‰ Iü÷˜OõoA.¼sBÒ­r<æ$í·ÏæÂA‘„L�"xâ}¯¢ Ïwj<É)¥-ß}+ê,É]ûóËä{»ÌÁ‘ÏKG ó«q"HÈÍM”Á�BHñÇ ²�Rz wÈ`ÉYU”~‡­h‰$!=ŽQú»·,7HüµÈc÷˜–ÍGÅ_J¯wH1ޤ÷1J@t@2º…RŸð^¨=HÎ=B›ãFÁ¿qÝÙLé׸C�o\ {(=Î\É*–¤}mـà ùù¼i‰Èaðïwœ\¾gêìgIÚSON®è‚û®°$äì¦KïÆ[â„ÄIœœq¥@•Uvr<¦úBÔëÑ$ò¿LB2 ¦^Ž£KÅ‘õŒ6¦ü´z\7mg*Ã�Ë9‰“�lA kN;þÊ7þâ8 !Ë'@p:9߯á:À«‚‰“ê­ŒàøV/Ÿ½|'q¨íÜŸçüFïùàÉ´8I н`.–Ct=\Õ' ¦GÝpÈn u,�Z�“„Ò»RºÜÕÒº@·/ã$áô­ÿ•üw P3ö¾˜¨�“DÒ¿¾¿ô—Ë´S·¼*ŸÞŽ“D3È'�Gw»™²„/NbÈPŸdß‘û-?IË?‘-ÕŽ“s½xß‘Š�q‰‹–¹Û§$ÿÿ��›$mEUl}{�xKœÄœÛ*…ÍwUl²ö¾!Þì'±„»ï(5¥žn‰Œ“Xs7{ßQ0Šj¨L/,[‰“Ørï!þFkU•†¦æÿ,¶’ô1¼ì²6÷]4†ó/¦¬×ïËÏã=Õ Hz”Ñ:N½BNñ§Ü´f$óuUë&ÔðŠç´’)¥ÛØGpH>£”²WF)¬í8ªž3WÐ Hr)¥ÛÙGpH>¢”®b>£²Üæ5¾>ÌÇcŸ$aé·õõ5ìÏ6IÛUGë Øk¯”¥Úx%ëá˜'ñïÿÏJ¸«œyÈ$IZù^B6grPméæ ¬{™±NÒö“`½ò ÌÂg,áž)ÅÎ/aÕ�q’¤/Ã;iÇT_`?‚A’²e®à–†ê6=êì›hb›$yuôöĨš‹lGØI$û­•7ËèViÛDÓ$§­5îI»É^­ÐF’±OPôVKK™N¥“-�Ä2IêÖWLïAÃmg�V’LÙ‚ �—²‹-cÆ0IÚö§-ïAC-«P,$gÈÊGêhO–i©„»$Œ¯,Ë¥Í$9%Ö÷[´4ñKÛö²ñ§9fIØïAýÌW&’N€ðzZ]¦lšo¸ŠU’œ÷ ^u×¾2’t­”kÑÔ6éËFkuÅ(IN o#øÅ>Ã*yI÷ʱ€!tµMn»diäŽM’Ž¥ü%ÑÝ«¢WgÆ5Á¬þ±¶hk.žðÁšpq­˜$él¿þ2¤kt[A„¤gí  !´‘ï¼ ¡þ±HÒµrœðuç “\R÷ØúHˆgö®`Á¾$é^%«‹Ò±äÏÁß„Húû‡ÐHBÈÌ`uõØ#éQ'ß‚–}(¸Õ#H2Ðwt­$dÚÁ¬X$�}*„®Z$C[ õ’�»Ë~{$ÐO…ൽŸd¸¯7|Í$dbõÏc�¤øS!0 _щŒ€t³‰D7 ¹¥æ¢X")ÿ`€�y7›ÿ½ªªsGÕ  œh'!×Ö5¾/—ê0ÿ’ÄÕMÇÀÆHÞXßT×À¸×(ˆ~²™Ò“�è$@rèAÍù ™Òc_,C¤†Rú-æ€eËÖЙiN5¥´X÷ ‡ü$¥�iÎÒfJ�ïÜŽÈ7”Òï0lß¾�>6SsÊ(ýñS݃”üwÞ¸6�<ö�xÃŽ%—¡ ¸²·„hãšP±²J<ù "ÿ¥�wï’¿Ž«9sDÖ$\ñ²ÿÉÄòŸÅÒ×܉dt5ÊÍ$¿/;7¦®KæNô/ Òk¢—djqVl]½ûIȨɦ\wÑ;ÇUtvŒÍqHÈÍZMt’L;Ø.{$äæÜå*IfîKüƒ$d¤F}$³ö„¶ùÆ" ÉÝtæ:ºH<³w…7ÃÇ$ ¡ÍD‰çÅÍíÿ�Mr“.=$ž9†¦V1JBnªE_˜ƒ¢…Äkj¹«$ä¦ú^:ÆÐAâ}g…±øPÌ’�ë/Ñ0†’S˜;ŽÇ. ¹A‡‰z[¿æ&!Ã}êM”“Ø»)Ç2 ./Öˆ�j’¶Km´cš„\¥ÜD1 «wol“�«|˜%A€¨%IfuŠ�q2L±‰RvOóX'!Ã|¨®G²¨$IÝú k�}Ì“�¡JM’¤n†Yõ öIÈPÌ¢_YÔ‘¤óª´2D¡‰2’Œ<^ÕƒÖ@¢ÒDIfþü§Z Ü8PÑŠH²ý�û\ë Qg¢†$'¼3�•VBB5Æ¢„D´¼õ���&>ò¨ ïo=$d@=fó / HºJÚùµ5&îIºUÙkšÒŠHHPS8q\“\$ÝÞšHT˜¸%¹˜UóÔœVEBúùÜš¸$1מb§u‘�~ðBì¸#éˬÕlI+#!—#¶a³âж+¿µ‘¸5qCÜ•ßêHH_KÉM\\� Öji}$¤o#¨i5;ÎI†qzcØÒ IH߆«�á˜^=§5’�> ×8Ã) £º:/­’„ôªsjâ�d$£/­“ʼn3’Q˜í.­”„ô¬\´1âˆd,�L/ìÀb",®gÖnÅûR)IÇHÛQÇq»¿dÖ^îïpä$Ó D@&’+eKÏÀ2’Ne¸iLV\ïšY üç„�L‹@L$ýêHþ{ D[$$�+/C÷{CÅþù‘‘Üð,ÙR9IÈÎNé°˜¤+¨¡», vô[bð#!™Z$‘›HIzú†ÉGñ_¯^ IºÊ6Ò¢bß{ q ?b�ˆÔDFÒ£¸’Ý\uÚI·ªßÁÆ�DIuˆÉåŒIŠH„$SŠ$o{áˆM$$Â×¶™·Qp, é^-oo Šš*“Ê«íD$÷E$&b’®Õ£ £˜;ØÂ'éQw | aUšPÁ_‡! AˆˆM„$�«ÆÀG1õù°…Kr1¨á8(ªêqÝÎo£Æ'™ŒšˆH:–OÀŒBˆçÙ=¼‹-IϺëpc¢¬jÝhn+".ÉŸ‹Å§j¶d•Nã<# É>< 7J`Vš³X�CÒËÑzlNÔÕv¼™·ç„GòçCHB²y&|’¬R'×ÓÓ Ùç�l’Kï¸bEaÔœ6’{ñ"|.If!ïKÎÅ“är{EQY'øjvYi6ɽå�œŒÁ1ᑤç;½wÁ¾Øb‘ôsY Â¥Õ´¯bîòe’üəτC’¶Ûù×ɬM ’þnk¦X£¶æüP__ûƒ,’‰NE8&l’”�O;…³µÉN2Àue!kwf`UŒ`�Ü)¼Ü—„eÂ$i¿ý9磰7ÚH+ª±iˆêþ%ì?ÆvW"LIòúÜŒÂÜ&k%¢¬:p4Ê»üô³•t±‘Lp'Â2a�$­�çh•´1¶Í䥵æÃQß ËV£ËJ2�µ’ ›‰�¤íç¹övXc-¹`&¹Jm—ŒP4tŒëe™\°�ÜQ�ÝìȈÕÄF’¸ôÔŽ ^,…IL$ÃU÷÷ FG_EËœ™D‰ˆÍÄJ’ðÉG˜ý‚˜Ë÷IôtUÔÔ}´‡Ï8õj"¹¹iž³‰…ÄûÞô–v^LE® $#jôôƒÕÔ£·»ñ›‘d<{ý§“˜LÌ$Þw—ƒ×õËc<±�’èë.®©“u7ÉB³‰‰Äóú—JÿV†‚‰’Q܉o×ÑÕï½KUdùL”dÜì†ca &FÏ+“Uc,+&]�)샋.Òép¸7@„D±ˆÑÄ@âyi3lE?"‘ûÉxþ ;÷ÑFí &Ë[µî<É“Û kÇ‘ —¨’Ü!¸­í>úH"{eC$ck•‹ø7Ý£$�í¬Ç'TÈ=@2AÕY#;IÂ{eƒ$£ôü¬‡L"$3÷Ë×�;J°Ý�Ÿd"¶Ô2:IB=Ë$7ëz÷ š„I¦ÉV(;N )È܉d’Û:Y´’7¶úI´‰„LB$÷ƒ–N:‹¿uÎ܉“�ßéF/I`û÷Ø\2U ¿É¦~äÌÿþg‰ƒÛùðt®üËþ‡„‹mÝç”çél%³sܤíx~qá$�"~“%ÿZsújJ›•,“æ§ç J7肼p’žpXéšÔ·Ð“ZfL£™ØLéªJiÓq­9I)m9¡wŒJ)mÖÿ-z‡ðÿ5 ×PúÍUmµfàQJK~¢wŒ9'èñ'½ZÓ¾”Ò¯zèã7G)]–¶p%r¡)>ÿ(Ü7Bó§<³ê)½Ÿ%„ܼZ  Lø27åÿ !\r endstream endobj 79 0 obj <> stream xœå�[o7Çßõ)ø\`i^†œÀ0ÇìCHj ûZxÓ‹MºqS`?þB’klý4<$53VR QL‹äáíüù?jçûÍe”QÓ;ÿl{§î?­¾¬Ö%.£¼ë£îÚ >¬~ýI}^}Yym]Ø|÷éÓý§•UëÿÞߪ퇇�«³[¯>þ¹:ûÇŸùúð×ýWu~~öóÛ¿_)£...¯ÞnšélTÖ„¸ná÷Õ»Õ»Ýæ�éõºoÝxû:Ú>ªÝÿ¿¿U/øÔ¯Ë»ÕÙ/ÿýíóùùÙ›û¯ýöŸ»ÿûªÎo®onœqWêâB­;yvÓ(ëÔÝï+»1«bkut}«\¯î>­Î�1Í…ºû÷êúç­PwÿRçÆøí[LèBß|/h‚1Í¥1M¿ù…Ýxû½ÃF®ïJúß«ÛÆ?"€½š©Öê&Úv¬ÁÓ¼™©�.è&øÞ��a4ƶ}|¶%Òw¤v›eßD×*m­o7;âÅsv„õÊv:Æg»BÛõfm•5^·]Œ±ý62vÏȘíÌY«mïÛí÷×cÉ –,¹Â’K¸oXÛ£�{Jl�×fßbÉ5Ö3$å±v’b¯¹‹sÊí””kcy¬�ëô�Ë<îd³Ù)ïoÕöÃÃGÉŽk”õÚ»­ª†mç»CûÍv�ê¨ïc×Øæ¹ø/ üwöâ­´à±G/ çkOUØø5UE䪰€å¸¢ª°ÄîRã8ì8ƒ(‡óTð†Úpâ6Pòž p•àXɇ}W@ÝþªBl÷ ¸[0ènRU�çž‚kª*RAC½ê©ÀAU±�AµÁc%®jpd ª2P•÷Ô†¡ª®Sä´Aƒ8XWƒ6h1àÔbãƒåS6ˆÒèNŸ®MYW¸q\ÕxÛTàxÊãY‡§<¤0=°—ß¡ @ë~; s¹çÄ?Ê\:´_ÿ9H¹Fé 2ˆ#4ÁÊV\OuE4!†}Lawå NÜ+F,4$^<ƒ5=u·&>—“x¤¤Xå`Á¦…'`a˜:IBiRÜÆ »ƒU!ÌH#)ö¥¡"9›”Ä Ê‰�$9¥&qi ¢AŽâ!AN…¾!§Ë¸ñKiUxÇ*iîVåqtéÖ0ÖÝ¢Tç£TTJûêY¯äFª“Q®bêd 6 ù5#ŽrIÝåCù§$�˜¦bÄ·~¶–Ì©ŽV0Ç…ü��Yù@¶EQ<µIX Œ4b=M\ÃUdÞHåâØ4CXØIªÊBw=³­d·c4‡,eKÝ%‘;%¨@ÌÖL†iwÓø@*ßÈ=rä1¹‚*ßbãP>ÌîQU¨CÑÅE+2h%2e2 +^%^X Åî@…¼Ù±©3‰—û¾Lb!9Ò\ŽCBH+ƒb zŒ½—PcBù ¢DǤá�¤‰â^¡ ØîòIòKaŒ)v£‘û ±ïKæT%ç›rà�=î8x#šÊÊžš|G,€TI=çžIüR& 1N…7›œ=*»ÒÊ ÛSä> ¨\“|T iz¹u;ɱ¢!Ép9¯g0JCAˆ1êXŠ‚†ÌgñÁ¨ƒû¹—1®DmxK°¸v‘ŽqèZ"tiF59º<òí¸bÈH™ÓgÒ7PŽŠ®9|/‹=í=. m‚U:ĦUÚ›¾Û„£>ÿ™,(.Ðò±}ж雸»|ü>äûí å]ÛÅ¿\^A�¡o4o¨ §‚(ðoé�¸�k(°^,‡¼qÐRUÁPUX@ÉÚ}1Í~wí'tÓ7½n��vô�C`ŠD±<ÞR1!üêøX”óÚ#ëÅøn6±×1DÆfŸCKQý ç®<|¡‘=‰q~8�T»HÂBλgøväÎùb¶éí3ãÝ& TÉàù)|¨3Ö¤4Â�›�xj凇Ü1ŒÏºŠlgYèÜän,HÚ`UXP/¾>ƒ=@š‡äAûéÔd×0 /itËìf?–“x’yLîøg顸HÃlVrŠTÎ,vw$BpïiO~G´Ú¶Aßõvì®ix±D.æœ×Æö}UO¹fž©EÅuBÐÆ´Þe¯̿çÙà3ªO\ âÄ2¯ßµkË�#ÓayÉ,Ò«°¢¯ò¼a�rx^�4™“ö*µØíá�§¾½§ Ðþ`¦ÜÓ�À­~-}%'Wi µÁ †ã¯’eêžY3—pø/šeåfI~o…ž‹xlVL¯/Nì–aƒÄù�{Ý&EǦED'™L�\-k¡ÐËs/àu=úF÷mhǵîér¥±mt6Ôøá1xm\éˆ×ã‚&àôkLŸçÚ*Î…»PèW1ùÊkáðlzŠ[? =Ï5^[¿ŽÑœeR¯Ì#[|¾°Z\$ãPÑãõŸHÌJv^¿FKc›®"C%wƒŽŒm*7PÈCT‰Ðøn<!ƒ�¨§ýÙ¯ �¹e‰Øšš–¥ŠÏg£;U•�÷+NT=›š\³p¯•™Îä·ê#]éÓ¼¹ _Þû±ó»eÞ܃ª(ﯧîò ¢³$ ¢üÝÑ ¯ô¤7(“ÂRÒÞ}HkCþªk.ëTe$½30hœ2Þ6>hCÎãÊ‹ ¶ØË-iSE"tͧô4¨çô˜Ÿ×ycNã亷Pr±? (~Ëa ,”vâ¥hÒyâ£P¡Ç4¥½ÏPlIL3‚¥šs~“‚" +˜y_›ª—¦G|É x+Úì0\“žˆâäAII~Ó’¼œÐS]Ì|.r™Ï,Ês•UäϱyD”\ž$aŠ ŒY½¼Ärd¤¡ÃÆ“ 6eŽ=S¼÷<çÃ<ÜñTÞ�]ïÇïd“x¯‰mZÇT½mQ‘Ñ^¦ù]ΚgL­ÜÑ»"ɤ÷‡ÒP2�¤ÉðX“± FÅÄ5Ë1EÞôÕDâ:éb›Ô†¥ÛÓéâ`~¹·-_‹0UgÒœ§-Tã»r¤=w+çu“¯-»tʱPöýu�q?âÈP–¾#é”'W™Œh—š)[Ä ø°q~¦¡"ÞÃŠŠ¬qá3±IUáe­"‘^è¸PvFàÛ®üè«Üø+OÀ7ÅM±â[kØ]ðGMo˜qG>n,Bˆ^ÓØ0¦” �uci‰ãJº¨û¾‰ýˆ¨US´Nàv–qß—¿ ƒÝ­G6Lx­_ÌšÜÁ„.ä…Õ‹�Épï+{õ¢ Õt|[f}…¤�»I¢š*º|Lî ‰p¦Ðè*Îl8É+´§�ŒJ�ÇG \͘y˜ö+›�¤­Óœ+ċڂC`γ7I38h#ÉM1åâ9×= ˆ„æ(¶²j€×¸ð¤³ð§ªçô‹8•äÚÇB³…þ×§þ†Û$¹S~\�$v4M{è+M@9Ã)¿¡¢ñ©¢w(ÙÄÞôË‘ôf‡äa’%â”ÖÌRÏ0”AL-2·?r7Ÿ ‚*úæL#Ss]‰]‰2Ü•’¨²pAVùtÖqÌå% SBÒ²,¢U.ù2ƒ&�`³& [Œ3XZ¥Ó7™“\DP”\ÞFÅàX[Ó¼[½[}YåMo” Á(g¢îÚ >¬~ýI}^}Yym]ؘ§O÷Ÿ6XŨ÷·jûááãêìÖ«�JpRK8É›NçZ«¬qV÷Þûƒö¥�'<;Û5{§ðYÁ%x¬êŠ ðŽ <Ü@ÁÎÂzÖÝŽ ¢ø4$ظ¡ªxرǪ¥#î.Í SxííÈ`¯9µkú¾S®Ûl§ètXÿêöÓξ‹N7ë�·›âéŸOUôFGîÆ³:£®þxl½5Q» l㢎1F¯¬õ­뿬vÁX·ÓƒÇ²ížÜþ‚z¬Á…ÐêÞÆ±ÆÛö[ãëQø?ìm endstream endobj 81 0 obj <> stream xœí}iWSY·ný´;ê|¹_Ò‡ @BèÛÐ7aeg7 QPDE„6 Øh)¥–– eW(ÍN£e•§Î¹÷}χû¸cí1„iv²vÂ~Æ3ÞñPaYOæ\sÍõÌ~��i€0üoçÄß$ëgæ‚ÔDÌH6àÂý\$d7دcÿMƒ0`æÔ\€òñÊš 2l¨?ã­ÿ±é\þå?œÃo° 2üÛ%H×ÿ¢ç¿¸Ù¯óA )k—AŠ õÏhçÌÌ“L½÷Ô¡Øä\�«`9¸°³³“™ß.A‚°`ýÌ|ˆ¾þÍ™}Êâ9`|œsÎOe ?œ 1Þmf꽇 Ò{Àììì¬ÿûIºµ ‚ÃÇ‘P8~† ЕµK^Yl�™1é{mý�v¯e6ÄDEO6@­þ=ÍúÓø«%H` ¿uŽtú8’ ®,¿BPY“çÿå;o‚øT°¥‚1ŸXüôœŸö÷J��ÜÜt�¿‡;š¹ãdµo‘s°âqákÿèÚ¨PONç‚Gþv?=¤}Ÿ)¡~¯ éÀµOÔÜ}sÓ=k“u\£F×F§þ˜zïIýIKc†NßgŠ Ò œt4 A¤ðù©Ùm ê+AY}_çAh¦7˜É�äó´cSÁq3•År´´ÿ’ Bhþ£Ïkñù)ö¸Hq Côäíå¨Y?™ÄcÌn0Þ�8RÁ˜¥¾ö"mKØuÐxFÿÃ? ÒDJÊÚÍÓèY?éƒg͉Å/˜ N[f7˜„•…âW�/]\™?Ú– á f¾0³œ“]>ªšÚÇ íƒA„ZÄ¿’Hcë+@³¡þùsý/©~('f‚¤7HÍ|a|RHe¡u¢dߌYSÿãÑ�‘|*ó÷ú©ëÑ‹X–ÉÔR‚„}`ýŒ/@ÏIVؘµŸ>?¬�7ÿ›eµ1CS÷£ýZò©à!ñ‹º¹éö~$GפæC lqÿ1¾Ûâ.À&ë¸PB²¬Öû»m"´o©‡SAxT}DHr¢@eM¯캤/ Âè¸ð'v„ÞdÉyþ–Êt€˜æv—º°©`lúiv,½%V¥æy éÇu¿gfƒ]°«!SÊÚ�_zš¾-B[ý¿`*˜BU0!}­®‚k!‡à}Y$Db!à\ðÓ×ý6”QYEê‹]ôbõnWpú3RÔ7v€yB�ûÏ/!g¡­ÿ±oƼp ¾»IŒ!fz�N{ÀŠõgض¡m<¦h)AB¢X]nÝîCŒ²Ú%ÍáùW†ïügªÏkž &Ó4"ABLÜÜtß~O­®Ö�_Yüi=çço©3@ƒ¤/HúB’¾$€ÅÏÔ¢ž¥Îe~%GIÛ¿ŸZ�n«Ô"çB’.§HH ¨wñ3VMí¦‚ÑÊâ ¿žÁý×|ˆ�ž5 ÷û#![ÑâžÑÐ#X쥂‡ÝvÌØ#a_Š�£g7¤Ë)ÃWWuN�ZÜñÊjÎÏ÷]!«ï¤ç2XlaƒÌì3»EÎnJ‡_âûLnwquó˜N²"HÇ­,ž0UËhÉevø¶I–“òC Çc1HÎsNö#Èð)ÒAŸ ÆÎi_&óC?Írô|€¼’â—„£€.á.ÉT狀bãO©odðÈ€ Ð7B`~[jî•û]Üñî³La¦ã×:`?ô²Ï›p¿“ÄØâþ•à]Ü1Ÿd%™ ®¯Œõ“ÀŽÇçMP_Rü’°o�º¶é„-î)Ü‹âÃ?¥Tðf¬‹vd­öï3ì‹û]•€¾= ¼p>Y¨ÃN‡!»3¥¯öùÿ[‘&;œp@—¤³/·RÁCHûüÛH’Òd‡“ŒÕUÐîÖãoqO[*ƒA&cy/?ÙáëÏÐP$ âÁ4n|p¬®¼1+­©àáùa¦þëüNx Mv8I˜õ“^¿sšÃ|y$#©` f´›Kšìp’g¤ �-ÎË#™LcFn© É¾ éåÜ$40|Ý9ñlwÆ.ee><"EÌ@¢½=ߤÉ9Š!®îÜþOúÆB\©à¡ú ÒóÁôçÆÒd‡ÜûLa‹;NeÁT¿šb0@ÏqiÿÏ—&;ä$à ï�“ýгÅ�=ü±8ãWFþÒd‡?ç—âõ…-f‰-<4~e@_Òd‡œ»ÃÎýëâÜ_(ÛÇ£,Ѧ‚±Èúé ÔyÐd‡ù€›ý:€{�HH·¿�Åÿ;Èî°Ð�‹¬DŸ ÆdfŒÚ|’ý:0ÇÑRó|ÖÁ¤æ?;oqw»dq‹%Y‰¥ÿ–Š4Ù! Á~¡}!ØâŽ«¯iwâ n�¤H6ÄÌ¥»D/MvÈ*@w¯™ýBãê¾ÈÆTðP¦¿¾±;Ùa\‡{áH8 ì:h:ƒ¹Å=«SÁ˜dCtºG�±~Ršì f aUì:¶“¬ÜHcf×éM¤É¢Å÷wLí‚9• Æ" æÓÝÙ"Mv`Çu€ÄØâž{©`l}¡O�´þ%¥É¢jqNú>Sé~ßc/†Nc:o©H“DöyÓØ½^Œ-î¾\O×5Ÿ¾�2i²nLnгØ¡?ž” baˆö¥­p$MvÀÖÏÌnÓ“4›�[HeuSÁXd‘!pÚþÎÒd‡Ì¶àúi\�¸'7ŒEØ‚˜¾ò¬4Ù!ƒ«`øwçÄGŸ²Nv*“ðMºÞ i²Cf0õÞ3ò–« £cò’RÁ£ôEͧï�/MvH3ØPÿì¶{ê½K#®” Ë´ÞR‘&;¤Ð5ÚõÏã˜� ¥‚ 0�®q–Òd‡t¹¸{9ú °’ÐWº†šI“lq?»Ûâž{Ø‹¿t•ÖL•ù§nؤT0}QiëC“&;舻EÂL S–2>ŽÔ¨d<4åä;€•f-¡bzrxi²CŠ€¾v°ØîÊä¼Ñs+� Užl´·ûÍjò�3éÑ—ßÉúÉy¿Ô<Ÿ0x4š×W†d…8õÑ¡Íß�\ eÞÅ']Ø×g¶s÷NÞ¬y?/Mvˆû&}g¼Åýú:uy²Õl1”šõ�µÞOöõ™í„âJƒ¾¤É �ý:0öß4?éC‹ûÍ·Ôƒ_¨û«»\~HÖ7Wæ_[w`_Ÿ¹À4ÜR‘&;ĉ)?˜ Ñì×� Ø)ä�5:,«0WQÍ­%¦ ýÔ’¾ bFžt› *Z §Þ:„yï¤ÉÇa&àœñ;§ü c³D¿s›¼÷[´¬"õÕÒ^j,Ó]}+USåä; +T£-­Á¤,~I“‡�ƒ×ógÎÌ7â.l�ËÏbĬ(}µv––é&%}¥ÆîsÕáJ¬J“waµS0}I“¶¸¿uŽtbñš¾¾N­<>JV‘ì¶—–i'Þôa_¢YÇKÏ{šKI­!ò˜C›¯šùDønJ“"qsÓ=þžoqÇÑ.¸ôžºÿø˜˜­¯¾rC±vüµûrÍ.v�«4–iòR+¥Fí¦~qCà÷]šì€pí5·?dæqØ Ý~M>ø%1e!öùEš±=ØWl61Hw�«ÊË“Ëd²�úáhßë)êõõbŽ^ZX_ÒdŸŸšÝ¦ ¾2.«9?u÷ðòE<Î ]�úÒsI_ñ‘£ ³N«<Û]£V*¨ær¤,ÄW>zé­àoñÉ�ì mø�>¯ÅÏ3­¬ù-jå×””…HºªtªÑ_%}ÃÉDIE¾Ù¤ÄG+«)ÿå$).¨¯úÎkáõuÒ&;°ë ‘wq‡·ê2>Þqñ#uÿ‰ÊB¤Ý5ºõÈÓnì Xœdƒô…GºUkuñAAÔ×O/ÎOÔd‡™/ Ù�oq7³‚Íø±�#I¬ÂœöuêòU¹¡¯‹«]:ƒªµÆôòª3óÊB„-ˆ¿ ¶„D;Ùaˆ««R¢÷̬ùmò§çøµgæºtùêž‹UØÕ‘ ééF•Z1Ô[ƒKVßy î„Ô—È&;°Áäv÷W‡Å`pþ¹ò«ØcV$}‹=úuÏ…lÕ—�1kµJöt;~eñ|3Í9Æ[?9LeúÚÞìšB<}»E­U‚–òW¸e’4_ÍÑ7ß ¿Ò<Ùau´»±µ¸6Ó'Çx{ÙQVž_Óƒ__`¬6âRMQ˵¿µ¢ÁRØ`)Œé6sÑ^�¾{±¯»²võ5Kß|#ÀòKßd‡iÜøàX]xbÖ6ùSš]eÄû+„Ùj¨h/òn9ñ(‹£ê@i~¾úæÙ΃kµÁR„ ÞëÍÆƒß-6ì:À;-Øeõ�^F�D4Ùa6@_n²Ã¬Ÿôú�Ó`ý8®eÅ1Ó'Çxw…°T*Z1èkò(²êÊËò_Ž}Û‰«8_“'—=ÚóxGd=mè[¢ïÒvï7!ô ®lºgšìÀ\szÖOb¹<²ø‘Zyr²”µ«¯DEUA…­Ð·MfLYÃ:´UWS髉ËÕZ!“ÉNwTE~«£ºD.—Ó-Ö˜âz>AxÝ-£ Þën9hõôŠ#ÜW¿4Ø9F4.DôV½œ$}ž¶ËDã´«åé•dï8OSËB´ø 2Ù0|Ý9ñŒßÊá˜<’SÜ,âòC²ª¶Ð\_0�‘çÄÕz¥:oÈQwôEâòyÚ tê2£.üõgã„Z©¨)-ê©;(®³]pæBäÌ ³]û:~›­ðe½î–ò"}TÚ9ÔS£S+Ãÿ®R‘wª½*MEº >"ûâ';\~K€d';œ{ØžIß©ÌôÉ%.?tÖ5—ÕxÓ©¯YŽjí/×è”ì`Û±ë3,.²©\&“- îîËF@½L& Å5Ü[+“Éò5ªa{{ºm¸·V¯QÉd²aûw!#qèÔV“álWÍÙ4Æ_j訒ÉdF½f¨§Æçi h[7ØU�tŠ(L ¢Ÿ«àt0ÉɸZÜSŸé“K\~HÖ5›ªò¯­§eÄùôGgi­ÁT¢‹Ú@+®åó=r™¬·® }½¦´@£R<Ÿ ¢Äõâ*‰âNX†¯§¨ƒ�2™L§V†óC$®Ò]äÕ°‡£}м¼�úI„ÝÍÓ1‡N­Ô©•©ô7þrODŸ?ùÉ,ŽMÖü¼û†}I‹ŠËɆæbS…^p}]|Ü­3ªk�;rP\pP±^§V¾¼ê|0b—Ëd�5¥|·O\Ó.›L&«-�.-Ö”Èd²iWK¤¸ÎÛ÷%¥ƒ]5pwÀV´·Þ~†¤)H bÒ“ø#³Œ*ëú-àLŸ\âÊ#ÊÖVVlÕOý!˜¾Ül³J£8eOì¶c¤¸†íPGWÈFTß`O·×Y^ ëŸU†³;$®…ýÄ:ªKd2YU‰¡½ÊIs!Ü—�€T�Ò~]bRwå';X惉~±&“úºù�>Éå‹xôÕÚQVhÖ]} RßdµŸ®Ð蔾�„o;FŠëé‡R‘×`)*Î×´è¢Äåi«”Édý¢O?ÿuWke¤¸îžëŽüôÅ"½¦Ì¨;Èq²9EqÁæµ°™²¾‚ô\�Jh²py· ™[Ž1šâf¡¾:ËŒeÚ‰7}Éo²>ÖÖBc¡fùb2·#ÅõzŠj­4¡"ž«µ"¦¸P5#¼5 ³·®L&“ õÔ!®îšR™L–îf�ßæéë):Ob²ÃÄ[0õ‘^}¥¦OޱÛ^n,ÕNüžŒ¾®¼²”hjª “;%.´¥’Ëåá‹ÉQâZâk¦½¸†øjŠ2ñE¿{UŽ˜âéƒÈö*SZÅÏÑæè©µ &7Ùaâ-˜Ù&د fÔ›é“cì#* Åš+¯ì )kàV«Z§©¬Ã(qäÁR|™Q'“É.Ø¿ ´Y+5~W\Lq=Ÿ tj9¿­Û§…IrŠrÄä,}ëmj+<©ÉìW0 '7haõµ�Ù™>9Æ>¢"¿H3ö"Þç½#5j�b¢?Õ5™„¸N·«y2™¬±¼ˆ²YËá+¨y‘勘â‚-U§Û4*…\&«4ìueŽF‹­¢X¯Q*y‡0Ø‚˜Ò’Nn²Ãä=½EOnÐBYÐ`™é“ct8+uêKÏ�Ñ—w‹¬î*6Õw.D/Ý$h¯++3ê"­¢x…l,3êöwFÝ>ÛÕh)R)¡ÄTʼFKÑí¡}ö¼ŽFK™Qó>æý öŽê’|þÜY.—ë5ªKÑE{Z6b¯fè»):ŸÝsœ3¡É“´/»‚S×—T¾Š´»FW ºô´û0eMüÞW\‘o)Ï’¶±# 1•“ß Y�NS+OSŒ_ËÑs Þ\¾þ½ðgJúJh¦AV ê0‹Šu–rC[GÙ…QöU-2P_ê‘Xú~ЩÉWv´DWê$͵kôƒÇÉ÷o@O› +Qq!}Í�Þ-�„|¢3}ºz,°ß̨¶”,å°EG«Ûmà4j®L¶a_Ø"¡ÛS£Ñ+Ï?Ú7✜¬WiôX.-fßL3$S?dƒ´w øü¤/˜Œ'€w Ìn;ÕW3}�¸Hº*ò‹3lW}#Üü*”yã×Ú±/l‘ðôÙú°¾|Ûd#eÖå«®º3’ßK`ÿÅ–·ê}öŸ Þ­äo£ðú¢¼[§â¼ä•ÜLŸ˜âBìè‚G�&“våÑîWØ%ûÅ˶Å%ûòCò¨ •¤k÷_\~H^žheÜÕ½}åYyXÈ»õ“£ÿtm¯ÃÊxjoÙï¯R.ÙÆ§¢˜]êq{jzûÊIºêêtGÔw½óÝ/Û–î‚å‡äÐ…F»ÃJÒUӾ΃¿nÊÛÉxjzùª_º RÔ×ÀÙzµVqꆭ¤:¿Ôœÿx ÃØ‘Üã“Ûtœ-ˆ“ôÿ¦×ÿý8u“yïÖ©Ùíþxô•´)îâºû€Ðh`Š^ü$ ï&PLuIéî… ­N ]ËnÙÕšï7‰Ê+ ·~rD¾àØÕ6ô‚»—†”yç.6Cý–è#  ¾ªFM]ÑÝDø:ùgö ÖëÂ?#—ËhwMøg–’5uErù¾GR(óR�_”»Z&—YË °¯É\â³#�óÞ50`=ýv}rC0{ ïÖ)ç‚…‘Cô•âLŸ#Äu•ª©+Šü.—Z­0•è/^¶±Kö±«mÈÒ¶¶¡hx¤‰]ê¹»BLûºjà¿Øl3…_jé.Ðh”r¹ŒqW߸ӷxËNÒUjµB.ß'.Ï<ÁÉ7¨/�·.?$§}�Ö ƒL&khúþRH\j�¢¦¶èêtû�;}gê•Ê<…"oqÉŽ~Æ} ö²ÖÖÍ.ô@Sµ»`ìj[[GYŠÊ¾Ø¬Qå�’�J™bǸÄh}-P‹Û19„#)þsJ�€–ƒõyoÞ‹ú½©Ïô9Z\ݽð»]æHqiµÊÈ8r‹Šµ EÞòC2�d2Yg�%ògZZK##×Ê#Ê`PGÆJ@µZï¼óÝ‘â*)Õ‡óÕðOŸ©Gÿhk…ÍÞ^¶+õP~6à¨Ô©”wÛÚü5ßܬU*÷9$ ÂçóäâþDdZ7¨Oß0eèºíd×A¤¾™és´¸ìèÕÐÒZ)®Ž®ØŸÿ+�`~8>Õvñ²íâe[e•Q&“]ÛÛ YÊ WûÕéŽHqÍÌu!ÕD½2Nx‡þ12 ¼¿J ]h”Édv‡ýco|òÖö²ÛËŽ˜O›o/;jª KuÚßív?E!Þ´Ùt*¥ð=B'›/|ÔÒ:¿Èyþ™rmý¤IVa@e}"Øu0Ï»[ 5Óçhq¡šF×^¸AâŠZÕ»ßrU…kø‘@yãýUªÀCR8�!ÞúÉ)®á‘æ¨ ÑsæŠíæHq �4GþÌ¥ñ–Há/ÞîËχ¿Q¡È3[ôv‡uÚ—d›�ï.,жmïÉ껾ZZ$} O/õÓØúî0§Û€7Œó,XX&ÙPÿí7´P¦¸G‹ËZ¯²ºOÕDŠË3XõcŒ»Þ *Ö¹OÕ�]m›öuÎ.ô44™"Åe(ÐÈå²å‡Î¨ˆ).}l{�2Ì�¡zþë%‘âºxyß1w”¸Ð‹SLu¹Õ à;‚är¸ŒÌ$ãá¥ñV­Zé./÷Pâ�ÖV�JÕõš";kJ tê0‹ôjk±¾·Þ<ÍØ²×˜7N¾£·úÉEqÌ”•qÎLLïZàA óñ<œñ—nq±×{Pµ�½Þs´¸L%:¹\vãN_ä+«�‘â2[`Zè[ì‰ü™©ÙÎHq]™„¦|•Uƨ×'Hxé¯w/å‹S\aÞ}@ �4 ¡×ßÀP}üÆ]£U+o´´¦,Äå¶6�JyÙÑ ÔC�»&ƒ¶Òd¨4¬EùÈmu¹ß<“›'k¿OR‡©µË MsN§Ÿ¢8Z`÷Ý(plÄ:¯,ô«ÿ¦~B_‡‰ëö²£Üj@eððW¾A­Õ*#¿róžC­VDŠ m‚zû¬‘?ÖÑeŽ×Ý„R™§TæÝÜ UZÆ_9³%'.Ä�¡†È÷hÞ}@44šŠušg›¬#x¿£C§Tžï­P\ä>›ë¥ÁÎÚRøy¥U+—ÏgÓ0”xønŒB+’P_4 õE¥kz—Ÿ$ýN'@ˆ¦#µ úŠ×­ŸS³�S�ªvFõÒ�ïëü0q¡ì1ÜŽxw…¨©-ŒÚs-.ÙU*(œ3ç–’w§ÏÔ«”â[ÚKùmWq8�tŸ‚®Â"møgâ×éÁúkû�•Ñ+ÇÜ0FqqÉn*Ö6?D<ÊBü¥«Ë Q ¡¯˜âB÷ùo5ZŠÂ_¼u¶sж=s<½â8o¯#š,ágøõŠcŒhìo­°7˜û[+¯|o¸çTGh° vU¯^ÏÆ‰)Úv°'ÿÆ`'z©SU·Îvüîm{>A<s õÔ€KkŽáè�WSÔmëo« Wkå%GÃãK 2`E1DÓú “ÂOŸôï½rp¿²?ž§~^eR×A(•y-í¥Q§À‡‰ -l¹WUµZ¥N§ªåÏÈÂâ‚Í£6%¿ýQ(òärøóžÓur¹¬´ì»¸n/;JJàѰÁ ®©-D§ÕZ­rÊû])ñˆ«¢ê½°PSYe¬k(.äsBS‰îØC„±«mZ­’,7ûùÏÌ„øKg§A­:—²¾º"ç“õ°wn'Oÿ¼½®@§Fï�µXÿzŠòyÚy»gñá³ô&kQTßûy{�R�ö¤rdÅvž¿ei³~×ïËI²µ²XñRr™¬«¦$ÒÏ =óg£>Â\T‘—¹}8Ú‡.u"ßQô ԪÔµ«/†�ñ…¢Œ�Ó»B|觨à^6x�ëÃd*únl²™Âìè2¢â¨-f{dÌÖd3]9Э„¶K5µEÆBµ©D×Ú^¶xË>0Tßd3ÍîN…ƒAV¶´—ö3l{½n²ª÷m²î®NªÒlÑ 4¦]G—5J…y†æ¨Àä�ïn²™Î 7¢¿ÖÞÝk±Vj ‹´•UFÆSs¬²<uµrº¡!QY…ù¸«Ë VEÝ´P\¯§¨Ò]äw‘¸TмöJÓõ�ŽG£}(è°§ÚzëÍìé¶§cŽ—W�Kƒ�Èi-lÄ�Â�œÏ3'ȦgãÄ£Ñ>gs9Zö‘â²ó^ÖbÃþ¢åÒ`'ÒÕl�zf�JÌËç{žŒ9»ªår9ô…ÛÓ zg“åɘãÍUjí´c¦¡�(+;Z\»d˜¿§§ÿýäIêçÈël9�I†—U˜.R,‚‰„¨#j#†…Ë��æ�zµ³3ie!>ïé1jÔIÛA+.”†­ª‘¸¬EùǾì³qB§VçkÂ_±U˜:V•"ÅõË% Tä)y¿\úÞH¹r¡G‘—§Ræýºç*�ž9Ê‹=j8­4ä2ÙËIòý͹¢wXÇ“¦wvv‚ « ùåM·{“¢ÖˆGYY¤¯‹—m3‡È(“Ëe¨C #—î‹%¿Âhø#‘MÖü­§§P£ö´%©¯£Åeãoë‡4 q ÛcûÏ?Ÿ nuM»lS4di�-oô]½F¥ÈË‹r+E–5aq]rÀBPke´ƒMƒn«Ãg|虽îÖÈŸA^‹—öê¨ÈgÀYiþ€„•ÅÓOQ«|èîæêê’׶˵év‘ ¦¯‡ÕçÓD[k‰\.ÓéU¦=êh’ËånÏñ†´rÊ۩׫ì–R”Ø Åv{‘FMÙ¬1×|*âB5ðš�¸¢V5º�Ü[W¦Úß�°ÊÇ —“¤œ·ˆ�úÙÓm‘âÚ3?Œ¶Üq4Z"(zæ¨ Æ`W5ïí¶û¨·=�~˜'—›µZGIÉJ{{Âú¢i®®.ÔÝý-©øµír\®$t-r}ùzHºª¡©¸²ÊXS[ÔÝk°÷/9Â+$*Å¥º:eæk»Ý¤ÓöÕ'Ð�þñþ…ž2£N¾_\¨¯S+'iÛ‹«ä/—Ùl=XŠGr#š,èù_N’È»±¼(ê™ÃâZ»F¿¿L{ÊË#ÅÅX,?wv†Wé6E™µÐØÛÐ�Œ¸øü0Ôߤé`‚GÌ€—gÎì°l 9}�JúŠÁá‘f�Fy®¶*˜øqŠú²æëÛ«Jâ×Aè5ªþ¶Ê¨âÞaâBgÁм¼*“¡ÂdP*òÌ…úJ“!R\(ëCjÊã…§Q)†zj¢Šê÷/ôõð¾P¯®-5¢èYlÐ>Œ7)®ß'¨�30éòX,‘âÒóI A©´êõV½儵ùùÉ)+¿‚$é'Éí[|wXöÏ‘‘µÑÑ@rù¡¤¯în²´ª[íÇ4⦉ëG•!¿í@Mû Ï÷ÖÚÌaRÍÖ³]5ì鶘¾.�öóýXVŸS´­ÁRTfÔY‹õ®¶ÊgãÄPO�½Áül|Ÿ‰ýòùÔ�4ØUóh´o‚l’Éd aß>ñ釫­²Òd@íÄýü«EiÙÞ`~zÅñþíß;Úknî,.^hnFÿ8ÓÐÐm2Yõúb�¦D­®+(¸RW—’²öâ×¶Ó [ "!}­�Žnö÷‡’Í×%}ñ¼»BÔ7šŠ Ú½½X”…ø‘ j ùMåÑ=H¢"h° ¤4ÑñÍUzs0U¥$GØ‚HAŠúœ`}#À‚ø@0©ßûþ2ýó/)õf;Ùë=Å&mC©qŸ¬ÂüDµ†FKaüƒ&ÓÊ‹}õáûW|ÐTäåéÕʨÀt4áëí§oºP_ ó™¦a 0ÁÄpU?¹úüûËôÜ+/�·hµJºº<À0Ø•…¸E’�…5¥IÏ�h¦W+M-:qV+3î¼AÞ\¥?a X1˜T "¬ê;Sˆ_'P_ð¶£F9×fÃ.¨ƒúj.,¬))H(@¤ƒ·ÏvyÚ*;kJ,…­•¦ÓU‘åñ¬˜ÜÙÙÙ¸r%¡øõhãàñ„’ªo¼;IúZ~H65›ŒÍãÞìRŠÉm’l+.®6‰"~%Áß'èÍÁdÖa&H’¬V›�¸àõ.�ÇÏ0[$™\}þ„èkñvŸÙb¨*-ø�þ3âõÕa*¶å‡{˳‚kSô‡ÚÏàVБLôä a‹$¹Ã¯OJúº:Ý¡ÏWõV ܈›>}u™LåEú§Y¢¯7ô–hÖý|TâÚ½øO’œÓ™¬¾¨ŸqK M<}¦^£QŒÙꓸGŒ‹Eõ••š�º§âïuDÀzþU±kçh†(*@ Û(Îé Ðôg·;¹óåÜÓ×òC²£ËlÈW¯t§zÛ‹¾@Yii�>þbBƹqZì j�χõúP *øá¤¬m¾ÂŸÄ“|È!}-ÝåVƒµÌðŽØ•’4i‹¹Ä }ÑS$¢€•Ügx&駨ÏN§×l®ÿñÇTdÆ6ïê¶�ìøÛ+ÔÏÙ?Úuf®ËX¨±Uš¶y›»¬¦»¼¼H¯ýy¯Õ;ßNP[ø…sÀ€%º¦‹ƒ ’$ǧm‰6Ã'�¼“|rÅùìÒ;R¤m®.ÞÀ-�´r¤ºÚ QÝå­3Ã7ãÔvV,¾c×~0ÍNò€E›�Õj“~àß³A_#c6èˆÛTĽø3ÀQ^_w†¢½£…ϧè?.�\²™OFÉ×Û·�ÎM~zB”…ÀjµÏ««×¬ÖꌘõqµJoŸ-”+å‹cyµ¶6_£:èÜ. ߎӛÜ’‰[Y¨ƒ"�ëøc±fµ~êëㆆRÈŨ/8v¤ÙT\¤ýÅ)ÒFÜôñZ}½N¥L‡¾²)`ñ ” ¦c(Cœà††6\®µˆyC‰òÍ8õ@LõC8v¤D_WUø�Æ7ë8ÝРU*e¤´ÃºBmŸ{¥¶I0 à¾Ã‘ÉT0&Öàhú�'éú¼xô]¯uÊ>›Åï:)©`LÎ56êTʰhê »dâç¶ÓùŒ$¯ó~hx•…ð�Çó…wîMîò¬oLâ×;¢QŽõÕçÌq*d›št*¥Ï“’¾ÞÂ’`Ö(+DÓ_ø‘¨¹Sºp¹8Þ81éýF}Á±#]f£Qs�ḭ̀ š˜9ßÔ¤U*§] \Ãÿ°&©?Îg�¬õ™aÖFG·N�ú"èd.¡°AÓ›ü‰@rͽ0?¼Fg^_Kw€Ùb¨(/ø�îþžÅÆÛüˆóðx‘xÖŠëÏŽrKƒ—‚=žOgά�Žâ–Ñ¡X`›/°$¿2¬¯«ÓùuWs©ß…%‹“·[Zt*åç®OûÑU¢yg¿’dˆ¢ü¢ XQ€Ê¢¨/ “´¾^Oe(?„cG4Š!G�” Íåöv�J9F4¾œ$¡ãÕØFmïÆè, X»ÊøÂ0_ñÕÛņ Ñ4,n$­¯kéÕjÄÕ竘ö\io×)ÍÖ"ùþÑ Y°P½}ggç¿—–¾ àVLbñ§Û[‘ôþïטŸŸ¤Å_Ž©6–•éŸõgñmÇ sËét”–¢Ù eF]¤Ëè»1z«?›jp¤�Ó -Ÿ>M}ê1l„ßéLºy>Mú‚cG Õ¶Ó¦ÿŠÍn“d¥^¯Ìû>8R«VV•ž^vdWÀB·¥B@³w‘ÕÛRV0©É•éÐ×ðH³V«<í¨å¤òEâ¼i³µåÉåa‰5`KbÊ"É–ý¯3gRt½ ‚üäÊäœ{__#S××îmG½jætk€Æ¿P³—~Ê‚E§Ã®—xeÅ0ŸæÛÀÀ¿/^ÜaYܲ AŠúûÚµT.q¿ž!SQ?v¤¨Ø¤{pª[* ¦È¡ª*”*óòŽã(*iús6ÔÛ2«¤°ÿJZ_ìõ“I[WWüa |;EN´P/TW× —jj°«&.ò›¬ Ó™´u§È±³³ór~À¥ðWz=“pqŽÑ)‰+ç‘Vª ¦p¶‚‡ÂY Š€ƒƒ;,›Òþk6}ÁÛŽ:åøi[àd·¸ Â@ ]£X¤¨m†™±X„²9vXö+š ›Âí¥÷xY¡±#……Ú»Ã]Òñ T²Üf˜í\Üd†ðdؤ/§Àøu¤¾ÐØ‘ÊJã˳'ô¶c:Ä…_/q3ÈÏôI“µ Èâ'½÷xR9_>,~ÁFÜ|ug‡ùã þ5™Ì.YAkA—ë]g篵µé³9Þ{<›Å�Ê{wP_üØå9O=çÆ¿,³�ÁlKƒ$é°Ÿ�s¹p/pÌàÄ×ÌõÊK†7YpìˆA½p¡+àÊ)G\<̺ ìó³†ý9]Œ_ñ§©üUÙ¡6“I«Tæétª‡#à䨠¥�)vÔdšÈZ�$7�Nì~2¢4Ût:¹Ì£ŠÕjÔŠ£ÈË©®Æ¾2³�Y°°Z Š?˜ïs²“+ Je¸Õ­Çd¾8s€ø%ý|Yl“a0Z ŠŸù›)°A%ñøUo4¢>m�BñsgöÍyüç?vÉÄðµà ¯/ÜëWì@­_I¤úIRK�Áp£µyw`_¥ÙK쪉“ŸÝîß(J<Ö‚âÜ‘$GI›GP.é+A¢O$ì’‰‹$ùŽ$?Ÿ¼âÁÔWjÉ Ú»a_±ÙBüz‰›ÈZpÝíþ(¬¤À¡âOjïB�?øÀ¾nEÎ,:&Ò4G’[ýý"·?PÜIårJ€·¡“\©�QnÉÄO¹^HUA!ÀQÔ³œEwÉ·`_Æ"$Ú™b—L\d˜¯0rI© p¸ÁׂRiîEð$ …LˆA¾¥¿jŽãwkÁ›7³ÎZPä¼ä/W&ݼ±«/)?ŒTÿ¿Ø…s¼²xÿö¿gf²×ZPäØaÙ?ÑåÊ”séüË¿—'cÎñŸ‡4ý�a¶x}á^ƒ¹ŒµÑÑOgÎÀɰ©Å¯À‰¯ÏøcDìÂ9–°ÞnµþÑÝýARVúÁ …\®oRݾÈq)KüµAd}¶m·jk[³Zq¯»“‚o„€PÊÊ:�ç_�l¨`ä¶µ ÈÁñWá>¦¿`jt¢ö_Ù°ÉÊykAñã#o¾á÷xR1·Ùµâ?ñ+ÈßuÂ/œ# GMñõöÿZXÈmkAñÃïñÝîPŠU¯P®×7°«&®O9~HâNOÿ�To�²R™ ‹Èåîý”@–\(Þt» #Îß'èf7—ìååH}åÞþ++î� Q>߆†N µ øÁ9�šþìv ð�Cúÿ11Òþß97Ê'Ç€”µ�šÐ„xdz�â?&2ŒŸïo÷KUAÑc›¢8šÞ䳚ÌîCâ?&öST€AHÖ‚Ù‚mþöDêÁ+°wy»L’ ØÝÑã9�‚�êíÙ…Ã$gnû6ëô%îM–d-˜íRÔ·k×R¼üf¶ØöŠÿž~ˆ¢ÖØr:%kÁ¬Æ¿?ÞÙÙd±ù³áˆ»pŽ‘ßÃjµ/m6Ée:Û±³³³1>ÎjµÂ,q_±ÿ4:ަßuv>­«;±£|r ¬Vû¼ºzÍjæƒ]¬ñ+ îÈb˜¯|.GÓ¸W„!±fµ~jnæêê„ù`_ ‡ø ƒk££Ûýý_¥T0ÁÕÕº»á‘Š‹0(¦#æ ˆkƒÈZp³¿}pP²Ìa„øBQÿx<©šð ñØ•åç[ò°‹è0JÖ‚'ÿx<_\®€Ë•âå¯Ý•ƒûüKÌÙ Ÿ¦ÿñx>óúÂý¶KÈ.GÓ‚Ö°(K´½¸akÁÿ³´ô�4Êç„aƒ¦9~«"Lÿ"™X¸t¨²$kÁ4”�s»Y¨™¬o`—Ï”¬% @eñ7^…éßÈHÿ|@Äw%kA ‘øÂw\l t—0Ýô¢½?­Ï(j»·W²”‰->µhÓgqëmb?$¤¨ÏÒUG °«,!ŠÈ‚CðþyqÊ ñySÓG»]²”p�²„<�N_âlÇ [ ~ž�}ÞÔ„û ” jì*K øµk !Ä>K„ ?MsNç·k×$kA qÝ(2K­„(Îl0HÓoØp:9§÷;&!› éç$r¹û�ß»!˜hùB„©`ØZð¯3gÞJMMÇ ’¤8Ù|ß‚ä�Ò—(³$kA ©ð‚Ÿ +ä¡ïFoù·ŽÒÏ�ºðó!÷û#!»±Ã²_ÑdXA?ù�=ç&k×Z�×îwFB.`mtt³¿?€€÷ƒqLÙÃ.¥}䯴üðÃçôzÉZP‚€°EQï=ó´_�Œ¡)ÞÁ¿š¢> \®‹¥þÇq¿rï=žMþºŸ€ Ûa¾ØÕ´�4½évs p¹p¿ rA‚ø*Ðdó]}ñnÀ᪻¨”¶|ÕÖ&�ò‘�n| ÄOæp ûÑ�5n)E“a¾Ðô{ÉZPB�Ó óC�ú£B¼¸±òŠAÞ´3@Ó_$kA ™À¶Ó¹™òäÊð]x?à¥Øeà7YÈ¿]2픀›ü쀠әŠ9[poÔã¶Ër»ÿñx±òHþyxkAô¹!ù·KÀˆ Ó‰<Ï“ËèB|ý ‰ Y½m9Ï›š°ueÐ4çvûy}áþÓJ�ðÇÏ–â"шܳ²‰¬o?ojúÐÓ³.èiu¼JG© EqRUP‚hÀÔW"ǾèLµF½Ú:ëýýk££‹_ÈZð€ ¤TP‚ØÀ¡»Zñ¯ E­°A’‡�É®�Ž~ÙaÙL çsÚçuÝé’²$ˆ¨KüØË)!ŠZ³Z?tv®¹’wXöåà ­õùMa˜¯¯ þ©$HHEýJ’Üár¹\;|íìŒÇs ðjaaggçˆL…ÈZp«»û‹d-(!°È'W±ÍmæEýIîÄ�}íììŒ;°mXPYIÖ‚²€—üåÊÈãàPxþHR1¢áǽf³€}ò[üKIÖ‚²;,û'Ÿq¡vAx,KèIÒ¯¹{ E}=ojZ·Û·¤“, Ù‰5«u³³3Ä7ÏyQp‘âkRs{“¬%ä BüåØE’A�ÂÄ®[iâ’µ  Ç�,û÷�Å¥,’”¬%Hˆþ½^ßxò‘µà×ÁAÉZP‚„x€”…Ú–•Ä(ê›d-(AB‚ØUjª?˜ î5‡¤z» ‰#àr¡ãà¨ú²ä½p?£ يϼš¸°1ïžµà°d-(ABÊ€W5)ê/šòY¢d-(Züüb‘s endstream endobj 82 0 obj <> stream xœÝ�ytÅ�ÇG6c/v‚9œ X6!$!q²ëÝõ汉w÷±!!À&1 à@ Wƒ±±Ë6GHÀæN¸üx,‡ÓŒoMÏhF£û–FcitŒî±4’FÍŒŽ©}ÕÝsvUWuM#>$Bêžéþº«ºê÷ûþªl6KYuÝbk/ �Y°€[—[}…Ê©7À=+ÙŽ.ZsÝIF_Q!±âv ²ñ–£—^À5EÆ_U¡páý@æÁ¯Ð�>ÿtä÷̸°‚`õ�bëe”ƒ‹ÖÈGǤ«³˜“~²øÁµ£—^—:ðßÌ»Fë8íf�ú“ÉGK K~оaæuZÃgîÊU€›—N5,‰-_6ùbMç’MJu¸söàŒ†%wäš~ÁfRtÙVœ:l8stfÃ’ÙtžWm‹ÖáÅj„£àÝ §\Ë*Ž–†%³ÿ´-pwûý‰šÕ„C�Ó>¶ Ý ÜǪŽÖ†%sìiÚ°;a•JR< ކ%c�öÙ…êNXx%£8| +©5ÅskANß—üœUΆ•äMZ„£Ý gÿŽQœ‡ÞÎKAÞ£E8 Ï�pñŒêäÓ°’|ðåK Ì�À>AϳaÉ E8 Ê�°èÇŒâäß°d¨Žr'0OÐõhX2ÅÏQ¾«`Ü Ìt}–Œý%Ê·ˆ;áŒÉÝVJ„£ Ü ÌtVJ„£Ü §^Ï¨Ž® +Éû©~§åî„d¹# Ý–Ì~õ�Åî„ Ý”4,J„ÃRwëÝ�†%C‰pXçNÈ-w$aTÃ’)þ³ê·[åNXz#›:Æ5,J„ÃwÂJÆ º‘ +‰z„à w—ْ5;Þ2^AÞQ™îN`™ ïlô¾`xÃJ¢nb5Ù�°è'ôçfÛ „á“Ô¡™XMu',ÿ]ðtBØdš<”‡‰î„ó˜Ü”�@8Wnž<뿚¥£›rgùèØè°ÓD}TM¬&¹X'èÏ£÷¹£?d^ïC‰p˜âN�Ö#¢óª|Á½£¦ê³gW�‡¥7Á�pÖ�Lâìx'uÁ=ã.åqM@ØCº*ÃÝ ŒåŽ�~˜qÅ�q·yò´A'‰¯0ƒÝ «Ù’5;g]rgØ$}ʺCÓÂrŽÐHwëý¹c9—Ý9YjŠ<íaáL¸Bemœ;A¹žÝvÅuû'=fÈsàã9u«G�r'0–;nÿößuªÌxuöÙ#¾ÙN�b7Æ�ÀXîøÈøK?n¼>oûFܘCüùÈNò%àN ®G”ÃãD£©oÊØù…ý�áGú?�=E¾HÝÝ *ëe¡è”3h�U¨Î‘½SÞ¬_¨¥˜uv'¨®G”ÁËÊN9ƒ–X¥aê86U—ó+5��®îÆrÇí{(÷Ðl˜>ûG•¯Fµ"Ý Œô‡÷Rï¢9^mˆ:{ú°�•*K½Ü LëþÄâþoŒ×è/ŽýÃÉ6ÂŸÞ ^®NîÖrǧ�2ÝJC<·‹È›#G#äÏ$Gèuq'°–;ªwÊÔé­ÏÁ†Qµ¹ uÓçòV‡q‚¾í¯ì·S¯×C•$û»ÔãIä F¾îV7åCïk¹¡Úxc¾š¤90ÞA;„<ËÏ�ÀºÑck»¥ê˜^ú�j u�˜áÉÇ�ÀºÑSl�rU±fN=²9Z9Î4?L´¸ÜÁíN8‡¶*žÌ ôª˜—á(‡ºôG‰áC^wc¹ã¶×¹î¬"š¿>‡Gº ‡‰?Kº.wëzD;x«Ž*¢Ç9ÏLb�hIÀÚÿBºwk¹ãcû¹ï®l*/}ŠË&ª4�`™tšÝ ¬åŽ»3\‰²i&À@q[Psôš8ÓèN`]�ˆ§SÎÀ¡YHŸèdîvÒü•t#šÜ Œôm¯ñÞ\’Ò N}“>®óþF²�±»X×#ÊHƒrãžèæ8Ëî‰ð†EÞ%LP™Ý ¬ô¬4(7î0‡>Þþ¤iÆèN`-wÜ™O§œ�k¼Wë)�|,1û ö&wëzDÏëæ5u�iÓÇ=Á×í¤ YìèîærÇW.ƒ•’PŸ†£Ë§jÅÿoå°QK0Ø¢é I0š;�u=¢úZÜ�#ƒÌ/é¦19ò„ð„ôÓ$„û/’QÝ�ÀZî¨O§œ³>%½½É)hF¢ë£F´ÊC¬ÁPs'°–;>NXz1œ'†Xô)KOC‚ÐÅAw_¢C–ÇYÛ\+uÚ%.A¨lBsGMS&–HZf‹ìN`]�H- Ê�#x‚þ6ªŠf©ƒ°&FšÌ ·Jòøf�wEì·‡`í˜ØøZ‘Ùg3w!MÀîærGŒ7ETkC83E„5�°Rša³$�ƼÕÞôŠòL�úš„ãpªµ¦yâÞu„ Ö�À:AÇ{SôÀ1 n`u² fAXS{adÆ)Êãˆ#±„Jw"y&PcuÏEQWU�ãš.a†s'0ƒ’¼)zàèW3°zBíÙ·„5ÂhÜQšèDyêà°øûaX‡äcm>è×±©G ãNXΔÌbJƒòÓCÖ§Z‘çCòxa£VKòøäþ¹ Gòˆs²>8Ò�‡øÈ6!Cˆq'°èó¬�r&Dƒoó„"χä)™ F&IžvØ.þ¾=1CPì¦a$,AHŒìÅ1ÿ»RŸOQçZÌiP~X«³ë„ò×Ha"1Dy¼¨#RkJž^HNˆŸ bÜ }¨Þ]À|K‡;0/5Qž:˜(•å©„âï'P-ËÓ ûi_ˆŸ€áÜ §ß­¢ƒ7Eü ƒoõ$¶eÓÝ­ôb‹�І…”<ÎhB<ס’´>ô'ÜíâÜ +ÈúÜ)g�kðmŠà ‰ yªf`°#gªÒòÕ30èŠÍª|!Þ¢‰s'¬ åý½)º�eðut ìô�pÊgÖçÁY8uéË{úb0SŸÑã-š8wA:å 2 ¬î¡nMÅ<¸Ñ}2‡·hÞ‹q'àôÉñ¦´G£ÑèD¨GWJ¾¨¬Oå„¶@/X‹æ¦¯)å±�¡Ð'×›Ò #¡P8aÄœD«dÐl4Ø�ƾ[¡Î/ÎÀ¨£ÔGáMé–âåƒpÎ¥l`uøÇL¬Ë©!Ü´†”8=#+ì£ô¦ÈòB@|‡zêKõþã‚à¨õu¶'(—·ÃW*ÔKúyZ;Û¤|oy½ËÑØÑ&{N*}mÍx šãuÁŽ<?Yaܤ6ÌÔ“MÉãœF3›6Ø6a\(E‘¥iw�fi„ãè?üsèCNñÜ– aCâ sø«=žàI€åCzF~tDÎLêƒõ¦¤ä†ÐOmpf¼ÞS#”5xœCâ8Õ5�ð¹KÛfDy¼pªÖQ1Äs§ƒUî–Ù9q¬;T&¸jz°×Ú=n„ÁW•½²Eózšaìì âqxoJZž.@òÄ3‡üsAðK³ç>Qž¨8{vÆÑH­[zžºÑ·’;Þ¶ ·_ âlã*º]cå²7%-OìCò’)­®¯†‚’î¼ ‰Q!)"t£@C··k„‚Ð {cš’�AA4ø7vÀóñ£àºåTq$}HÞ”´<ô�´%#•Çãb_‚Æú(öª%H™±UÉ3ên(ú$k‘¤î(œíÀ8ËÇ[¥t6ø2ðÑw�>+Ÿ"¥AÓòŒ ØA›4ðÁ‰ÖšŠ²$ÏT"-O#”’|Ͱ�+Þ°(�PÒšƒÊ9umº°FÍàÛ‡F§‘Ñ=[à»�Þw“: Ö>~„ð)y< èIË–²N'�<£Pœ6U"yjä g;jPYò ©!’ÈóMe49ƒoN„Bc1ÃzÕˆEcç.`Pgѵ�ôIÊS‚CBZžè4ú_× ’§Šåœ$�svVÚŒ¡p®<è¡Êz�;û†³F;UqÒ´"(µÓÊa8­O æ»’7|óÅTu–‰‹ÏôåqU¶MÁˆ;CžtçΠØ÷”ÎÌ69œ-Ò‹½8Ðk|RÈ–§EüWïÍJ²”Žúsf¿D«,ú!ˆŽ«/)ñvy¡¤©=О4–µuû\Îzin_Ù�¤•õNWkw»,k}{·¿IHM»¶Ðœ>Ét)^Ÿn©†³½b+HÊS ¡ñØ�†©Ÿ…s‰„Ž¡§, £Áq8]™#ÏŒ E`8cXP­SÄHú¤äñ$  "¼QG…q ¥¤«w&à´Љ"ñ½ñÜFô™k FÎAL…·ª;ÅÒÇOàôiB±ÿ€¿^î"êúå™WM0î)mîßé¥í½åÉ$àl� J¥sžòþ&A¨î™œöe¨ã�âb;åxƒoJaýÔgú«Ü•BMOu‰£rDÌàT&¦œî®YQž-*Ãb³™î2—/�Ò_Øå:üâî#™3©µ*êdú™wæóJ]#Žîq|X©l g`MËDí³O|R“8§#b¢B|ðF�<î¹Y¤½gn¶�Ñ/�X%¡„ã-E<þ Òû=gE0N}êÑ#TOhè4Ý#=¤¡„gðMË3ˆ:Ã>˜lƒÎòºúú 4òŠÍ‰M¬ÉÓ$¿‚¨y¡èò£u»a)&[±_è~Z®‡…OŸ^�ÃD+û•‘FrHgðMË3Œ”é“îXpôÌJ]£KpÀ)ñWÕHžv9a*ŽÛƒÒÀÇÆm'áLÇQ…¡eý)8yÖ(täÒ§¬m`8Ø¥!˜ÕW]¡¥Ti`MËCoƒ>)/*ô‘ÆÊ²²1èΖGv»hn„b(Ú[? ;蟆söÜû¾e NŸÿVè³Ë„0¼?B‰f+ ¾)yêá´#-ÏlLlPè„xFãJf ûQƒJÉS)eIwì '‹®Þ¶ §Ï”ú�;.91Hý'p�çè“”Ç3…†ãIyœR] ‘<ƒÒ˜CìšËaÔ!PÞP–§îKÞã1øžâ¾‡‹‰-ø‘Ùú”Oú¾ ×À„Í.Wim× q¤å¢sU‚à ‹òT&âõw§ôb�]‚àèÇ�¢<ö=û‘<Pg»*£Íà÷8+æÂŸ™«OCÌÔ'r�eXƒòè4&[’òxá\htv<„䑇…­âkÜ3#ÃSpÒ-Ësð)ð’'”>�Ju¸W©|²r‘aõñO±~v¶Á·%:}Õò­) 'þêƒáQ¿³Ur†—µwûÜ Ò´®Äšµ‹¿öJÞØÀK®Øíðõ«ùmþFŸÅJ‡ªQú8C¤Èæ` ß º•îžOâåP°åë}–(«¹ž2DO¸SË{Ñ9Âd`MÑ‚†7-sñƒ‡ý †í§e¶þ FŸeJ31<–µ±jmª3XÓ„`|rÎÔfÿ–ùÑ‘ÀMÀNW&“õ×ÇÓü‘Ž!-+°V´÷Ú²œZ‰ïa&`gmPö´¾ú8úÇ8üã _U0l;�Ë5˜RÜÏ*KstÕÇ=ÚÇUòD3øªb�º'.ŽaÚ×¹Ê�ÚtÔ§*ÚÄÙÙ«|UÙÿ�8àŽ³1òØ.Ølœ>-q¿gHÅ૆ý5®G¬[ŒSÇfû’rÿ}ôq&óª%ìáY¡–óÑÙBN¸_ª,~ÓCWh0O«b—æjí¯Ñ6êÄsïçIâØl¶VÿlÞúTDüy—5q¯!E=Äj�aRllĘÕYŽ©…û‹}¼q�AÑê¼>{yð«OkVÇf[�Y"�YG rȰ¢œÁ÷(q5*W�Ì¡ŽÍ¶ò>n}Ü£'ŒÜÿNi`}O}›[6¯âcÓ§*Ún@§œ�h`MOá�ª¬Oá®Ïòªc³}A/Ðõiž®Òs,ˆ£:Öä˜L¦xÞå~tÀOóÚþ䋘í}©úø£:�qTņ’(�GgëÚ<7gøfm(u}JNŒò/‹ÉŽ£7ÃŽü� ,Žfuþ ó±jú”GzŒívduÆ�uzDàtÀ/õØVúÛšôiÐw ªBÝPBXϯÎ÷õÙôö?1M*TöÇ\æx£}¹ÚyÅÙ„spqNÜõ:ÃGM,ðn‹Ãø>̵±€OdqQt ›>žð€ÝN’Ã�¿Uÿ&§:×Y\,ø1‹>µñãfí-PwCVE%‘ÅÅÂëèúøâ&®+AZg†…{¿ «8(|xæk^ɸZGÿd± Ô§ ïcB…’Èâb1n7í´>îÑa3yf::½ÏsÀ…ÇRúTE»L[ÎF l‚¬K"‹‹e¸¥¢$}Z¦ëL ŠØ_åVçö³ RÇf;·‚ènùšrí¢ÏR‡¸½ÆDgcÂc`_x6Vlæb?¤µaé°'²ø8³ðu„sùnΡµ½GÕÑ’ÈâãóÊðØ ˆ)L7µ�kÕ¹a©ÑêØlÿ¨Ø¯¡nF´m=’jû«¢9‘ÅÇWsÃcÛÖ½ð¢Y}aÉJ:‰,>¾Ž[Z^kþ”“·ùŒ”üút“Ô±ÙVã¾ÿ3&Äý\hp&²øø.î ž6|äÃ=ܬ×f­Œ(‹OO<]WÛìX•»ØVXÑeñ)iýÝ8ö §:?Ë+‘Ŧø­¿a་´Í�¼Y\`ŠOÔ»ÞÁà–Mp S| øƒA1ÞÁ —1ENÁn�ò¨!¡xò¾ê˜ú>ÏS|Šö%øHuÈûc«²Y·D˜âS´­îû6¼É7Õ1‘Ŧø-N¡i'i:Ä­!ÕÑ5‘Ŧø­¾ðžŽâØ_ägËeV¼ÏsY‰Ý¸}›~[yá妢"‹œ»€mzmà@ÞôY•› Hdñ�)>Eú¼©‹:‡øªŽŒIdñ�)>Eðm¹� ß`ð�K¬–$ Lñ)Ðe£E¾Á �‰,>0ŧ@J€åß`�Tam!„]Üó @ïá �Èâç®ü9}¸ƒÆ'²øÀŸ‚|¶Á%ï2¯†¶Š,)Ÿþ=i‹LUèÖÖ�+>E<É ÇïïCa#}Íe ÁŸ¾"IÛ«bb"‹ \ñ)à Ðs9*¯¶0ðÅÆâ_ã¯\cšg0hv"‹ ¬»í}¡ÅVÇã¨4?‘Å®øh Ðó ×›`LÑ\ñ)ЀæpTZ“Èâë®c@Û_Ñ®ŽU‰,>ÎÁ†Çxh]žÁ u‰,>pŧ€)@Ï㨴2‘Å®ø±ýuu8ƒ›i›o" w�Œz€žc0x§Õ‰,>¾E¸µô‡�hV'¿ k ÁŸŠÐÚƒ…‘Èâc-é¦þ¯ŽvG¥Ö‚+>Á µoÑ£ÂÚB®$ÝØKŠ+‡£²�Y\`‹OEr+àµ;* ,‘ŶøT$Û!®}0xG¡%²¸ÀŸŠd µ—×`"‹ lñ©HÚ!®ÙQ©w…µ…,źë@FZsýžó¬¾)ÁŸŠHhÍå5FTX[Þ]d‡¸ÖÁ`!'²ø …ÇP€^kyMa'²øÀŸJ�ÂwjSç6–¥‚ç˜âSÄ–U¶Ó0«Ž’¹ÚÈ k QŸ¢¥….Bo6Bb üHdñq±2|xŸô~>õfFu,>ŧ÷$Ã|‹Ö3©³¾P�)ú�S|zÛòÔ_N&ÎÌÒ˜Tam!ßɼݛ37ÿ\ø².÷Ñ 7‰ŒâÓuÙ¹—?TWg¾%²øHŸ^™ÛRаu©Iæ_"‹‹dñ)fW¹"l]³È¼Ldq!Ÿnù&öoÊM™%òY*x¾qò�`3i]*¼>ó6‘ÅÅâpûÅJ|K™Y�ω,ÝùjîÐz~'²tç’ì©™.K’¸(sj?ïYús~*4´éR«¯¥9O.Lµ¼Âº@ùŒXØüIIdéÏ™÷|’Yú³âæÂIdý?tµ» endstream endobj 83 0 obj <> stream xœí�{WSçºöù@ûC¬Ý¾{ì½ÆjIá¨"ˆ ¢ˆ"ˆO2O xªU+­x@É…Sð) ˜¸SVvYµ*| €HYYxÝž°–6ý‚ee¿«ŸE ժø²²©²²øKZwRQÏZR­ Є鲲™�')ð)0=؉µÚ'Õ?€"Á¯ZÒtŒ=Ö�T˜˜àº%ÅYÕõ#P$`Wò'˜T€ô@:–bPQ“š++{Mú €l¯ßIE}jL €åõâ^\Ño^õ)°* °ñÇTöb�QSee·ÊÊ®‘þòHÇlYÙ/ªU-h©^«¥?(TüëÂÞ4cXÓªIÝ"ý�ŽŸT«ŠNøÎkuSÀ&  P™\?OŶ ãÿ{Yµ*ÌÍ¢º+i~c­/nÈwúý€Âe²¬lBëZ /£ÀÜàuI‰§§ù� ”–À§€ÂebcwÖdYÙ—ªU`nþw}]Rô µ´îPòúá<:Óë]±M“¤¿*tðÛÆö ÜÝ7¯þÑÿ¨¶¤îS ‘þ:`SÌ”•Ý„‘^(HðoÜT/îB�”•ý³¬ì½jRaÒ_'lŠ›ªUMÃH/obî¡¢ÃS`pú 4Kfee]�fdzJ¢GSg¯y‚QÈ7‘uH!`F*Û?::Þ4#Ó¼Ä „šº«HEPZÈõçÌL$yýúŠÏGúËqë=ê>çRö› t@æËtYY™sïG¤¿4( #Ó´LQË®ø|‹4=5 P™‘é™UêÖ{4%)ÕÔ*st¢) Ó¤¿@(~$š–h:Ì0ËJ #©&µÔ×'´·“þÒ€0ÑZ_@fbMjM2í—i¬ rBèE=¥(Ū&*‘e…öö`_ßœª€ReôõPÇÉÚØZŸ¦üaÚ/Ñ“‚‡ô× EÈ,B·=JÏÒÚ1*A ýêñÌ‚U¥ÇŒLûƒìèë!ícTlõ/ÌM ¿ÌøWáV²I¡yÕƒdŽÓ4)‰ad–U>Á펀U¥DšZ_‚ø0ë_õùÃÜd˜#ýµ@‘°âó‰ N~’úP¤éB—\.Ò_2ä�µ> «’“Rôœª`³,R›úÂÉOR± ³lYYÙÞ� ÿ(r&—¹‰eNO­/™&óù%ŽXÒß 0BM éŽQqZe˜Éææ05  ð@³èÌKÏ…yš_:Ê¿éçŸui~ZeûGcÍ“Ë\Æ&¥Hdy��’èëa(•@&(ãQ�€�hЧ”SÇI,+²ð‹"PH\ £óó4‹23%sü³.ÿÒÀøÆ‰§Œk}Ú@‰½FS!¿VƈNòÊ*¶YOW‘þV@üš¹/…єĮ÷æ±ã2íÝxÒÁóάÔú´OU ˆYþÝ Ò?(â'y3’r¤¢iI=”‘þ† ão9¿@ó ( Ñq½y‰ãyçÑ/ªºÎVe¡Ö—äTÅ¿;� ‹ôOÌN²IÞÌåñH까ôwI™\A“"=þ– ˆlÒ#Ï;ÅAx‰V�+Ë>¥ÌÿÊ ¿€¾|åF³`U�”´“¼Hæ8™¢D†¡­0%Js¸HO® ^Lå#SHù Y°*‘A³è¸ìF°*Ð@Ï$o†UªI)Þçõ’þ.`Óa6 ³“á4í~‘ãeûŸí¢_¼UEPÓ%˜@€xôOòb-�`^^f–�ë=v)Í^¯Ì²« Cú{€5&O@¢±U¥´zͤ°dÆŸËSU ¬tÉVvÀ"|Àè$ïü9zî*ûó(óË6tL÷ÁJ5)‰ã‚ÇŽ‘þŽ@¹iò‹Ô¤àá¥ä&…¯«Äx)¶%±©þÅMŸªÆ›'eë€2£“¼‚—}5Âü<úA¿\fCCºïª&xì˜È²aX%VOI[ûâÍBâ6£ÝJbý9»±š”YeW-$€%�¡IÞ¥“Ê*Ö¤Ö¬ê+ø œªÂ ÀøÏÿu>ðþ„jUºk})¬*¥ÙmêT¦a†C©(] MòFk}šzu‰9Ým8˜a È3ÊxÔ'«Jq!•¤Ö—J¹ñ©©0LJ™€Ìú%(¥ˆ2ÓÄ0z&yk}šzy‘YÝ#W, À@žáß�àÕAÚSº~‰›ÒqŒÒ:X1þd³W›‘Ìù%Ö/°“Ë0Ö”Ê$¯Çƒ'yÓ6N$«õiŸª.(-èúOU ä�K¯ÐDˆS¬*UkŸ®Z_R«R›+²¿ªBæ&—¹É 2áEú§ù@™äu»•IÞM×ú4õz„Œ,²€` ð;±L_z…ødkc3¨õ%­²¹¨N® ˆ† èù0É›ÎJ„AöWµ>Mýú¥�]8ø–j�¤<@q2& ¿¨<ᓵ‘g\ëKy]•íæ HJý“¼†j}šzsÞ€U‰4�:À@ðKì¤H� h*éR¾MÕúòÙ_ @q£’7ƒZŸ¦æÏ°*ˆr�?èñ‹Œ_bµ7É,æråPk7VLÊë°ŒNU ˆs$Yz#(:'y7SëÓ¶ª³.ª È.~�ö ”?èÑŒ2Ì~­/•[±1ke@%äYWàM?œª€¢Aç$ïʦk}‰š»Ê.žÖëS d‘€Ä)')!™;ä²Ö§iUÊñ-k§*HŠ �“¼ÙªõiXÕ(»xÊÈ]Ë*V§* SBg¯S—žÑI«µ/÷µ¾¤’Òn»5bUjȉÛh@ =“¼Y¯õ%ê—Qvå¤^« sœÈq"MC0�Ê£û–Ò;ªy+ÄKLÞj})Ü*[{–ø0‡j: H@A¢s’7µ>m«ºÂ,7’ìñHª½’þA…Ä¥0:?¯”Âø„Ë )%^*ßµ¾5À¬-ZW@œ�“þÙ€1ôLò 4ýæs6Gµ¾$Ve D^¿¨‚  “‘ß‘¹Fæªõ¥p«,5WðaîèD3/ÁZu `Ð3É›‡ZŸ¶UI�`@?ão¹«7²â $Äòš¢Ö—BÙ¨ât’I°* P&yi:õ$oÞj}ÚVe$G‡Xv "€�äLþæ› são¹ÀÆI^¿@OɬIj}IOU¢Ò\‘¼/Q—¦Âܤ’ùHûEx§¦&:É+%9Iå¿Ö§)C ’jRAˆ’À¯P~‰™üÍÇÇ-0e­/ù©ŠÙ| O4C`ZÞ©­})&yIÕú´­ê"«?"€�døCT Dó+T�Õú4VÊ^ôÍÕ^bfd(¦C¦¨0M¿£éd“¼dk}šúuÄ@D‰øñ$oˆŠJ*ˆZ_*·’Ùøƒ¡¡‹*™›‘é€@A`*BjËA²I^“Ôú4õúKFŽ–|¾w'N�þ‘äÁ�þ¸IÞªõ%“¬Noâ`5¹‚ €I�hZd˜nä6w­OûT5l`U…IJïNœ�‚àR!tæuñ)Åoì”+ÄZ_2á¼ÅŒg¬”å·�˜€´“¼+'™¹Ëä�(ý©êsó¿8x¾¯rK>ÂùÓI„�_*žZ_Rmâ` qROòš¹Ö§©ùs¬*¬æ*þÀ¥‡’gñÇ)>Âû嘓TqÔú’ˆßÌ’%HÈ‘z’×üµ¾DÍ]e>3`U\‚ð (°¤œb÷ñaŧˆ»IÎÝ*ÓÍ8D±*8Uy$õ$o¡Ôú4­ÊPŽî†àÒ@-a¹ùäÙ"¯õ%S¦± Jáºð«@€ü�b’·àj}V5Ê.jĪÔ-µ\쌊( y®‡‘?Ú°]:ö#Ü\0ÞµÎËlt�<é¿L ÈI1É+ø˜WÈÍæe(ïoj(Šô_�+fŸ_dFEm~+‘Z_RIt!V¼¨Ôšº¡þä�è$oâ�TáÖú´­ê @Ü99-A�9a„ÜîÄIÞà ýê"yûȧŒ%€p\˜ãÂàdxnøìoƒ(‚ÖBÕAòP(’ŒDËÜ´DMI4$€™�ä o|/Ÿ`‹¾Ö§)C ²šSÀÿ¬kì3<7¬¤u@­on¥³'€LÉôÌ*¼Sc,"TS–b'y¶„j}š2”ÀÇÈŠo|ñϺðcvJ.Ú}}y�Ò\¡»8³Ê$n"ï@/JÐ!E-"Žæ-ÁZŸ¶U}alþW‰fˆ6?ÁcWC¾‘ŸÒÚµ¾l¹•¾•€¼ÌL��/³—^Á;H�@QrÂ$oÉÖú45Þ@ûŸ¤šTÈãY«21|�ö‡”ßçý µ¾ì[•ž ¤˜ÔÄ¢vÕ©‘½^‰eŠ’Öûϡ֧mUg�tª³ìB¢š®HúoЀ_¥"Íé€È@­/'V¥žO×úRR4«ËŒ²Ž~@€¤ê:Ùë�Nòé—…–Í‘)kÕÏ9UA°Y™xë ¬²ªUA­/Çn¥ç`æ HFçÇ�77 1“¼PëKoUF@dŽÚÛß@0i,Ë'*�¨ñÌÃÞ‰·^eìL*V¥«��&Q’~±fa!ŸŸ$C­Ï¨UO™EèûînÞé$ý×^¢ „¶lÙµªêêê€èV†yI?ÀKJ¼ÌúSŽ+VáŸý¿û‘H„ôK Oô7|y½µj}†d4Dâ8ÞéœÙ¿"xˆÐÚÚŠ²¬Sa·N†È?·KQ²º¼"ÕÁŠŽD" }Oú%fÅç ííQ“Z>µ>ãVe0Dfˆ&Å–-[l6[Ô§Ê­åÌX'ù‡vIj­¹"ù80/1�ÿ¸:)Áüoé7É µ¾ÍÈpDâHcã?þñ�¨OY+ÊÏ>ì%þÄ.i¥Ü³4‰wBHI7É µ¾Íë—+Œþ<<Ñ܆µêyä-ÇÝ?xPòzѶmµGµÝn¯°¶l ÿ¬.m))­CHI7É µ¾lÉhþ%"€óƒÄq2˾å8œ¤†õóÀ@}•£¥«nR ÿ¸.u©[)4†ªpˆÄBHé;É µ¾¬ë—KLHwD燵5šÆÓëâFÍ!Tït4ï­#ÿ ÉÚ+ù°bR“3 %@ì$/Ôúr$C 8X±*X«žÂÍz<!Q]b/&ø”È0¯Ýî­.gs'Xyá¼E>±PæÆ%jB¢Ç!¤¨Q'y›ð$/Ôúrª_/0’~«Ržœ æ!FHæ8M‡ŠjÞíntUmk«žXñVƒx‰N°âef\¦2 EI„ç/íØ�'y¡Ö—'«úÒH§:Dç‘aBÏüáÃÉŽQ‰Vµ½ºj[kõd�üƒÄK-ë¼Äª ÔDÆ‹Š„þ8u*Âó2ËB­/Ÿz3l̪ 8‹Èn·DQ"®¬ê0)¬Šj©v54W�/º‰?¨A­�j[vCHѰ€Ð²š(!³ìâ)ö—+pŒÊ«æÏ±*ˆÎ<ÑÔ$»Ý²n‡Š·ª&×Õ°*sHÂË+6@ІE„)Ť$–…Z1«2’²LQAت” �R}H¸ç?#…hzW]uýöª±¸«2…psE¬[á� Ás) ï”&HÓKœ2É»2ÄA­� Œ&€(À-»Ý¯Àª ¢¼Úqõ ykŸ~«ÚSW[³¥òÊk8U™F’ºÐ>&äRX±*8U(KƒÔÒqZ±ªÓ Ôúˆkî*»dd­ºÄ0¯Zt»!X?Kµ‚W¬¹�J­=õµ5 •W^�U™F—,­%€ü´Ÿç!€ °ÙlV«µ¼¼Üb±ÞÙx“>´4HÍsPë3‰æFC 2Ã@°~‚´ú[Emò'�aºêë\uŽ‘ŸŽ�DƒÖÅoèdxÞùly@Ì�Õj�ݽpaðÕ%p(sÉpˆjR"ÇÁ©*58â3HÓi‡¤2³ªî­ ®ZÇÅŸˆ?ŸAQñrl:0$€å*k+ ËËÏÜMü± J”’rÌX³úB¿ºÝ¬I4â·ôgݤ¢êkÜæªu|ù¬Ÿøó+5‚™Æ§ªÙ?®ò"lU25åÖrQŠ­ª¹¦Šø3¤©¹ËLè˜ÞU¸Àš¬ø|¯iz¡è⩜ª¿q[Uµýü°*s‰_ïZçEJñ,H1%Ãs-¯RçZmöŠ)¥åå;·ÖžhAú± JÔ/Wa"€7ÅÇ�K>ߊϗÁ„TÆrootºlç¿?Lüá Ú ¥e�…Ó2)Òãó}Ãs-·Þø&nö74UÙ+?¸•Ãfíji þX%ÊhŽ>P]Múg ðUÔÇ�‹¹?FÅɳ½ÑQYÑŠf”Äâ^d§Xêb †ç†¯,œšXœé›o¸ûß1fÝüÕÔ8”[*kù©ž]ÄÈ d2šV÷)u~ü1é—aÚÿýßÇšš«Š‰‘ʧ¼-;•g"ÿdm®N Þ€ÀŽ P$̸L�. Ï $î«—Ì7ß®™V×þ­••¶ý‡öŠIöñ2(™^]Pž{¬ŠãÆ››…R]«íšÔÅ}5¸C±ªÓ÷zˆ?™A‰š’“òKÜLØGú5[¢àcÔØÊ ²ß^¤oϱ±…5óÕÀö&׃YÆ=¸Ën³Nr`UæÕ¯AwˆÄ0®t•^p´kB3ë0ÿ:ÖÒb·[�u€øc¤!‰� û.=cÎ\£àV7Ïð"7¶| £¦DæÎ�ñÕ×÷=øPÇvÛ*¬W<ûˆ?�AÉôëŽT¥ü¡%†Yñù�Èû�T2�imµÛ­'ÀªÌ)%i‘C}ù�›_«Ê—ÂhLöLÊ4/r‰™^¦ï=Õ8IiÊ{ªÝn³^vw ƒ’ÉPH©E½Þ%š~©îü'îMq:·{·ÍfœÞGþ± J/1~‰æ‘?èñ=¤_ÈEθD�IÊZà€LO…¹k L´kB§¸Sí6›õ‹þâdP2½ùÜ@§zéD·ÿíoJׄ×+êšH« íí6»upj?ñÇ2HC²bUþ '°„ø7ýü³.Ò¯è"£Æ%j\¢ð†�›¯˜ßé=IÅêØ™›Í:ÜßNü� J&C E<‹�wM¸Ý¦5)¬‘v¥dá À©ÊŒR›Ù)™ãŸuñ‹3rÉÝíæ¿ÄŽK4>Fa“º=Ç~óm&&…uâ\§Íf=ß§*“jî*»`$G+9 E×Vñ¡E�g!_É™^£v›•í$þXiHbüêΊ™æÿ8ø×ç|„'ý/xøg]�7‡ËÈ/)ãÕŠI…è»Ï3w¨¨>=ße³YÏÚCü™ ÒT AšY6<8Húe›5d†yKQïóµ)[ß»×n³z.w�,ƒf§°a‰ á'ÞŸ¾²\ä5óœ2!xü‹G«Z?FêšH«³öÙí§z`Q­I¥$€œ4bUªIátEÒ/Þ,fYYÝ¿V«šÄÝÇ�ü]]v›uàË=äË DIœgWÉì•ev"Äø…b+Dä~–=þ ¥$T®',gÐ5‘VçFº•›ß}­ÄŸÉ MM)š`A ‹ÇVEÜt2Ó̾}v[Å‘ó»É?–A š™©0§,r~AA%ý’/0”cTP P"Àn¼Î°k"­†G8¾½-ÄŸÉ MM)ôàY„~ñxh[q»ÙŒ®wwÛmÖ¾³mÄË Dñ²€™§Î�~á Jnr�ò‡”cT@Œ&1·~¦7Ó5‘V_^í±;¬X•Yõò2³2d¤­¢`#€çz©flJ×DZ}}à€Ã^qèd ñÇ2HC2ˆVÔ�âM!åÅ«§Ñ5‰ÌÝä»&²¨ ªUyÚw&ƒ4e8G³l�ªÄ¡¡e†™Ch•¦ ·Ü—¨;==›µçX•ù$+�iÞ�Ìÿ_ð©4Œ¬ø®†¼ã3!x¦ÂŽQSAæþù0)¬+þ^GeÚÕDü™ Ò”’bĪð©ê•ÚÔMú5ž‘ãD¯W’Šå$«»ªUíãšÈ?™AëÂiõSaÎ¿ÊøezB€=I©ìü?}ã-#+¾€sŒ’˜™EæÁ÷ù3)¬Q¾×YeëÛ¹•ø3¤©——Ñk`W­È²¼Â²‚º¨P.ÀÖ>�zØÛ[i¯ØÇ6>ƒÖ.§ÖïVø0«t4ä*&r=Œö}¦LÙûeo ¼Á¤r×5‘V“3}UÕöÞ°*“êÕk(G/_¼‰DH¿ä5ˆ ôEýNÓ+,.R‡Šj¶··Êaë@�ÄŸÒ¥.‰�mÀ7,J®¢2¦ ¹Špv|ìžhºF~‘ÙðãÊ}×DZù¯©ª¶wïØBü™ Ҕщe#‘È%�éÊïNœø'ËF’ ¹ÿÜ�~èësUÚ÷ôo#ÿ¬.Uár_¢x™á%¯¢pñLÊgÌø®ód Îæ˜ÚXë ˆÌ×yéšH«Àµ~W�£» ¬Ê¤2šbÂàe–•¼Þw'N”ˆCEõìÈ‘šJ{ÛÁ-ÄŸØ¥*ZÓ§«’X><虉`\éægÇÇWwŒ¿áâO�j×Äݤ¶5»¶×V=½è&þdÅÉhŽXv9/Ào9n•¦ß!^?Ê�â¬j{uÕ¶ÖêÉ éGzщ—Ù´½)Å¡ºûÿ¦Í9~˜1<ïäŸìñÿzhBfø$ �×–Ù{æëšÐiU�µUO.€U™NF@dŽ[æ¸`î#€ñUÔ[u×”û’i…¢Zª] ÍUã‹nâÏö¢Ræµ&¿ÄÙ¢Ú ™ñÏP¬J¢“ýˆÌÜ5‘V÷ÑÛÛj¶×Vý0wU¦S 9�F]§é§ £4øïB¤,[U“ëêX•YLj]ììû±©pÁoUŠ=Fù5o£ ¤kB�U5·Õ6¸*¿†S•éôò2:fl­zŽ"€…ööG}}!Ùçƒc”N…hzW]Mýöª±¸«Ê‚I­…öfC8Tq²�ãÇ4ùóþÔÇ(^bï¼(l‡Šêþc¦µ½N±ªóˆø“§——YÁg¤S=À‹ûú„öv‘¦Á¤ŒZÕžºÚš-•W^éj3&Å&®¤Û¤&EÚ/2~�ÌLÇf˜�E·_R3‹Ô˜€rÒop*Hß-¨® ]VÕQ_ët|söñ'3(N//±‚‘µêÙ�–¼ÞM/"„» ‰?ù Q{êkk*/¿Däø¨M÷N$=RùÆ/XȤHߘ÷Ì΢€Äñá¤?–™öþòÎ’ «jÛÛPët<«2Ÿ^^4–‚êÞ9²É7…2œ¥.î“×k  $0̾†:W­cä§#Äû…%eG_’M³›Wa%€ ϵ\Yè ™i^NU½^È]zÔq`k�ÓqïL?ñ'3(N†@XöYWWÆo „Ð5ŠzFÓxŽNR›·ªî­ ®ZÇÅŸˆ?ü E¹s¨R@.<¦‘¹ãGyÉ{u¹ox®%õ1JéšxÅ<(ð® =Ú¸ÑUiÿú4X•éd4DÎtIÅBßx<!‰ã$š†Ö¾l©¿q[u­ãËgýÄ- `”kŸ’˜)™C*Ùö–ì0<7|eáÔøÊ/yS_ÒñýõOä$¿Ve»uò0ñ'3(Nú@ #fôÖ{«î•]PM *VUUm?ÿ¬*­Cåü0¥^{qh�¸í1§OÍÈôøòÐðÜp\@|¢¦C̽gÅŒŠSwÿöJ{Å�c½ÄŸÌ 8éI‘YöÏ¡¡·ÆÏSx±í[Ž {½ÄéÅ*÷öF§ËvþûÃä½À¬â%Æ/d­ ]S~‰æƒô¥úÌK ™oéßáôuqhFòÎÈ´ö¦¾kׄõº›+í×�"þdÅé͹”Õ?Ž›Eh™aþ2ôÖ�<mqåHží�ŽÊг{‰;‚ ¥s’§fñõåk4ã/r3âàát@¦ñ¨W ݘg‹»k"½Uyší6+ï;@üÉ ŠÓÂ9�ùß0Ç…9n‰¦_RÔ¬Á:FçÇO45I�\2©ñdåÝÑ쨬8óàq_0•x‰Íâ<¯¦Iͬ2——LzŒºFc²gRVZõ|;_½b¾ù®äÊ}‰BÜN‡½b’«2—@d– cÜF»€Ð§.%ô3Ìqp’ʧ†š«:}¯‡¸;˜D¼À‘+“’9¥Y.ÂOýϧ3«fï�–¨I‰ºFzŽQ¼@ß.–]Y‘{p—Ýf�äÀªÌ¥ ,»ªöN„ ¦{=ž¼üº&ò®O[Z쎊ã_ îä%±94)‰æÃƒ�÷§�ç#|ά&CÖŽQ5-Qz†šùSX ùul·­ÂzÅÝEüá ŠNÁS½E ö|>e´! j}ätf×.»Ýz¬*GwRÊ: e<êËÇŠUåÌj2‡—© Ùƒ�Qz¾£™%úþp’Ò–÷T»Ýf½ Ve2=ýŠýê5õø¶g–7VlÕÍç‚ÏVÑAun÷n›Í:8½�´S�Sò=u›/³ÁcŸ2g¯™±ó|ôÏ¡‰ß}“«,/S:×J½k"­|Ÿ¶ÛlÖ/ú;ˆ?œAÊ2¥1nö‹¯†ùä_¢Çßè½™Rº&š›Eµõ"+OÚ;==Ìöí½ îÆÆË{öÌ»ÝÄþ…¥ íÊ›kpj?yËÈ»r±w‚—9|Œúâ‘bU96œL˜<«ìèŸCüª®– èšÐ¯ãg;m6ëp;ñ§t‰ëÅ8{÷‡Øâ3þ†»ºÂ�¬øR¿;b»&VÕÐÃÍ?c=Û·[6b·Zû¶lyÖßOüù_@Q­Ê(ÉSU¶}j"ˆ.>õ˜óÅ/ ~Åãy&¯ïåè[?ƒCЉsŠU�ïƒS9M²·^&ü fGV|ã’�w"ÙäC×Äzkßæ{'Æ;;-‹Õb9ÖÒr·§çëžžÏZ[·8‹ÅfµžØ¹“øó¿€4ÚÑa·Y©ÑNòÆ‘)'©¬¦x™á%:‰üðßÓAÓ9>FBŪtßÇM…è»ÏÈ?ù NŸžï²Ù¬gí!ÿÄ.=ý4ÅÞXÐ~k+#öïN¥ ˜øYb˜E Éë&¥hÓ‘R�uu‹…Ú¾=îã—;:Vkg]ñ‡ai¼³Ón³z.w7‘œKil˦IMIì•eöÑïWþú.‰�p¡TŒ¬øFCܸÀLž©”»dc5½Â@×DÆ:{aŸÝ^qªg7ñçvIéé-n*õ ¨˜Ô�WJBMì{DðxB4½¤v°ÇG+Òôfª[*+-K`ß¾Ä?zÒ×7ÕÕýlj½{·VVŽìÞMÜ L.W—Ýføry+É¡I©ÓRÙ“_PŽQOÞ_»²ll4#?Lž±3²â3øx}�½]›Ó¹‘n›Ý:´¿�øÓ»ôrŒ{|�M;ý‡­jv] »Qdͪ:>úh¼©Iðxää)À«Ñé´X,žÆÆ´ŸÙ¿u«ÅbÖò© Ç[Z‚EÜ#L¢™}ûì¶Š#çw“7”(Ë�J­Ïûø�±ù™ñué[¢&‚”Rñ3ò}Ý|Å|ó-ùç|hxô€ÃQáëÚIü1^Üšc|o¤fP�ý‹žEȧvMH4Ž-÷iåUeöD½¸gî�èߺõ•û›¨—G�.y<5v{¹Åò<¡¹âI_ŸÅbi¨¬Œ~$HQ %ß1x½»Ûn³ú´•¸­d]þ,9”ÒéªFv}VÃK^ÒŽ¤�³ãã#£M—^!CÖ ]Y×Èø!»ÃÊ�UåN“ì­9c¿N…Y^òžý‹~Í0³ê¯ÎhÅÌž¨Ç[Z°UUVTœÚ¹3DÓqŸÐÓÐ`·Z-KµÍöb` îOïõô´º\±7\7»»mV+ÓÔDÜ,ÈêëöŠC'[ˆ;K6•¥;)¿Ä� h`¼ÉÙñ1i;Ò!ÔÔíÂKe§Ò¥rlPˆ¾ó#ù{ñid¼Çî°zÚw�¤�žOqɺ&’Ô@Ö–˜ñÿsš—¼+>Ÿ¬Ó¤6×ûw§§g›Z´X,�N烃cÿtfÿþ— ÿi¹ÅÒ\U5ØÜüÝáÃÉþkŒÚè~ªµõƒ—…�Q“"=!Rc‚›úÊTŸBÈØ1JéšX¦ï?…“T®tÅß[é´¹÷4°“žÜdÒtMÄ‹¾ºÄLþ~2ºÄ,Ù…T2mò¡z±½Ýe³Y,‡Õú¸·7ö�vª>5²{÷©ÖÖV—ËZ^~¹£C dt»¯vt¼ÞXåÛ¦öfÌÆüz,˨ú¯”šîªVµ�k&î2›•â/›=Fñ3& ¿H㊟iQ65Í2þU_ê˜øX][` k"×å{�U¶Ã­[‰?Þ‹@º&ÖŽQkK̆¿¡®.}Øò'¨ f ùÔ&ý½¨W‡§:kk£|yôh¹Å⬨ˆˆ~EhÉ㉎_í¯¯�~òýý‹¥Þáˆ~$HQ«ÕZ^þºT/­ööVÚ+ö±…lUÊ1jsüÂ/r~‘ž=¦=FÅâ_õÂ,fô¼‘¡k"ošœé«ª¶÷¶€UmJscÌ=#]¼Ìò{é)�8}r»2tªYVOpÑãIÖê€;+lVë‡�´·[,–ƒ ‰ŸŒ›¿ˆi<ÛÖf±XÜ1 „7÷ï·X,»jjˆûAÍööV9líGÉ;Žqm¾Ö7%s£¯‡&ƒ^“£âàÃêÛSò¦þînÏA­/¯ò_?RUmïÞ±…øÓ¾@õb‚½ó³Þ7ut‰Ù…G4/hŒ�,"$QÔïªõ(ê𩉽{wº\?'4Eˆ 3ÖÑ�W'E?r@­Ú]Þ³'î3†©¶ÙÊ-–ØæŠŽš‹Å;x•x]¥©W÷�뇾>W¥}Oÿ6â¾c̤6¹tBý5Ìä&–}£¯�ET›^ò�hNº º&iêæW­½» ¬Ê°žó̵7ÞÂz–˜ýβ«LÓ—¾±ú—ö®Šij²X,.›íjG‡°ñ�:kk-KÇúñ'HQ•åKb×úýƒ-j[Eô# n·Íjµ[­¸*ˆ…;4â.¼u¼¥ÅZ^Ωûu‹UÏŽ©©´·ÜBÜ}òs˜š’¹[ïÑtXû×°BÁÙùQYYYblÇô2}º&Èiú6ª®st4Ö½ ýä/ =»Î΄t½£�.1 Ê'Ò´þSUZ« Ñô±;lj·ù‡ƒkníèÙ½›”Åb™Þ¿æ­în‹ÅÒZ]­é,‹Åã,þ½{-KW̶¥gêuU]ÌuU2á–ÂÏÛÚˆ»In­ª¿¿Öéh;T V•±IÉìt˜�^¥¯ÿFÝz_·Q©9~ɉDbÛÿ k ºö5ª©¯lßVGüù_úîŽÞ®‰Ì–˜)&Å0o9ÎP0í3ó‡þ~ª©ÉYQ»,ÝZ^~*fýìg­­‹epÇŽdÎr§§'ú‘# ×UçÔë*”nßÅ/G�âÿ殺¤ýç��ú*GKWݤ@Ú†Ò�¤üõNLÉÿî¿ê�ð1*–H$òlù"Ï;ýê,ÕÍWÌHè0‡nÜEu[œ{¶‚U¥’²kâ;½ïßÍ,1{Ëqa– ³¬Þ±_ݽKÏ­δµ íØñy[[œS ÆFÍË)ì,.›-ú�awVàs]¥)ܼÑèt7‘üè„ê�Žæ½uÄÍ(ùIŠ6´ËnýÅð2Ň9~u0ÅæÿBäöÙ]×Ǻï¼÷„ýæ[0)éö]wýVçÎúêç—<ÄÁŒš`o½Ð×|ž�%fa–i:èñd·§"µÎ¨¢UU±ç¦¨³ônÝýȃC‡,KSÌuբǓx]¥)<`UR+,~Eh«ËÙÔiF«R›ÜŒ.Qá2}G8=#yy™Ê¶KfÅç{M+{Ì$šÙÙ{àSæÒíî­M.Ū.“6“éy€¾¡£k"»KÌ‚�HQ²ç¡«ô·é!šîߺÕZ^ޝ™ÎïÚë,±£»'Ôë*oÌuU@½®J‚¬,ËÍîîè?kmåš›Ÿku$Æ©pw λÝÛ\ÎmmÕ+âÞôÁ¤$6`ð$å—Øé·ÜŒì».ÝNgÉÌBxpPô*ËaÄõ÷]ð;û€ü뻩mÍ®íµUO/º‰»ƒIôÃ5%YFÇmTö—˜)&EÓú­jó{*D†yÞß¼¥¥¹ª û”æè.ÞYñu̱k`Û6=­xÀÊYQ»qg5âÜÆÞ†wcãäÞ½šÿzg]]�ѶŸÐœZðx¶WWmk­ž ’w¨µ“”‘.t|ŒRrzúm!ÍFéDPËáÁÁ¸÷Ôò úñC8U™Kتk«ž\«Rº&üBšûe|ŒR§ï³¿ÄL¦é‰æfI_§:n½ÈîÓõÛÇVkìè.ÞYQe³Å.ñ«µÛ-KÚ3°ê‰™#Æ;ØË-–»ÝYQQ¹Þé±Ó力±ZòxìV«Íj-ÜSÕ EµT»š«ÆÝÄ}ÊÐIŠ—~…âCT èÑ ÷,t”H�íÛ“Eê,}Ê>zVe.Ý{Doo«Ù^[õÃH ßU]U®Põ¼s½Ä¬ãc倖Ï#UœB4k@—Ô�‡b¼æqo¯ÎÖ<`u©½=ú¼ÔÂZ^~a÷naý¿Ö¬~ZlëàíðTrGÌ–§BÔšU5¹®.µª ŽQ+~¥Øn£ÊÊÊb#uR¼­Ï0g9âgP¬î=¢›wÕ6¸*¿.ÅSÕ‹qöëéÞÂy\bö÷û7¥.¡¯¸™mêz4µoßžšš« ×U\ºÖ<`Un±¼ò£g7¸4]„–˜!„~:u*Âóºîªô­¨Í–:tB+u1NxÀêxÌÑiBíÜ›Ð%øP=OµÅlÆÀ'¬m••Oúúζµí©©‰» +Dí©¯­i¨¼ü™í05%qü;z<4xyáäðÜpÞ^äù'äõê¼ü�êåeª2�î?fvu5Ô:íJÀª¾¿Íò)»&È.1‹ðüoçÏÏ ëœÿ%þް²X,±ÉŒxûpÌR ¬Ï6±ŸRwe01QÂQ“ ÑôhGÇ�††¶êêýõõ§Z[5—îšPÃìk¨sÕ:F~:’—“Ó\¹ª³TšE)þ�ÿyž‘8NdYÑ UÍ��O™Q¶º*íw?ë#n%¹ÒUöá£4Ç(ˆš’)²KÌæ†‡WÃ: €zVÔæSx`�ÝÝ…ÝÁþ<á¾)qµÅ.õëfBiñµÛ½[ý#¼1_cÙ­Ö+F‚¿;|øPCÃÔ¾}D¬ª{kƒ«Öqñç�£ÒïBç%vò7ßÅ%æÌK Íám”&"Ç�77멨ÇꅬʌڸÑUiÿút?yOɶ^Œ³wRvMà%f™ó‡È÷;… ±ìë¡¡´aUxV‘¸Ca�ik³Y­ý1K-ðö¦„.Á¥„Õ¯Ýnky¹ÃjM,ôu¨Ž¶Óåúþða|“5ÖÙ‰íïö�:¿¶ÄÃZžÕ׸ÍUëøòY®NRrºy^™ Háÿülò7é×x¾éT[jC‘: ó|¬ÊŒR­ÊvëäaâÎ’Eý`o¼NºiÊ”KÌ^ ­0Œ®à<ÞR¥Õ‚Û_…w°'¦{öí‹[m1ªv¤wÇD cáˆá»}q㲦ëê4qlNq�¦›«ª’%‰|ÖÚZc·__ßODî¦F§Ë~þIn¬*õI*Ìͬ2üû“�¿Îóžô«› û].¥OÉ U=½VeFu÷o¯´WÜ8ÖKÜ_²¢§3ÌôR‡R¼‰ãŸuñKGL¸ÄL@Hgpž{ÿôëb{ûN—ëë�»£«-¢[›”ã†z�5’p�…ƒ›«ª®ttÄef¹l¶ØüÇk8hØåíè誫ÛérõmÝJÖ˜4¬j{£Óe;ÿýál_K%7)|Œâ�ü/fVÒ/j’ „föïç�NC>%Ðô“›`UfT¯»¹Ò^13tˆ¸ËlR)º&ð3>èæçûùg]¤ßCÚ,"t»ƒêó¹°z*R ¯¶ø1æÒª©ª*î#øˆd³ZËÕk)<–ÕZ]}¢¥åÁ¡C¢ºÎÝb±DïÂ(u†C]gÑTUU­þ+µÐ÷íáòú-d,ÏöFGeÅÙ‡½Ù«ø1É*~~™á6ðëáÀ“žw’~9“‡w:ŸíÚ5×Ò’¾L±¡dA?¹ VeFõzší6+ï;@Ük2ÓÜUöÑ7Ú…§ïO í£Ò€ù—˜a“R6’¥¬Wüê×/G�6:�Û6^ZáÕµq—SxáRµ:cu·§ghÇŽf§ר6›Ø¸¥²Òb±´¸\ÑVÀÛÜU�r½ê–ÝÄ4RòîhvTVœyp(;å>Í?eG:�úòUÐñ»Yg®¥eùèQáôiÑÐRM÷ý]XUaF!n§Ã^1É U�³wžiWBø0ïRcòÀˆxè´ÐNúM£ lRz"€‰?�õ+nƒßµ¾·¿¾þNOOôàƒ·[l©¬ŒýÌŸ.´·w748¬Öƒ[¶à~ø°Åb±Y­/´úÕ«TS‹]‘A\CÍŠU�¾×³)“RÊ}¯s^f'‚Ç.>eÎ^ó T*M}úNŸsÜ{„ ÍU…†H1§�¯Õn³Nr…dU?Ø›¯“£Ô]Ð~Õt·Q©Q=hZ ¨V%æ`EmÞôb``}=>+UÛl÷×'°œåI,&HÓÑ�ãœâØü¬¨îôôàsVìgöïo«®.Wk‰�Nçñ––üo¾ý´¥Åî¨8þÕ�LMJë×0™ÃǨ/)VEúek^Þ#ôŽeÿ2Ô¬ ¦5Ôf«°^qw7 =z:ÅÌ,k�¤ ‰™@QM‡(*E0Ÿ*r¡gýý'ZZvÕÔD]ƒkn¶X,R/¦ÀÇ1Íñ¨Aõ¿p,fEÆçmmØ�Î}jŒ.!>éëËó÷{f×.»Ýz¸U%Kë¸ö;{ùGŽQzøshè­×+y½a#€Ë§XH1§¼§Úí6ëeÓ[Õ·Z]|XYbÆ/ ÿ ]èKÌBj¢“ìõMõ/­–<ž5 «¹ªêjGÇk­SOt… fÐp³Ú¡qo½çðþÁƒxRøtkkôs†vìÀs^±n¢éd­3û÷ﮩ©s8êŽÎÚÚÑŽŽØ°-C:·{·ÍfœÞgð0Eom·Ù¬_ôw7#M%ëšÀKÌ"X)ÔcTؤRä**Â?U%ÚÚ¶­|}?­Ëf«µÛ1UxÆ*q… ¾ÌÂí‚QÇÙ[Wg±XŽ$T±�MÇô±�ìÞ]m³}‘Ð*�ã�VksUÕ¶õ¾ŽmN§æÕ˜�´+o..ЕYÅÏ/±ü;4ûߣ }‰DH¿B Œe–ÔÉŽ°‘àâæÑ#ò�eP¢ŽŸí´Ù¬ÃýíÄ])^ã콄®‰"^b†M*Õ©Jí¸ î/ÙÕË£G‡wíض­½¦fwM ³Y¯Ô4” »w[,–¾uWz…¶•ö8!u¤ëØŽÑ�t××ã�ºûêêªl6—ÍÖY[û­º#6väY?Î>îÜDl¶*j´#}Åoã´^æ¿÷¬‹W ¿†A™Oä8Áç3tª‚ÓêÄ9ŪÎõ™Èª~ °_ý’Pë+ö%f²×;±cGŠn¥";R¥PŠ‚"ÃìSOOë÷xa\O×Ô°¢iÜ*o-/ßårܲ;Îöö&þ»ßª›Þ-ËfRHF;:ìŠUub?š´üüÑó”Rëóßáìø˜ôë±à|>�ãBgȪ~½È>„µê¦Ôé/öÙlÖÓww(e!Ò {-®k¢d–˜­E'{[rïŸ!-y<§Z[û´:ý‚4m·*f­žVÛûµ>y¿zz:×Ö†ÿñfw7¶žØ°ÈdëñœW¹Å¢y}¦_ã��v›ÕsY9Umiq]þeCˆÒ;!¬ýÆ‹nJç%/éWb‘â8�eƒ,«3ª @L«³öÙìÖSv‘5©'·Ù©Pü1ª¤–˜¥Ž–‹®§Â¨ð&¥Ý55Ñ�œÞ¹Ób±� ÁZôxœ‹%ÚϨÛ-zÒþYp»;×7ånþköwuÙmÖno³½²¢õà–&µ^ëóKܘ€ü"�·øÎÒ!¨V!Ò®)‹$€˜VgGöÙíCûÛˆ8ÔË1nö�ö1jê>-©%f8X(�Þ?£:ÕÚZ¾±¯oJÝÛΈ5¬^c5TVFÛ-¶©Û-î&l&Œ• ëp[{µÍ†¯®6¯³mmåjG¢³Ö~uÞý¡ =Ìñ"7)Ò"5&a5Û ¬™”Á�ç~XUaR �p8*¼];ólR/ÆÙ»Ïâžsʳ?Jå BèùÉ“žOúK`É\TiêyìöÚ M×9å17V¸SÝ®^E]XïÄøA݃»”Ió¿ÜZ]�/°ŽlÝš­eí55•êƒqTUl悔ü«›—˜›+¾i�ƒcT®Á&6²U @̬‘ñCv‡•Ë£Uý4ÉÞ~©±ÄìÂ#2ñ»f ÂóïRDcïßftûÀìJÝ §vîD��ø÷Å´µŸU³†˃±jRÛ*v×Ô|«ÕY‘±‚ê0×v§©>ùäK¹Åæ¬`®t΄¸›+Å|åj“2èS�bf]ö÷:*+<í;ò`R?ΰ3‹°ÄLƒh°æ›‹¸5˜Mß>ÝÑ„£�™¦¦Ø _&Hþ‹o¾êŽ`Ê-›Q£êƒQÊ­å¤_e¥…Ä0ãMM)*ê‰R@n�U™TWT«rïjÊ©I=¹ù¡k–˜%F(È0É"€áH•¨·ûëžžÛÄmöÃÛ-lI¶[`¹-‹/I&cVt¼¥ÅëSåàSù¦ý£�”+C¹Š^@L«Q¾×Ye;¼sk.*±k–˜i’"ØTñô&ž±J=´{§§‡Ú¾Ç`åBˆ½Þ¨IÙíJ=é×W)Ò�#€ &€|{‡ü3¤©É™¾ªj{oK–­Jéšø–˜é%E°§*}zyôè…Ý»§ºº’}Âóþþï³ÔÚ—(|ø•8îþ¡CGÔåååV«Õn·“~q•"¡ŸÔ>%£ ßÞ‡S•I¸~¤ªÚÞ½cK¶Lê§Iöæ KÌ ±ˆPˆaÄ¡!�-ÐàSÙРº´6u—Ef’h:ÌqoñZTúúLA„ç㸹–Có¿ÁììhV7©¦¿pÕÚ÷75d¡kbš‹vMÀ3CˆCC²Ï— Õ¿¬wúi®ÌX²º!Ìq2M‡æ- å1×Ò²d<XIù†ü3¤©éÛ¨ºÎÑÑX÷b&õô7¥l†�%f’"ª›ÔÄÞ½}[¶d¼]äðßKTtQ­M.2‹^ùŒ}ô�ü3¤©k_£šúÊömu™uM<¾ÇF—˜•••u}VKÌ2 Y0ñç<(VrtW�×+±¬Ì”Ð6•ÂB1)�g!CÀ‹g9H1­nÜEu[œ{¶³ª¹1æþlt‰ÙÀx£6ƒv0MˤÎ qýÆŸ¤Þ#´JÓ’~35 ê寔.¨4Nóç™oH?�AÉtû®»~«sg}õóK]>5ÉÞšcñ1 –˜e Í`z*H ÿ ìça˜¹––Poï{²(pNýï#€½È~3 €&Õíî­M®–úêç—ÕÖˆ*™I=ã™ ,,1ËÚÀ9[¤JãP,]öz#½ëí�ki!ý2ôò»zó»€�¡à¹Ë $€˜VwRÛš]Ûk«ž^tû�ì¿ÉJ4©ïo2|�õËÞé KÌr�¬º’�ð ñ‡v© W\×~þ÷žaþ/MGà$Uhà Ñ`H1³î>b¶íp5ÖV wî¾´¿#±kbZö޾šXñúe¨Ïç �eÇ››7ÌÿÒ4Tÿò'–×3øÂÑ# I,™E¿ð“ ƒ’ÉÿÕ‘­;«ª*?km½å;ü¡kâ1ã_õͼöN.ûF_‘~é9�ê¾²ø¡*Pî%ǤÄÊ,û–eÃêï ¤_À¦È,øÇi˜ÿ5£.LBçw÷�iÛÒ⪲WÔ9 ÎÊ¡ý-÷~ ‡ç�ÿ%í_…B_ž¸èvG"‘ kÕáH•{“ŠÎ‡Â$o‘‘YðÓkP4£î<¦?÷÷9Ýf­X‹S°–—òÉ'‡}-ÃsPœÏ‘Hä§©©Øàè¥ (ëZ[ÖÓf “¼ÅGÀ�bfq§Û£+ ?ùä“üãÿùŸÿIúUVr$FËj“-ñ§z‘)îÑ“¼EL&À^ö»ÛäŸÉ Dݺë¶9¬QŸúÛßþöÿñ¤_b¥ˆf0ñ{Ñ(¶ó@Rb#€E¨þ‘¤–ûâ[û`’·´É,xáû¬*�úf–ùù*fYåÈ)VEú…¤A1)Ž{GÓÇøŠ¢ÉNR0É d yÓì}fñŒòKæë¡¡e†Y„Ê|�ðçRá`8R¥s(Í2Ã, ¤dSÂIªä‰FÚV yГ›J§¥ÒõÔÞ¾rôèë!XÙWHlˆ«J¢dÝ\x’7¤&>�þ›LÁ{µ¡bÅçÓïSü„�œ ×úp%„w:noÚÛI¿LÃjøïªÏ'‚O%HZo5Ñ0)õ7g˜äâXQת�~1Nþ‘^|š}À-žap«XYY™ç¿þ‹w:I¿@€ Á&"m f>`j?X`’HNfÀ?NÒÄìŤ'×™�—sœHÓãMMê¤PЄԃÃ[|cUòŠVA5Ÿ'"ËÂ$/�šÌ"€ŸCH6­õÉëïb®�‹lR’GÜ)HšTê‡ ÇýAÓÿ¢(˜äR£DSÔZŸ’n«zz.ª6%¥Öw–Å&%¨?˜ä-2”rÖÀ@)û”œü“¼€QDõw¿·F"€š~z NU ×ú°I…%&y‹“ozz†[ZÂ¥gU©ŸÊïf�¤®È&ýWo9.̲aCÀ�b\ÑZþ•òB« Lò-Ã--Oûûqc-qïÈ«I%ÏÄ“¼M é¿ ð«d††ª Ä�¢µ>ü+åë¡!�aÞAe¾¨YñùÞ��­”Fìoj‡‚I^ +d :­õ­Õ=`’·døßï¿�D"¸¨NÜJrhRêkj“‚I^ +(&e°S]I¹OÞL«ØZLò– ‘HäŸ×®½å8Ñë%î&¹�Ò/‘îÊ&y�ì"ãVŠÒoU+§¹G� PC±µ>˜ä-YÖš”p³zѵU¤¿Ô†I^ H5ÑÔ6rWµø qzú­õÁ$o‰#Ñô*.ýÑö?9!:Jã&y�œÑi<xá<$€¬)¾Ö‡í„IÞÒæ7¯÷Ï¡¡µ«œ·*½�˜ärÌZ°¡\Å/ „™}ÀÄÖúð$¯“¼%ÏŸCCxDR­ªpG€õ< `’ÈJð©SF#€K<$¶Ö‡Mj‰aBjÜé¿O€<ÊÓ[]?‚ bgURÔ}R &y�|¢DŸ??7˜ä |?>ûVMãS¸, ó=¾6É;887î»»ÅÐV¡YëƒI^ 3"‘È×®½á¸ØE‚CUzö }( °,^[ “¼€9É 88H{¿°­*±Ö“¼À&yÃq!–]�{¿äݪpJ‚ Û¤Ö&yaÝ`n2ˆžäf¤UiÖú`’È « #¨)¥^Wêo€ù4)+û`’((Âj• ˆ­Ò§¥“ôãBKѬõÁ$/�E–½Þ×CCªx·Rî }FM &y�‚#èñ(µ#«*?cÎZuÍZ~€À$/�-^ YVÞúÎñü¯±~‰u“‚I^ Á&%ë®lK óæsÆüV•¬Ö'1Ì*ÇÁ$/�]dŠ ©Ý8|!g�ê²ÑZLò.VŠ6yÈãìâgÚ÷n¸©�úûßa’È.ËÏBqÓµr¶;�ž¡Ö“¼@á“Að«/s&€$«õÁ$/�S ºÝÒÑ£á�V%fµ¨sY_Ü“¼@q€#€õ·¶â�‡ßsÄ�)*u__’·êúï¢0É äéèÑ%�GãæhÓÀRF%­wž_t¹`’(öWU�~1nŸJQëƒI^ o¼TWÔjì{ÙDpt+»!áIÞñææŽ�?&ýS€¬‘Yðóy“JVëƒI^ Ï(+jiZÐÚ¢™A®"ÞÄn(çôÃïf^¯¤îÊ ý#€,“Yð�Óf¬õÁ$/@�eÿÓ\WnÔª2p():É«Zé䄹áá•ÁÁ°Á ‘�µ>˜äò/¼¢6¹Ëè:Iet!“¼@‰Fè­Çc(XI¹i–ZLòd‰D"NO I‚ RGg0ÀkR0É ”Ñ`Íê^öÉ�|´U<|ÌÎ]Nõ•À$/@%>›¦“½}dõ+kãQø¿ “¼@é! r»�œªBƒô·wh‚µ>˜äÌC˜aVi:Yý<.X¹ŠÊ¬ó &y�ReQ] "d øýøA®æŸ~ʼn¾¤·f0É ˜�ß(ê}ò·O4Xʸe¿òa’(m‚)¿ø ê�^>Ag=$m­&y‚ q"Ç%{û„qçùæNReee—`’(mƒƒ²zTѪÊnÈãìüg©ÞÈ0É ˜‘ãšÖ\õ,Óôo>_Æ�0É ±ˆ4-ª£²ú­jñlv@R×ú`’0?AuEm|–¢Ú•wc×®µ]ÐM &y A]¨n(x“ ik}X0É ˜<Ð$Ò4ž¨ÂÓ¾‚šRºëo»ävG"c›‘`’’�Að¯ÃìÃÜÔúðûýÏ¡¡ß`’0="Mÿqõ*qšChYuüG‘HdùâEÞéÔ{’Rï‹eÕªH[`F‚�¨Žº°ªà ik}ÑIÞÕ£Gÿ„I^ øK]RñvttÑã™Ûø›ït.»ÝžO{W…'yeŽ ’ûVÀì`“’½^ýVõr”Ó™òè1ûòrúLòGdí?åùwxµfŠßÍX&y@'²×;±c‡¡µêz@ôÔúðI*‰¬¨¥Ò? ÈÑÕšÚ‹a’ ‚[aõû”š’ʪôÔú”I^–ýãêU¼ç“ôϲL¡ßæÏ¡¡¸Òz˜ey§óY?Lò€!þþoÿf4øÇ)�‹*�µ¾èzqýŠ�?‡†VFY=U©�ç° 2#ƒào°Ôú”¥�ëKfHÓ�[„d�ç¶*˜ä€Í‘AplˆžZ߇I^ÕªHÇ�Þ!$ªÓÁ!š†I^Ø$D‹>æÉWÌË‹z�`0É ” a‘þB È,X�`’È a„BjÎûfÒH'`’ȯ‡†VÔ>%À)¤6âÂ$/�E2ˆNv’Š.=#ý=EÅ"B!†‡†´gêÓ &y€\# É>_xpÐh”¶2Æ«.c‡I^ §`“2¼6ÉKÓ’ÇCúËŠCÀ2Ë®®[é/(Šh:DQi €Ë,+2Ì*LòùE‰ÛNV%Ò´²šã–áN 6)Í`Y�ä  À$/@™¦•åqÕ?˜äLƒÀ²ãÍÍѵê0É ˜�h°@Ó¿Ã$o)ñÿÐ#u’ endstream endobj 84 0 obj <> stream xœí�w`ÕöÇgJ(é6Db+(¢øÛ3êó! Ê¢T;¢"½HÍ„PBSš Š<ä!*(ÒK²¡" ¨ôjèEJ©{~Þ;ýÎÌîÌì´ÝÍç²uöÞùíÜï=CQfRµI“&÷^ôc4üC’è…‰‡1µößqƒÕ?s]“&Mîªôc? ã¶½°òp KËe„2èŸn©½Ù§-Q™áðàJ�¿•˜šºZâ7ó 1øoÝ;¿{(EµŽ'�©ö»Kfúÿηc¬cjêN‰ßü µƒ_üùù­‚È,¦œ;[™¢†çÞμÐΦŽ_œ;jûj7‰ß´K½5ø¯= _‡RXëx.¥¦NÜ�léÏ �?R?Y[ ‹Êûäç¿é•Z9øÅûÀG!O;žBÈ~ƒê“…ÛÙ–ÖvRU{,ö]©ßhÂ]~ÓzðƒìÃ'áúóhhØÆ_QuÇì“R¿Ñ„�~CmØ×*JNrÝ ã7TÝB?ê€þí-Gá?å)*ÖÛ‚j1qÒ«\[ùÍC^¯×[‡¿hÕÎOíß?¬ÑŽž>èa}¯76 O2.Z¿ÏÔ‰íËÛVSå·d•Ìd³~› /ðeë€Ëö¢·,~¥Ž÷Qü÷zƨ'Øo5òÞL=9jò{ñèÉu:ôßl}ª¼1qjù,‘ñêYø;Ž¢b¼Ï£'ÌŸÞæe;Oÿ4÷I‘ß<ƒL&ØéÆ&Mê^?¼é­3F<ƒ6öz¿‚¯½^ï3̧î2}ì,tßÏ�¬|€¬Û¸X¿¡ÖA?Š¢öž�íƒZU2§£ñyc<óI‘ßÌE¯óó›W.âÉÂpdõbü0ó>Š¢Þ\Óa…èáÞ›­«[þ›çk±�Y¿¡2¡-ú3—m*Ûbø~'!XŠ+ð-nMÔxs6zúEQÿÉÆï|‡ßxö¡bƒÿAê¯FÂØ„„„ѧfÁöG«Ü¹f[g¾Å%9£…çœß €u2¿�ÁÈG ˜1­›òzʳ:âU¸ÅE­‚á¿Âüæšìô?DýÏYW·@4Ê…aq‡ý¦ÜýàG4ÌfÜCᮦEUȺR�¢¨ûa#6În4`T½��ç© O�<u7l®½Ð+õ|Bü(ç7_ÃÇ2¿4\=G˜ÁåsåõTõœ¢ûðÁ¸e3�ùÿæ7MàZì—=T\×L“I“PXUxÎù͇Ø„ßÜ„ž,‡—ñ'Tüæ^8.ëBFA;üWð›øˆ¢:Ãxkê„r‡ýy¢™?»?>&- a ~±#úߥ¾ÂÕïãñ¸+~g{SÕ ØO�&~™ó›Uh!N΋ñ;‹À‹ÿªøÍtè%¼:²ç&ð<‰Ÿ ~³²ØXä7e~/†¼+�›Â¿ÄùÍrc`ýæ(ã7ù¸¿™ ñ'Tü¦¬ä_Œ»’ÿ óÒoÆ�¨�³—F9�}ÈŸÓ[ü;/NÁ�e ô¿7:RŸ2íxÚÌ3�évXbï鹎–§¨DX£òӜߜ€–¼ßTaýæWüŽ˜E˜ŠßŒ…1ü‹ ý'ñÆH†ÌoVÁ3:ìa:ü'nº�ÃάßÔȃûqx-~b Ùù žf-…Wð';‹ê ò›F�ÉÇ Á&üw-ë7O²ëTŠz fRQ'²²‹¶J&a¬ßÄ_ð7¡¨N0KüÞƒ°´ÌÙl<¨}mÄïHýæŸÿÖŠ‡à>ŠºŽ«ü4ë7Cš×æe¡'w³~sÏoþ‚†ì¥Û‹¾ÇûMgXʿئ£?±gX¿éÁ�JÀÚíœûrr›R-r!ë:î5ÆoââÕµZÿ3¬¿¬ß @•_Ä´•4+ÞoböÁ«øAŠªÇ„•°~s;le?^3÷Òõø�ÇþÈß1È‘Æ�¸øM,¦¨9—o—í@a;v1þ2¤3îÆ¼!ò¶©l„¦E­ÇVã?&ÀøMíhzCQq£LæÖShbó·¨è&Y/ð~S3·ð^ü úŸÂ�wG`ý¦ ߆?˜_.kI�#æ òP æŒã_l Ç»|8ùdâØC_Øû`�V's¿ñg½P¦ÞJ¶¯¥ÊŸòOx.ñN´¨N@ñ›N ¨œ-üyÝjR7šDQž0¬rÌS‡®°~Sî"¤<Ò¤ …Cúû_¬SþÞî{·¢jšÙ]¤/q~S=ÛEõ‡­ê”¿§ûæ?„†óÀ¸bÒ`ÉÕ«=<�0b¿y"£ýÍ1UûûO¡èòC…9ÞR6¡íšÄ/�Í]zκ¿àùäXÓàÚ®gX¿ñ~ÈÓx7ôa>™P�×ÿ™ÄºLl,á4MHÀ‹Ù�pÊ[9öΩïSÔu……íË—owù ë7·ús?hÖýPß@Æ×Ty ùTð½wÜœ pÕÀóXÿ"³ž;ƒéSâ÷£ Üþ\¼xzo+W˜ÇQTt&^{qTG¯wÊÂ�QPè¹<€bX=’õêå,.^ìIÆ1Yȹߊª$Þwœ ¬p~CM@ñÍ– {8uÀ6UmSÏ#ì‡y¿y qþf¶ Zàx1÷$~ï‡Ã…áð³Û/ÀU/ë7k·àH4·‹ófnþÇÙ~žá¸hþh`ò£Ÿœú=ë7ÔÀB.^\�ýÒyKÆ 9�Ó’|ñz¯×û|Ó²ÜÓkúÏߌٟª™ž¶Ó>{��ªô¬×ûÀ?îÝÀËÁÄßk¾3åË¡á‡õû}>±uì�^n£Òƒ­¹ý©›{N›™Ô²‚5ÓMm/~¬ém++[K¯ -ú¿¤Y“û?ÄÔíOqÜôzê¬1oqM*¾ó¤Y£Þ�í‘ÞáõzŸ»›<ê¥Ì~;³?õ0,­Ðuæ$ÑÎD­–^lµ9Û>ϼ^¿çôýs>0ä˱�Q{¹ß©þHnªñ ™Ó>D¯a”¹EŸëøtEÈ´¦¥`¿qº:ÐÕ�•ú�…„—ßè¢Ôo,$‚ý&n›|o¤“¸gÛD§‹PJ)B½N©lÂk•ñá„§ÙPºu©9´Ñà=ëDzáEÅ4MÓɳÂ�ÆÃè÷+jø\äS¯�yÌé‚„Í‘¥ÞqP¬ïÐÅÒÌ鲸ž˜çK½YÎé’8M¥Ž4OÒ}N—Æå”ñr¦êô\^dÃ�Q Ãîpº<®&î ÁT¯DóúS4F1 vî°”û‰ï*6U«è]ŠÇ(–�×;](×R«—ÔTQ»þ¼¹�Ìmhº- ߌFnìOšê ߊ Ê´õòjÙÅÒûgËèR –›*œó éÍëz2Þ•Æ(–î2rD�‡)X*é§‹e •ñ¼nXb¬ÚÅòž;~n¢¹²¥’îqº`6P­;[Ûwª{š+5ž·£>ª%…‹öÉÚÀé²YÎõý„f¢<³èåQ-)B´OÁq4ä0 knÈ×uâ*ß‚�çÕhŽjˆ£}4=qù‰¥ßätù,¥á¾¦³Ò}>ßʉ�'Š£ZÒh߬tßš±K}t�†‹„+÷ñó™‘ }˜ô¹É'j£Z’hc¼U©Kõ šŸ3l–Wù8~’¶’G�.´+�Dû8ã­%±TÄF¼žw³ëftœRU팷T:=ì‘ÀØ6ÒnVÄBiÑ’ÔØé’;Ž8Ú'1Þ’‰©Þ‹@`9>0,£8VO à8CowºìÓeãÍ•š*’€ü*RqŒkõéqÄ®1ƒ Žö©�ho‘*½}°z7+!Àô8:U¢h_ãqŒH •6¨›•òm ­B4ª*DѾ@ÆKŸ&5Ud›%i£8–«N�£OU!Šö6^ÑOG‚0QãÅÛ`¶šãD›ª¢±l3O•uŸH,•ÔÄ鲇JÌ ÚÇ(ŽE£U'’– Á¢}Œ·Vªªw`™WôŒQ¼¦É\†!r– A¢}ɳµ�PU„wŒ=îM}c�Úôøß~4"¢}Z�G¨*ÂYÈôŒQ+?‘; ¢¹Óu²!Ú§Ýx„ª"|€Œ][7+#}¶¢ž+:Ž|ðÑ>]Æ#Tá*dèúÇ(Ž%cçn ?æðÑ>�Æ[,ÝÃSX Ñ1Šcí %Ç ïŸnà¢}º�·P**ÇÍ™;†£xæ+w\ÏéºY í3bY#ŒU· ´jŒbùRê8®ÒÜ0Ô¾1ŠCrÜáC7YC(ãÂèÅ–Ú‰Ðh»HGPœ­cÇbQD´«{¬¡”qÁêžTU¼íà]_Ú¿`ƒSÆ`Ž;¸[UQ®Ó”5ÎYˆPUØ-|z%Y õù�1…æ4°Ë4&*¿çÐÅB¨*líœ=o¤É ”‘çÇaŽ;¸WUQ}€cck BUacç\n¸b‹ÉÈ-úÙ~;ÈÀǺÆÙf ]Ü0ÖÁ1Š!ýS©ãØÖ9WŸ®V$w8>îàNUÅm_8:F±ö!T6uη}§^¤ìâ-vZ@ 4=nï´T€ ÆÎ³“±þp™HU…-Àæ?*R–;�v™ªâ8€ÿ°Óva!UÖßžÉÓ.Èø|©x«]µÈ·).SUä@¾ÓVáXM$L´úöLeú),¤¤\*ÙfO݃°|<ý/k�¡�Ëà¿´×i³°¬$îÓd­0~¼†"]p‰ã¤Ív‘ª¢l+_!’¸�uÚ,,¤ªÂJ`Ý9šŠtÁï´�‹eÑ(·¨*ê]íóm¼ pÄi›ð�ªŠ-›>¨U~~Ö¿ÓâJkdí§wYe =”Mü ï§ ÏûÿtÚ&ní5Zð:êßï˜-HU…ùÀë?×[$÷´«Õ=«›mÍĵLú˜ö…CYBq¿m³€�æë/ÒQÿ>+jj€•É�Ì5‡fnëEO['+Ï!¿{‡PU˜*ô<pkA ÷tÈËGz�H:×’¦µ6\³á SU˜(,ó¶A µ{ÚÕÒ½ìßÞ›NY \žýþcv›@ RU1ð“ª_q°¼§ÕÈA×´«EÓž³w¼BKš­ÚOïñÿe¯Ô!U]kJýë|‚bÄ=íêûdú�¦Dwõ£iÙŒXÄÿI;«RUaаáÿB*“{ÚÕw4=ضPNå¶4M°ŸþÃ=ŽCª*L>ªÐh�?Ó¤Ú…Ê×4ý´)Nœ»ÐMœgé§÷Ÿ²«êÁ sU„*,ÓqyÈeúÃ5æ™ÝÖ!WåWhš@ɲËï–½q™ª"4`ÅÞfœEýÝÚ„«˜À’ÇÌó�àÎfÔ Úá?oCµ5±œ¸ e(ÀÚ©A5ZšØå?gÊuBdŨ¤ûÍôeâÛ!³�×¶¼£ä¢åÕÖÈiÊ�2Þú¹YÒûßÜà8kÇÑô0«UžFè 3b¿ºÇqª £ÀG¾1¯L;Jþ6ïbÆH›„Ãè·ší)®éŒMlF,bk‰ã9§8HUÅKFfƒ1/™š"Ôñv•Îæ«láqhO“�´¶±ˆ­Å®qRUa@XáCí-M8Ý®ø}_“¢¡ T{ ÿ€¦±7$+c!Tú€5hÓ3Ë:Û®æ› •ãi2_~œî·ÙÉÊXU­szËdsRœlW%m¯ª¸Mõ×™‹O6Ðà6¹ Y ¡ªÐ'l2Ë’29×®–K•ûïW4Ûk¸Î†žih ꊜSRU¡#róÂ÷~ÀNµ«5ÄÙDú“okQûæºÃ¿5X ù®qBU¡YX¡‹!�–&œiWiÓ$¦ÞÖ"¦ùæª#�/AÝ‘¬Ì§ ªÐ(¬>Ðä…”'‡¼‡¦�yRõ:]ØkꟋpG²2Ÿ‚ªB“0aœµ·èp ]‘S=CA-b›e¯hdF,ÂÉÊ| ª À&¦m-¨a{»úFÑmhú?¦¸M�w¹ë›‹pI²2…\ÁB^1Om}¡lnW “|óDè^#t6ÉflÊd»ÅqV)‡¼Ê¿öƒ…²µ]-¡ä2 !N¼ñîR!̈Ÿ$Y™Ï·ŒPUVï·Ì¦RÙç8«F+ø GˆªŠ2‰Ã¸+� ]ÝÆ�å’œS2U…ºð¦öÝ/À®vµnB· QUQ·�gÄbÜ’¬L¦ªPÞ?ÙðaØ“0}j@· EUQVèlèf®%Ü’sJ¦ªè¨d†˜Ä�—ú°¥]}Ämhúmƒaœ›>ä/‘lòZâBÉvs/h©ª¢Gm3”ë`4@n’Î æ5Ã�…�Ë&&ñ×azbY×$+«*Þª¤`‡j=¸�³åòª+p–÷ h­×]¸†i3bgÜ’¬LPU¼¬ÔÀê&YPùàXÜ®~JQö–P;›ò-…ΆždItýŒÿ+.«æ®Lt’b¨ëžqNÜxÍêvpŽÖï‚rk/ÑEfX SBœpIÎ)FU1¨¡‚YÙ:pïSMj ÏÃUîìrŧmÙD2¿C^<\Õkè7 v6( ’@²¶Û „ˆãIW1Û{ÝãÅ–(÷ M+ωÿÿÑí;åB‰-÷0; àŠ‘jNCnnL凓¤Ø¢7qsÛ•ìð‚Àó´áÄ$©véMœMV6_è¶ßᓚ\Ǭ(Ç(m‚ç®üåwÔûäZ¾"4³]¥MTóš�ÍŒu6ñ¯J¯cùŒX„sIÓçˆëÌ�ÿ¸k0û _É�¢g§€�œ=’aU!ÍkW\ú9 žÒ¼k€ô:6̈E8•¬,�°ã«h5ái.D=†ê½§6±�7­Ï‡ÍøÑ/�‡DžÖ¬²LkWÿUñš�šël®é$½Ž=3b»qœU¤àíݪUæ%Ñ £ÖTGŠ3�˹(`D�Û/£YÏÎk²<šÔ®Ô/t¨bÈkØÄ$)VeUlj$€K‰Í=¼-ÿŽäµ© ßÛ‘�ƒe»®@Ö±_¸w2Ía·ï4}È2% à�ÊÒ‰� Þå$†èl¤±¶�%v'+[@2ºâªÎ„1wöBñ¯èÁØwø²�oÃn|z%�Nïì6½°&$T9¼ÐÞXgCQÔÃ$ ”ÆÚBlN(� Û2UzH_¡4þ9PjµMþ¢ Ÿoãzߟ€R_n�«h’Sä·àTÈI•WàB¹¥RcÑö7=Í)ိÉÊÈñ[µ8cTï#}g’XZ¼ž›øî…ü/;º2˪ƒx©µ.YQâ“®“§ iÚ«$pÔNsáJ lLV¶Fz:\²-S£¯Ô¶bÉŸWسM»¡-¾aó´ÐëÃïü$‡e£y]OHíJñðBß�o®ù4{%fÄ"¶Ø•¬liªÄ~Ķ̵ҘÄð¥Â3¡€™»\@ãTF‘ŸY‘o”,kCIñzàùUøÂQcš¡´«™J�Mè ’<Œx‘±›’•ý ×Ê·eê’Øw¼0rg-�Ü¿öìû`—Ï÷\f^> (¤û‡h’Ãq˜WnãIç)t6JúFýŽÓƹ±[’•IO€(mË$ ‘|ä¿¢/o9^„¶Ãñ¦Ñ!8ʼxv𓜠Òm0sÛÜh»R8¼`Öîb;(ÝêÐv¬OV–ö™Ø|*Û2 ¥KLÉA˜õ¿ Ìñ¤cï™D¬Î9µF²³§º-ÓH¼Ä¤S•t„,ÔÏøöÂ~’³¾¤DTþs`rÙH»’^Hji^¿2/§8<¹a±6 à2ñŒ8ж̃K+ßæ9ã”®à}Gà/<ÉÉ+2Š�‚:ô×fqCª€þvE&ˆ¢{&˜æ5T|šéÈ3V&+[(î±oË<&±µŠióѬ\ ï2žäœO„wŠ úraÇ¡3'8�ù…«¿*_Lz'} ÙÙ„p’kñy©ÑV&=ÔŽuÉÊæŠæ‡A·eÅÖ`ɰµøŽfð“–Lüüù…E—q­Ö—”„Ö,t¶+"}@%¾Q8ÁÉÇT‹’•¥‹Ïß–ñ´Û[iƒ“/ïf~’ó«d"œ{ñ4©ËÍ ­ßvC¨7ÑÕ®þg]g#œŒWÑbÛŒ%ÉÊÄ3bMÛ2žÅ&–“â÷‹Â$‡e à¸àEÀJä_!ßçÛè8êÒ\G»Z q›îæÝ5�œ|삵¸Ï’$€ËE7×Ô¸-ãY&EÓ ~DéÀ&ŒÌ Phµž±«r2Cª4·+Iú€aÏ•5ÑmÁÉ$ÇÎCK1;ç”hF¬}[&¶ƒÈ2šn¾M,ýw4²+¬_qtùWÈýåàÅÂP:Úg¥8ó¥ÑÄ$*4¥¥LsEÇì$€ó„±žm™²oˆ,£÷VáëK`›H‚|ï–Æ� Ÿ/c÷¹ËçîUµ$§0š˜D�Ž£«°ŸK%!­WŤ ‹Š¾wè2N\Á0â N-ü�&4h¯œYa]À�äKÀ¤'Ùx  ÐÅ{¤ßÙzæw…+)¼C§xïz“½†¢¨gDZæ>9ú1-ç”hF¬{[¦Ò‚aÆéÖœâÃÈ\ y#Vzá1ìò/¾ŒÝDz¤ÃÚÌÁ’¦ *F“Æóá8v«ÒÕ0) à ~Fld[F,ÔÙ¢6üŒ÷Ê™HÞ ŒlïOÈÇÑ»�xUž‘Å­ÂåkÏ–¤] yĺÌ‚Œ˜6„ãÌÓgË0%YÙ"nFœÔÚаXh ÓßÞ+x‹ $ŸæœÞß�µ¯² �þk\Ú}þòi½ ¶:Ÿ>ÀšÎÛ^ê7ÉóõÛÇ΄žsŠŸÞ–©)œšWÙàÔHÎf&;%þð_>²Í—8UAQIv÷mÕ72hWü½ß®¥¡ŠF)û:á86� J¨IÓgq�M{À×~Äf†Ñ‚lÊÁ�ä"ÀÓ›_ À·ýX@>VyåÒŸþ¶Ýwö½’Õ$€\ú£Y�´R¾‹Ôq†;�{U‘Ð’®å6õBÛ– . õ]„ó;p$ïôý¼ï\ñYäE%ìz¼6¾‰J@îð‚Ñ,HÚ©ø¾ÔqF¸CUZ²2nFò¶Ì-¼0Ч~>m>_!«LöelBºÁ3Ì“8ÀìÛuÙïÏ9¢-¤¬˜�½÷¡Ñ,Hº¨ÔMê8.QU„’p1ÛY›°-#œ1›bu¶¹´Áçû Î !㋜DðžÈ9®þ¢~ íŠMð¦ÁÄ$:©ÚSê8.QUÏ9õ 3#öœ{À‚ÐŒ{pùÖ_�¬Ýìæ${Åò`»Ï·Í�s׃ì &²Ì°ëÒÕ«ö(ìOȓ΢CÈ‚¤òà�KT“r3b³¶ex`Ê 3ê´á„  ¿hƒ°�åû p\™I"��ŽLøöp‰Rгsü�£°1A¶+œ>à�êæT[ uˆd&ã­½ ©v $dgÄ&nËð@MœÁÙ´ÿäÅ‹ÇÅ9töÁi¤ÿb�@œÀƒÖ98z¾°àï­>ôâ–+Šâi»BéLLb�¥‡\£ªððëL¦·‚ÙÒ3u[†šOç6°|çáOWfIý…ÍEà¿t6 Ø-…­JÓeq@txÁh$Çè).QUøöë;÷È̈MŽ”zžg­’¬sƒ30ë³9J2ŠýÐâŠÍus˜wÖ¼sá½_[( `!ö¾U©†“„qpÈ5ª ß¿Ž%ßá`©Ñ›S¨Â ÇZÒœvÁE|˜�9··¾©02¹%:fÃP9±¹ßΟŤ0˜)DîM’:Ž[T:’•¥Ï¶ ³ÁÄ´e­ò¥5<Œ§)¿³‡‡÷ãÐ`.ˆ¶vw_…µ=ðL€’�¾ô©!%& RÇõ_•‚ÚŽÖde8�µEÛ2±Y«Xr׊Íh ʸŠf9¾mÅhT|Ø|óeðŸR 'çùÑáã«sÛÇk¨…54#Ç-ª �IW�·r[†޶NÀÿ[1œ;|²')8(:lž —Ô7ëÏâcëç­©µ6ž"Ç-ª ßo’.eí¶L\WÆ(ŸYWÍ­çý%™XnÁoëÀ¢dä8y–Õ[ ÏJýÆ5ª ßÿù Ÿ@i¬­Ý–á€VeÃŽßðr{ƒè°ù ’þúœ´°âÁ!€®QUKˆgÄVo˰À785!>l¾ãx`m΢ºxÐ"aŸV$‡�ªÂé1ñLV†fÄ6l˰ÀÉÖ‡(6íãUê›ïr¦Íljuµµ 98ä&UE de(�µ-Û2µûÛ?ï;�ÂËRCNÕg’ƒCnRU¨'\2ʶmF˜b§M²A]�>w`=[ê­RèU…Z²²ùÃmÜ–a€ÛLÿó´ê½•ûÔ±«âÁ!€®QU(&+KŸcøæ†`€_9R‚ù#>°{3 •  kT ÉÊÒ¦Ù½-ƒ€Êw6³•µÓè·CÏ'k*U{Ig¢[6Çe9§VM° Ç:-4Y8š~ÕÌ,¦@ §¸esœIÈ+ –Žvb[ g:j†u³húE´çz!2‡ÓÓ]ã8(YÙɃÌã5rÄ:�#“,tÐKÆÒt¢#U)t�ªÂ·>¿0/ÈÓç´ íæÆyÚÚ Î ¤ÏI¦‡=àPÕƒA ]£ªðí(ÁióÒ>Ö—˜ÄL°pºCõ_ñ MqI´OR¨7y�Uì/@º�’c]�\Lx^¶xƒS�oShz€k¢} �@SŽ™À†£W ÈÜäczA@å;›YËjtZÃMÑ>`²ñÒ&s IÜžuÖ8H8ÉöÕÂB$2rW´OB˜ìäB̆b€³³Öémä}mo½×á›I¹-Ú§!t‰ªbyû¦{vÜâ´m¨¸wéá¶nú.Á¹&Ú¹.Ú§!aêù!ƒÌÜi«°Tú€ž`_$=}6>õîÆhŸR輪"mÆÝN…§JûîJºlþpg´O)tZU±|”ó”@õ>6mp¦ÏÃùÏ]í“C Ç9z#‡®uÚ j÷cÇçj&W‚‹£}rHàçTi3»Û˜¤C7 üÂúz/`Ò@¹:Ú'‡:¦ªX>þ§6¤Ô©;Èê3kg0vïã®®68?�:ŽCªŠ#:™wwHó¸%ÅÚ‘{1{ƒG×GûäÄ÷�:ŽªŠ´™tkËÒ8‡Ä¡&þ Xm.�nDûä�@Æt‚åãéçlÍ$¥ƒÆßYVíeÜ­UÃ"Ú'‡Ú¶`ù.%éÿœ¶�:Í- N¤ÏårŸ· ‹hŸ¤ÐVUEÚLzˆ{¢} ´³dà^ÉßÍ&\¢} Ô%€6ª*–�£¹)Ú§À ª=Ÿ»-IEû €öåªø.…îëö%hÙif×zítÎÒCîrºv¡AmRU¤Í¤i×Eûä\orÿ»p4gç0‹ö)@mQU,GÓ.ŒöÉyÒLU¿úÃhŸ„ÐUÅw)4íÊhŸ Ï[æõ¿? w®ÃhŸ�JÇjU£Üí“QmˆIý/:æÂ–Ñ>¥Ž“ºÊS)ƒÆ(÷Fûd<`N® •Ÿö ÓhŸ„ÐJU:ðáæhŸŒö#—™Skް�öÉ!€–©*ð5ÔÕÑ>’JýBVµ­ž*²mGûä�@‹TxŒr{´�¤!=&´�sa ïhŸRh‰ª÷Ö}N’©ŸÖ! ÜÌ1–p�öÉ!€æ«*ðÑ>’¸ž! ÜKƈŒúQØGûä�@³UxŒ �hI½aô'ÆÇâÕwdDûä�@sUÌŠ"<¢}2ž¥éIFf|Ë'ˆ Ñ>9U ‰ª v�—hI™÷hzªî�›=æÂ)Ñ>9¤Ð´]=fŒ £hɵCiú3�ŽÃsሜhŸBhV® fŒ «hÉ£ºg|ì1ŽŠö)@MQU¬cN|„W´�Äóº¾wÌ…#¢¢} @TìnÑ>’jõÜómñ‰‡¹â.–BCÞœawfÂ/ÚGr?­ùÞi³“%FŒ¼hŸ„pÔŠP¼†£Â1Ú'ßÄUËáþ˜ K$Fûh$†²9ÃŽQáí#©ÔWÓ=ß„c.,‘íS€ßœáÔ�Ã3ÚGÒ@ËRA8æÂ©Ñ>“Öücc1vnŒ ÛhŸŒƒ/øc.‘íS€RU,cǨ0Žö‘”ëN¾Y pÌ…#’£} @ý1v~Œ ëhÉMxÍ *À^4št›ÈŽöÉñ¼(­¿^U?F…w´OÆÓ¸RÊ@Ñ1ŽÄˆéjµB õÅØù1*Ü£}$e˜ÛÔ+­1—Ž#½& ¢}rH ž{ò*ìð�ö‘Ôb¢²5¦Thƒ‰ŠhŸR¨YUÁ�Qí#y„©!sa‰’hŸœ8B¨QUÁ�Q‘í#ñ¼ÆTN²Æü6…ôšè‰öÉ!€ÚT‚ #$ÚGR…• @É1–(ŠöÉ!€Të„FÄDûH³ä‚âc.Qí“S½�Ä)Á޼ cTEûdpKM,”sሲhŸœšR`UÅ·üŽ^DEûH*rFù‚8æÂmÑ>àèª ÑaÑ>’[9ÅÀ,ùê;*£} @uU…hŒŠ´hŸŒ–L=»]ÿ´Ük¢2Ú§À-R šªB£"0ÚGRîC4·,GyZ’n¥Ñ> ¢ªB4FÑ="0ÚGRwÝ÷vôÀÓFê6QíS€*œ\�Q‘í“ñT[v¥Û^l›(Žö)ð ´MÉT¢1*R£}$ÂÔݘ#ª£} @©ªbí4Ñ[íS§ì›|WÝÑ>à*cT$GûÔ‰{—©|ÔGûäxZHç+Å1*é§Ëé •º¡Ú·Š¾®68¤p®ÂáѾTéYíS�~#£Ýêt�£zïÒhŸ „©*ÄcTDûQÎé¸B8üñѾR A ÅDG´¯CTú@Ím¢$ÚWŠ1È €/•.AK !d‰Êh_)z¨Ý_æ5Ñí+E×~D¸ÍÐ{œ.R)á!Œæh_)z�£;ÚWŠî€=j8]˜RÂ^Ø¥4ÚWŠ,�ö•b„ÇK£}¥!±4ÚWŠ<-š9]Mü?/^ž„ endstream endobj 85 0 obj <> stream xœí�Ûn7†ïõ¼.Pš‡Ý%0 Ø–eô"’ho7 P4I“:@¿�d[ZGŸ4Ã¥d¥H ²ÇËÿÏ™áÚ†Ø/þgœùÙ®}›ú`n?L>Oæ’жÎÄÐw6§Ö|y;ùí'óqòy­íâÙÕ§Ûoæ_¯®Íò×÷““ëhÞÿ39ùõÓÇ×w_¾ÞÞ™ÓÓ“—¿L�3ggÓË…šì;ã]ÛÍ5¼›¼œ¼\W\oç¶åÝúmçûάÿÿêÚ|ûÕ]7““׿ùxzzr~{÷õÍ_7oÿ½3§³«Ù,¸0=3ggfnäɬ1>˜›w¿ô˜7]ò¶ }2¡77&§Î¹æÌÜü9¹z±ìÔÍæÔ¹¸üa²­ksÛ7�‚¦u®¹p®é¿°ÅŒËG3†J®nÆØŸœ·©ñ.îè€o�óÍ3Ùè³ ®Í»œÜFçšóg²1ëûìº]~ìœói„�O–…|UºÅ‡W×fù¡döûÆøhcXnÃe`ýü‡Éd÷Ð}¿¡ûáaô}—¿Z¡'ÁŒŽS\i›òøXC†'îÝ¡ø–”Ÿk›Š$àñ žGôÕ%5•´Ê#öœ”cÏyúÄj.aåã&\èÂæ1o»´yᬠü š˜».@僡(¿"�ÛÜT˜+²*´ ÌD™Uj— &Ã@�Éíè« ÖAC¨çÜêù`ŒÔ¡ïÇL9}†{;*Ï ޤ©Øâ$«b$åèvQM¡wwtPD3pI¨™‘„#ôÝ6ŽÀ@‚ÀNn éF Ò B|~BÍuaˆ =ÝPû*RêÑ8¢ÛÕ\‡9Nt"6…=¿¥ž³iïð¸�à6D{ ïþ(˜’r¤4Y­üð¦gGÄÐí¬üBÍ " -÷ŒúdÂÛwÅ* VÔ`^Ét80—ç•È»²¦Dkpƒ¹ ‚²Á�½?�îl‰bà‰!_‹ˆ£à´©ÆÐ‚S³þdލ{¡èqZn*Rî+*¯G 9XAŒ‘£Çå¢=»"Ùá-�`ì¡/ÚåeN<=Ž�Ó2ŽI§ÿšÔݾn• \É*& 3ÐQ1&Áæ"äßE:"ÒÕã¥!ÿ� Zp- ;0P›‹µ#FD ";Vb«ºý»äxb(xr=ZQpâ«—ýAåGQYÏq ¨)(ÞåòÑ\¥ç +EJÓEóˆS”ûA¼)⮟pì{ŠÂ ‚½ n’�1Æf+ö⦃Œûã6(~jЍbñ4Š%|@W—€rÅÃ3žxQ‡>m¤¯&ÀÉ€:ÈW<‚8wë�FyÓ!*8Ø`VlŠbVªæD47¢U˜Ì:DE2sÕ̦€è�¨žÔ²²}UÄÈb}S¥ÁúoÁHs+†&dÊ)ör¼åM·f#ðèE€¡¾ˆqÿŠå™ˆ=Ú–�²Š¡R¤¯W5ÀôŠÑšC”äVs!¡Ò'XG†ÅÕéëç�â«JК[PZò j\©È� )ôe¦„ºhUD·ë³\ß%Nk:(*Ö�qQ–K–‡9\5Ê1rš¶/ã4õ��u¨«žµ  ’p€ªQ}X ­â+'êðØQÆ‚ÆÒU"z ® ÒÇiA�*nrDD�ñ( .˜¿ ÂMäf‹C)zijD�ObnV±âE_Ÿ‰à:.Ë%jJWK l#kYñ’ v× RIšíê¡rçÐd§��ÔnÍ=©‹*ù>gõK± wn@®ŠÜÑGo}jRÈ;ýù#qµ?²‚¦¤b'>RAµ¹õ–JIq^ésyꈟ,~'C„:}ž��kj‘¹ÞOŸ£9Ý6]²® n÷¥®Ô/ˆÅªKy�Pïul•>Þ«?©k±ç:Ô »@‚ êí§ä«úµ_¾°þJ¿(ò[×$–óH©}Ky¨>„ƒæê'õÂ5Q¸b O�ÂÓ/‹Šý(¸æ¤­ÛBûDû°äœ/¬ƒù¾Í 0‘EgY€L–�Óç`޲¹ >ÇCÔÔ¸(£, 3.r¦Ÿ»|å…*j8&ÊΊY²RóqÙ@YMÔ )AºÿT�;ÂëAÙ§²w§©¯Xp dO) µT‡N¸õêc*Þ4ÒSI=ozÖw¯O-‘¬‚ë|ôPù£ÎçISu> ¢—ÜÉzþ]½Ielè÷­ÇUí,5Ñ­ü�ruö©øVþÑ#×hEÜZ>¬û1¸ªßXZ0ž÷…)?RNr—â®Ô¾â³2$Ñ¿ñ «1Z�:D÷bÇÅôתe媢€¢.ß|ñ¦Q��‚è÷‡>yÅwtýãËïø’ïD�]¶.„ä�wÁÛ>Ƹ5ÍåV#•}n6²„'‚ DljJ|"� ’`‚µuðÄÜL‚Ný¹•;jŠÝŽôU"�S›K#ÈÅß!@Ck-øÎ†fþÇ%B^,§.Øvþ«ËOkë® ¶™/Œn¹(Vß®šè�íB»u5žüœ™~º×žCgÛù#M›lï»®7ùþ­þ)76¦¦oÖLx�- XýÂc+>4Á†Þwq‡ Ù¯lˆ9ÙÖøöñQŸRkr—mj�kê‚…î¥Ô, �÷Ö5~WÇs|P:�ÿмö endstream endobj 87 0 obj <> stream xœí�ÛoG²Æý§7ÌéË�%ËÎ…Èb½ëÕ…Ó£‹�xƒÅY ¢ OÚ,p½‘<ÓÝC1¦©]X~Ù÷9ènÎpDQ¶DQì²~ÐCb»ºk¾þªêÑ#˜…Ú—¥„ ª$ÙS®#ªŠ÷Í�pA�H”KJו¤Åû,�¬3J$ý¹Ü�vûd}ë¬ÅûövÓ\(éäp7Jë_ž·Û'£«-�4�¤#J]‡T‰4M÷þö_]rgeá=Hï›aíÙ¥ëè€*qܽLÓt\#ñ˜˜trUÄXÌXL©¤T’â6à³°Pn Xþá¦o7Ayì6ª“vû·µµˆ1ɘ 4!$¡ôœ1·QŸ€†ZGbáèDÒw\ Xà¾ÞþíéÓ“v[ÚC‰RÅØ9cŠR×qÓÑG&�l.)ètr×#›KýVKe¹$)� ‘�K¥„pý¥fÒÉžHú‡ò²¨Ü6‘cã\2UÓïP5• S] 2.¶G¹ä:®+HÏS%æj“” J‡ ¼døÜ\m<Î>ÿ…y}+W"=zôH!¤<ï}­–"$³tRpÓ•܉I üü8 ¥÷|@x)j¤©¤ kµØóòËN¢àtrM½ÑN¬Ó){kC(­}Qv52ö<�±4'’4GÓ[Ïë"ä:®ÕÅã}H�NÙ¡„ŽŽÿEVâ•Da<ºéë"têy®ƒZQš;g´#<ÞgÙç?z®ïwÑÑ‘ëÐnËY­ÖÍ 'Æ"ŒN mEd'Òé”ï>Þ‰Ðó²(·¡‹Ð[ÏYÕ$(�;k6]ǵBhIGêtÊ®6ã*‰ïºíÎJÙM')=k6£zÝuP«BÁ’4J$¼Ÿ°0iñ¾ëÐfäÒHVÃæñ$‚0aIÒÜ®"\áýÄuh³“"ôãÈ÷óÏ:�šë–$¿“ÐŽ¤»Uª‘¦ù~lê¥\"° ¹ë¸––ë–$ètr×|Ð.”ÂS�BHÖj®ƒZNh -Iy"•Ä’4_ú¾?l4Æb8Ænºyc-I4(�%i¾ �$w]R*„HŒ]ǵ<”Ù’4wbJßa,óËãáÁAšV@Æ/?%·$=—ž—"”›RÒ4ýx|ì:¨Ê3aI²‰T6KÒÜÑ.‚‚D (lo °…ß²§HÁ’DÝĽô‰dI™Ü¤eLŒA"˜ fŽ#²§rK~> KZ#ME˜.U�Hw§Þ‰X³ÂíV KÒÜ)JÊJpÓÝ…J[’æË¤DÀH·g’ĸ¬œ%i¾X‰@€DpG–Ã’4w®K— |’Ü’D«oIš/)Bÿ©Õúy£cƒ­-¸énÂX’Þ-Iu®ê¼Â–¤ùÒ÷<;| ¿éÆú­–ë¸Jçé×[}cI)tW±@§“ëÐJDBi/«š¥ýV+ûåUÒ4ýû/ÿå|ì$1–$µ–¤¹S”„¹ìÀEPÄZ’ò™$KfIš/ÃFãœÒ$oƒ²/,p:WKoIš/ Æï=OåšõúÅá!Hvz$Ëj$&6�\ÇUv>fHB@"%RP8‘L:¹Ž«¤ýãsßKÛÛrUßVX¨òü±àDº羯²é(6�”ﯠD`<$¦ÓÈ’ÃÛïŽ"d\„¯¤D°Ê–¤¹s^« …“2#U]µ &,IºßvÅ,Ióe€PâyqÞ?Θ4‡•븜ÑÕ¶ò–¤ùcünk+ï�J0¾Xv�ÇûDû�®6ÆÅÊZ’æÎåñqš¦¹ýr¹ �0—^ön˸Üü>býß•µ$Í—4M/dvÓ)ã"PËxÓ¡­ÈÓÓÿ &IÞeg›ßG®C[¤™U˜÷�+ŒÏ,W£X’†òŒ±Uœô@'„Η¨Ñ,I FÕj*—ìðR¸À’´xB¢(²X’\a%Q”ÌC°ë¸fçøÍK6‰–¤Å`%‚±‹¡ËÊN4Ô–¤ñ¾­P¿¸aH¤E‘¦éðåË8·_2À8©àôËÑÓxÅ’DàÝv±Ä�†Èv÷蛎Ò^Õ$‚‰á6`IrˆmÏ'©êU禳’ñ¾-°$¹F$aêpUõ‹mnI²‰–$·h‰ã(ÃMÓJ\î}+Ú’Jœ´‰T"ÆÞmoçöËØó†%–¦[’BБÊÂÇŸ~K”–V"˜´$`I*Z"88ˆ ë ôîßw×üýˆ†ñ¤%éX’JGDˆ0õÒ(�|ÿ-ÆåYz¨=$a¬Ó)»ÚÀ’Tftá]X¶ÒEè¬73æ°$U‹¸ÙŒ67óÂ)2#Ä݆„¾è[¦LåÒvÏëD`I*9:‘êõ^¡¥N˜¡…®âÑSÚöúnP´$±Ž¢Û=W!·§GÈûB£�`løôiÊùâ#á<ÝàïïæÁ’T9®¸(M9ÿøõ× Ž!MÓÿ1–$’öôR°$U‹ ‰@2X__ðÒCkIÊ×$áNB¸"{�HÕ#²»Ÿ KcJO¥8Ñ@€%i™ÐÅR½nç<+BN}?ZHn»þi¶“,IËA¼¶¦¿ì¬€iÆÑ«öË‘¢�$w’€%©úLH*û²{ Žj4ÐÆ^m†Û,=Ó¨"r¹éÁ$kI"ÁØ’dsiîÿàAi\Ø�r~9o‰Àï(Œ-I£‘’p"-#‘ïŸ5›¹ýr°±¡æ÷MÇÌŠd�NÙÜ6ý‚ä’rÖlƾ/³é—Ê÷cÆæ"\·$¥iúS,IËŒô}Q¯Ë¹JS-I{ÿ�Ë= K¹3œ±û4€%i•‰67uW]½ž§“6;ÍÔh–$À^s*S/¥ç]åò–º„áyÑç ¦Z’p¨ÓiQ�eDr–�IÑÎp„âÏ5ØÅm`I®ófcã¤ÝÎûV„YD~Óÿ¬-I? òDÒâ$X’€Œ“vû·f3.8Ãå ¦” K’)É8ì’ÆÄvofÁ”r±¹9!¶‘f’@± \ÃNOÍÓiB"°’±Û,IÀ'Q„L•Ì‚­±%‰è\–$àô¬å2ó8Y‰àÛg‡t´ydЋ۠F>‡dì_çöË¡×_-I[æ#Îu˜@5øµV;ÊÆþ«¾þÃ�µÝS[lƒ% ¸ÏÑÑßü ʪ=ûÇOþ¬_èüÆ�Ïv~ú—×xí:^ tè•‘»1îØ¶‘„æS‘³HÎÓÜ?ð¦¾þã³]×QåÂv‹àNŒ¶¢É7Ý‘¤š;g¬<ÿõäIÇ>ÌY1Üuà@YÀû ÑÃØEÞ-rå Ò‰$X'öwãæÎÙÏK3Y@¯0¨øZ:àþè‘Áåf0$\c¶ºžE�CÖIlk[þßV,ÁŠCà>øæ¨Ùà½#2˜,‡h(ê�HD»=§ßx1œøã±éêÍsÉÑ/¸¤ÅûužøæüñMÎ\Ë"‰ŽŽÈáÄõÎ�mG"ŸÅÒꑵ`›Ýë“Eµ¤�jÄ,Þ«ÿ«ýõ×OwAö[-U¸àzÜlÌÝîÑ]¥·ßPT¤d¡ðCÑ8ˆoów&�F¿Õ²¹4l4ú®ƒŠÞDóìÒûfH;º½qJ ™þYDÖR{§¿\ù¾Èz0Ɔ�ÆCý€S¬Æè™'³iEµùºçÂãokül¶þYqu\êü€KÐsUÛ–ÞŽ´Of4¸öuÊvû¤±s6ñu?cã·Iª¹ý€kFJõ®@ÏÕ´¢Úöò‹µ­Ó�oÚí“{þszfEv"ÅŸ<™Óï8ªÚžôB9*ª§eQš¦ÛGïl:Íëß¾Ÿo¨O9ÿðÕWóú›�“Õ8”èpŠL­…£W§4ŒÚþÙù «îL¬¯;ÙŸÜ?b¡ z7½¨æ’u´oŸîÅl?ò_�>P#}ÒèÞP,U‹Íï£æË¸~ h(ôhµ@ûÐ&•êÑ×½N§ &MÓA¶ÚIOºU�ðáÊß›ßGSÊ¡Ph2�÷ùº¿+—?ÿœïuê{<é–ûÙEíFuÞ›òdf‹j;ÿa±‹±.^¾�Ø%¤?ÓÔAà¡IÓô¸{yøË�'ò]õ¡‘ƒß WTTß™5Z ó³ø€Oãïž³N²ýÃû4M'²ˆåó‹I„„=rð»ÃPÇ…·™†ê0 HÞÜAåïžëcçšMÏ ¨2Ì/Š67EvÁ% ¸àJ€ÞJ̧7wèi¯g<&µƒsôÝÀu¼#Daèw„�xüØuD«Ë¸¹ÃÌo¼©¹c�h¨è^é†ÍŠFC™sI™ÑpŸ�Z <ŸmîУÔñ4¸h—¥m}µßn6—zS!0A�+Ÿ[iñSÍÄþð²Ïá…clÁû�W–¼¹ƒf:ú­›;ÊLÑ—«0>m6]G´ä�Ž ±¼»©¹cdº¾¡¹£Ìô ¾Ü“vûÍúºëˆ–“¢�tÄT7#::‡oL.ÝÊS]6ßO²sé¬Ñ8i·]G´l|·v‡æŽ’£²…ÎàË�/·iîHÓtçÇÁí›;ÊŒ¶lo«l® äÒý¹}s‡Ã'³‡àCÁ à\º hî(3ï_¾Œ²½„7m>Í"›;ÊL̘€biVØž^‹; jî(9"Û�"�ÙÛu8e‡è�°1)Œ oàHÏË=Þ1¥ÃÃC×UEb¬ÓÉôê¦iúáøØuD@UÉ%Aé»­­•z9æË•IÐÄÌJÊù`c#ÛÁ“.0+—ívÊù¨ñ¤ÙŒ|ßuD@U¹xúÔ^pŠÁØ(ÞÀ¬ÝÝ`ðîC^xëé�KÀ¬tŠ0�í"$�b ˜•³Z­›­Óí·Z½zÝuD@U‰> stream xœÕ�{T×Çw–§E1b¢¢6‘ªñ™H}5jƒU۠Ɔ&ÍÃÓºFcµ�‰h|‘“¤%c06í&š*IjåcÔªˆäDE|">€à‹Ç‚‹(�…ÝoÏ®;`g¸3sgg÷ó×ïîÜûã·À½w¾÷þæŽNç×¾¾’;Zë 2¯ 8©u Ùà²ÖA(#4hJÕ: EwÁòÕ<ƒÖa(Á° Uƒ´Bz3jcµB! ~‚´ÓÏä­U+Y¬€í×ÒZ¯V‰_[Uæ£åy‰Mº–˜«R<2xÙî˜#¹Ñ~ð¬*áÈaZ3Þ’Þ*dÅ1”< F<2˜Ø€wd54Æ7Ô£‘Ũ;Ø(³iïü‰r4²R�/eOÎÏáî@ºáÈ¡_¾ ”ß<§‚h†#‡^ÅÈ QоS> Žºåãx'EFÚìqÔÂ!ÆÈ™'q¾«Bw+QÚMiH J>©gìÐÃ(ì¡Ô¡á v*ŽJÒ|-ÿd Æ](ù©rŸÑÕ0)÷BŠ~Vv j£Ý%§`x”†Ûßâž÷ØÉÙwÁάÜW2¶I#¬ Î6Óm¯‘, ¿‚)¹êãž/“θ{ôJÉ‚A„Ø&=g¢è¿Hìô—û¶ Á ÆÛ°}-¿àGÑ€i²]=\’à¶¼ Z�¿«õWTÉ`»]fFýg°Žè 6]ÖíæÍCú]Ø/oZ û�½«X‹{ãÅ+Ó&ðèR^©{9Þ�ãŸ×̘«Õ "D[ø½S��‹T@¿õ;fJVQ0ˆ0±”ß6â¢ôö£#ÌÞ+* 1Þ9ÀBÎq»°¤,Ë‹t[Ó›±˜bdäö½Ë+ ®Çtií_¾ÞÛm=Ý€Õ4#“@÷ü^¸5½E*·ã™rf›X}Á ÂX oZÕ§ã°„v`ÅH·5´[5Ì^r‚—U.Eë™)9¦Ü ‚A,�oÖëtÌ­¿n²Ã6J²‹è«Èð‚`¡Ë�Ï ÊdKP(õæßk‚A„áU§®²CðY˜Å«·¥ó)œ‹$¨§&?.ƒã�lqP=$ͶaYÞ ‚ ßgþÕ ¦�XýÖíñ¦`D¿¨¥Ü|­ÿGDðØŽJÈÕt®º¦ÛxS]T–6ÔîmÁ Âl~Ô¿rØøò¾` f=Š~BR/IÁ@Jðl"¨¶- Õ4bÐ=tœ0õŠ�7$û óq»£v†V‚�˜o‘%>À>݈U^‹FÝʰLìú˜:ZÛ*2ÉÞPF/42Ä:�®³)Û¥k¤68ËËÇúÄ¥Ö¤ MVúqæ»Àm3ÉþA·7½KE«Òfþ¡W#.õL,ìÙ&²´ô ÇY3n¯4À½<‘üiƒUìxÁ�v¡_‹7È,O�7ÉdO)ƒ *…E³<%¥QP-û»_ˆÍâuU§Õò9ãO°æWÚ]ûP›å rV®aÍB(|„QÌòDŒœÆØótº:êu…ÊôOºáÒ5òt‚jÙDü©8J3.bB–'ˆǽ `µ÷ÂãáZž¸“J~CÔžåÜQ໥e°Ó ÒtVpy‚œýìé'ú*x7#Ý—Ö$²> stream xœí�]l×uÇ ÇBô!IŠ AóÞ—¤ j7 yq ÍSŠE�ÄyÉKÑíÜ�™]‘Ô*–µH¥ )îÜYR’«éL' ´`l4^Y$gîÜYQ¢©–ê÷iïÜ�»Ãå‡DjvïÌìùaaÌ=îœùŸsÏnNL§³ÑZºƒ}ŽYDX„=N¼Ðé¦ãªÍ…¹ÓélÈtJóаÈéN—›Ž ¨6 KÛólgIEXäz1]‰LÇTÂbêÅØ$—Wdy@WbÓ¡U…ÈR*",¦SO`_87îÊY˜Ž¨$NWȤÒe•ϱ‘Õ˜¬ÅÎ�»¦£* ê©ú\?þøòú}â—«Vç„ ?ËB¦#Žƒ°3®R+=©¢$IÞî?4×>"„d.©ÔB(B(†Ô*+Îj@ü�°P%e‚±äßßù8IÓ¡íƒc,S+Í«ˆ�qŒP„±é¸€Ch]Ýr¼@¦–’@YÔ¾\\Ûc¬\I577·×n‡„DGúÈJˆ¦ãƱ–|5h]ÝÒzBóÊ^Ó�Û7Ë(­téRÂX”�W!¥Ûõ-ËthÀˆy¶Cº‘µì©–ï6¯ì™ípÆ~×ná”F”Fé}ËÚl4L‡ ét6–¶djeI…®FxE”\¤" Ó3J? Û†Ã2`Y‰{ñn§³¡“Ê^��'SËthODß²¶m[ð!�ñ=(´Œ’$Iï—[V¢Ûʸ'�/SËth'€²‹�POCBîaC^åíþÃ$IF�¿nŒ™À=a:®óȶ“ÜÓP` šƒ)¨-¿¹KõIåGØ“©e:®Ó�XÖ^£ÚöðõPéŽc:®™ƒ2NÿüAÙ�ÏÌŒÖpúÅÓ¢ú1Ñ`�T0È&g´ìpg~~¦°-¯�v¿8=®RËt\õA^Ë�•nt:ýÅEÓAMì œîÒe•J-ÓqÕ�¨Ñ¹%Z[ͦ¨ïìŸL*yá={ü¥>€:5@&U®%­ùZÊ„Åi^e~"Ã-UpRMŠã2¾®²Ã˜�–THÇAMÇUsÞÛÉB=MUcvZên) *L�uËú-B�ëꤒÎ;µ¸(}¨�ÖÌÞÒš>�ëòœIJÜh<8>aÌt\OŸ�ã%´Óª=Q:í … c�ª,ga§õ¿e³Óšò²ƒ ôÃ……Š®…ÇL&U%ì´f™Té+‡q*œUÛtd-¶œü9•ÙNkFˆ(ý@»RXVX©¾rvZ³ÃØnŽ¯È´Cj§µ]9;­aݲ޷íP畺4]zE+g§%ªh§5 „JÅÒëhyÐn—Yv¨‡�Ö,0ôÜÉ­„±‡%–jc§5 ¨´žýÛ-«ì@ؾ‘ªJÛiͪ]rÙA9�–4ú±J-ÓqÇQºÕlŽœÊK&;´Ó"LPNª p{qq£ÓÑ…OÕ-ÓAÍéÕguµÓª=�Î�V+Ì�ÐÈÑeÛ6Ù¿¥ª~vZ³À>Ù�ÒȶÍN; &Ò]gÙôK6¯n*àÔì»l¨d‡K—ŒD‚»\¾î1‘·Ó‚}zÕE¤SÊ:µvÅÔí¤gÍNkÛt$'¤tsŠ©uÐNK.º …*�ÀXÊ™¢µé8Á´ZÒ‡Úi�]íÃB¡z0”²Ù?N©˜|j��V푲ùsZv”F–Øi ¼v�¬F3e§5 (ÙALEv8h§%K÷4µ&ñu€YDÞn`b²ÃA;-Üå¨Ëíð©-�ãlµZZ„ß]X(|·ÃA;-)ªwáö_�ÙjµBljGïvÓ7Ä¢~?ØiÍ,‘ãp×ÕîNÊj5ØiÍ,á¹sA»=T´( ‹˜„Z隊)w-8©fˆ ÝæÍf¬Ÿ†ÙU‹SÿBåy4Ê+yL�óÑ,¢’J_9ä”î]¸p:Ùá;­ôi8�¨� ­èöË�N.;àžÀ9;-"ç©8ØiÍ8yÙAœ\v ©Íî =¤·”¾ N2d <�ìàvê…*µÔI•$ɯa¡�¢d~Âi›íoÜN«÷› š}²!áãœ,¤çQ—Ûlì´€c�I広lö/JÝ¥�’¬¥_ ÀN x¸¼¬�¬£d½Pì´€'äáÛo'IrÌ´CºPh+¿PÈeÂe`§G’${kk�~¦—,¢ìÝ0I’7ÞR …†ëdÉŠ žL-Ó�e'È™:É�ãl#ÔOw;d»_²{Êl m V ©€'BWŽ£/´ö-k«Ñ žX~s´û%]… vZÀÉ[-ù†˜¥Ö{nûÊOMFÆÃÆ�é0�Š1&;üfþÕë—ÞÈû‰€�p:®_Z½uþŸï´‡›Ž¨óŸ}5³~"À) ~H|ŽX`±þ¯.,é§áÿ´.üò•L¿'‚,ÈŠ Òꈧ©%«©ÞOþ�“¡Rúnë•wj:L ¨ýöOöHW®â'¹AâÔQ+¼íÎG„Üi.þâÒk¿jÿÜt¼@ÙqVêsô³û–•�‘€�}üuÃý±?œŸAè¿Ýó¿¸ôšé¨�’Ò¾´®‡î'>—GÚâ6—Q�ÎFsy뵋׵�Óºe½wö¬éØ�2"r&œUÞ¾è]y£Ïpç'?·´¹xåv§³!$²6ô­—l£2`–l£µ²qÿÀ#ϓƑËë÷Ç4„±]Fÿ D¨k2û7Z�>”‰y¶C=qí�=ÕûûßGI•žZ†þ , ÕûK÷öÜ5™l°SþГKø7Ù਑;©œW3 cÉ%ïaÛÛÃ,B«ñ!9‹ä¢³^,µ©Þc–ð ½Ñ(K­iý@YpÒ¶Ý"Û•«�ÆùÞGzƒÔ-n¬Ýµ^ß}’ßíÏ«Éÿ@Y°.‹Ærd_ML©¢AYëëèúéu²™(ÚgU�£¹ö0Å@``Æíï7Þx÷wdÆvtR•Ó (Š| o¬ ׊Áð»¼É~úÛ1�^}5aL%Õ=Œ�Wuäøž¾i…¼€´mãA»-Ò7 ïA^ՋǶð”æi³íÛ*ð¦U”q‡âª.´…‡º±ÜyîÇØLÙ£!Ê™Eð&XÆZx?Z|ë÷ÿàÓ‡¯�·ðü{uÍøhG¹¤‚¢½ä¤n¡|Á»?ÖÂûë—Ïú�>ÿÿô_§háM‚¡Q^9΄LEƒnáI¼Ëmá=óÌ3sssöÂK_ýöMÇ;'ŠÕË ¥‰e=4í3ŒñØ^s-¤>ÿË—^6é>òΪ»%0{\¬k¢Ñ‹� [xþ> ­\}k×I]DMÇ;Îh<Š« [xÈ�¬kb4™y …7MÅà¤$I²«Wö¥Æ—¦#š]l¶ƒ¼�}ùÃ-> stream xœÕ�{\”ÅÇ_n‚T4°)EÓ45ŠLóž’f—sÊ"˲¼'5/õ±¶Ò:püäYÍ�ÔÖL -e�eje ™&"ÞHQ�‹ŠrSî²°û;Ÿe¹íî¼ïÎ;ï¼»òýƒÝ�ËóÎûÎûÌÌoAhÕL:}n™«ÛÀ¯4 t(SÞCfoŠ[ÅÅ”|:—˜ÁÅÔsp�‹)ù¼ ­ShÂzºÊ�gj±;º7s~.ò#ì&ÞçiÏE~ ­À®]ãÇ b|å&¿Úì”ÓóE²\âGï<|ç!¿Úí9À•®ä­aæWn%•}y´†™Y¨›ÌÃÎ$“;_ç0Åhz�‹!ßt,åbˆ‰ñ5x‡“©ÁãXN¦d3¬K¸‹$t¾ÎᾬågÍý¾ãgM}ò±Õ�£½že˜ÎÑ-A—°Û‹«Å—QÙ‡«AºœÇ~Î6·:¿óíxÇÚs7š��yÛ”¦Ý!¤uáovx�ñþVÅi³—îTÃpr:«a—Œ‡ê„Cž‰Ø¡ŠanQ¢’íže˜¦’i;VàÆp‘¬6SVÌÌPbüéηkȸɳ4³""f<õpp;%"Q3A,¯ p½Ê¤Èü7ø“øXê4qáÆ¤Òü“ñ±ë´ëtºM»�dU]Üûɬיƒºp›¤=)�ïÚ=ÛC8­Ì�ŽÙöA›çð¨#eûV½>ÜzRÆ=øI ë·ðe£ÉnèÖ쇅~Øu¾n�l)9þŸGø>!ÿQ‹·íùú!,iÙù.Ê8=�û£jl5>²Oåì‡g"þ×ð¶lѺš#ðPþKHæì‡\†W̯}¿É_¨¬O"3 16‘º>333óF�ùçá†$å~¯¢ân!0¦à=_ŦôÊÅNO›´%z½^Ÿ[jþ¹¾!‰ƒ·86¯0Š{ ZO·,Ä“—x¯Áï*.÷Wn†„ÿY$‰ü™¹ûáþa‰Ñ8F±íÿDŠX(ÊÛ�Î?èú1.óYÀ¶¦Í¯ÈYþ²òc{rr’““•\+$Sç%x�^‰2;p¥§hî’ Mo7ÄYPp­©Ï™_‚Ëñ²+DÜ6ášJ·�oeõ³¼™nî|ù²e*FÕh®Eq[q¦ù.ô»ˆHžÆçÁð$O{|šè×âÓÈ:#Çßß«&ã‹ü¬Iòî_~VŸ—rì|Ÿ©…˜p‚7á9AÖ žIØÂÉvØM¼ÇÉ”#FÞg›Ô«/q±=´’³ˆGœ»òÂìg¢Tü¹EÏ blfñ°àþ;q©|;ä760Šx˜ˆú•¸áw‰4•«ˆ‡…¹"áÛ¨ºÚ‡•™`ñ0ÐáâD±,-²:(2Í.â‘ÏÊ/D³<“£À²2�Lúˆgö.ÇfË^?)ñÈcï\©Ü×PڃѰr�&�‘lcY;_"x¤;�tº„ÅL–—á†b=“ÿpT‚±ó]ƒh7¨ÉŽ'ÿ—#S~çËKÄCɄǡ�×Q|%×.7%ûiBÚÞ�9 zÊÀMÄCEß«¶“­D"P"ë90¦ÿfn Q+èÊéqHFçÂUÄCCeßé2Qå-âqÌ�s´%Gki÷^]Â.ªo+?¢éŸpŸ “n)A �#§)ð:†M4åTñ8àÎ\…{WàÇ¥Ú§K§}+§ô�¯YÄä¨w6GÈ*þþpÐùšE<Î—Õ Ùò®éŸë`Oœš" î(”YáQcí©| �šŒ:$·ÆJdHôER"5™IÕ‘¶Äû$6Šf¾‰ºçD3ýDs”£•¿´ß ˆ�*¦M»”£UœÝ!þëe6JÈâH¢ˆ§™bŠg+'ïg¨´‹ÜùŽ­Æ‡µ|‘Èp-J²Yæ–üs¡±OR�O¥j=d¬å·Û–kþ,µ5Ùw¾‹ðµä 0½ÖÀu¹ÑŠ*¶°t5.Øt¾$�M®«µxà^ÇÖ‡xŸ„õ„p ¨ˆ§‰ òïLWsLûrÆŠý«ð|‹�"ž&®&‡eŒøV°ÖœƒâæÎ·ƒ„ˆ§‘öFÞ ‰F ¬£O·Ý8Øømoû;.Üá¨ÂÐJ7W2^Î×™<¹�ÓS^{pÅñ|üÌ óI"å*­¯e3Wo2ËØvW0«¿|-"žPŠÒ‡aüe÷ œd¿žñ„5sZ¼OAgÖnЉxŠêjƒÜÕb û%X?GAåþUHO€�Jªß%æ¾qbåç .(μϔÔ^ÀD7}=Ì0£^lØ;QMpØo *ûf¨£+ûúS¶Y*ñÐyØÑ-Ÿ¹ê°/ë{ÒjºÒ!BTó¥((a{€tŠ8àD „žL¼ªKlûž’_Ç=L_äEÒ@=ÇÓ¦\‘*ÂïHŽ}Ht×dƸp/Að3Ý ŽkF•Ý6Ú�z{½Îö. 9/ˆwxœ H�´Äˆ@À.ævp]¦ù¶´ǹåÉÙö×^ªõa�ƒ–A¹–e¾=8#aaùü[ìü¶¼FY½cD€äù-ô=VƒIŠyîˆÑÙûñÂÏT5Cu•@‰Îzz%Ôº“¹_Ó–¤�à‡Ï5Ç“ü]5cB„ͯ´èg‡“¥.JÁa­ƒÕK�0}-pEkáOÆÚ ÷Êçº\HòãÁ ©¹†¾Ú| fO8©+$çݬˆ\M[’ ’Â)Ѹۧ¾—MÕˆˆÌa<åu}r9l—øÚ¼›Í²Ï›èÇì]äz¡ºr ,Ft„âQi¢ jæð8i�N§ÓÖ¿%úá�3Ø>Ñ@%GHDÙ!H£l�G†BÉ©-D?„7mÿ îa1UæJzìA-~i?u é ûá}Ùj€Ý"€’d#$U�ÍxžáºF5I«=…­Ö~ñbvó©cÞá{êÌE´òñ—B`®’íZöl€{‘H›ó ¯¶”¾u5t“QÎÚÛ%ŒºÒQ:ÔPg5”�ÐPFâÔšD$°1º!€¢ŸÏz—¸÷ÚžÐÜŽ &�®Qµ¤J’˜JS¬ív1¶<<Âô v•Ì)ÒP�¡²n+c³dÒ§!€ú2V^½®(¡¼=ž¡ê°¼KuNÓE¼ÿ\ «êÓø•¢T`ç'9‰Ðè" <¦¡—í‘/K²”æL·vIªoRó‹8i@M”ØŠlO<ÏyüÀrD³ ,T‘n�Uêô ún·ˆî#o"úwU·Ej²È”†^�×–YxZÅ{Ü@]Ö¨¥Çh¯<Íñ6ûùÙ�²[GK?m!pS<€úì(åÙ1ëàèdÞÅiª5&ÐPšLºÂ’á`ƒJÔY•Ô$õT©Ãjf.�hÚ§¦NrK —.I•Úî˜ÿmõX…Nêaœ’Êî–°K!²%€ºªíEW<$í ‡î.À‰ÜÑW?àÿÜèy ¨‹#Î@‘ñý*Õn· ß@|ZØ}a×ÉC¡)€:¯‘y‚Õ”‚·¤ÝÎÀ ±¬þ‡ñî¨ê¨*ºaª5ÁûR¤VÅ;›*EüôŽ,œÅqãG@ìoo5PŒ7ܤìmÝE3'â9c|êN®¿ý€ (ø„~S„m£®- ¡"±œ”<.!õiö ’Hp9\áÙtAkŠ>'÷q?� —sðüK¼÷íJìû—�TaìcQaloåÛæ§œŸÊ_~xÛ¶xy"Äð��˜·Ævþ·ò¬>{Mˆ-‰㤃$˜éý¯ô ë'·¼½ˆš?Ü=gWiÒ,5ÅëüY°«8U÷æ„`Ë7gµežç=Ï.Þž•óåd&°‹p¿‹Õ©¿ý¤ÿ"?ë㎦U¥ï\:Åisž\ñ0î‰ðLóÂÃ÷uÖYj 꽓·4³äïá¾%Ù %jÀ[‡³pÖ)oªÒÞx³µßáõŒÅW7� ï#ÚÕMàÂNNg”¹š«Pk÷ƒS鎢[=²¥böºº \ÐBUA±ÓØæ3ôo%ÜËà`2Ì{P¨*Z|¾ @–dþÒ`„ÓšÃÌ l³OìÖ4-—–½ãxkðãsÒžf šÆçamkðãËÓ-üZ‡m µ„œÖçÇœ ¤¶>?ÞÆzë„ÀÐÐÐÐO1ÆüÒ0,i ~l·ý?ñZ4Ó ‡h ~dá^ë„�áááá[1ÍüÒpç´?PNšŒnu÷Ç“ Jq[�Qäÿ¡ÜÂÿàà-x>8ØÙçxÉãL"%·ðcmÃ=ïÄó8å3ì&ˆËC4M3Aã5Ä]Ïøë09ù?ªÂ÷޹ºXiâ]Ýøì> stream xœí�ÛnÛF†ïõ{] ôž¸$ÀeYF/R ©�ö6p“E“4®ôñ J>�Ž>j†\S Ú d�¹3³§ùç°Ë‡fóÇXcÍ�EçǪñææãâË¢¥ø²´&ø&uUšÛw‹_0Ÿ_¡p¾Ü<ûôéæã™öï›+³ýpûaqṙ¿'?þôËÝí×›;szzòêâ§•±æìl¹ºØ°©]2Ζ©åð~ñzñºËÞÛ¦he«÷ó/’k’éþÿæÊ|ûå“\ËëÅÉ/½ýtzzr~s÷õíŸ×ïþ¹3§ëËõÚ[¿:3gg¦òd�óæúýÂm{Ì™T¹"ù¦2¾1×§ÖÚxf®ÿX\¾Ú*uý»9µ6l¿¬ŠÒ–uÙÄGB,­�Kkc³ù…1.Åè3¹¼ž"e]QEgÃ\Ùþ;�Œ®.¼-ë}�\kãù�d ¾pMmÓ¾~LÖºj‚ŒÏ–…|UÚ͇7WfûaÌìwѸP¿Ý$úË pí—•iBÚ?é¡ÜŽ^°þ~94Mª£{Zþ÷Íìx‚XiypSjq±)GMù5‚U‹[i �û–\Aד¸¨ >¡ï+Ozø†4EYs”Š&œ?—Ì+ŸünB™ªÝ ö 5å�ÐS°÷„BoÌ{Ì=¨)Ò<ôôè6Õ»¤Çƒšò¨Š»"ŽÇ9¨)‡³d¥f.šp2±wiÂ!ÖüB¢y] æîˆÞ='BMÌ—Ùôà'Ö’�ê‚h�÷ô¨¨©(G48j&�#Î6C@ 8ŒšK" Õû�Ú6J(.W½}c¼AÆu„ ù@BRcL5ÒÒë1‚9‚D×ê1—í\2 ¢¶ozŽX·ÍÛ¿%+ a¢}#Í‚qïê$ˆ¤�b4‡ö-hÅeÐ !œÔ„Ç'mÆõ� A�d·×£ÕÑ‚_�„—rìd„¾uðŠÊƒyW|Hq““�ƒë¾Ìf¤FÌeÜ‘iÖìÃfYìvÆÙ¯^zú¹<Çæ0èsø{"ä9-\ÎYâM˜Ì wX( Ê^¾P¦÷(K Æ ;QØ·C�êd�{Q.#gr€fIÀ ºh dytÑlïÅœ_h‰xÌ>á$MEK¹ ûÕC…�Àt»çELmG¹,hI02ÂÉQƒ=à�%² %êýëY" JDÍÕ) 5zèoÿ2=°j„”<ô6s´¡¢|§hÔ›¬^c, Í^öç"«Ë{6â&Ìõ.¢9.ÃÐg“E…yô.!�©”Õ»M„.HÐWEÒÐÎ’ÝA0Yvë55w91òØQ¾p„¥¡<Á&F�­‘ÏÄã�zàh­Ð¸H`ËžÏägDAzèÂ5§s‡²þp_7_‘š^\¬,Q˜Hñ&Y­¦¬€LøèK%ª Ø”cR_qƒ€!‡ÇÔ¡«5Ž„P2¼âq€^S²ãˆP2z ¢°ë´lj1_Ù¹ uÔe.èÛ#® ]&Œôi_5ØÉ˜9hjæ�•—aDj&c¼IÍK�ÿàø‹"-ÖÅÕ{ j§“÷X˜–Ï%q�ôf$sÆÝôD¼1ÃùƒŒQ²TEk…›¹>­îvNÃëžGSžÐó šÚ09ˆžŠ‚4!R s5”ìmá¢Äýè“Ç]ê0]ÈËçÀGFsL¶‡½ã|×*ä¬?Ó›J}àV­˜¡ˆ�ñÞ˜ŒH+c �újÄÍs”Η@`è¢>˜ O¶!<ÒÛ��ê °"_%dΰ>Â4Ü%$ÒÇ›D¡ÄiXàÿC‡†#BΆišÁÛŒÕR·©_0"͈o =°©Œ·é+Ö¾¯³ˆ>Ar4ù­‰9ÚnØ_Aí��8ˆ»cÆŠìb(#Âch{¨©€Ìõ€ê�UЇ½DZt”Aô’=sGUqz¤5±vR¨‚æ1ºF¶g©!Ø©Üàe–úRíþôA¯�<Êä¿ò@Ÿ0ÊXÆ”ñ¸ì l¦Ñ–H>Äi²,쇗ÎÛ<¾ŽqÆ×ÎUxQ²­ ë}匳ÞMapÏèÄàjWÇ�Véa „€M­ˆ€Ox""¬�ЙîÏÄ­‰�ÔOP— sKMq·#ûª"‚U‹K#Èåû�v Ò[kÞ¥ÂÇöu§¾Þ,§ä‹²ýÕí§ÎºK¾ˆíÂHÛEñôãS�-’/WãÉoÞšÕç{îMª‹ª4±©‹2ºÔ˜äZ¦el}lb—ý†²aýD¾ÞÙXÑ¥öð®«.ï¶Aš‡G[Ñ·M÷Õîq-ÍýsMô…o\ÚDZyàØvû¿;Á endstream endobj 94 0 obj <> stream xœí]ÛŽã6}÷Wðy�Uó~ ôu°Y ™v_ƒÙ$@�™$³`?!˲¬¶�Ä¢)‰r;×H¤ÈbÕ© ‹•Taû㌳¿WuA²OŸ7njŠ4†3%ƒ­¼3ìëO›ý�}Ùü¹Q•�fûl×úôy#Xý燬i|ýesóA±_þ»¹ùçï_>~ûú×§oìööæ»Ç<1Îîîž·Ýxa™àÆÖ=ü¼ù~ó}Z÷•SJ±Ê;nY¼VõPŽì†e]%êÏvL8^I&…¨8ç\2%š±Hç+É9»¡�ÚÓÞŒSòPÕ/óµ"Xvøÿz G?v}xÝÜ|üãÇ/··7÷Ÿ¾ýõão¯?ýï»}y~y‘\>ݱ»;VOæÍ‹fB²×Ÿ7¢YYÁ¬••Á1ØëçÍ-ç\ß±×_7Ïß5“ÿúv˹j~t•áÆ› ÷m8לë°ýÃxÜ£ßÉóë9ãw\TN ®F>@Î…]hŒ¢æãÇ&Ù(ÎõýBcT²Ás;6�–sáÎcúö•[Ö×V:V ¡ÜvWý˜²+„bRTJ½ÙûÝÏm¥´µV·3#NÌ 7Û…¬\°Ar¿§H)Ï�¢!EB ažxüà«H¼$¾²Íž±•óÖZ74{¢ùQˆJåŒÝW=A GñŸÑð™gHy„oÃýÀ±íÖA¨;ß)ÆÂ,}AFÿ><@5íÖ:Èœ/׌m«¼EïP»cÎwä2g°v†`€âD\’Ðù‚!�0‚žPs Q èz�Ƀ¸Ñ3Ú{"ਢòBŸÑJæÃg™¥¼Ì!›e›’])ØÊX0e?kyvsæ&@€F�žSó‚™cpëÀ’Ñ‚—kŸÜIZoŬݧY³c�ÍüœHö] ‹®+¡:cŒ�žoŒÓªÃmÑx Ÿ+¿åRö\Bîhv 8�¾hyµDoÑŸ’:%¸_ÖþWæÉ¡k,¼PùÜHðñiè|Õ>ª…ç*Êi¡z@z„ åí*‚ƒ^ºG úL Ÿ,*µ'êô­Šr<Á½>�‰¾‚ 9Îȳ¶“¢_0Â:žÈ.óŸ Š+•©bð¨`çäœål¹ÊÍ’1˦|Ѝ’aq‚J.(ë Š‰zՉР%=p�‡| çž8@˜£zz,QÇAX£NT5,Ǥփe®&õñ«VvsíŽáÝ*Ð7œï\}ÃñÛpAß°2ÐÒF�sçŽÎÒû0dèµ¢ÖÇu!>"'»&ÀT›¦_(˜› 3 `ÎrpH„�²Eè)7dÔ†Ó•a2‚šiÁ™3¼®hT.:ó™‹ úéúŒF093ââÁäêÑY»ƒJ„g¹7)dm¹ì®ºÂÌUÀÌ‚RΫzŒ]ÿ xêç Œ 0AY¾äÓ*膃ø“#¤‡:ïcõ�|õyíªra�™“°pèn^¸M ™–ñÚ§”BB�ün;@" —˜2¾³8Éê8áèþ»=‡Dßmdq¢TÆ*Œ«’3 Z÷ÂNÊäør.ƒÃ�r Å9 ×†/ó¹ƒæÊá¨olN¹ ÛVPFÐOú^UÌ”*†Žôȳ›1pâî"—W±yNYÌtÑe1­Ì®Ëi>æs‡aº¨]I·ùFdÇ4Æ`Ë’EšƒÃì(`]¶Œ§ŒUÙy(‹®†~œŒù¯K&åt?“ã ¥/àæ lc•LŽõC£x7WT>.G–¥ 裮„�ŸWO Þo™‹€h‹kYºÁâCtW‚H£W¶"<,ó ¼ó€�Ã/¤–B‹’‹Ñ:nò"ꄃ,ù.ŸÁÕ»VyøpDÝrd�yÙ™ "zÌr¹¸Þ"�åt&]OôNh\-[ŽœsJÇoøŒDc ¢W%ä#w ô&Ÿ9%`v<ܨtâ³ÖcR?¡”Ê];×);蘡W¹'Ûû—¨™1¯•‚ç²_…6 Öj7J‰ÞË6ɲ¹9vϺÒT爱®ìzø³øQi#8h¹è¹l‚¼Ï‡ 2K.3X•éšÄE7ô$® ëÖIå •~ðÞ¦µ�&§«Åìur§Á\5‰·†ùg�ã™ôòa—r?Rê˜ãnw8WôÎóaº„ }Æ 0ýËéÉÃtX…ΫÓÓtó]ƒ”’6 =�tlºh=rýÀ±ÒwÞUàÂ`ñ‘ÜPzÖ¨TB¾N‘ÆóUÛèÕ<4â¥^” �EWÅöjðœûÚ, Ø9Ý G줴Z-Ba!\qèBr#—=>RæMæô¹‚» Ú�K`!ŠŒŽã‰L¸3¡69&MFí Æ¤áò nਘtùõGq-9ñ^¾³Rä`PB’@ÜÅ`qûa$`ë£å£=½c,´hú.Ýú ãã"óL2ž»Zó飨ábC†z•Ö¹y½ç š% ¾ ¡vô*-ƒ�ŸF#o…j¹úX ç`Àø#½3´ à£j&gvá­HßÕùŠ|Oz4§aÈû/ÎçÑ�×bÊ@k—œs”põ"ÙŸ%í‡~óX…ý¿3œiNÈÏÊws'<ó�­ÝŒå3B�왌„„nqÜ5ê&¤¸À2J ÅáU˜! � d ³Wa�¢œ ¤Gè(ØPtáÅà†3ÓÅGÐs E½d9j–\SfÔr^‰@h„é&º§~"—A‚`Ét2øªY¶49Êx){}ªõˆ;¹‘1Ð×ΜIc8“Ün³fg/‰Å}Å¥t‚ .E”RÃE§ºµõÂë“1’7„@PðUOˆŸ�ˆ á8îÍp="XòhJ`ç½ O;$À¹rˆÀÉÃE+ˆ š¶×NäÍ^Ûm4%Ã;M„z«Ùí<޳ÏM3xÁ~Û|ÜHç÷„¦ÝRœ{JÓn)ÖÕ?WfK�»öŽ ¹ØšvKP²#lÛ-Á…ްmïJt}4í– »>švKp]M{GÐ\í M»%˜®�¦Ý|×GÓÞŒô{BÓn ¦ûަÝB×GÓÞ¬r{BÓn ^w„m{GpÂì M»%ØîË›öŽày7ª¦Ýt7ª¦Ý|7ª¦½#Ñ}yÓn ºë£i·ßõÑ´kBk,ÙJê°u%7µ§+šÖ¯[YéZìÛFäwí^š«.‡tÍÍ¿%gO¿o{¯·Ùÿ¯� endstream endobj 96 0 obj <> stream xœìÝw\S×ûplmk¥uÕ-*à®âþ9«â¨{ÕÑŠ qˆ #€QDü*"VEE‰(*C†Š€,d™aï%{dÏ_ñ´··a @„çýÊÉåÞ›n Ÿœ{îs@oA¡PlllH$’²²²�0ÚÚÚVVV………Ýý6>ŸÿðáC"‘èëë[\\Ìãñº»E@XEE…ŸŸ�@HIIéî¶ôv~~~††† ÝÝð©©©EEEÝÝñƒÓ@rÀéŸE"‘²²²º»@$~~~çÏŸïîVˆœþ’;Ý@KTTT¸\nw·ˆ„Édªªªvw+Ä NÉäééieeÕÝ­ ¡”””º»   zØñ‚Ó@2UUUikkww+H¨–Çz¼v¼àô�L<OEE¥»[@Bõ°<Öãõ°ãÕÃ^èIàÍ  %ðñeéaÇ«‡½ГÀ›@KDÿŒ¨ªªzñâÅóçÏëêê:©1Ó¦M;xð`'í\t555AÿE£Ñ„Ö)**úî»ïº¾m=ì3½‡½ГÀ›@KDüŒ¸ÿþ AƒvìØ±{÷îÑ£G'%%µû'Ož\ZZÚì�LLLÚ½gq üþûïqòòò„Ö�ü,’ürÑ·§´´´fWHNN.))éòv ËÌÌÌÉÉidž‰‰‰eee�ТvJHHøøñcw·â_’üæнDùŒˆŒŒ0`@bb"z˜žžŽ¿æ‹ËåVVV6»!•J­©©Z8dÈ�–òsKšî§%\.·ªªJô�××× µ'00P^^¾¥õi4ZCCCqq±P~¦ÓéÍnÒlJ©««këï¡ç}¦‹òrœ��Ÿ={†=¼|ùrëÇ×ÓÓÓô[[Û‚‚‚v·íÚµkêêêsçÎ=tèP³+ôïßçÎ�íÞ?âêêÊf³E\™Ãá8:::tèÈ‘#AAAh¡ŽŽÎÉ“'Ûú¼\.÷Ûo¿Ý»woë«UVVž;wÿ÷þòåË€€€¶>ÆÉÉ©Ù*ßl6»oß¾jjjíÞ³Øõ°¿5b$Êg„šššžž^ÓåGWWwĈ“&MRPPˆŽŽFËMLL.]º¤¦¦&''÷Ýwß¡åk×®9r¤Ž��Ï_ñØÀÀ[bhhˆíÿäÉ“–––ªªªh?Ç�GËýõ×G�¡ûyyyXŽe³ÙÚÚÚ#FŒ˜8qâ¬Y³âââÐò5kÖ<~üÝÏÍÍíׯºÏ`0¶mÛ6uêÔ%K–Lœ8ñúõëhyKù™Éd8p`ðàÁãÆ�SWWÇž—ÏçëêêNŸ>}îܹèU¬Y³ýÈÒÒRFFfîܹòòòÏŸ?G étúæÍ›§M›¶dÉ’I“&ýù矟=˜ö™.ÊËÙµk×÷ß_\\Œ:433³•õ8ðÛo¿ÙÙÙ=ztÈ�!vvviá… ZÊÏþþþ ¥#;Æ «¯¯eM.—»~ýúÅ‹ÛÛÛß»woÆŒ¨ô_ûò³@ ðõõÍÈÈh}�7räÈ��lÉÌ™3½½½ÛñtÈ�?þØÒ÷ooïÖ�lëakÄH”ψY³f¹¸¸4]~þüù¥K—R©T�@ðâÅ‹aÆÕÖÖ¢ü�-çóùrrr$ISSsüøñ(7ÆÅÅÉÊÊ*++Ÿ:uJ^^þìÙ³h}‰¤¢¢"%%¥¬¬Œv˜žžŽ¾Ê-[¶lÆ gΜ™;w.ö§´téÒ;wî4ýýèèèìÞ½û—_~9r䈂‚ÂêÕ«ÑòèèhYYY•“'OÊÉÉa3¿ÛÛÛ£§›2e ~:ø£G�„%K– ý¬]»-÷ññ™>}:ºóæMì�ÕÖÖ.^¼xóæÍ§OŸž={¶¾¾>¶+999//¯)S¦(++ïÞ½½®cÇŽ)))III©©©¡ ï5vvvèáäÉ“/]º„í„ËåîÛ·oÒ¤I†††‡–——G_Õkjj,X°uëÖÓ§OÏš5 ;½•šš:zôh##£3gάZµ Ëüíù@KDùŒX³fÍåË—›.6l¾_kÓ¦M7nÜhšŸeeeñÝníÎÏãÆ�C9¼¥ü??xð`òäÉX7)6H›Åba÷ãã㥥¥±.n*•*%%%4~C__ÿÀ�è>›Íž4iêM5jv*OGGgùòå([VTTôéÓ�æ`2™èÜÊÒ @¯£©©)”ŸW¬X�öóñãÇ>}ú îz‹5hÐ ”u7lØàää„­¯¡¡�î3™LYYYìBK99¹yóæ5½¸²²²RJJª¥ñ‡Âçg›™3gÒét¡ß§††öï…Á`Œ7�c±¶¶^·n¶¹è£Ê[brÙ!(™‘UÆa²ù"¬ %Àܾ}{Ò¤IØ“ÉD爯]»†²X¬Ñ£G£1­çgiié–¦l1?oÙ²ÅÚÚ-ŒˆˆÀrìÒ¥K±±Ä cøðáhÜææÍ›mllÐòððp|~Æ””” 0 ™n)?ÿüóÏXy�ÜÜ\ìy)ʦM›ììì®\¹‚i{öìÁ¹fIKK‹ÞŸŒŽWVV–†††ÐIó/‘ˆùÙÎή¦¦føðá999#GŽDùyøðáaaaØjË–-³··ošŸ:„ÞT­ägl}EEEü�iÑóóï¿ÿŽ�£x™™™fffÛ¶m[³f�””k›ÍÏÓ§OWVVƆ)(( f�3æÍ›7Mw.4þyðàÁ©©©è~zzú¹sç¶nݺzõê¦OÔ4?›˜˜` €åaeeå7nÐh´Aƒa;™4i’ššÖΟþÙÕÕýHNNÎ××·iSÛ”Ÿ7mÚ„ý{Á“““SWWÇžwêÔ©è»ðÿýßÿÍ�;÷ĉþþþÍ^¥Ø&ªjê¹åœ Ó)Œæ—ÈH/fÓX¤D 0gíÚµ ,pppxúôéâÅ‹ïÝ»'‚ƒƒ‡jggçïï¿}ûöM›6¡®ÖóóÖ­[•””‚‚‚¼¼¼„†òŠ˜Ÿ---'OžìááaooÿÛo¿aA( `ذa<ðóóÛ²e˶mÛÐr ´þƒvìØ�­¯¯¯O$}||222îÞ½;|øpÔÇ%4~ƒL&¡ï£F�zö왇‡ÇŠ+°üìææ¶hÑ"ooo¡1¥ eĈ.\x÷îÝëׯ J:::ÚÚÚ¾¾¾ééé¶¶¶#FŒ½ºv¼rrr455ñ=¥_"Ñó3o¯¡¡!//�òó°aÃðï«–òóôéÓÑÙŠU«Va§!ZÉÏ‹-ÂÎn´)?ïÚµËÜܼéjîîî3fÌxõêU}}=‹Å’’’ºRi4Z³ùùòåËøòã¨xýúõçÎ�kº¡üè)…ìFGÃ9€/šˆcü8Îýû÷ÕÔÔ<ˆóœ��pôèQ55µ?ÿüû´ Ä�C¶¶¶.,,ÄVUU?~\MM�H$ BðóóÃ÷°à¯ô¿víʱl6ûüù󪪪/^d0ÿûßÿ°uâããµ´´ÔÔÔnݺ…µ‡Åb¡õ-,,˜L&¶>›Í~öì�@PUU544ÌÎÎFËsrrLÿ +SðìÙ3555}}ýüü|ì³>11qÙ²eTWWWQQ=z4–CòóóOž<©ªªJ$CCC±ö<}ú=¯‘‘QÓkÐZ�?^yyyšššø ùÅiS~®¯¯—‘‘;v,6~ûz•““Óìø KK˱cÇ¢1;wîÄò§­­->?c³ödddôë×_õÎÊʪ¥"uBùùöíÛS§NÅÆo¡.Ð;v`ã–“““ñùY üðÃXw1¢¯¯¿gÏì!Ö�êáá1tèPì]š��€ÚÙR~Þºuëýû÷ÑÂ>t$?S©ÔÁƒïÛ·ß3ôèQUUÕ¦íl%?s8œ~ýúµT­Z(?_¹reöìÙØi¯ÂÂBôõ\CCcÿþýMŸ777»Ïb±¾ùæ›Vóhúæäó¥5ÜÈLæóÚ«XzB«† Az#¸F¦ã–/_ŽO ÷ïßß¼ys'=—Ðñ*((ÐÒÒÂ’ù§MùY \ºtIJJ 墢¢¢)S¦lß¾ÝÀÀ`ìØ±øëçÌ™³sçÎ)S¦(((`CÖÝÜܤ¥¥:´eËSSӠ円†&LX½zµ®®îÈ‘#­¬¬ðÏžžž>`À �`»B„ò3—ËUQQ‘••ÕÓÓ;r䈜œÊŸ÷ïß—‘‘166>tèÐîÝ»úé'|~Ö××G×!jhh 1 +V¬X¼xñÙ³g‰DââÅ‹±Xhjj:hР½{÷þþûïcÆŒAǽ¥ü|çÎ�qãÆtssÃÏùG&“Qõ˜¨¨(ü¸>ŸH&“ýýý±×…šG&“_¾|)T¡%77×ÁÁÁÙÙ ÃB󆆆bOƒy‹ŒŒÄOƒ‚:Û…ê×á÷‚ yyyÍžé %“É^^^ø_NDDDKE­±’w���øR{èÀ5=dIIId2ÙÓÓÿËáóù!!!d2ùõë×øç-//wqq!“ÉØ…º!âÿÆj*/!�õ2†îA‹Êd•Õp;Û| ?‹…¿¿¿¹¹¹©©éãÇ�…zùÄ«ÙãURR¢­­Ý‘Yẋ$¼ý„Æ?€´õÍYOç%°}âé.á´ðtfQ·Ã—0�P***/ôº›ÍVQQiöGeee:::ÍÖg�d�Ÿ�Äj÷›“Æä§³ýNa´P 3¯œÃ�Áгèëëw|bÐ5( ~– !åååÇŽëÈÜÊ]Oò3Íêø›“Éæg•r“ƒtP2#»ŒÃâÀØè \]]›-$�µµ5Vb·Y•••ººº/_¾ìÂFuœþ’‰Ëå*++‹kol.?÷#ç]jc)iÿDFF ›¥¤àKÆ`0tuu½¼¼º»!à3¼¼¼tuu….¹jªªªJ__Í(!ùH$ºš‰RTTD$žۿKI§5–’öýÀøTJ‚4|‘ÊÊÊtuu­­­) tJ6›M¡P¬­­uuuËÊÊDÙ¤¦¦†D"µÞS-!üüü ±šÉH2™Œ/v-v¼O¥¤#2KI{ÅÒóÙPJ¾8 ÃÕÕ•D")ɃÂðg{žñêêꌌŒœœœ:ó]#|>ÿáÇD"Ñ××·¸¸¸ãs.Ð<¯°°�L&kkk‹>+h5–’Îf¹GÑ<£éñ¹¬Šzø+ºG}}ý‰'»»!ŸG¡PlllH$’²²rwY½‘H´³³ë²ðŒWÕðO)éHZt«¬JI]­¡¡áÔ©SÝÝ@ÔÑyIlïJIWC)i ëÐh´Ó§OÛÛÛwp.c@×£2ù”"öTJ:�™_¥¤à 㢻�ªªêùóç :rÏž={ïÞ=ˆÐ|¡l~f)'àS)é·)PJ$Ôå�'((èÈ‘#)))íÞ ƒÁ033»sçDh¾hl.?ç?¥¤9PJ$Ô…–(ÉÉÉ¡#šÉdš››ßºu j\Ðpy‚‚JîûJI§B)i�0/¡¤IMMÕÐÐ(**j÷X,–………�� Dhz _PRÝXJÚ5‚æ×XJº–àÐ=ôõõ)Jw·ü‡ŸŸßùóç;²6›}ùòåk×®q¹p’d©©©±³³#‰Ý=â¾·ÓÖÖ¶²²*,,ìîwD{|¬åÆd³Ü#KIÈeUB)ièZ***0æYÒ0™LUUÕî„Ãá\ù„Ãሩ] £jjj´µµÉdraa!œè^~~~á �ÐHeïCëE4ÝýS)é�µ\Û]@II©»›š!–ãÂår¯]»vùòeøŠ$!ìììÈdrw·üËÓÓÓÊʪ»[!u4^R>ûuÝ5œ‘ñ©”4$iè4�Ÿ%“¸Ž �dz±±±°°`±XbÙ!è"‘Ø‘‘í@쪪ª´µµ»»â„/%ý•’† n�Ÿ%“� �Ç»uë–¹¹9“É×>Aû(++Èt‰ÂãñTTTº»�‚Áú·”tp #ç#”’±ù"ò³££cRRRw·âóbbbN~âííÝÁ]‰÷¸ðùü;w™1 1î´ÕñçÖÛôøƒÂâ4–’Ni ÒIŒÌRJI@LjòÙáä䤎C$EÙ³•••X®\ãp8ß}÷�ššZGvòâÅ‹uëÖ-Z´ÈÔÔô³ƒ� †ººz[}úÜ»w�üIyy9úQMMÍÍ›7Ïœ9ãàà€ï�~þü9›ÍÎÈÈ077?wîª(JþGbb"þ© ,--Ïž=Œ_îêêÊápÒÓÓÑ~еZÓ§Oüø1Z¡ººZZZ•¼ ËËËKNN>wîÜ¥K—ÊÊÊÐ:­äçêêê7nœ9sæñãÇØ@ÖÄÄD2™üË/¿ìÞ½µ¶ªªJ <}úôÎ�;}úôÁ^Euuµˆ¿íÎûLÿë7êÔ©†††NÚ?h…Ø+‡ÃÉý‡$WYa³ÙͶ³¥å­(**ï9”^˜Ÿ1üO¥¤£³KI¿ˆ¦ÈcU6@�€ÏëH~ÖÖÖÞ²eˆ nÞ¼¹qãF>Ÿ�Fn?~\JJÊÄÄÄô”‡ äååI$ÒÇwïÞ½eËlW&L¸uëÖìÙ³ÍÍÍO�:…Ö÷ôôD›Ï›7ïâÅ‹ØÊaaa#FŒ¸páÂ�;wþzÒ3gÎ`?’••½}ûöœ9sÌÍÍOž|øÛo¿íܹ- 155�={öš5kPƒKKK�¥¥¥��AŸ>}Lÿ�Et1—vpttŸÏŸ9sftt4z8aÂEEÅ–Æ9rŸŸ-Zô矢û¥¥¥ýúõËÉÉAeeeW­ZE§Ó±•SRRúõë‡ß›²²2ŠÜaÏž=XƒûôéƒòmKùy÷îÝæææXû§N�ŠïWWW¿té’Ð&%%%}úôiá7Ú%%%¡®uñrrr222êȨТü¹M™2EMMíôéÓ{÷î>|øÝ»wEÙóðáû8?[ZZÊÉÉa—Eèè舲ՠAƒš�ðtàÀ�BùÙÂÂbìØ±&&&ÊÊÊrrrXÝ?ÈÏ�­–ÆKÌg{ÅÑ]#KI—@)ih¢ƒùùÔ©SØÃÁƒ§¦¦¢ûÍægyyùÙ³g+þcøðáNNNèG&Lx÷î]KO�ÏÏ|>ÿ›o¾IOOÇ~:þ|l?²²²Bóóòò¾úê+üX‘íÛ·£kú¹sç°åÒÒÒYYY­äg™9sæ`í6l˜»»;öS±çg‰dkkÛyEç\]]I$RMMM'í4%b~@÷CCC‡ŠýˆÁ`„‡‡gdd4ÝJ(?WWW£AD˜üü|lÄ�F NMME'°ï›t:=,,,33¿!úR\SSôñãGl¹¥¥åü!Ô ‹…ŸÎ¯²²Rè &b~ÎÎÎÆþÁáÇÕÕÕÑ}|~f2™¹¹¹M÷Ö&�Ÿ[ÒÀà§²}?0œ?•’.¨ärap|ÒIùEP|?°@ PPP°··ÏÅÁ2ê„ """Zzj¡þç~ø!66{8uêÔ/^ û²²²XŸ6Âår‡ ‚íœÏç�7Î××·ùyòäÉ�?Æ·ÿ›ÍÏeee}úôA]ôm¢¤¤Äd2oß¾mddÔy3nxxxèëë -ÐyÚšŸóòò¾ùæôþyõêÕèÑ£·mÛ6kÖ¬uëÖá‡$5ÍÏ>>>³gÏÆR(9994cxpp°¼¼¼¦¦æÌ™3‡ ¦¨¨†jÔŒ=zûöí3gÎܰavnBZZúþýû³gÏ^ºté÷ß‚–7›ŸcbbÆŒƒ=ÔÔÔÄN9!"ægkkë�7b£¢¢ˆÚ�å熆†eË–u|ö@ÈÏŸEgñ3J8þ‰�ðÞ¥2s>rØ0O8 wë¤üÌçó ƒ_ßÌÌlÍš5X§4vQa[ó³²²2Öåçç7dÈl(oÓüü×ç¬��ÁúõëÑÕIwîÜ™4iºßÖülbb²aìCßþ–ò3‡Ãéß¿JJJK/­%Øqyûö-�@h¥s¾ƒ^¾|©««[YYÙIûxmÊÏåå娴iêÈýñÇß¿�ÖQQQ9rä~«¦ã7fÏž�õÓ’H$ì/háÂ…è¼ •J3f º’´¼¼üÇ GëìÝ»÷¯è‹îõÕW&&&(ÃëééíÝ»-·´´œ1c6¶õ‹+?ëêêâ„TWWKIIUTT`ù¹®®néÒ¥666Ÿý}~ÖY«§n‘4ïxúÛFd&+)Ÿ�]Æ)­áÖÒxl˜pä¿X~vç-¾”4~E€ÞH”t YYÙ¡C‡öë×OVVë×j%?ÿõ�xíÚµaÆíÚµkÑ¢E/_¾DaòàÁƒãÆ�ûã�?V¯^½víZÔ¡ÔÖü\UUµråÊéÓ§¯^½züøñoß¾Å~Ôl~¦Óé¿ýöÛØ±cçÍ›'''‡ Zn=?�?^öÏŸ?Gç¦÷íÛ7~üø={ö¬ZµjÓ¦MøŽåfó3úí >|×®] .ôóóûìoÁ—‚‚‰tçÎ�NšƒÛÛÛûرcB_@g1?�9RVVvÊ”)G�E㜜œæÌ™ƒ­óþýûáÇã·jšŸ·mÛ†j\ÈÈÈ`×®*(( |Îår‡ †În|À¯/483?? “æóù¹ÿE¥R±ÕªªªBCC±_þÅ6m$RVVŠ;úYBÇ…ÉdÞºuËÈÈK2âõæÍÑ˃€öiëø *�ˆ=LHHøá‡ð+4ÍÏg„ YYY®®®ø��=š0a‚µµõÖ­[<ˆÞ¿_QQ['..nРAè>>??yòdÕªUè~§Žß¸~ýúúõ뱇ƒ B_W§M›6lذ«W¯ÊËË¿yó¦é®ÚªõƒÂá êé¼²Znv'¹€�Åz—ÊôýÀp�¢=~G}ÑX?9(™‘ÁLüÔq]RÍ­¡ò˜½¦W–Çk,%žÎt oìÃO*`×Ñ»y�4ƒÁpuu50 )�/�ªªªÙùóM?R�p0öO25{\‚‚‚‚ˆó×´U@@€¶¶vIIIgì íÎÏ)))ÒÒÒØ9‚Ë—/cýÀˆŒŒLÓ387nÜÐÓÓÛ²e ¾`ÅÞ½{ÝÝÝ===ããã±…‰‰‰?þø# �Nš¬]»ÝoS~NKKëׯú.ÌårÿÊäBùyĈqqqM_õðáÃñíÉÉÉ‘––ÎÎÎF�9ràÀtÚ´iW¯^EÕíÆŒÓñwlGþÒYüª^Q7³”“�רq�ÄxKw£= ¡ºGÑü¡fl+µˆ�[ÎùXÛØqÝ#ËYðù‚²O¥¤Ý"i/cè y¬ªî(%]VV¦sL×ìÒÕ—ÁqÑ9Õñ p“ð[LnÍ#7ŸC‡�´c #Ýò³djé¸ܽ{·3Ær‰ÄNêâÉÏh¿‚‚‚­­í©S§F�%ÔÛ¬¦¦¦¨¨H&“­­­±…4m„ ø5·oß®¢¢bgg‡ê6cUWWwæÌ™¶¶¶'Ož5jTRRZÞ¦üÌãñ&Ož¼mÛ6›�7nß¾](?+))­^½šL& ]Þ³gÏš5kðË/]º4~üøsçÎíÛ·ONNk¾þ†……ÅÊ•+±a`íÓIÿy¼ÆúeµÜÜ�œÔBvL6+„Â|“ÐØqíBu §½Š¥$1ÂÓ;®3K9EUÜêƒÕ²uE=/•’Ž¢Åf³Ê뺨”4ƒÁÐ9¦{×Ñ­Û3!ÜÚzóŠ>|ä¾zò³djå¸0Œ?ÿüÓØØ¸3úŠCCCµ´´àTZ'qþ”–Žl`` ©©©••UÓ‘64íÆ�¦¦¦¯_¿zF|¢æñxûöí333Cƒ–utt¤¥¥±(îïïojjzíÚ5üX#2™ŒÕ™ÉÉÉñññA÷“’’ð—`ŠŠŠ,---,,òòòÒÓÓñ½Êè¢ESSSTÓÐÐpýúuSSSü�Œ°°033³›7oâGF¹»»cÓÊðx>_@eð?ÖróÊ9”"v\+4�é—Àðˆ¢= ¥:‡5ŽŽðOd„¥3òX%œÂJne=�&Ù× ~Ê?¥¤ÃÒ˜…�SJZO_ÿep\·ç@¸µïö.©€xô¨øßt‰„�¨"++‹D"}vµüü|}}ý{÷î‰ýPTT”¦¦&6«#—.‹jIIIË—/=z´——~9•J�={¶²²ò¥K—LLL,XpòäÉ®i’Ä’´üÜ:‡_Kã•T7^Ϙ˜ÏŽÌd%3¼ã;x¿£ºGÒ|âéÁ)Œ¨,VRAãõŒe5Ü::OrÊ5*%ÍÆJI犵”´ŠŠ ŒyþroqyuŸí8@røùù¢°@444ŠXé�å8~ü¸ØÇrÄÄÄhhh`À±è²¨Æb±„æ÷Áp¹Ü��2™ìéé W¾¸üÜ:*“_QÇ˯ळãQ!¾Æ‹hú³÷´gïi/>â KgÆçþ]ˆ¯¢Ž×]uçP)é äÆ ˜ÄÈ*åt¼h‰’’R·‡@¸uäÖ“þA�Ççó>|H$}}}‹‹‹;x%h7�W\\ìëëK$>|ئ) ‚ØÏÂÇÇÇüTé ƒ”••±I´�$àr¹ÊÊÊÝÝŠ®Àæòëè¼²šÆŽë¤vT+8…áOw�ü»Ÿ÷§B|‘™ÿâ«¥ñX�?ƒ ‡+È+ç„RKIû%0ÒŠÙ´öFzÈÏ_ú ò3øâP(‰¤¬¬ÜÝÅ {)eee‰dccÓluÜÏÊËËÓ×׿ÿ¾xÇr$&&„ö5 4E$;o6vÐEEED"±»[Ñýh,~e=¯°’›Qòw!>ÿDÆË˜ÆB|OC©¨ß§d(Eì¼ ñµå[þçñx‚¢ª¿KIûÄÓ“ Øõm,% ùùK¿A~t=ƒaccsüøqñž”OII!P™S,PÕ¸înø™L¶³³ëîVH4nc!¾Ædr>rR>âÃf�q|Gu §yÅÒ“áŸf�É*ãWs«;6ƒLc)énT&Ë-âïRÒÕT‘‚4äçöÝžy¿ßº[Ýâòë›®pÏéµÊ¡£195Ín®ú"ÙÝ_,-�ü è.~~~!<<\Œû¤P(›÷´[MM�¶¶6™L.,,„±R݈Çã’Édmmmü$¤ ­,~õ?3È4âûg—ðÆ2×îQ�³{‡P ñ¥²sÿ.ÄÇý½_^Ç�ËayDÑ=¢h±9Ÿ)%-Æüì·ð—•_}ýµô?îÜ»ÿmbZþèÅÛM;”æ/^¦|�ô![Ÿ wBïÔ…nOÂèöǾ#†¦–ØCç7?ÏœÛl0F·· ù÷œ^[Ý{*%%›W×t ½“Ò?üø.¹¨ÙÍ—®\{ÁúägÀ—.//OWW÷ÁƒbË‘žžN „jù‚v¨©©±³³#‰Ý=b¨·#‰vvvž;ïŸB|¹åœÔ"vl+”Òx=£{TãäŒÎaÏ ƒ ñ¡dªxô ñÕPy y¬WŸJIGf6–’n:zDŒùY~ÒTÝ“âòëCSK3~ò:$¾ ÁÅ/rÊô™7Ü\ý£öì×P˜3[Ï~�CچݞœÑí‚õÝ™ó`‰†g¶ý®òÙ­âsZÊÏ­ß ?z :�~ýúõ“'OŠq,GVV–††FLLŒ¸v赘l~ õßB|�…ø^c…øþ™A&:‹•Œ ñÕrëé<·q0IJ!ÛçCãØì°ôÿ”’W~ŽÍ«ûêë¯]ý£šþ«�›W÷]¿ïýc³ZÏÏ195†¦–ËW¯_»yÇ­ÇØòÐÔ’CÚ†ó/Û´C œ@»òO=¢{|Åš ¿núíÎÓ—ø]YßwÚ´cÏ‚%+3F]Á¬ï^¹ãˆ­àAQ×Ô�/hN*üöÛïâsÐr…¹ÿgýÀÝ÷ K9|Ìxùêõ¿núíî3¯Öó³Od6®Ci¿&~eÿ¸lÕÃÚ –*œ±X¾z=äg ™ Ãª—ÐÖÖ¶²²ã¦oÞ¼!âÚaNNަ¦fTT”¸vMQüò:.*Ä—ÃzÿiÏhú³PªÓ{Ú‹º_"ã…˜ÈðŒ¡?}OóOj,Ü¡ª¦.–÷×mÛï*£ÆŒ;wÕ62«²Ùüã²¥ø!*»ª•ü—_¿|õúõÛv;û†Û>y!;a’ ÙýhÉŠ5û5õÞDghꟚ8åg3+ÛÐÔ’ø‚†µ›w›]yêzÑæþ?pñ‹Dë«kêN˜<íêÝ'N>a‡uŒL¯ÜŽ/hxüò­Ìx9,ñôNì×ÒG÷-[efe‹R±ô?FfV åk6n?~þêSïPóëvÒ?üèÓJ~N*4³²5³²=jtvÈOÃpá¿t¬¬üûŽØ»ùŸûß�B~Löhô²/ÖËÉÉÑÕÕµ··çp8bÙa^^ž¦¦¦xÇW€ˆØ~E}ãpë˜lÖÛd†WãyíI(õñ;ªCP›Ç´t‹Í«;wÕVvÂ䟆78c›[+´Â¦J‡�c›ÍÏ÷œ^�••Ƕµ¾ï´|õú¿û·¿ú õ!GçTû]¿¦ƒ“½#(óý¢obŽú�¿ùæÛWï“›¶óÿ–,¿f÷ ís´Ì8¯°´ü¤ùµÕ·Å4ü•Ì×lÜÞtCïðÔ9ÿ·˜töR+ù»=ˆÆçg“K63fÏÃÂø ™à‚ýÞ&55UCCCŒUÎètºµµõÉ“'?~ü(–hiiuÆÔá€ù{øôGNrAãL‹�É�W&:½§9½o;ø©ZuB+8™ñ4”êøŽzöÚ3qågìfýÀy´Ì8¡l|Ôèì‚¥Šø¹›ÍÏÇÏ_í÷}ÿÑ2ãÐm؈QÓgý;§Í˜�ú‡ÿgûhòÏ Ø&ön~+Öl˜·è—í{Ô¦)ÌÑ20‰/h¸íè)3^®ÙæÝtp›¿xº³tåZl¹_Læ�FçT¯Ý¼ã¢Í}lù}Wß÷?cöQ£³íÈÏʉ{ök@~ ÆöB~~~çÏŸï>}}} ‚¸†^‰Äàà`±ì Ðk±8�¡‹ª¸%�s&†¦}*Žù÷tä¾ëNÇç²2JØEUÜê¿Sº°¹ü¤|¶K8Í7�áB�ËeuRý:3+[¡ËñfÏ_šZŠ_§Ùü|ù¶~CüMËÀdá/+ç.\ºnËN¬cùuxÊ�Ÿ†¹Å¢‡;÷îGùùÉëé~hi$É”é3�|Â~Ýô›õ}'üò™óÜvôüièð�”b´äÕû䟆÷x�nߣ†ÏÏ�ñ¹"æçÃ:F¶ÿùH8˜°¬b2™ªªªbßmNNαcÇÈd²XÆr”””hkkˆ£i€N”Îä䂯whr–VvÅå R Ù®´÷iÌy¬§!Ôðt¦¯|ò:dѲUξáñ ï)e«ÖoAÝ­qùõ*‡Ž.X²",í£Ð&Íæçðô�#ÇŒ=i~ ‹¯¾QéèþàŸ†' ­oïæ7j̸ðô�¨PÞXYy”Ÿãòëž9wÇ^õˆŒòø‚Wÿ(Ë[±­.ÚÜ_½qÛ8¹ BƒLtO^øyæÜ%+Ö`Kî»øŒ;íÄÁ#Pfœ,>?GçT÷û¾¿ã«àø‚´NKùù¡{@iiôûyðüÍ !?A~ÞN½S'w�feeuêÔ©òòòŽï­¬¬LGGçÍ›7âhZïÅ`0\]]I$Rw_ÀÚ»ˆýr]БÎdñø‚´böóZ…YKã%°�ÞÓ“ÿžð[Œõ7ôMÌGËŒû¾ÿ~ß÷ßö» Ê´h,þv€h€6!è�À/_°dZîñ6~ñòÕ? >ZfÜìù‹P:mìûýCõÇÑÊãå'îÓ8—_›W·íw•Á? /?qçÞýÇNœ7:w­ï›µnËÎAC~5fÜ´³ñ¥MG—Ãr� ½Ž§‹½~]gß<ƒþ²ë.~žò}ÿþžÁÚ··°´�#F�ñ‹Éìö×Õñ Fðvê�:û¸gggëèè<|ø°ã£ƒ*++uuu_¾|)¦¦õ" CWW×ËË«»Ò{=þÜÞÞ¾»[!¡:»3YD|¾ û#Ç#ªq²•ÊúƬÌ"3™Q4÷H:~¢ð/%?[?pV˜3ÕgŽÌª<}鯤i3ðW#Šx ŒÏµ}òbéʵû4Žuû‹Ë #x;õN]pÜi4ÚÕ«WMLL:ÞÿVUU¥¯¯ïáá!¦¦õ®®®ÖÖÖÝÝŠ^-77×ÈȨ»[Ñͺ¾3Ytyåœ1ô7 Œ�µÓçó¡&šˆ°žþŸš®_J~ŽË¯7>÷?…¹ÿ7uú¬i3f `óƒ·évÏéõÖÝʧ.Z·cÒ@ɼAàbôÙ·�NÏÍÍÅJCWVV–””àWðôôœûvzõê•””v ׂ -Z„_!44tݺu¢Ïã²nÝ:qÕ Æ«©©Ù´iÓ¸qã~ýõ×1cƘ˜˜4v}P©RRRõõõmÝ[``à† *++?»æ™3g´´´ÚÛj‘ܽ{×Ðп¤ªªJJJŠÅbµo‡]ùo$++KGGçÑ£GËQWWgddäää$¾¦õp***0æ¹{ñùü½{÷vw+ÄI’;“ETRÍõާ{ÅÒ‹ªþó‰Ãåû%2Þ¦0Ý#iyåÍRQQ‰iû(¸IÈ-6¯VYY¹ ßh ‡%?�=úÈ‘#hn¸±cÇ ågɱ}ûö?þø:��å熆†Î{Þ.ÈÏÍægÉïFh4Ú•+WNŸ>]QQÑ‘ýÔ×ן8qÂÑÑQ|MëÉ ³E|‰Gá‹ëLQY-×÷ãe =¿B8³8|ŸxzxÃ+–žRØüÿU‰ôòmt·ç@¸µïæ“¡¥Eì’7èDÉÏ›6m;v,—˽zõê®]»P~¦R©²8t:­Ïf³çÎ�¡  Ð·oß¹sç¢ Nõõõøõ ZßÚÚÚÐÐpôèÑ“'O~ðàAÿþýûí7�@­¨¨ˆ5ƒD"ݾ}[ \»vÍÈÈhÔ¨QS¦LyðàÁ÷ß¿cÇÔÉùÍ7ß4�g(?¿{÷næÌ™}ûö�?~qq1ú‘»»ûòåËedd† ¢©©‰zG«««ñíĺL©Tê¢E‹BBB¦OŸÞ·oß ”––¢µ”Ÿ‹‹‹wìØ!##3räHMMMô’ëêê–.]üóÏ?÷íÛwáÂ…X×=…Bùå—_æÏŸ?~üxôìqqqÞÞÞ“&M4hÐÀ�ÑB”Ÿ¿þúë���3fôíÛwÑ¢EmêÒï–Ït///�Û‘�444œ:uÊÁÁA|íê±¾ÄäÖóHòQè�É"ª¨ãù'2<£é¹›ÉútÿU,=.›˜Ôø’[Ú‰ŸŸŸ¾),­¬Û£ ÜÚq»a{ßÎή³ßi ÷%?oذaÇŽK–,±µµê¦ÓéRRRØc‹õÕW_íÙ³§¢¢‚Íf¯_¿^WW¿> ´XÞ655�1c�Fûå—_8P__ÿÝwßåç燄„Lœ8ÛJ]]ýÒ¥KÝ;{ö¬‚‚�F[²dÉ¡C‡êêê¾ýöÛÂÂÂgϞ͙3§iû©TjŸ>}”••+++Y,Öš5k°ŽÜû÷ï'$$ L;}úô‡â7¬©©‘’’¦©¯¯ïÛ·¯²²rUU‹ÅZ½zõñãÇÑ�šÍÏ\.WAAáêÕ«|>ŸÍf«ªª¢ñ$555ß|ó�ªªjUU“É\¹råÉ“'Ñ&ÿ÷ÿ÷øñãÆºIqq³fÍÂïÍÀÀ iÿóW_}µoß¾êêj&“¹bÅ ´)))=}ú´ÃÂ;(33S[[ûñãÇËA£ÑNŸ>mooÏçÁè]@’“[ïÑíG¡§v&‹¨º�˜Üøz³Ê8Íþà2ùžÑô¤vDFã7ˆVþ©ðùü‡jji=pz›×S®ªëÙ·¸¼:¿èô?mïkkk×ÔÔtê› ô*¢ägEEE777•¥K—úøø|6?KIIaÆoݺµyófüúM󳆆†@ صk׳gÏÁСC“’’ZÉÏššš�`çÎ�h(ìO?ý”œœ|ïÞ½¥K—6m?zººº:ôðúõë¨a³Ù‘‘‘ööö .ÔÓÓÃoØ4?ãÇ�\»vm×®]è~³ù9 @VV6÷ÞÞÞ3gÎÄv‹½ü+W®üþûïèþàÁƒ³³³+‘òxÒÒÒø1'Íæg)))&óï®’Ë—/ïÙ³§™ã×%%¥{÷îOOÏv¢n*•ú¿ÿý¯ƒc9 ÆÙ³gïÝ»ºbInÆÆÆ�=j÷æ×¯_Wÿ¤‹{~ž>}*!Cå»,?÷žÎdÕÒxïR™Ï#hé%l^ /·ŽÎs�¤¥³“ دãèîç- åúu}eeåˆD‹H´³³ƒð ÄKÄüÌd2|óæMó3V�âÁƒ7nįßIùÙÇÇgÔ¨QMÓ”ÐõƒwîÜÙ¶mºóæÍ9sæ=}úTUUõèÑ£ø ›ÍÏØË¼}û6–ÛÍÏŽŽŽ#GŽTÇAe¬Ðn±á+þù'–õµµwïÞall¼nÝ:üÞZÊÏXôµ±±Ár¸(Ðq/--µ±±ÑÒÒò÷÷ïâiÜ_½z¥¡¡×î=0 33³;wî@„n‰ˆÉíÊ•+C‡2dȸqãnܸ!ôÓ©S§>|¸ÝmHJJ :|ø°ˆe( ÆÅ‹׬Yƒ†l!$ �_š7oÞ… °oŽèê€!ŸŒ?ÞÖÖ-lú'Ó]Ä›Ÿ{yg²ˆêé¼Ð4¦k-µˆÍ嵸Z5•÷<‚–ý‘“[Îq�¤ÑY½ñwhó³@ øðáCCCC—åçÈÈÈáÇc[mÛ¶­õüL¥Rìéé‰m‚²eKù9??ðàÁØrñæç¸¸¸áÇc9Yh·-åg333“Û·o mxêÔ)¡æ‰%?#999zzzaaa]™EÑXGGÇvGw&“inn~ëÖ-¬¾"À%¹ùûû�3¦  à¯õÓÓÓOŸ>Ý¿L ó3‘HT?<�éNK.`sZý¿R^Çu� Tr?Ö6ÞAs€ˆDÏÏH—å熆†~øáÊ•+QQQÇŽSPPh=? ‚Ç�4èæÍ›AAAÖÖÖ³gÏær¹-åç²²2iié—/_fgg[YY�7®#ùyÕªUä W�^ц ¢¢¢rssííí}||ZÏÏ'NtppHKKËÍͪ�íãã###†ª[‹7?#)))§OŸ>qâÞ5._¾|öìYQê6‹ÅbYXXØØØ@„nJ”äfkk»xñâ¦ËŸû ûáÃüç`bbâùóçñ+°Ùluuuìt*—ËUWWÇræ»wשּׁ¬ðë3™Luuu¬ðš‡‡ºpïÏ?ÿŒˆˆG�ER¾¾¾?ñõõõññAÓ»»»cëGFFâ×GO·gÏEEE 4¥ z:,¯]¿~Ý÷òòÚ¸qㆠ"""„yÒh4uuuìÓœÁ`à_f`` �� ºïææ†§¡££ƒ–s8œ¿¹aÆ•+Wž8q}R£Ýb/ßßßÿÏ?ÿD÷5446oÞ¬øÉŒ3&Ož\]]�µçöíÛ«W¯^»v­™™ú¢®®ŽõÜúùùݼy³õC‰×Òq�ŠŠ"‘HçÏŸÏÌÌ}oÁçó_¾|©¡¡ß¾=°ÙìË—/_»v­‹‡ H>QòsIIɘ1cÖ­[Œ_ž••ôÉž={Œ��±åÇ�Ÿ:u*‰DЉ‰¹xñâÀ�Ñwᤤ¤Q£F%&&–——/Z´ÈÜÜ@›æçØØØQ£F999åææÞ¼ys„ Øwj̉'°>d|~{öì9sæLã,……#GŽÜ¸qchh(~[ƒ‰'ÇÄÄœ;wnÈ�!èËæ_ßg÷íÛ”••¥©©¹|ùr´¾žžÞˆ#lmm³³³OŸ>=fÌ�&"##G�íêêš››kmm=yòdüÐQ())Agr§b°ù1Ù,ç0Z\ ?ÝvK *;œËë¸ 6ß#Š–]ÖL©gh]·_�ÀÀÀM›6á—Œ5ªƒ¥ÞZÑÊqçñxAAAG�µ²²jGo[û¤§§kkk?yò¤}˜Ãá\ù;_Dÿ뮪ª266(·ëééá'Ú–““C_Ø7oÞ|ëÖ-lùÚµkщ$Ñ�µz �É�„ÅáÇç6&ç˜lC„äÜ8AíGÎóZ5•Çå |âé y]zõ4 Ç€ü,!ÒÓÓedd|@'’LLL–,Y²{÷î“'ObƒÍôôôð/SQQ ½ž8qâìÙ³±vΘ1ÃÝÝ]ôß*ü�í$l.?1ŸíN‹ÌdÒ˜¢þŸL+f»GÒêè�Õ8‚Saém;•øß.9222,--÷ïßÿ×ç;6az'ñ¸ÓétggçÇ?zô¨SçpDø|þ‹/455Û7–ƒÇãÙØØXXXtqE>‰ÕŽ¿îÅ‹ B1?×ÕÕ-[¶lÛ¶mkÖ¬Á†6a,,,ÔÕÕñKV¯^mooßl þùgT ƒÏÏ•••ƒ kºí¼yóÐ-ågCCàqYø‹5„ò³¬¬,êg^¾|¹PKÚ þÇŠ‡+H.`»†ÓÂÒ™ më’TÀöŒ¦S?…í˜l–"£¥¢vðY***0j´·a³ÙhCÕÕÕÙÛÛ9rÄÍÍ­iE±Cc9ž>}ÚŽw&�Ç»uë–¹¹y[©öH¢$7 �ãÇ�£ÁùÁÁÁƒ JKKï b~~òäÉž={Z:d�=š5kƒÁ ÓéèÛ�»»ûøñãÑØ.—ëíí�Ö¤P('N¼}û6V;�P@ù¹ºº:44tÁ‚ØX‘ƒš˜˜ É7ØzÿóÞ½{Oœ8�®Dê^¼xqnn.ŸÏÿßÿþ'//�Úéìì,//�®Pæp8X;Å{€(x<¥ˆý<‚JaÖÑÛv½p\ëU,U¨K+f¿Š¥öCh…��AIIIw·t) …¢¯¯ßÖ­ÊËËoÞ¼©©©éëëÛÙÃŒëëë---Ï�;׎±|>ÿÎ�;fff]õ%œˆ×>|xذaRRRsæÌyñâ…Ð /^Ä_Alii‰8±xñâÄÄD�@ðñãÇ#F ý Ÿïéé©©©ÙŽzz|>ÿÞ½{gÏžíåº+“›ššþMeeeµjÕª.{öŽÓÓÓ;~üxgìòsGðù‚¬2Ž{-0‰QÕÐæ•|¾ ”ÂôKd ‰+ëy®á´vì„P(”£G�båæ@�çå奫«ÛÁ`™––fjjjddÔ‘ E�ÞŸÏž=kkyg>ŸoooúôiT…¬wêÊä¶uëÖsçΡZ eåÊ•øÙ%ŸÐøg1‚üÜ>|� ÷#çE4Ý?‘Q^מA†\ž (™”Ì@S60øÏ#hEU0^ >$‘HÝÝЉØl6…B±¶¶ÖÕÕ-++Ë>ãâ⌌ŒLMM…FÌŠW]]�……ŹsçðÕ°EäààpêÔ©.¸òQ2uer+//×ÕÕ]¶lÙ¼yóvïÞ�Š¿}AžÐ_ÅÒ *;4Ä‚Î⿊¥ãÓrh3„yH"ƒáææväÈ{{ûN «h,ÇùóçkjjÚ´¡««+‰DjëV_:WWWü ëùúú6­† „”×qý/¢éyå-ìCeò=£éIÿžvù�Ëòýð÷h@2544� QŠØâú¯P^Çu� áNWSK=WÔAxt¨ÝÃ$''„®ŒÐ�§P33ÏŸ?O"‘¢¢¢Ä»g>Ÿÿüùó¶Žåxóæ�ŽŽŽ¸ŠøDÔÀà‡¥3]Ãi)…lŽø‚mI5×5œV‚«×AcòÝ"iù�;M*´f'ìyRSS544ŠŠŠºøyNœ8qúôi±§w4–ÃÕÕUôù´µµaæzº�É�È`º„ÓóÙl®8G#T6ö<ã'Xasëo¤ S@·100€ŒÑóøùù�?¾ëŸ—Ï燅…éééYXXäääˆqÏh,‡¹¹ymm­ˆ›‰Äââb16 „ÁâGg±\ÂirY,Ž˜¯ãËþÈyA«¦þÛ—Íç ’QYPêÐ�TTT¸\˜í´§a2™ªªªÝõì\.×ßß_KKËÆÆ¦´´T\»åóù®®®D"QôþíÐÐP--­.»¦€^…ÉæÇå°œÃh±Ù¬Î¨€‘VÌv�¤ÕÑÿ3$<�”Ìèx)è˜y¶§êö#Ëb±<== ½{÷Ú11wK’’’´´´ž?.âXŽððpMMͼ¼|øéÓ§âºLµ¦¦æüùó¢�刊ŠÒÔÔïxz'—ŸTÀv §…g0…­Åå°^ÅÒ…’yîGŽ{­“â:´‰„¤, vud«««ïÝ»G <==Y,1 \äñx...¢�刉‰ÑÐÐÈÊÊêøSÐ;qy‚ÔB¶kí}³žÞYUãøAd&Ó'ž.4”º¬¶ñ*ÂZT«H‰JYÍ*--uww×Þ322ZY¡¨¨ˆü�v4ö÷÷ÏÌÌìXÅC�lii©���–––¿¿¿XFÝ£±nnn¢Œåˆ��'ééé^z_�^Ì~A{—ÊìÔËç B)L¿Dç¿}âĉ„„„îŠÇã9;;‰DQ‚qJJJ×Ï/À‡/ä|äxFÓ’õ�>j‚Ãåû%2B)L¡¯ÔžÀ;žž˜¥ž’E”ü¼dÉ’Ñ£G£ÙÜ„òspp°¥¥¥‹‹ ƒÁÀoµk×.�#FÐÿŸ½3�kâZÿ—ßmkm½­[«õ*ÖZÛj[kÕ.¶•Ö¶·íµv³µT!„�°Èª"ÁŠA6 âB1 ‹BÀ°É¾!ìûN€ٓɯ8·óÍ xÞ¯ùcæÌ™3'™ |æÌs>Ÿ—ðx¼„„‚’’’Ξ={ïÞ=¸¼££ƒN§ïß¿ÿ‡~€uéÝ»wG3À !JUq¤wdd$11‘ÇãEDDüñÇJÁt:ý÷ß�‰‰ …H!A ÅÃ㸸ø§Ÿ~RÔϾ¾¾AAAJéžÇÓÏ*ÓõÊd²ääd�’’’ï¿ÿ^Q?§¥¥„+W®Àdxx.¿ÿ¾��Ohhh__RY$ݺu �Ç“H¤ÞÞÞ‰¯Ë¤h¹~†),,´µµ%3z)//G£Ñqqq“ŽiWWW£P¨ŠŠŠžX¬´öI‹ù©å‚ÞÁ¹™I ”2~A½òtDH.Ï` òj…ãó…:úyÏž=ÖÖÖJúùøñã;vìðððÐ××ã�7�.—»jÕ*¡Pøí·ß’Éd¸°½½}ݺuÄ`0–––K–,¡Óép¦CCÃ-[¶l߾ދ ‰£³EzzàÍŸ~úiÙ²eHZZZV¬Xñá‡:::b±ØeË–ûŽ=ºsçN==½7ß|ñLûõ×_ßzë-<ÿÓO?­^½ÑÏ_|ñÅ÷ßÿû￯Y³FQ²ª¯Ÿ!úù矷oߎÇãüñÇÕ«W#úùĉûöí#‘H_~ùå+¯¼bhhŸâܹs¯¿þº���½½ýúõë‘xìo¾ùæÐ¡C$éÌ™3ŠýŸ B?ÃOt:ÝÂÂÂÇÇg†9Ùl¶«««:±µµµ(ª¬¬l&§Ò¤>¥Œ¯˜,{Vá‹F“ –6©˜V\Ô JgdÀohêèçíÛ·³X¬•+Wvvv"ú9--mÍš5\.®fhhˆÁ`àõ›7oþøã�r¹<$$ä—_~� ÛÛÛ{ì±ÂÂBxÓÌÌLq…B�¿ÑØØ¨¤Ÿÿñ� ÃÅvvv¿þú«\.§P(ëÖ­ãñxp¹¾¾¾•••\.ONN^»v-2ðûÍ7ß úé¼\.ÿüóÏ‘Íñôó‹/¾¨ó€÷ß.LLL\·nâÌöïÿÖωä‰'ž€û900°jÕ*¸BEEÅêÕ«9¼éççgddëð§žz y˜9zzziiišjsö‹ÅwîÜ133»|ù²â˜üT‘ÉdQQQ“Ær444˜™™ið 4]l)¥ŒŸTÂiz#B(¾ˆÏhSžQÝ!¾SÂ×l*pÐêèç·ÞzK.—;99a0X÷ºººêëë#Õbccß~ûmxý‡~000 ‘HžžžK—.…µe{{ûÿûÿ©ïááahhˆlNI??ù䓊煻wúôiÅÿüóÏ�;wŽ-WŒæp8¾¾¾Ø·oßË/¿¬ØõÇŸ�?Žl"ñÏ­^½ád0/½ô\ÁÏÏï_ÿú2 ñ›o¾ùðÃá]!!!/¾øâW_}åáá1óx==½üüü€€““'O’Éäæææ¶9Ûðùüèèh“ÈÈHŧ›©ÇrÄÇÇOËÑÔÔ„F£‘g:àá¤wPšZ.H,æ·öÍé½!¾ìv¯¦S…xnë“Äðx³æ/ 3D}ý<00°zõê“'OÂúÙÍÍíçŸFªEEE½ûî»r¹|xxø™gžqqqÁ?`Ë–-þùçXýüûï¿+ÊZ333<¯²ëg‰ôÁÈår<ÿÛo¿!å‘‘‘ðñÉ“'�=Š”#úypppÓ¦Mþþþp%¯¾~vpp€�açþþûï6løå—_¶mÛ–œœ ½÷Þ{t£ÄbqFF†““ÓŠ+nݺ5þe™äÊÊd²êêêëׯ[[[c±Ø°°°ŠŠ ‰D{'³ …‡‡›ššÆÆÆ*ÅÕ«ÏÀÀ€«««§§'òêA%---h4://oº�0}òt† ¾ˆßÔ+™c©Ê‘ÅäóU¹jô ËÈy¼Ù¶û€™ ¾~–ËågΜÑÑÑ�õsqqñsÏ=¬Êd²¯¿þúÌ™3°pÝ·or¸§§çO?ý4©~vuu=räˆÊ¨Œßèîîõ;’J?ûì3� —Ëóóó—/_ÞÕÕ—ñÅgÏž•Ëå kÖ¬�E2‡ÃÙ¶m¬Ÿétú믿·9<<¼wï^Eý, üq%Ó<•ú966ö¥—^‚nÙlöo¼�èg¡P¨ÔHkkësÏ=Ç`0àM©T «t>Ÿ¯h acccff6ñ¥™•W¶««+!!�Ç]¼x1++k&ü³ ‹Åºté�¦R©ÓSûR©ôæÍ›X,vbÏç¶¶6ss󜜜tX`°GdôJÁí^}·dÆ.’S†54š ¥­_E W0ª«;ç*ú¦Ç”ô3‡Ãyþù瑸å .¬]»žµ÷Í7ßÀC…ß~û­ŸŸrxMMÍ’%K¸\îÄú¹©©é…^øþûï ;0V??õÔS{öìÑÓÓÛ±c‡®®.bñáááñÒK/=ztÇŽ€-8 úé§Ÿttt wíÚõÉ'ŸÀú™Ëånٲ嫯¾:r䈮®îÁƒ•H ¶mÛväÈÄ»oóæÍo¿ý¶îßœ:u ~vøá‡^~ùeCCÃÝ»wüñLj~Þ¿ÿÇ Çi˜››S©T¸<**ê…^øå—_ ß|óÍÔÔTxFÛÎ�;¿øâ ›£G�nܸq†Æn_Ù¡¡¡ÌÌL##£³gÏÞ¹söWÑ6ÚÚÚ¼¼¼p8\VVÖôÌ¢ËÊÊÐh4ìý2^�ÎÎN “™™9³Î €Až,«J“Ï«íÏËÔ¼.¶”œÇS9?Q(†ŠøõÝÚûv `&ÕÏB¡°³³ÙìííUœ�ÖÕÕE§Ó­ÀÚÛÛ•Þ¹·´´ˆD"©TÚÒÒ‚*M†ã�¹u0‰¤µµU±µ%K–H$’ÜÜܱ̰2º‹PZZš‘‘ÁçóÙl62â*²³³óòò$Éðð°Òye2Y^^�NGêwtt4+ è×QRR¢Ô~ss³®®nvv6ü¡Âžxâ ä›ÉÈÈ ÓéJ&µµµt:ýÞ½{ÓŽ[@PÓC,—••…„„`0˜'NDEEÕÖÖÎ<­‰f©©©Áãñööö¥¥¥Ó8ü¯;ÖÅÅÅÓÓs‚Áö®®.,›žž>³žÚË0_v¯FHÎçUµ‹¥óÑÖ?:òÌR!že29õ¾ ¬Y…h Åå A)þYk!‘H‡B6™Læ /¼0—ÁÓ¸² ÑÑÑŽŽŽ(êòåËEEEŠ6ÚóNii©½½=�¯©©™ê±R©ôÆ�Çrôôôàp8øu°˜ByuÂ[yùä£�>Ò`Eu˜É•íëë£R©nnnFFF^^^wïÞUœŸ/ ÊÊÊÂáp^^^mmmS=¼¬¬ÌÌÌ,11q¼v‹eiiI¡P4ÑY`þá‹ ÂzÑ­<^y‹H4×sÿ‡šNñíÞ_µx.m¥– d`Ê X ,8ý¼°nnnF2ËÌ%¹²�àÞ½{þþþÆÆÆÎÎα±±ÓP­G"‘P©T4}éÒ%¥Ä‘“ò×µpqqñòòï]@¿••Ubb¢†: ÌB1TÒ(ŠÎå•6‰„âyŽÈb´‰ã‹ø#ãøÑÕuIŠøó+ï`JèëëK¥`¦óbC*•*MÜyƒL&óêÕ«–––8.""¢²²r~ï�@kjj>iÂAE¤Réõë×±Xìx&Û666qqqšë,0wˆ$ÐýæÑ1碑@4ÿ¢´´It§„ϧ'�liL>�+˜ÿ~€ú`0˜&Mh! ¶¶¶³Ôx{{{\\Ü™3gŒ��ýýýsrr�´�s—Ë�ŒŒ411‰ŽŽFœXÔ¡´´ÔÌÌìÎ�;*÷r8[[[$û<° K¡ŠVñ­<^~�P’�@ryA½0¥lܱe6wÔê¹oÄm€Fhh(‰Dšï^4 —˵³³kU­q8�N?þ¼‘‘ѹsç(ÊT£)4E__ßåË—a=,«Hg6ÞQÎÎÎçÏŸGÒ¯+244doogÿ´‰LÎl“óx¹µB-Ë… yNµ�V!oÆâˆŠ-Pí Z‡ÃÁb±$©½½]&o,dd2Ygg'•JÅ`0séA'‰Š‹‹ƒ‚‚Ðh´½½}ttôÌó�OƒŽŽ :�®æÍ,•J¯]»6^,Çðð°““Óõë×g¡³€f�ÉäÕâ˜|^vµpˆ§-Ã¥29½R@¯Œg”'–@wJøÕê>퀶ÁápBCC1Œ`!£¯¯okkK$«««çñvª««‹ŠŠ²µµE£ÑÁÁÁ¥¥¥JiÐg›úúz�`kk[XX¨æ!%%%(*))iì..—{êÔ©«W¯jº›ÀL‘A£3ïb xLG›²]K¤­B�S-ï!^ÉÓ*E Àê€ÿ¡··799™@ ]¸p!##cJ³üfHyy¹“““³³³bVô €c9.\¸06–›Çã9;;‡‡‡k[ZÀC É{$q…¼» A?W‹”3<{1¥Œ_P?Qøun­0ƒ©Q&h%</;;›H$¹¸¸ÄÅÅ)f´œ= ÊÍ͵¶¶öððhjjš´¾T*�ŒŒÄáp J»�‹‹KHH�Ѐy§…5êöF+¨Ìâ7¿ðE£Q¥M ,W´Š)e|‰v©~´‰DÂ`0ÂÃñX¬••UdddUUÕlGÝK¥Ò´´4sss"‘ØÝÝ=iýââb 56…Š@ 8{ölPP�Ѐù¢­_z§„ŸrŸßÍÑ:å ÏŒ/â3Ú& inì6Ì·5 ‘–––ØØØÓ§O›˜˜äææ ‚Ù;�H$Š��G¡P!!!l6{âÊ,ëôéÓÞÞÞJ±B¡ÐÍÍ- Ì´Ì1�lir)?¹”ß9 �ÊyÔ¯†/»]À«éœH¯±w¢òdä|^ï –ê åôôôXYYùúúVWW«oT LŠD"¡Ó馦¦jΘÓ6„Baaaa`` …rrr"“ÉJÚUS°Ùì�� ?±7Haa! …JIIQ,‹Å^^^üñHÜ ˜UXCÒ´ AB¿¹W«3[³†¤äüIlœù"èv!¯yB� ã!¬¬¬TÚd¡²²…B-P APMMÍ�7lll0Lhhhyy¹Æ6»»»‰D¢¹¹yZZÚJ˜Åb�:uÊÇÇG1–C"‘\x€Dô@ó pew‚Û…¼†‰–‡Ûw±¥ä<^{"ñ,‘Ê“K'‰‹€ “ɾ¾¾óÝ À"§ªªÊÌÌlq¤eïîîNLLtuu522òõõÍÊÊâr¹l¿©©ÉÃÃÃÚÚ:77w¼‰�‰„D"YZZ*šxH¥Ò?þøÃËË ¼EhΈ,“)ˆÍçÕuIdÚ­œáùŒä|ÞÄ6 4šH%¿N8‡ý‹ ›ùÍmxH Ñha¾{¡I¸\nVV–¯¯¯‘‘‘««kbb¢:fjÂd2����œœÊËËÇ«ÇrP©T¤D&“‰D�9NX” ñe9Õ˜|^u‡xA×7öJbòyìÉò¶Ö‹Ò-EZŽ��­ÌB¡ððáÃóÝ‹YA,———Ã3mllnܸQSS£O¹ÂÂB[[[�0^òñÞÞÞ“'Oúúúòù|¸D&“¸¹¹ …`x 0M¸(·VHÎãU¶‰% $¦¾¦S|»€7ÄŸD>>*`$Ixx¸••ËAPPPÐÙ³ggÕ°(á ¡‚zá­<^E«x‰LF›8¾ˆ?2Q‚ÁQZû$· x<Ñ‚ù\@ky$ @Kx¨n¶¾¾¾ÔÔTwww###OOÏôôô���i·&‹ïܹcffvùòe•fzùùù(*55Þ„ ($$ÄÅÅHh€šÄPq£(:—WÖ,iµ»†2¥M¢;%|þdªxÔ”#�Ç™,ºÔá¡’4€ùåá¼ÙAnnn@@€‰‰ÉéÓ§ccc[ZZ¦×ŸÏ�ŽŽ611‰ŒŒ;i±§§çäÉ“/^„c9  wvvVJ¹(!C¥M£Ê¹¸Q´°ÒðAryA½0¥Œ?©àæ�ÚAOlÊê£Í’ææÍ›¤ÔÕÕ�Ý+•JCCC»ººæ£kjqíÚ5¸ÿ³d<êëëÓÒÒæø¤Ú|³Í2™¬ªª*22ÒÊÊ ‹Å†‡‡3ŒiØÍ …‡‡›ššÆÆÆ* /‹Åâ+W®XYY!ýêÕ«§N�Ò¬C`Ñ –@å-¢[y¼‚zÑ‚‹j€ yNµ�V!�Lg"�fñnèÖŽ@c¨#i¬­­oß¾ ¯÷ööZXXL\ÿäÉ“†pvv®ªªšvß¼¼¼ðxü«¯¾:voEEÅ#�<âíí=íöa …€€5+þÍÅ‹‡††&®ïîîŽÇã7mÚ9“NN•[·n*`mm=¶‰DÚ¿ÿ\ö ègE:;;ãââ\\\ŒŒŒˆDbvvöTG‰Y,Ö¥K—Ðh4•JUáyyy(ŠF£Á›×¯_wrrÖè',l$Rye›˜œÇË«Ž˜r?‘�zÐÑ+ÒÉÂ1¤29õ¾à~3p¤šDI³nÝ:xT}}ýÊ•+'®ÿÆoœ?žF£áñøçŸ>&&f&=Ü¿¿Jýü×®âââútÕÖÖnÛ¶MÍʇ277§Ó鉉‰¿ýöÛŽ;ÔñXøâ‹/æX?;99}ûí·ô¿ÉÍÍ[èg-ahh(##ãÂ… FFF!99¹··WýÃÛÚÚ¼¼¼p8\VV–âÝØÓÓãèèH$áê?ÿüÓÞÞ~Ò'>Eh4š½½ýo¿ý6ßIà^>L ÚÚÚ¦xOM‚T&¯ê“óy95ÂáÉÜ*´‰¢Urª…“þ†äò¬*aN ð¢FMýüÃ?\¼xq¬~®¬¬<÷Åìro¼ñ2�)>>~ÅŠ°öV ÚlllD|k“““ÙlvLL �¿víšì�FÇêçÄÄDÒß´··+îâñx$ �Çûúúö÷÷#奥¥ðh62(ÇçóI$Ò™3gþz:@ZCHGG‡R}X?#ÃÝ2™lÙ²eȧ.//'nnn555Jßž’~†+ÄÇdzX,xýþýûgÏž=þ<ÜÄû÷þýûÁÝÝ]1”%!!add$##�Ç >°ùØË8ʽ{÷ðx|pppXX˜¢~.++Sxý£�>zóÍ7mmmƒ‚‚¶nÝŠÃáÏ>V?á°nÝ:ÅÌã­­­/¿ü²žž‰D:yòäÞ½{áòK—.}øá‡¾¾¾—.]Ú°aCpp0¹�Çã�9²zõjüßÀÒ=++kݺuîîî!!!»wï>{ö,ÜŽ¢~æóùO?ý4ؾ~ýz___ooïuëÖÅÆÆ*öVI?óùü^x¡¡¡ÞìêêZ³f ,}©Tê¦M›bcc}}}—.]zúô鬬,¹\¶aÆ‹/^¸paݺuñññð±;vì8tè����¯¯ïÖ­[Ñh4\>ž~ \³f�···««ë¦M›ýœœœüÊ+¯Ü¾}ÛÇÇgéÒ¥ÎÎÎ999ðä¿þõ/OOÏàààwÞyçüùóp}"‘¸sçÎëׯÿøã�þù礷 ÐÏjR__moo�F£ƒ‚‚Ô|ÏRZZjoo�ÇãârssQ(Tzzº\.�‹‹³±±™Ô¤ººÚc>Ò“3ï,òáâÊÂX”éq¥�‚©Aò†žQë¶»•6w¡*çÑ¿Ÿ"èN ¿´I­×޵]âÄâɧÀ4PS?3™L==½óçÏ#úY,¯Zµ þ¿,—˳³³‘qfEý,—ËwîÜyíÚµ‰õsHH¼^]]ýÄO(ÆjN¿ñÞ{ï)êçŸþƒÁ ›Ré§Z+&ˆ‰ŒŒüàƒ�Í´´´±ñ¯¿þ:¢Q9ÎòåËaC$~ãÏ?ÿüüóÏ¿ýö[XÿóŸÿ¼wï\?55uÍš5Šñ¨cã7\]]‘gwww;;;xýСCH0ö×_�’’�¨/[¶¬  .§P(/½ôüÑvìØáåå…œwýúõ𺓓Ó# Àñ###Ï<ó Ë¡8þüÓO?ÁÏpoáy…½üòËÈud±X+V¬€?—¾¾¾Ò3Žšèéé¡P(+++�páÂ…ÀÀÀèèè„„„ÌÌ̲²²êêj‹5222�–+,‹B¡œ;wÎÈÈèüùót:}âd‚²²²p8œ——òÞ¿««ËÑÑÑßß_ $&&ZYY)¾š ‘èKM›wÝd‰�ð¹ðûôn!H.oî•ÄñÓ*}C X9�þŽNd´©•ð«c@“Ï[ˆ¡Ý`A ¦~f0555/¾øbee%¬ŸkkkŸxâ Å�˧Ÿ~º²²r¬~Þ²e ,G'ÐÏd2Y±�ŠŠ dS}ý¼víZxÀV ©TñÝwß}ùå—Û·oß²e ²k¬~f³Ù�<òÈG}¤û7K–,�Ç™:´k×.CCC sýúuXLÞ¿ÿÙgŸU<×ã�?®h¸1V? ¼øâ‹ƒƒƒmÞ¼‹¶±±±´´„_å¿öÚkùùù£ïKJž{î9äX‰DòØc�ÁoäwìØ‘œœ —3™ÌåË—Ãë*ÇŸ W¬X�l*Æ?ãp¸'NÀ)7oÞ\\\ Ç™<òÈ#{÷îE¾‡'Ÿ|v;ihhøôÓO7lØpìØ±¨¨(õ$ôôô{zz˜LfQQQfffllì�7===áÇ ccc=== sâÄ �àëëD&““’’233 F}}=‹ÅzØ’ëñx¼œœccã3gÎÄÅÅM0 )‘H¨T*�¾té$‹CBBlllZ[[)Š¥¥%24–6V]õ´y�`A–�Ö ¬z·MkŸ$±˜O½/è\ð¾mC|Ùí^M§Zây€+»•Çë^ØÏ @›Q_?Ëåò#GŽœú(üyaTδ´´ôññ¡Óé_~ù%RØÐаråÊ>øàí·ß&p!“É\²d ¢Q‡††y䑞žž©êçâââgŸ}yÞQÔϵµµÈyÝÝÝáB6›ýè£�VVV*~Š¡éÝÝÝׯ_ÿý÷80ö;W‰úñL&3//�N§“Éä«W¯º¹¹9;;ãp8CCÃß~û ‡Ã988ÿÐÐP2™L¥R³²²˜LfSS‹ÅBÞA,¤RieeeDD‡³´´¼zõ*“ÉTù1All¬©©ixx88ÐZ¦¤ŸÖ¯_�Ä?o߾ѓ~~~o½õ¼Žèçîîî�?þøèÑ£pùÆ�oݺ‹ä¯¿þZQ?#²ÍÛÛû�wÞQ<»¾¾>�WÙ1%ýlcc³wï^Ä ™ò¶víÚ¢¢"xÒŸ‹‹‹¢~®­­]¶l™’;î·ß~kccƒl"/»Uêg‚^{í5$îâüùó»wïV¬ðóÏ?{xx(ÕÚÚúÚk¯=zT1XÚÜÜ<::zlû›7o ‚7=<<�ø“)ég¡Pˆx¡H¥ÒcÇŽ!úv–�áóÏ??yòäØï�F£!z>;;û…^{¬J4ÿ A‹Åjiia2™ÙÙÙ4�L&_¹r% €@ 899áp8ƒ#GŽàp¸S§N„ÀÀ@‰D&“ÓÓÓïÝ»Çd2ÛÚÚT¦ó[´µµÅÆÆ:;;ûûûß»wol¶A.—ibbÍç󻺺üýýSRR°X¬JûôÑË4ߊ,J‹ú¿�nŽ4¥Œ§„¿hähÞÀ|^›zG$�‹ùjSÀ´™’~–Ëåý§FôsMMÍ–-[>þøã½{÷¾þúëÕÕÕpùo¼ñ /èèè¬X±ÂÚÚyÕîçç·téR]]Ý÷ß?((HQ?ëêêîܹó£�>Z¿~½bð,ƒ—-[¶ÿþwß}î†QÒÏ�@OOoÍš5ß}÷ݶmÛ8×?wîÜÚµkõôô>üðCWWWEý /¿ü²��Á»ï¾ÛÚÚ {\ëêênݺÕÐÐp÷î݈–V©Ÿår9ƒÁxå•WöîÝ O„Dâ1`RSSáþïÚµKqØáÇׯ_¯üpëÖ­+VÀÁ¿üò �‡…}yyù¦M›tuu÷ìÙóÖ[o!Á!èçgŸ}VGø,·nÝúç?ÿùÙgŸ½óÎ;ŠúùæÍ›+W®DÎ{öìY8¹³³>£¡¡áÎ�;a--“É,--7oÞü믿9rdãÆ�$i²;èÿ¾j5kj±XÌb±˜Lfff&…B!“ÉÁÁÁD"‘@ ØÙÙa±X==½cÇŽáp8�ÀÀÀk×®‘ÉäÌÌÌ‚‚&“ÙÕÕÅf³ç¾ójÂápîÞ½ëååeddäææF¥R• úúú._¾lffvçÎ�‘‘‘ààà'Nܾ}ƒÁ(¾+�úY u~;½ƒÒÔrAB1¿…µx…t±G“n«9Š.ƒä´ Aq#°z³Ž:–ÛÛÛ‘ø�§èG APyyùýû÷¡;;;›››UÎQjllÌÏωDb±y}ü—쌉‰éìì,,,Té3ÐÛÛK§ÓÇ6ØÕÕ¥¤¨áaÒÌÌL¥èЦ¦¦ÜÜ\�@APGG‡Ò!µµµ¹¹¹J¾­­­t:½»»)a±Xã9èÊd²²²2ÄnN‰îîn:�®$À•ÆÕ?ÿüs …rÿþ}:�ž––¶k×® .(¶¯ôd¡øñÅb1r]Ølvóÿ‚ÂápètúÐÐ�H$‚}†!úôÓOSSS‘ó¾û¾¾È!ÍÍÍt:]É”X çææNiºŸ6ûoðù|‹U[[[^^ž™™™˜˜H&“}||‚µµ5�ÖÓÓ311ÁápÁËË+000***...33³¤¤„Éd²X¬ùMS" ‹ŠŠ._¾ŒB¡£££Ÿæ:::|||,,,ètzvv6 … 177WrúY —‰;ýòt† ®�ߨ+QÓ~ÁÐÖ?:òÌRw ý^�0³J-_;˜!Ú i”æ.zØlvRRÒºuëçpÁ>Ȱ!‡Ãy÷ÝwU†sk.—ûüóÏ#Ï&l6{ûöíˆ5·fц›m† ³X,&“YRR’™™èååE p8œ‰‰‰žž�¶¶¶&>>>���d2911133³¼¼¼¶¶–Åb�}îÓ,ÕÖÖFEE�8qƒÁ„„„”••ÁOÁõõõÁÖÖ6%%ÅÞÞþìÙ³fffŠ3±~N"_$]Æ“.㋳"UV¸v®¶4Vå®�Ö»·®zj›~æŒÈè•‚Ø^}·d‘¹7öJbòyìuç–·ˆRÊø“¦#�  ’æàÁƒH¢‡Ïç¿þúëûöíƒm. ݲe ²k×®«W¯ÎM—‚‚‚àóîÙ³g÷îÝׯ_Ÿ¥iÃÍ67°Ùì®®.&“YPP�™™I&“¯]»èáááââ‚ÃáŽ;¦§§‡Åbíìì‘H &“É %33“Éd644°X,EëÅiÓÓÓsçÎ�³gÏùøødff •——;99�>}ÚÓÓƒÁ˜šš"Þ8ó«ŸSnûíÿêã=ï¿mtø@u1)O�¿tÊÎÈíŒyMI \ÒYK1>ò�âTÇÇäâ�‡ú;ã�Lßßõ¦£�áØ½Üî¬Ç }ü ÊcK²¯­_÷¢öèçAž,»Z“?jI±È”óhp`§øvoHíôˆ�=’¸B¾P¼è¾ ­<<’f¡  ÕI ®qÆN=Ó8àfS¢¯¯¯­­�ÉdÞ»w/==�L&“H¤ÀÀ@�pêÔ)wäÈçääD ®\¹B&“i4Zvv6“Éliia±XjÞ0\.7++ëâÅ‹FFFx<>>>>))ÉÚÚÚÞÞþرcFFFp°Ç<êçLJðêUËc®yUÝ"ž·ûáÛOárôñƒ_ñá•€3žgq+W\ ­]³*“ ×�7ÇXV\¬ÌS©ŸG“•Dufj¹~æ d÷j„ä|³]¼(‡[mâø"þˆÚ�ÝœQ«gõÅ6Ì�Œq#•J æ» ©TÊb±ššš˜LfVV•J%“É¡¡¡þþþÁÁÁ‡ÃýöÛo†††8ÎÙÙÙÍÍ-00ðêÕ«d2™N§çåå1™ÌŽŽÅð~‰DRQQ†Åb­­­ÝÝÝ�?~ìØ±Ã‡WVVΣ~vq258ôÍØòÖª;Èúi{c,ꢫí,�ÀëÅY‘þµ©ÖXïãaƒw2� w‡†Š&ÖÏÉÁp\é2¾ªè–⮚’Âi´�‡MFrð¼ëç!”_'¼•Çc´ŠÅÒÅ9ÖZÚ$ºSÂç‹ÔýtœÙ”b¤@#ØÚÚ"ÞÀìÑÐÐ`kk;ß½X´…B‹U__Ï`0233“’’ÈdrPP�¯¯/�@€£ õôôŒ��q8œ«««§§g``à�7®\¹âíímiiyøðáß~ûMïó¥Ó—>½Ä×ó¿÷ÞxuNÚ9X…×iñ¯oÙ¯ã�Lqf¿"åomÛì�·&žÚñök6úëç[W=ñN¦x'Ó·¶m¾èe«ØŸåÏ/Ã;™z»[ïÚñÆ<êgCc³¢Ñ­<ÞýfÑbMH Éåõ”²)dÜæ‹ Û¼Åä7 4ÍÎÎNÉÐ,\.×ÎÎŽF£ÍwGvFFFX,VuuuYYYfffBBÂÕ«W=<<ÌÍÍõõõçW?ÃqÎo¿ùêŠåÿtv8Îi§+íe5ÑÖ½´ �ä?ÿܲ†ò8ùpñÎwÞ 'ÁåRN!2æ\”yuùóË&ÖÏÈ¢ÿË׊úùí7_½ì{igõs`쵌ú¢a>o¾ï Ù‚ä9ÕBZ…@¢ö¸ºD %•ò™íàý)˜ ŠˆˆÀ`0T*µ³³S1Á0Cd2Ygg'•JÅ`0ó× @ihhÈÎÎŽŠŠòõõutt444D£ÑÎÎÎŽŽŽÇŽÓ×ׇ‡ çQ?ÃKZBÀ'{v¼úÊz^oRÈï½÷ñ‡ïø]°W¬yDï?½l{RW­|^q.a|”�ÞÁïÓÝýÉž�<òˆb‡šúYÀÊ}ôÑG;j’áÍù�>vܰº·ŒVËì)Hf×¼eî‘ÊäôJ½R ~87Éï2õÂÙíLHuu5‘H´µµE €™£¯¯okkK$‘Ü:€¹ö/,,LHH¸|ùò™3gLMM���O�:åçç›››[UU•’’ræÌ333[[[x®"�FÓý,.–° Ö®Y• ÞéÉÞ§»ÛÙá¸RµÛ7.ü{ßA®Ç  …ngÌÿ½ïƒf¢|¸¸§!uzúYØ—ûØc�5VÄkƒ~†ãŸERauï}Z]leO±@¼HÆ¢%RˆV!È©Néñº ^x—!Oä¦GOOOYY…B ÷ððÀb±‡¶³³óöö¾~ýzzzzmm-’úÎyäççgllìëëfjjjaaahhÛHΣ~>{Ê,› ¯·W'/{v)ª1Ðz÷ƒÝo�=e6ö^oÎòç—}ýŇ ú …ŸíÝu-”¯_ %(éçñf)Ž�ßxoç6'Sxý‚›Õ¼ëg‘TXÃ*§ÕÅ2º‹øâ)$0ÒBD(¥Œ_P?µ¤'ÌvqR)_ýH3CCCµµµéééׯ_÷öö¶³³;|ø0‹õðð§P(eeeHfO%º»»£¢¢0ÌéÓ§SSS ÆÉ“'���1Œ™™’ÃhõsÜMïõë^ÜöÆ&Ý�ß}þ¹eܬàò÷w½¹ôé%[6oÐY¿^zS‘£~<ðÙ3KŸ°r‘’›WÜW­|þà÷û>Ù³ÃÅÉô™¥O+ê纲ؕ+žûò³÷w¼ý;=ž~.Ί|aõòß{k÷»[ÑÇj‰~†KEµ¬Š´ºÛŒîBžxAN`á‹ ;%üÒ¦©¥ÛnaInðÔ7èðð à¼ó±±±~~~§N�266655=sæÌåË— ÛÚÚ&õŸäóùééé...h4úúõëííí###¡¡¡æææQQQfff'Nœ ‘HHýy�ߨ,ˆ¾G»2Ü•…”´W'7W&(.Š¡Îœvzg-E©‘ž†Ô¬”¸‘öêd¥½Ã]Yô¤ $¶YúšÓ”üŸ¬ÜœÔ°®º•íÌ£~†KEu}Œ´ºÛå]<ÑBRÑ#B(¾ˆÏh›Úì?ÖÐhFoŽÚI ,Và‰–%%%III¡¡¡�F:::úúúFEEegg744ŒŒLáe=A ÃßߎÓ(--•JG=r333Ñh4‰D¢P(h4�Çûûû+Níœwý –±ËŇ$2q}_å�?"žÙÍ8 ñe· F3'Nõ¨˜|^7X=ðÐÁf³ �F‹ŒŒôòò²±±Ñ××·±±ñòòŠŒŒ¤Ñh ƒÍfO»ýžžžèèh ‹“'OR©TÄ�²­­ÍÕÕÕÙÙ¹±±122ÒÖÖÖÇÇÇÓÓÖÕ@?ká¢NîN‰LÜÐÏL«‹»ß™Ç Mûþ™mØ#£2¸±wj¦ÍB1WÈoìVÏ@«áp8¡¡¡pÎ`Ú`±XŸöööù¾£ç‡ñ,ãBhhhRRRII‰¦|#�NÇãñfff‘‘‘mmmŠ»®_¿ŽB¡ÒÒÒø|¾———››[xx¸‹‹‹H¤} ô³.êèg©LÒØ_•^WÖ™ËÎü¾Ò,pF[ÿÔÆ�¥2yJ¿¼ej‘Ò0Çp8,K"‘ÚÛÛ�#4`&ôõõÑh4 Åd2ç»/³‹:–qMMM�@³ç… ¨²²2 ÀØØØÇǧ¤¤Di<¹  ÀÂÂ"00pxx¸¯¯ÏÁÁ!44466ÖÁÁ�ÇSá�¦¯¯¯] –y_¤œB}}ý)ÝR™¤i :½>®´ãÞ°Ö¨è.¶”œÇëbOM¾¤={H0ý¸ú™ÐØ+‰Éç±§î›QÓ)N,æ‹$@=€Àè \)˜ã Ð$B¡ððáÃóÝ‹IДeÜ,Ád2���½½½‹‹‹Çû‘–——[YYýñÇpILL ‹mkkc0fff---œåAø–)ħ½†*,š}•‹l°¨½†J ¹€ÅbÆ{Y >2HÖ®»[ŸPÜž5(˜akS¢¦S|»€7ÄŸ²xnï—ÆæóF¦–\æ õçªê£U÷ÕlXÆÍ,‹L&ãp8GGÇäää ÂB|}}­¬¬îß¿—ˆÅbggçÁÁÁ†† ÇrĻ›£ç{úéÃÆ¯c¼  Ÿ³ÁÜÜWsi7KTUUÁq.\(,,œ4˜ª¶¶ÖÁÁÁÃÃC1ª¹­­ ‡ÃÁY¹ûúú°Xlvvöì÷°`€ Yû`SFÃ�‚6ú�¥áÆåò‚zaJÙtB—E(±˜_Û5?QR0m4®sFFFš r®ÓÌár¹Sj©¯è‘«Èððp}}½¦»©LWW—ÆÝÌ´�ßWóe7KôõõÅÄÄàp8‡¤¤$uì;¸\îåË—1L~~¾byYY …ºwï|3Ÿ8q‚B¡Ìfß ‚:›3“ò[ïöóz5Ô¦<§ZH«H¤SÏ2HžZ.(iVÏ`ᡎ΋Å$éĉ*]dIMMÕÕÕ}ï½÷ž}öYu: HóçŸööNòW=%%EWWw÷îÝÏ=÷œ:í'''Ãõ—/_®²Â‘#Gžzê)‰dú¹®®]»FR€Á`Œ­³cÇŽÔÔÔiŸb}ZGGgÓ¦Mººº"Ñh ‘H„ÛÿüóÏ÷ìÙƒŒó÷ÝwÕqrrúÏþ³sçN¸òü±oß>•—ÌÞÞÞ××÷çŸÞ¾}ûwß}wáÂøÙÇÌÌìÕW_544ܲe ƒAêïß¿ÿ³Ï>srrúæ›ovïÞ�\‹ñÊÕAOOo¡XÆÍ"‘(;;ÛÍÍÍÄÄ$<<¼±±qª-Ü»wƒÁ„„„À�BŠôööÚÚÚFDD ¿ˆàà`�™Ä rº‡Û³›Rî5S{¹“§Óâ‹ ;%üÒéÆ-w±¥1ù¼á©{D€ö0©~þøã�|§§§¯[·ÖÏO>ù$�FƒË÷íÛë4˜±ú™Ãá¬Zµ o~÷Ýwóòòõ3‡Ã)((ضm›ŸŸŸ\.���ß°aã*‰vìØ‚´6V? ¬Zµ ß¾}{QQ²w‚ø�ŒŒ %ýüôÓOgddÀ›}ô‘¿¿ÿ¨;Siéš5k�þ£P(wwwx}éÒ¥»ví‚Õ¸™ÙsïÞºuKGGgppîÿ+¯¼ëçþþþ§Ÿ~þ\yyyðÃü}¾ôÒKHÿ�?îéé ?úè£H¬/’¸ÙÜÜÜÊÊJå'²··_¹redd¤bá�7¶lÙkr>Ÿÿúë¯ß¸q·ì±Ç‘†´ßÕÕõØc�!úvlÂè‰ÑÓÓÓr˸Y¢¶¶688øøñã^^^ùùùÓKïêêrsssrrR9­µ¦¦�F#¿;øÊ:;;Ãoˆ€™Ð3ܑӜ’ÓœÒ3<®ŠBñE|FÛ4_qFdä¼é¤ö­bRýüé§Ÿ*UÒh4XïÁB‹Å:::"›*ãŸOœ8qöìYX‹¾óÎ;p!¬Ÿutt6nÜøÕW_ÿ7w-�¶¶¶FŽõòòúá‡�M•ñÏVVVnnnpßvîÜ©¸kJúyÓ¦MȦ©©)�—Ëå®®®o¿ý6äüË/¿Sl‡G5/^¼øå—_¾ôÒKð¹ˆDâ| òÙ?`lÎ�;‡lº»»#úiÿ‹/¾X·n]UUR^SSãëë;¶|Rý,‹srrÜÝÝMLLÂÂÂÆ–«Oii)‡óóóS©½!ŠŠŠ²²²RŒêÏÌÌÄápJ!ú€F`q;ï5§f7Qº†Û Q�g9{D“Ïkì�¦úK¡¤~Uûâ™Ýf&Õ9T*uíÚµðÿt‘H´}ûvXšN¬ŸÛÚÚþñ�Œ È}zëÖ­Èk•úY$í{€««ë€C2h4ÚæÍ›H$�@X»vmEEÅåj²Xõ3§accsâĉ„„„uK¥ÒøøxSSÓÛ·o�7û�Ãáœ:u*00P±“ÉD¡PjÚG3¤®§+±’–^—Ô9Ô�EO•ü:!½RìaÀ¢AM�“‘‘qñ⍤$Ä «¿¿_1SCAAAqq±â!D"Ñ××WqAëׯ///GJàü)*£=e2•Jõöö¾sçÎXuÑßßñâE___Å—æ­[·Nå8^__\_É ¡§§'..ÙìííEb*à)~ȸ.<èç÷€êêj¤P) å––,«x¦Ž(ŠÉdμÀ¤´õKÉù£3þúy½ù­w3“:›§ä”Èh'—ò%`Ê XḎΠüâ‹/f¯}ÿ¯¾újöÚŸ9nnn§OŸF6kkk—/_®2°dA³hôs}}}XX˜‰‰‰‡‡Gnn®F¼©°X¬¢EÌXŠ‹‹Q(”â“ì—‚F£U>§±W“Ïc�üßøÆ�UÐFÏh¸Ó>ØA“{Ð5÷Jnòø"0ô s¦sBCCuttvíÚ¥”FMSmذá½÷ÞSœ`¥…TWW¿òÊ+†††x<ÞÔÔôÍ7ßLKK›ïNiž…®ŸÙlvBB‰'lllâââ45G‚ ÔÔT uóæÍ‰ç1ŒR„ÆÀÀ‡S'A'0sj:Å· xCªŒšÙü¾Â¶ zCb§aÝ;8:v=ÈVÏ`±1g:‚ ¥…o_q:ž6#‰ étzqq±ÊÀ•EÀÕÏb±8//ÏÓÓÓÄÄ$$$¤®®Nƒ�744œ:uŠ@ Lüˆ'•Jƒ‚‚œœœ”D;—˵³³KLLÔ`—€ñ`´‰ã‹ø#&äðû‹Ú2é ­œzÙ=Äõëèæ,¶—k§\|Á€ùE*•"æÒ …††8NÃÝÝ=''G³9Äy<^XX�ÎÎΞ¸&—Ë%ÞÞÞJ£ÓB¡ÐÙÙNyÌ6¥M¢;%|5ƒ.ÅíYwëZØuˆŠˆ¡¸Âé›Ý€–ƒÁ`´<à°àhhh°µµ�ï^¨‡ÃILL´µµµ¶¶Ö`œ†"YYYh4:<<IÈ>]]]ÖÖÖ7nÜPšœ%‘H<<<�ÔBÀìÉåõ”2¾H2µˆå!»¤=;½>¾™]+’J)eüŠV`õ -¡¡¡Šé¹€‡(&˜ÖBÄbq~~¾——×ñãǃƒƒkkkgã,ííí®®®§OŸVÇh®²²ÒÌÌL1i AD"ÑÇÇg±†ú´’çT i‰tšÓý†œ’ŽJõmzM¥o6À¢…Ãá`±X‰ÔÞÞþA¦�L&ëìì¤R© &""bJöVsIcccxx¸‰‰‰››[vvöT󒫉P(¼qã …¢Ñhê|wïÞ533S™á1,,ÌÍÍM³ñ$ÀX¤29½R@¯Hgö ¨ADcô–tÜK¯�k¨–Ê@Xœp8œÐÐP £L}}}[[["‘¨èŒ­=p8œ;wîØÛÛ[YYÅÆÆÎêTÖÂÂB,0444ie‚®]»fcc£äì }êÔ)�@0;=þ‹D Ñ*9ÕÂ>øVwˆï”ðÅb?¸ÂÁ²ÎÜôú¸Æþ* ¢X(H$’‚‚‚óçÏͶ¶ïííõôô´³³SóD�àüùónnnJéæa(ʉ'T¦Œ4ˆH¥”ñ ê'ôÚPƒ¶~ilOɲƒ+ºß™—V×ÐÏ”ÈÀk´—¦¦&‰djjzîܹ¬¬¬‰Í–gŽD"‰��555MHHPÓЦ¿¿ßÑÑ1$$Deýììl,;«ãä€\.ç‹ ;%üÒ¦™2õ ËÈy<6WuðLjh¸¼+?­îv}_%PÑhCCCIII8.&&fnô'ƒÁ°¶¶öññQß�¼¡¡ƒÁ$%%©Ü[ZZŠF£á„ïÀì1"„â‹øŒ¶™ Z®ŠÉçu²'yr䉸å]iu·ëúbé¬L= &R©´°°ðÂ… ÆÆÆ���*'âÍl6›H$ZZZ–••©T^^ …*--U¹·¦¦…B544h®›€ †ø²Û¼šÎ™Šg‘J(â×u©áÌsÝ…iu·kY@E0÷´´´DDD P(��™™9ÛqR©499ÙÔÔ4::zJæ±±±X,¶µµUåÞ––333ƒ¡¹ž*`�Œ&œy~™LžZ.˜Fø_<Âè.¢ÕÅÖ°ÊEÒ9úÙ@‘êêj"‘hkk«¯¯?ßF/X,ÖÇǧ½½}®øÐÐPrr²££#‡#“É,kNŠPWWçèèèîîÞÝÝ­þQb±øÒ¥KÎÎÎGe…žž SPP ¹ž*` IÉù¼¶~ ø3gW ³«§¯~b^eO1­.¶º÷>PÑ0g@�Á`¨Tjgg'°°žGúúúh4 …b2™³t ©TZ\\ìíí ÇiÌމƃËåa0˜ÜÜÜ)844äââB$Çsœæp8–––éééê) š.¶”œÇëš,VYÊšEÔû‚™ÿÑHøÌž’*ºL(n�0ëÐh4;;;.—;ßü—ªª*333�'…omm�ŒŒD¡P®®®s§�A�N733»zõêT ™ÛÛÛq8Ü­[·ÆË¥Âãñâââ4ÔY@5mý£#Ϭ! ˆçúnIB_(ÖX¦$¡„_Õ[J«‹­ê-Jøšjc±µµ3­´ �F 4ÒÔðð0…BqrrÂb±ÑÑѽ½½ivª´´´¸<௕©[^^ŽB¡rrrÆ« ‰\\\"##gÜM9üåÛÛÛÿöÛoóΘE¦+ÕØ+‰Éç±G4ð’®“-�Éçqšß'”ª{Ëhu±ÌžPÑ0;¨i· ˜3„BááÇgÒ‚T*-))ùK!TVVÎWBp�@põêU333:�>�>P©TssóÚÚÚñ*H¥ROOÏÀÀ@�|Àˆˆ[[[ƒò}/n�X)õèj:Å· xC| (^öȨÕsßð,ˉ¤ÂêÞû´ºØÊžb�˜7{'€‡==½ùî@Ó¾.mmm‘‘‘fffx<žN§ÏoêêÜÜ\ 4�!™Lnoo?ÁÜF‚üýý/\¸ ‘¸ýêêj •© ‹’ÜÜ\[[[‰dr F›8¾ˆ?2Óƒ£ð„Pl¯­o.òq‹¤ÂV9­.–Ñ]ă4ÐÏÚÉT¯ —Ë¥R©'Ož´°°ˆŽŽîé陵®©Eww·»»»££c]]Ý4çóù¿ÿþûÄúŸD"�={VScÅD"‘J¥j¤)ÀBÁËË‹F£M\§´It§„Ïi@<‹¥£É «;æôí†X*ªeU¤ÕÝftòÄ`ª h Ÿµ5¯‹T*---õõõ566ö÷÷g0ó§� ‹£££MMM“““§Äb±ìììH$ÒÄ£Ê111NNN|¾Æ"PÑù#¢áyí ,`ÔÑÏíííôTTT Oþ'W___çgΜÑP7§@ooobbbrr2òêÿСCp4ej1µµµ»víšy;ã]—‘‘‘ÔÔÔÓ§Oc0˜¨¨¨)å™Uúûû}||¬­­g’û/;;…BUTTL\-77×ÂÂBã9_À³äÉÊë.•Éé•z¥@ª¡I~­bJ_¢þú™¸¡Ÿ™Vw¿3�+ÒäC(<$¨£|||V¯^­û€•+W¢Ñhu¦k�>}ÚÂÂBCÝTooïçŸþ§Ÿ~:pà€ŽŽŽb–gkkëÙîƒÁxñÅgÞŽÒu‘Édeee/^466öóó+//Ÿ÷8 ©Tš��`jj«ÎT,•@mii9©ñuyy9�ž�,�@??œŒ½î)D«äT 5õ#kê•Äòšˆ Ö R™¤±¿*½>®¬3—+œïîÀBBMýüË/¿Àë###/¿ürJJ ²‚ •¯Ñ§ªŸE"‘Êvd2ÙxƒÞ<O1n!%%eåÊ•ˆ�µ’iÛxúy¼ö¹\îxA*óGóù|‘HÄd25«Ÿ;::nܸann~æÌ™ôôtO»¬¨ª««íìì<==gâ,-‰|}}ñxü¤ñõõÿŸ½óŽk*Yû¸w÷îu]Ë.kAA Š}­×†D±®º*V�æÊbR¢Ø¸ ¨ˆ"""(ê â*"H¤‚t tBBo!ý½:÷ž›7´BŸï‡?’Éœ9C朜ߙóÌï!£Ñh2™,ö¾ºêçщи3Ù¼÷©m‰dIxm|…Zÿ%åJCëИzî‡Ë.ª%E�ýSÊãš Š†@ Ñè­~æóù{÷îuss6Å FZZzæÌ™ëÖ­J-¤ŸÙlöš5k�|uuuCBB€‚ÅápK–,Y¶l™¼¼¼‚‚©S§€u°��hÆ $ iÙÃÃãèÑ£³gÏþÇ?þaggÊwïÞ}íÚµ®þ‹Žú¹­­M___ZZZVVvãÆ�¹¹¹ ¼©©içÎ�‹-Z»ví‚ ÜÝÝA9�dz¶¶–••]ºtéüùó‘Ý–––'NHIIÉÉÉ�}4ؽø‚ãÞÆüâ�‘R$±%~ ­\Ÿ„VjÃP�«çð8”ÚܲÿçòØFF'ó¤·ú977WJJ*%%…ÏçŸ={vûöí ÌØÝÝ}Ö¬Y‚Y¡;Î?[[[c±X𺪪JFF†Éür�òöö^·nXºuôèQoooPÇÔÔt×®] Í'Ož(((€ú F^^>!!�Ïç‰Ä±cÇ‚YÙ3fDEEuõ_tÔÏFFF¿þú+hÿáÇsæÌNhÎÎÎ;wîujjj²²²Àk''§M›6544€(‚3f€×X,vÇŽ`&üÁƒ’ÒÏNNNiiiC'N�Çã�Ü/^¼ècðââbççç×cM�fhhß—ÝuO�çBqq±‚‚Bpp0xëåå…Á`º©_[[«ð_vîÜ!ÑþáîÝ»"VFÖNŸ>Ý±Ž¾¾þõë×%ÝMñAƽ¥��Ô–Y*1s¹6&ÏïS+¥z ¬ž%—Ç¡ÔåE�>—Å42Ä\ �@ £õóøñãÁQ^^þÏ?ÿåÓ§OÔ«sçÎ}÷îò¶£~®­­•––Á¶¶¶çÎ�å·oßÖÕÕ¯¯\¹rþüyðzêÔ©‚Y›€=/0�@Ê¿ÿþ{³ñã�?~üø±«ÿ¢£~–’’¬/''Îçó&Ožlmm��� 8)ºtéÒk×®ÿËš5kÀüù�?þÄ|ÿÅ?ŠŠŠ._¾|åÊ•¾G þü�F#_]7466š˜˜ôhÊÑGzüÎÉdòO?ý´råJpSóøñãÇwSŸF£�3¦ý+/_¾”’’zûö­¤{Ýï8;;‹ˆ¥¢¢âááÑ}�¡©ŸÛ¸~‰­¹Ïl?$¥-³dø%²äò¸Åuù‘äÀä² ŒÚÁî� EDÔÏ{öì¡P(BYä¾ûî;$æ�ÏçoܸÑÓÓyÛiü³±±ñÍ›7y<Þüùó AaIIɬY³ÜÜÜ^¿~={öìÔÔT0Éùí·ß Fº®[·îÅ‹õóĉA’ŽeË–usíÒÏç›o¾)**BJV¯^ýêÕ+𺨨ÈÚÚZEEeÚ´i¶¶¶ PFFfÏž=º¤¤¤0™Ì1cÆ”––‚:#X?·¶¶>}úƒÁ|øð¡ï­½}û‹Å"Ç@7´µµ]¸pÁ××·ï;íQôóÂ… UUUAgõsccãÙ³g7mÚ´wï^Dç#ú¼uqqùå—_Àk6›moo¯¢¢²eË–û÷ï#Oš››ÍÌÌ6lØpàÀpŒ�Çl6ûÖ­[›7o¬ŸªªªN�:µaÆ?þøIžˆÔߺu«‹‹ ò/¤¦¦>~ü¸ªª ƒÁlܸyTPP€Çã•••·lÙ¢³À�¤®®îªU«.\:ƒÄG±X,;;;eeå­[·>xði¿+ýL£Ñôõõ7nÜhhh¨­­�èçÆÆÆ3gÎlذáàÁƒ` Ä‹ÅbÙÚÚnÚ´IUUéŸÏ/,,ÔÐÐX·nÝ®]»îܹ#ÛFuuõº®oBk¡ä&Šy¼/öóúôtfpáò¸%õdbA`Rit}[Í`w�@†bÄ?#,_¾üÙ³gàuKKËO?ýâ:–––úúúB›”””Ì›7/** �±û÷ï¿ÿ¾���  Z²dÉ_ý^777Oš4 ľv¥Ÿ­¬¬�8Ð%AŸ�K—.!j°páB///𺱱q„ B!Ü@W|÷Ýw åßrb×®]NNN¿‡3f óŠ©©©#R?ÇÄÄ`0˜'Ožô}#‡Ãqss;þ|mmÏS[,ËÚÚ AïWDÑÏrrraaaK–,ár¹ˆ~æp8k×®500 “ÉD"QNND¤éç²²²1cƀŪ‡ÎËË#‘Hªªª·nÝuNœ8addÄb±üüüäåå‰D"XÄzüøñ#GŽäåååäälݺõöíÛ@$÷Ýw»ví KNNþå—_¬¬¬@;G�=vìX~~~NNΖ-[@y`` ŠŠÊêÕ«Ÿ¹ººšH$jii>> †ÄÇÇGFFæåË—aaaÛ·o×ÖÖ5õôôÎ�;K&“ïÝ»'##DcRRÒÔ©S’““ƒƒƒ�ŒŒ€>¿zõêܹsýüüÞ¼y³víÚ¦ŸËËËmll.]º„›ô…–––«W¯ÚÛÛ‹8Íårííí���&\ýŸ¯¬¬üòåKD?‡……ÉÉÉ!7nÀ\H?·¶¶‚G$iòäÉHyVVÖ¢E‹Àk999Ä@[FF¬ÍÉÉ™2e þÏ8–,Yôó˜1cÀ͈Ïß·ohpêÔ©Hýôôô¥K—‚×���ßÿ}WÛ #==]MMÍØØ)ìø )==]ZZI›ž’’²bÅ ðZEEEII x]nÙ²Ì�;¹™Œß˜:u*òŒIJJ Ü,¤¤¤Ì˜1 �JJJZ½z5x½víZSSÓ¾˜½tÄÕ÷yf…$]rÊXo?·±$”ue(ÀãqËŠ¢ Þ&–k[%ì»�@ ÃQtZ||üëׯ»úÈÀÀàØ±c<蘻ÍÉÉiÿþý8 o+þfΜ)WœššºqãFðôöÈ‘#ÒÒÒˆ¥F\\�>v옛›rý}ûö-‘HD6¿~ý:2“ÙÖÖvçÎ�#GŽüñÇ‚&{GGÇýû÷!&à aDZcÇ=z„´Ï`0ž>}ª§§§¦¦fnn.h"�ŸŸ�Çã:„Åbw=ztôèQ<_ZZjooßãWÚ#CA?ƒ¨]4&[UUejjú×_‰Ò�Çsuuµ³³°œ€¢ëg"‘¨¤¤ôìÙ3 Ÿ]]]wìØ�TûüùóO?ýÔQ?“Éäo¿ý¶­­- `ìØ±‚ëìV­Zêœ8q�Ç···+((€ÓÄßß_¨>Ðç@?Óéÿ™twwßµk¸ñª¿víZP'00pÆ ÿµØØØ�;wîØ±ÃÌÌLUU�F#uÔϯ_¿jýúõà£Nã7ìíí<ˆ¼ÔÏjjj—.]b2™oÞ¼QTTç ——×÷ß/Øþ¦M›@ýŠŠ ,;k֬ŋ[XXˆ’ΩG ŒôcŠÞ§”DZ¹ˆU.¡³ß$¶¶JÌýnÁãñÊ(Ñ…Á %‘5­’¼…�@ �aÇÀë4}}}!—¹µk× &­svv>räÈ÷j¨1èú9)) ‡Ã¹¸¸€çé}';;ÛÀÀ@ðƧ{<==---‘IÔ@týÌçó·lÙ¢«« ô³ŸŸŸ’’RÍÏÏoáÂ…õ³���ŠŠ ŸÏONNž>}z§÷<øí·ßP(”––21›””4cÆŒŽI‹ºÒω‰‰²²²�&9êT?×××KIIåä䀷W®\ÔÏBoÁ]³œœ\§7A�êçÇ�¯[·y+¨Ÿ<ˆB¡tuu‘‰ô˜˜…îo²rss·oßþÇtSGDÔÕÕ¹¨ß•~æñx6lÀáp ~^^rBuªŸKKK'L˜ž³ÄÆÆ*)) f___%%%òöÅãñþùσösss‘€•Û·oSþ ˆ?)//ÿá‡Àâܘ˜˜3f úyÞ¼yƒIx<ÞêÕ«ÍÌÌÀ‰D÷×T*õüùó M�‡ÅbOž<)ÚØv2îÕÍdÿ‚šl_œÙãfÆ—Eˆ•uCÝêY"ðø¼ÊÆ’Eïâ‹ ´–!çN�@ ýÍ@ê4"‘ÓqÚ�Ë冄„X[[[YYyzzJä™ìpgPô3›ÍöóóÓ××�TÔ�Çû믿LMME_êqæÌ™N“<ö+¢ø?¯\¹y{ìØ1Äÿ¹°°pÏž=?ÿüóüùóïܹ ÿç 6èêê >d©««Ó××—““STTܲeKLL (¿råÊ´iÓfΜ9uêT555`z#Tø:r8$K¦���ŽŽ²ë?þøÔߺuk\\('‡êø¯Ý¼ySZZZII ‹Åzzz^¼xùˆËåž>}zÊ”)sçÎýí·ß@aMM�žžÞÌ™3UUU_n!ÿg¤~ppð’%K&L˜ ¡¡qõêUd=à… ¤¥¥dee§M›vôèQà'O§ÓÿýwÐþ¶mÛ@¬‹Årvv^»ví¯hjj"÷}ApÜì¶Ä’ÈÄ’H»wÎí¬/ÞÑäªacõ,¾¨è¦Ò˜¢�8J­¹b°»�@ ‡¦¦&²2D`±Xššš¼Ó¬¬,SSÓÛ·oKD“ÚÛÛííí¯^½ŠøªõHbb"‹¥Rá¹ð ÇÌäçç¯^½¹sa0sæÌžä#’¬¬¬õë×#q&­­­3gδ|„Æ�ÇçÔdG�ý«E„.?4�‘F¸X£¡FUSYLÑû8Jhusù`÷�@SSS$/6dˆ@"‘LMMlwõõõ÷îÝ322´ì;µµµçÏŸwss}*;33ÓÀÀ ¸¸X‚Ý�A×ÏÙÙÙ³fÍJNNIäÝÜÜ.\8‚Ǥ¤¤Ìž=Ä¢466Þ¿É’%´Óո׷Õ ‚²©Ÿ¹¼žƒ™cHí±¹ÃØêYRP›Êc)ïc)ï©MPEC �Ž���££ã`÷òÿpttôññ€�È4ýêÕ+É®Ô+,,Äb±½J·WPP€F£3ò 0ƒ®Ÿù|~HHˆšš …Ú¶m›•••(ÙÚÀÀÀ P¨íÛ·ÛØØ |ÐN7ãÎæ²RÊãbŠÞ73»Ù<¥ˆ–Îèl±æ(¥º¹<ŽSô¾ª©¯)J!dÈÂ`0Œ��ƒƒƒ»#�ÿlll ¢@û2™|áÂ…k×®�Y$!!�FþüYôM***0Œd'À{‹¦¦æ€yåA†=ÆJ•Ö†çû•Öwž(3¿’˜ÜÆd�@·º>Bk®ˆ£„Å…T6•Š·�@†8T*ÕØØØÑÑ‘D"ÁXèÁ‚Åb‘H$GGGccãþŽþmnn~ôè‹E–•I???׫ :�ŽÃá�5tƒ…™™™Äo% CQb¥š™��D—×r|Z›Pv ­¥2¾˜ð¡è]ec TÑdäÁ`0|||ðx¼:dðÀãñ>>>ý:óÌãñ¢¢¢ <<<„\û›Ívqq¹|ùr¯žÂ755™™™…„„H¶3bàää:ؽ€ ("ÆJu4ˆ®mþbõ\Óã6z¦¦…ú±$"º0¸¢±ªh� /JKK----,,úc�^cc£•••££c¯â¨ Æ¥K—¼½½%Þ1 ‘H†††¢[…@†;½�•B ¢›Û¹o[Kk`´O/¨i­N(‰Œ. .o H$Ÿ)�@ ý ƒÁðôôD£Ñýqå*//?s挷·w¯g±X×®]{òä‰Äû#6x<>??°;éGú+Å`·%G¾Ë Ï*±¾(ýJm+-±”U𶬡ˆ'‚· �@ ƒBBB‹}ðàÈÄ!q222Ðhto£—¹\®ƒƒƒ““ÓP›‰"çÎ�ÓÐÐìpH?"v¬—ÇÏhû�ŸÑ+ƒhˆumôO¥QÄ‚ Òú¨¢!2¤ R©¶¶¶æææyyyý´‹°°0 #Fûnnn¶¶¶löèÊ×îÄçµGgY1Ø+ƒhH§Ô·Õ$•F KêÉüëëë=~„9�ì»´aÖðôíÛöeeÐo�ŒvX,–���¾¾~ppp?y²q¹\ww÷³gÏÒh´ÞnûâÅ ‹öv˜r2œH/f¾OmãüWè‰h éžFmrÙ‡Hr`q]~ßUt}}½!Îðîƒ;1‘$jF-þõø—˜û—ß3}}}(¡!£‰äää„ÇãOœ81Ø7µ�Þ�Ãáúþ ––– û/ûƒÁ¸qㆭ­­&AAAgÏží§`¤Ÿ(¤²ý?µ2XÂáFÝDCD¤‘Q÷¹,&‚@©ËãòÄ¿åôø‘ÓÇAW¤ÃñïÉ‹Gö·í%:ªÈð€Çãyxx`±ØÐÐÐŠŠ .Lˆ5Ü Óé�Fggg‹×Bmmí�;wŒ��ÓÓÓ%Ý»ÿA£ÑÎ�;÷ôéS1ޱèèh##£ŸV2¨ªÿbõÜØÖùß•A4¤·42ê?—ÇF�ý)µ¹±T4æ4&6ƒ8èZt8þ%åÇc O÷èB C�§õF999ååå½ÚŠÃáéëëûøøôkœ¼¼¼Ó§O‹ç“œœœŒÁ`ªªªú¡_HQßÂõIh­nèNÎu4ˆ†ˆMS{CJy\Ù¿¨–Äáön‰Ä‰'HU郮E‡ã‰š¡©y¢ßFºàñø‚‚‚ÁîDÑëçææž;wîÆ�ý�¸066�F‹7¹����F£‹ŠŠú¡_ÚnŒ´´´lllJKKE90Ú˜<¿ÄV M$‡DÃ,!}§¹½!µ">‚ì_X“#ºŠþ÷º¾êêêý<ªÈPDSS³ŸVŠA˜ööv---Qj655¹ºº&&&ök—x<Þëׯ�ŒŒÄ Ï.**êK\JlŸ333aþúÑ›Í&‰úúú=�lï]J[Vi/Ž »-±$2±$’Á–p~ÏÑI3³1­âcxþ—»QÂc ~†úé-ðÈIô8š</<<�Fÿõ×_ýšò›Ïç3™L'''KKËÆFq|ªªª0Lrrr?tMÀ´ƒ£“¬¬,4ÝÍý �Ç�Ìb$ä÷Ú%†ÇçÔdCƒh ÒÂlJ¯LÏ÷#Ó³ºWÑP?Cý �ôxä�$ºÍ¢¢" ‹+W®ˆø º/Ô××[XXÜ¿_¼¹ÙÚÚZ##£èèè~èšdprr/œ2Ü pppèêÓDr{d&Cìô>Ð Zâ´2›Ó+Ãóýòé™,³Ó:P?Cý �ôxä�$ºÍÖÖVwww 30Š´¤¤‡Ã½yóF¼Í›››Ïž=$é~I33³ÊÊÊÁîd¨­­Åáp�~”]Æ þÜÆâô)ŒD÷­¬æÌªOáù~y´ŒŽ*ZRúÙ/Âûƽ«ÏÜ…Ê“òãî>¾}ãÞUbJ˜`yfùg×gN7î] Œò%¾a^ñ9ÑH…´âO/‚<ºÙã½§wdåd¤gL›0qB§t ´¥~–Ê*OéôÓ«—?xî õ3"ðÈIt:š±±±§OŸ~üøñÀ¤¤¤ Ñè�?Š·y{{»……Å‹/$Ý/ ŒZ¸\®¦¦fÇòbÛ/±µ•)™5€Ð º?hcµdV%òßäÒÒ™œÿÅØHD?ëhËÊÉÕ:<¡âŽ=Ûrþkèqïé�¥~ܹwûQ­ÃÓ¦O{òê"•¥gLSÞºé¸ÎùÙ³.]5ÿ·¢>¤qPÏðw¤M;çkë”ÿÙã®C?¾íJ?»½pÑ7:ÕÕ†P?C bÓã‘ßÐÐP]]-XRYYÙ½Sø/aaa?ÍÍÍURRêj"ÔÓÓ‹Å –Ô××ÇÅÅQ(”îûÙGž>}zæÌÁ’ÌÌL%%¥øøø~ݯdÍŠŠ ›‹/˜ÅJpp0‹{wl6ÛÖÖÖÍÍMÒý’<ð’1šé8ú´FŽÏÇÖúI]@ƒè~‚ÁjÍ¢&òß�ªÓ€Šî»~~öæÉä)?'ä~È£ef”%Ï_¨xÝÑ:�–ù9ô‡ñ?<{óTû�‘^šüeb¹$IfæŒ+·þÊÓK“ã²£òh™ž;Ï[0iv×o;._¿ ¸£¨TBb^Œèú¹Ó¿´âO`&|Åš_ ~†@Ä£Ç#?00PQQyËf³¥¤¤rrrzlyݺuþþþË UUU»r~pqq9zô(xÍápðx¼”” …š={¶ººzÿ¥wqrrÒÐÐ,ÉËËSUUýüùs_šMKKëtªªŸ@F³½½ÝËË �F‡††LN‡óèÑ£óçÏ×ÔˆédËãñœœœ†ExÉÍ�~S×7¡µ²NòÏ# AtÿÁ`·eS?UÑ©'õtû¨!�iþý´òÖÂöâú¯óƸ³§·îÚÒ±¾ã#ûÙó:–g”%�Ÿ0><)$�–™]‘:éljQ©„¯6Ëéz†¿ËÌ”Y±zù”iSŽiî^?¿~ÿBVNFVNfªôT…¹ò‚YÚ]úQêÇ…K”V¬^>Gq6Ôψxôxä3Œ &äææ‚·D"QIII”–»ÒÏÝ#¨Ÿ¯]»¶|ùr�ä�@èmk¢ÓQ?K„���íÛ·K¼Ù®£™œœlddäìì\__?0ûmii¹víÚ­[·úâéñäÉ“k×® /8xÉÍŽ~;‹çÿ©­€Ú»„½D÷MŒúÈ‚@¯˜G}Ô�ë”ÿyíÎä­»ïc™™3òh™;÷í0¹hÔ±þiSô�£¿uÚÔîý;/];Yºb Rîìî˜V’”GËL)J˜*=ÕÓïÏnô3òçì)¨Ÿ½‚='ý8ñ}|P-3>'ZVNêgD]VVöÂ… ˆâꪜB¡8p ´´tÿþý'NTTT3œUUU?~üòåËOž<‰èçµk×"ýôzUVVÎÈÈØ½{÷رc-Z”‘‘Ê“““�;¾uuõ¦¦&>ŸO&“Q(”œœÜ¸qã@S+W®õÛÚÚÌÌÌfÏž-++«®®ŽLب¨¨€ÊG�%‘H=�êêêöööfffé™L¥RMMMŸ?ÎÛt€Ï÷öö¾téR[êIxÉè' ]\\ÄØ0$$¤[ É‚Œ>‡ËŸÖ–Vܹ«ƒ�ѧ�ÍÈ¢&¿Ïõ'û�ÅöQC®Ý°ÚÖé*òÖÓïOéÓòh™ª»¶œµ4EÄêÏ“¥vìÙ–GË!!)ß´i“žž^{{;�N?pàÐϹ¹¹ÿûß;]¢µiÓ&###‹ÕØØ¸{÷n$nyãÆ�gΜAÊ‘þäççËÉÉ­_¿>88˜Åb!™ ×¯_o``ÐÞÞN£ÑöíÛ‡èçÒÒRÐO™””d¿³gÏÞ¼ysNN›ÍÖÓÓÛ·o(õêUpp0—Ëe0»ví÷L&“B¡888lÚ´ ´†¸Æijjjkk·µµñx¼Ë—/>|”]Œ ÅŒ>�Ïÿ�Ó—Ûk«gñ€Ñ’¢�ÍÈ©N Ëó ÍóͪJæñ¸}�þíð^,ÞykëtuÅêå@¯Ñ<„”ß~`ô³¥Ý%P¡ãßçÂ�&NH¥$Î[0÷]l(Ì®HݽçÖ�¨›÷¯¿ ÷Þ¬ºÉÒî’úùÀÑßû õ3"6¢ù ãÇ�¯¯¯'“É3gΚf,((ðõõÕÕÕUVV,ï&~cîܹÈE6''gܸq­­­à-¿ñéÓ§ &tÜ6++küøñÈDeffæ¸qãØlvffæøñãÛÛÿs-ËÈÈøá‡Øl6ÐÏß~ûmRR’`;&L@Úé4~CNNNH?ÇÆÆ‚×áááóçϬœŸŸïã㣡¡±cǤÐÓÓS(~ƒF£ýãÿÈÈÈ¢://oܸq@ñž={vݺuoß¾[IðïXTT”��AVVV_‰‰‰Áápt:]rýzüª=<<Æ�gaaÞžyòäìÙ³kkk%Úå�@SSóåË—"VVSSÛ¶m[ff&ƒÁxðà0<[?³X¬»£ÿ¹�IHgp6¤D÷ œ ùob)aù5-TPÞwýìððæÅÙÙ©àíF•õ¦—Î ñqYD!ýü!=bìØ±‚ÞtI�×*Û”Ï_9+ íêyoùÊeÈÛ­;Q‚ú9"ùýرcs«3zÔÏFç°*Û”‘· —(Aý �ˆ‡ˆGþîÝ»_½zåää$h޽fÍ]]Ýû÷ï_¾|ùŸÿü§à&"êg�0{ölä#D?WTTŒ3? B æÌ™ƒ¼mjjÕÂÂÂËÇŒTY~~¾”””P;!!!‚ë"EÔψGllìܹs‘.­^½ú÷ßwqq9wî2Wß©~NOOÿûßÿŽúÿÙÏår_¾|yäÈ‘)S¦lÙ²EŒÔ{ö;Æãñ^¼xabbÒGä”” SQ1üæÓDÑχž>}:˜IÔÏuuu–––:::—/_FnüýýW¯^�l¾gÏsssðdrÔÑÑÁb±™™™H�¤FGGçüùóV_1KL&óîÝ» >rwC¡P¼¼¼JKKÍÌÌtttUn{{»£££ŽŽŽ¡¡¡àÝ�@HII)++377×ÑÑyõê(/..¶¶¶õ‘(£wïÞYYY-X°àСC 3È‚…ööö;wîèèèàp8déqTTÔ”)S:æ¦$+W®Dú)8iO¡P®\¹ÚÉËË…¹¹¹VÿåÑ£GHe2™ìããC¡PLLLttt|||��rrrp8œŽŽŽ©©©x .ÕÕÕs+XAÉmLö $Cƒh1@”sze⇢�Ïå1‚.Ð}×Ï$jú†Íë6«nºqïêÁcû•æ¥RÁGzØ“³ä,l/Úܶ\½nåq�# Üæ¶å¤Ÿ&_Àݸwu¯Ú¯ÛvoEZ»ê`5aâAß9ÿÈ×?IýtËÅö±—ë¾Ã{fÎ’ÔÏ9UéÒ3¦aLôÝ^¸ ^�êç¨T¤Ÿ&éaO>üëþÎ};&OùêgD ~ôÄû¡–žÆáj7ï_Ï©LCÊß^iëkªßomo‰Ì]çÑ2óbpgO‡%¼läÏ×nGµëh¿�ñóôêúRðÓ·1~'�«ëÒÏQ© Û‹‚%a‰ÁºÚÇuŽx½{~ßãnèÇ·¢ÿ�P?C "ùT*uÚ´i3fÌ"0kÖ,WWW …øË/¿ég°°¨¨(..N¨5Aý ÖëihhäææÍž=ÑÏqqq“&Mº~ýzJJŠ··÷¢E‹€Ò8~üøž={²³³—/_~ëÖ-Pÿرc{÷îåË–-CÊ;ÕÏ<oåÊ•ÚÚÚ¹¹¹ bÏ?O›6íéÓ§ Å××wéÒ¥‚ú¹¸¸xâĉ¡¡¡ åÇ ðâÅ‹«W¯Ž��§P(ááá WH{{ûo¿ýæëë[UUUSScbb²{÷nQ†F�ø«­­½páÂÇûe]\\l`` 8›:¼E?8p ²²rÊ”)ÕÕÕˆ~¶³³Û¹s'Ríøñã/^쨟ÃÂÂäååù|þË—/×­[‡”;::Ý8qâDLUPP€}ºãTYYyêÔ) uæÌ™¨¨¨U055-))AÞâñxd²”L&Ÿ;w¼þøñãÞ½{Q(ÔÕ«Wóòònܸ!؈¯¯ïŽ;P(ÔÉ“'‘ [ww÷Ý»w£P(�´´4äŸÅáp ¢�Ç#sì¢Óß¿cEEEX,¶ï™µ©T*‹íÊ|X Š~Þ¿?8ŠLMMÑh4ÐÏZZZVVVHµ»wïîÝ»·£~~ñâÅòåË�ˆ�8q"b3mÚ4555pÃ%-- îCÝÜÜ�¨ûsçÎMš4I°þ¡C‡::Oêéé�Ūx<^¨þ‘#G@sss u…ˆŠŠRSSC¡Pêêê²²²Ïž=C>ꨟMLLÛŸ:uêñãÇù|þ™3gôôô:6.ÿ¬££cgg^GFF»ÒÏ sæÌAn`·nÝ*¶~ÔÔÔ¸»»O�:Upþ\DÀˆ0ØmYU_ÒØåÓ3YœÁœ†ÑBÊ™Çã’ªÓ"É�ÈRÁN�úêg¤·À#$Ñ£éïï�Ãኋ‹ûØNkk«¹¹¹‰u†¢ëgë+%%ôs\\ÜäÉ“Áò·ÒÒRYYY0Šèç––›ŸþOž<¹Ý(**O1fÍšÕ1ІB¡Lž<q,,,õ»ÒÏEEE“'OŽŠŠBê#1�êçgÏž)++ƒ¸‘¸¸8AýŒF£‘%Æà©SAAÁäÉ“‘‡Gd2,:`±XÀï¼���¿víZ7úùÏ?ÿD"£bbb¦OŸ.ž~ÎÈÈxûö-R¾uëV×Ñ+G¿�Õ’Yõ)<ß�LÏÄ8 h-¤œ¿œJ̦XJ¨ÐRÁNÑÔ"R__/ÿîݻǃù熆†ÈÈÈo¾ùF0�£Pý©ûŠˆ•«««;†^ P©ÔŽL]]]§·`­­­¢»S©ÔnöÛ+JJJÄnª«Ñoa6¥U|Œ ûÕ’8¼�Kc$Ȩ2ˆîT9³8Ìn– vŠã]Çç¾îƒ®E‡ãŸ§ïÓ;Ž”÷R˜ššŠ‘'2!‘H¦¦¦l°¼¼ÜØØØË˫Çã9;;ÛÛÛ ­$¾ úƒGGÇ#GŽÁÌápm4 ýJ÷£ßÜÞ˜RAö§Ôå Šˆ Ñ�*ç/ÏzzZ*Ø)$é4ötzqÒ ËÑáõ—^œ„Áb „€ŒN|||» àèèØ•á¶dff¢Ñh$lµ�¸»»[[[�¤'ƒ®Ÿ †™™Ùš5kP(Ô?ÿùϳgÏ644 n—F¢Œ~S{ýçò˜Hr@IyPTôH5ˆîJ9‹¸T°+<<óéYƒ®K‡þ_NeZøÇPS3‰/2l`0ÆÆÆÁÁÁƒÝHŸ666||߃Aâ`ûˆ¯¯ï… 'Þ‘Á ëgÈ "úè72ê’Ê> ‚Jë {5#*F˜AtWʹWK»�@ œ;wNCCCÒçÎ�CrŒB £*•jllìèèH"‘FÒ áh€Åb‘H$GGGccc�\¦�p¹\<_]]-‰~ÉbbbÒ1Mópçĉ}Ì ¦p8œN»¡¾­æSiTTÁÛò†¢¶˜ÑÝ(çÞ.ŽÀ»udÈÂ`0|||ðxü`ßÔBz �÷ññ‘ÈÌ3ƒÁ°³³»~ýºŽ�ohhH£Ñ$ÒÚ�‹Å–——v/ ƒ@yy9âÑ×+êÚè‰%‘Ñ…Á�Ŭ¢‡¯At÷ÊYŒ¥‚èŸ!dÈB§ÓÏ�;÷äÉIM«¦§§c0˜n²?k?~ìîî>ؽ€ îîî�?{óšÖê�Åá ßU6•J´_=0ì ¢»WÎb/Ž@ý �@ C2™|úôé�� 6ˆF£Éd²¤jÔ××ãp8ww÷²²²c*é.—[VVæîîŽÃáúî…No©Š/&Ä…P›îs¸D÷¨œû¸TpØõ3� AâââÐhtjjª¤,++Ã`0ééé’jphR__ÿøñc�Ë2Àb±�?î»xF 5WÆQBc)¡)h‡²At�ÊYRK‡P?C ÈPÃÇÇÇÈÈ¤Š–4ÍÐÐ0>>^R B #jSyLÑû8J½¥w)uÄfD‹¢œGÃRÁN�ú�@†,ËÉÉÉÒÒR‚æ���&&&aaa’j%T5•~(z÷±8¼¦u€b†ˆA´ˆÊy”,쨟!�a tçÊàp8‡Þ.Ókhh°°°pvv– ca[[Û… |}}%Õ 2ªàñy�ÅÑ…Á %‘µ­áZ3¸Ñ"*çQµT°S ~†@†#ÐzˆC§Ó �...q“ÒÒR'Y¡Ëb±¬­­¡%ÒGx|^y%ªàmb)qL›Å Ztå<Ú– v ÔÏȰf'.ÄÇÇãñx6›ÝcÍÔÔT4-Ùød.—kooïììÌã 3wYdhÂãñÊê ‰AI¥Ñ ŒÚþÞÝ€D‹®œGçRÁN�úvøøø8::v/ "qóæÍ³©†„„`±XÉÚÊñx]¹råòåË]\\:êg�]WW‡ü¿oß¾urrZ²dÉÒ¥Kß¼yƒÔ¿zõêÒ¥KŽ9Ò«¥êêꆆ†���¢o":MMMfff!!!ýÑøˆ^õF*C|dÛÙmYÔdBþ›R�W½‘ʰÙ6VkfÕ§ð|?2=K”Õ¢æœÃò|Ãò|3*?‰a — ŠÁ°8Þ ˆ "ž¶Û¶m2oݺuBó¥'++ëõë×cÆŒ©®®FÊ»‰ß8þ¼ ~^¹r¥‡‡x-ÿ,¨Ÿ����F8{ö¬ ~3fLUUUff&Pò÷îÝ;|ø0˜—œîVSSóõõúƒÁ å?ýôSzz:ŸÏ'‰ÒÒÒ���@NwÄÄÄDP?/^¼‘�\.wÖ¬Y Ë6�Gî5ø|þĉÁ|xxxøôéÓƒ‚‚ÄHJÒO?³,ëÚµkOž<é�ÆG0Ãúª×Õá ^#ÛÆjI¯L ÏÿºÌáŠá&­!†A4\*(6Ãèxƒ@ OÛû÷ïkjjÒéô©S§"AÈ---†††ëÖ­322rrrúöÛoKKK‘MD×ÏRRRÉÉÉàu7úùðáÃVVV‚ít¯Ÿ����~^¼x1X„ˆðêÕ+ ŸMLL�Íeee‘n„††ª©©M™2EYY�"¤Ÿ'L˜„7@UUõÑ£G@? þ›Ó§OOMM¯CBB<8eʔ͛7tûÝÿ?úãg–Ëå:88899I<ýʈG”áHJJBlÙlvTTT÷õSSS‰_A¢�ÄcëÖ­ &L°³³ëøiuuõ¸qã®_¿Þ—]|™l8å»§¼¼œ(@§ßChhèªU«úØ%‰0ìôL ³)­âcÙ¿°†ÄáöneD7q΢DÃ¥‚}aØoDÄÓ¶¢¢bÚ´iÏž=ÓÑÑA ÍÍÍÿøãäíwß}'x1½}û¶††F§­ éçyóæ!µ+ýL¥R'Nœ(º ¢~Þ³g�‹‹KÇnt£Ÿ\.7((èûï¿'“É‚åBúYII ‰mæñx³gÏ~ÿþ}÷úi? àûï¿/,5Aü̺¹¹ÙÚÚµ™b Êp,_¾|åÊ•àÞ¤®®9¼»BYYYEEEWWwáÂ…+V¬ÈËËëKutt:ÕÏ,ËÌ̬�±@ÍÍÍÓ§O±²“““œœœî9yòdÇ:P?÷‘ffcjE|ÙŸR›Ëåõ¬¢EY!Ø£A4\*Øw†éñ�ŒfD?m×­[§¨¨èïï�”`±X]]]&“I£Ñ°X¬�~öóó›7o�N§ÑhB6kBúùÒ¥K+V¬(..®©©ÑÑÑÔÏFFFyyy¯_¿^¼x±¾¾¾P—DÔÏ‘‘‘ÒÒÒ¡¡¡ÿ–¾���îîî ~WúÙÞÞþùóçàévVVÖ¤I“„Òˆég%%¥¼¼<B¼lÙ2 E»ÒÏ7oÞ|ñâÞÈÈȘ8q¢èÉÎ$þ3ûâÅ ‹öv /ä%ˆ¨Ÿ/^ B†:êçÊÊÊ’’Áeee$$þÒ¥K‹-Åh…ÅbQ(Ø/HWú¹+ …B¡ÑhBåÕÕÕ …ÉüËÁŠ‹‹»ÒÏt:]¨¾““Óo¿ýÖÕ~‹‹‹ëêê„ôsyyyUU•(탻W°B¡ïOR†µžijoø\A(®Ëï*€¹WÞÝDÃ¥‚aXoÈèDôÓöéÓ§ªªª` ªªê·ß~SPPغukttô©S§/»ÇÀÀ@AAaÅŠBfÂnnn‚ÉL&ÓÄÄdîܹkÖ¬y÷îݯ¿þ Êííí�ÙÅñãÇ_¼xѱK®®®‚þ(ª¶¶¶¨¨H[[xKKKð�@زe‹‚‚²eËìì쀾}øð¡³³3²ùáÇÁ\_qq±±±ñâÅ‹7mÚôöí[¡ý:;; ùo<|øøuœ Ò‘'$$¬^½zÙ²eëׯ—‘‘‰‹‹g·‚‚‚ŒŒÌ·ß~‹„E�Ó¿µµUCCCQQ…B!kºÑÏ¥¥¥«V­Z´hÑÒ¥KwïÞ�èçúúúÍ›7ÿúë¯ÊÊÊß|ó�‚‚•+W@ØØñãÇUTTfÍš…,ÇÈÏÏWTTܱcǶmÛfÏžíåå%ÂvÉÐ3�Œºä²‘�¥õ‚1b»Òu4ˆ†K%Å8Þ �чˆŽˆú9***22RII ÑÏmmmß|ó Äårúé' )…ôó¶mÛî߿߽~~ðàRÊ”)ñññÈ[Ñõó† Àº×Ž´¶¶ØØØìÝ»wÚ´iHy§úùÇ´¶¶vÿ/³fÍ�ŸœœœV¬X�”ƒ¨ð… ZW0þùÌ™3àõ‰'s˜ &\½ziGVV6##•F3ú–œÇçeT&†�^}.�…K%¼C ÃxÚ/$2^ÙÙÙh4º¨¨H=Õˆ®ŸAºywww Ÿétú˜1cÕååå‰D¢�~æñx3fÌ¡û"êgYYÙ> oE×Ï‹/îÔ &88xÉ’%¶¶¶>| ›yÕªUBaÛA™´´´o¿ýVhua¯ètd9<­¥2›ú9ªðm$9 £2±ª©TR‰K$NWqÎ5-ÔøbBLQHU“¨Ë–BKÅ0ˆ†tÔÏȰÃÔÔ”D" v/ "A"‘LMMûÒBUUƒ²éƒˆM¯ô3ŸÏß±cÿìíí-##ãäääîî¾páB[[[P®¬¬|èÐ!++«C‡M�:¬×qÅ¿üòËÓ§OÏŸ?àÀAý,''wãÆ�‡.X°@H-?}útΜ9ÏŸ?¿}û6ˆ‘FÒÏEEE222'Ož|õê•££ãÂ… Alü±cÇ<loo¿yófAýÌãñ-Zd``ðîÝ;ggg0Ï/--}åÊ�ððáC4 *;99-X°@pÞ¸¡áË,îÅ‹çÍ›÷ðáÃ[·n-^¼ÑÏ·nÝÚ¶mÒðóóËÍÍå111ÒÒÒÖÖÖááá<@R íÚµËÐÐ0((ˆH$¢ÑèM›6õf$…éqd[YÍÅuùI¥Ñay¾K" j²uÝo2`ˆ²B�ÖRG ‹)z_Ý\.J›]-Ý Ò P?C ÃGGÇÁîD$}||ÄÞ¼¶¶ÖÈÈY‡é;¢\õ\]]‘8第,Á@©©©çÏŸ766ŽŒŒD ÿüóO+++{{{oooÁ•€­­­7nÜ000ðóóknnF¬]8pÿþ}ggçÓ§OwÌõÃãñž|(è$¢ë.�Co©Ê©N‰. Ž û§W&V6– –™[o½5ª›ËcŠÞÇQÂh-•]Õé1«`�Ñ��úv0 cccä¹0dÈlll,4…(:ÍÍÍgÏž ’t¿F5Cáª'ÿzôèÉ“''OžÜ¸q#XB8`{ïËæ\·¦…JªNûPô.<ß/½2¡¢±˜Éé—,E}Q΂T6–D¾K(‰¨m¥‰—U°£A4DD†Â/ ƒáããƒÇãÕ!C<ïãã#öÌ3›Í¶µµEž}C$ÈP¸êeff"1#Œ˜˜ÿ;À»–àȶ±ZKë ?—džåùÆò陒𤕔rFàñyå ”¨Â·ñÅáÑ…ÁbdD ¢ûè’7Ú ¿$AàñxNNNB& ‰íkF$§ïF7áñ¸µ­Õ¹´ô˜¢÷„ü7iË(âé^‰+gAJêÈay>áùo’J£Åˆ?áñy5Ùdÿêæ‘y[×@ý �@ CŠ'Ož\»v j¼~Ú׌H*++ÍÌÌúu v[YCQJy\Xžo%,�–Q×F%ì¡_•³àRA�[Z_Y˜\öA k‘ú¶h-:P?C ÈÐÁÛÛûÒ¥Kb~@zÚ׌HBCC�œœf_<¯®•–Gˈ¥„ò}S+âËŠÚ; ~èWåÜÕRA.�[\—Aø\ÛÛ¬1Ð Zt ~†@ �!BHHˆ™™YSSç–S‰íkF---†††ƒòX¡�Í(o ¤VÄòßÄRÞçÑÒk[i<¯¿•s�K¹<¥67‚ìŸZß[1 ¢Eêg ÄÄÄàp8�ÏÒ¯@ûš‹ÅÊÌÌÄãñƒÛŸW×FϧgƽÉ}ý>×;±4ªŸò³eì—SXCŠ û§U|ìÊ ºS At�@ý � Y ÃÆð‡Ã988”•‰šl7%%ƒÁŒTO†!<¹FçÎ�#ƒ}@ñ£52©ÉÅuä´Š�áù~ŠBrii5­Õ’ *î*«`7p¸ì‚šìðü/™bÚX-"lÁ‡Ñ=õ324�SdÃ:�N Ðh4’Æ®rssÑhtAA/.ˆdèÐM´F}[ ™ž_LËóý\SZ_ º‚¢Ç¬‚ÝÃæ²Èô¬ð|¿ÌªOm¬V¶àCƒèn€ú‚ÀÍ‘A||<�g³ÙÝÔ)..600ÈÌÌÀ~A É zœ3‹Ã¬h,N¯Lˆ ûG¾#U§Ö´PEŸ”1«`�°8ÌúùÚµk(J[[›JýOÜ�™™™î)**BöknnN§Ó­¬¬P(”ŽŽRŸËå:99©ªª8plò†Ìž=ÛËË«cÿ9ÎÝ»w·oß¾wïÞ€€¤üìÙ³µµµ–––(JWW·ºº<ÁÇ`0[·n�1chÜÐÐÔ¯¯¯···ß·oßÖ­[ïܹƒÄŸ9séII Ò¾™™Y]]�…… …:yò$�NG>zõêÕž={TUUïܹÃáüçy%“É_޾¾þåË—ÅÓÏñññ†††4­·ÛB :DDjkk;>_…ÁRÎÌ*(‡Ç¡·TeSS¢ ƒ#È•‰•�%Yå×À¨M*�&•Õv: 2J ¢I$�VWW×ÓÓƒ¿NÈ�BýüÝwߥ¤¤LŸ>½¹¹YP?ëé驪ª&''ÇÄÄ,Y²äÎ�;Àm˜H$^¹reéҥį|øðÔ_°`Áš5k=z·cÇd×?~5eddä)**nܸññãÇqqqÛ·o?qâ(¿qãÆÎ�;kjjˆD¢´´tHHHyyyaaá·ß~Ë`trIÒÖÖÞ¹sgJJJttôÂ… ‘»ø9sæ(++?yò$..nëÖ­ÚÚÚ_¦VZZˆDâåË—W®\ z êÛÚÚZZZ¦¤¤$%%-[¶ìîÝ» <..Ôœ:ujjj*²_yyùÍ›7ÿù矱ÿÇÞ}Ç5u½§¶**Ö *‚ˆ{þÜ»‚huTë@F·2Që¢u/´ÐªµØ‚Ö:ŠŠ"3 Ô=I !�$�uó«žö6ß0` ŒçýÊÉÍɹ‡Ü(Ÿ\žsî›7(B£í?üðÃìÙ³ãââÒÓÓ׬YsàÀ´}ãÆ�‹-Š��ñâŤI“š–Ÿ÷îÝûñYî˜`-t "©Tjmmݨ—h097ÇU•ñEUù\JBÁ»“Ò1ôjYfE ç#ûä Êâ„pª?³‚¦\óÜAˆ>pà€……ž}û4=ÀÿP1?—––ÚØØœ={–H$¢üÌd2;w&‰}ûöÅO¥z{{×Y¿�_Å#$$døðá Œ��òóóçÏÑý   ‘#G¢û‹/þ믿Ð}SSSTÛ«W/åÁÓh´®]»–•ý3k;<<\WW�Ð066Æ‹]ÆŒƒ¿êÁƒ Ôo0™Ì,_¾\aû�!CòóëׯÑ}ô¾ñx<<âr¹ÜÞ½{cF&“µµµ9œ~ã4¹~ƒB¡4öU�I:@uªZ4˜œ›ûª‚u’bÒ²j©$9"÷U(Å7µ(¶°’þ1{çðÙ±ùa¹/ +éÊ)ºÝ/`aañêÕ+Mð?TÌÏl6;77WWW744åÀððp¼�@ ÐÒÒ***BëËÏxýs||¼üËåüŒŸ»Ž��:t(ºâÄ ‹ÚÚÚœœ===´S2™Ü©S'T¤-/((H>¨WTThii¡8mllL$Ñv"‘hllŒ7«3?Óh´o¿ývÞ¼y[¶lY¿~½‰‰‰Båü‹îGFF¢üŸššÚ¹sgS9ÆÆÆ�ÀßßìØ±øk?rþ hx÷€êTù´h697yª  DÕ .5± *(çi4=˜RšÑäèÊø¬zHdÞ«bžâú�í{�說ªíÛ·ÃÌAZÕó³L&Û¹sçŽ;P~ÎÌÌìÞ½{mm-jC¡Pºté‚—OøúúΞ=[¡uå稨¨Y³f-]ºtåÊ•x‡† 2äÁƒ }&''÷ìÙÿ»|ff¦¶¶¶X,n8??~üX9�5ÊÛÛ»�ªäg‹ÕµkWOqþNDDÄ€ðJ?ÈÏ-Þ= º†?-OÎêš*¨.ïNJóK²Ù)‘y!dŸ”˜ÂJºPRÛØ~J«‹‰´ ¨¼×,S¡ÿ�_ :88ØÙÙÙÒÒR£«Œ· ï×Bÿ¡9ÖB ­hT~ÎÏÏïÛ·/^ÿýèÑ£‰„Ïç¯^½zïÞ½øîêËÏiii}úô)..ÆÇ�aX÷îÝÑê|_~ùeÓòóß~Æ VVV¨Û²²²·oߢÅÓˆÖ ÓéS¦L�üÜšãÝ{ýúµç{òìv,***--Mƒðöön™¦ú>-OÎÍ4UP�jÄ|77‰ù&(ç)‘D.M/”6jIç’ªÂ7´@"-�]U¤°½É D{yy8t �ø*³(9‡�·†oYE)�^<رsGFFFcßjÚׯër���ñõŸY,ÖúõëuuuõôôV>sæLß¾}�ŒŒ¦L™Âå¾[ÝÈÌÌ Ï“©©©sæÌQØÑ‚ RRRð‡¦¦¦ñññè~rrò¼yóÐýG�õêÕ«_¿~Fï­\¹¯yðàÁÈ‘#µ´´ôõõñù}EEEk×®EãtttÄO’/X°åa™L–˜˜¸`ÁùÁœ:uªo߾Æ ›2e ʺ¿ýöÛ€FŒñõ×_ûøø˜››+ŒΜ9òV˜7o§ãããMMMÑýêêj{{{}}}##£É“'ãߢ££Ç�7`À€ùó绺º:t胇Fäç�¡Ê»÷êÕ+|­•³gÏ¢oˆ ðôôtqq™?¾£££úFÚDiii6J¼¼¼Ô¸ ›‹/Ö÷¬§§§“““òöK—.)lyöì> . /ÂTQQÑ©S';;;G«¼_Õ)ZZCrn™©‚ê‚a‡ÏÎa§¾¡½&?K.ŒfVÐTëX¼‚¨¼€hzpiu1¾±i D“H¤½v{Sé Ï¥mëöúÍ‹�»vÀYhе¹ÄÅçóG��Ϭ©©155ýùçŸ5=®V¡ÍÍVE•wïòåË‹-"þþþNNNzzzª,xôèÑÖ�Ÿ9Z(æÀ�³fÍB÷Éd²wÑp~=zôĉ®1*•JµµµZž:ujåÊ•áùóçûöíÓ××Wq=ó´´4ômýƒÄbq÷îÝUiY'ùOKkHΙ*¨FµbAAE^rat0ùéZ`;­œÏVeÿ"#2÷U =¤ŒÿÏ—¬&,}ýÆõûO×xm‹·»Þ¹|¥éßCh»Ú\⪨¨èß¿?ª»�J¥AAAÆÆÆêÍmW›;š­ŠŠùÙÒÒ¸`Á‚û÷ï£ûEEEW¯^uqqÁÿÈ‚SÈÏ555^^^øb5¨|(++ ïçòåËçÏŸG…aaah{aaáÕ«W¿ÿþ{ùR"‘˜ŸŸŸ““söìÙ+W®àß+ÑŸlΟ?ïâââçç§°.ß­[·”W�),,¼råÊ÷ߟ��€oôóó+,ü'„”––âëÞ eÕŸ?îââråʼ ÒÆÆæÊ•+h<×®]Ãÿn%“ÉâââÌÌÌ\\\Μ9ƒoôöö¾yóæ§Ÿ~êù/”~O�:µk×.¼ÙÔ©S}||Ðý‚‚‚Ë—/ÿðÃø�d2�@À{�_&722’Édfffž9sÆÕÕ�Öýõ—»»{—.]ðW5özCèÓÒJ’sk˜*¨.˜ +”æ°Óˆ´  œ§ILbAE^Ã'“1VXI�È}—V.øg™ýF-íxÀ1:#BãY´-ÞÈѶv¶ê;þ´m1qEFF®[·nìØ±3gÎܽ{·Â鬎¬-ÍÖ£ ùyÆŒ�?Fõ9zzz'Ož¼yóæ˜1cÎ�;'ÿ*åóÏóçÏúô)º�a˜±±1J}t:}È�!¿üòËýû÷ûõëggg‡. «§§wúôéŸþyôèÑ.\@¯Ý¹sçºuë–.]zéÒ%333|ÒnLLÌàÁƒoݺõûï¿oß¾ýرcò{WÎÏÑÑÑzzz...?ÿüó¨Q£®\¹‚¶Oš4)((Ý�‹‹344D÷«ªªæÍ›gffvûöísçÎ�;•EÙØØ,]ºtùòå—.]255ýâ‹/ð]:tèÚµkoß¾�8q"¾ñÂ… øôÓO]þ…Îç+äç¿ÿ±£õ»"""ôôô~øáww÷‘#G¢5çe2Ù“'OÐË'L˜ ™6++« 6 ñ|ñÅfffhû¹sçöïßß¹sg|¿ò_=T±u‡M+Iέmª ÕŠk˜´”˜`ò³¨¼×ÙìT¿¤¾¢nL†1+ò©þñŒp4‹Põ¢­­­HũϢmñFb¥Y[[5Ïñ UƒkF´"‘¨±×tò[¿±{÷î#F Úøyóæá×þ.,,ÔÖÖ¦Óéø«”óó‹/ðlŒ×Æ_¾|yÛ¶mèþñãÇÏŸ?�îÏš5 �…ÚÚÚè”ïÎ�;7n܈þÌ]VV¦¥¥….sùã�?š˜˜ uf”)ççéӧߺu ÝÏÏÏ×ÖÖF§�ëËÏ'Ož433Ãÿ¼ŽïÈÆÆÆÒÒm/..ÖÒÒB§|1 344¤P(†éëëã'Ûß�8e0:wî¬0B¼~ãÅ‹666ãÇ�GKýLš4ÉÃõÉÍÍÕÖÖV(�Þ´i“B~F×EBïÛ'Ÿ|R]]�æååuëÖ­Î÷GgÝOj<9·þ©‚jÄ”‘KÓ£éÁA9O™oÜ\�HqµRTÎàæ¨/ "+kÊU\ ÚÂÂBãA´íÞ༠è˜àšÅí‰D:xð ¦Gц©˜Ÿ���Ѽ¶ü±¢¢…Ã.]ºÈÿdÚ´iòKÄ(çg ÃÆ��–^177G'±e2Ùýû÷MLLPþ477GQP"‘|öÙgTꚟû ]*(::ZGG�é?~¼‹‹ Þ¦¾üÿüóÏhü555Ÿ|ò ^O‚ ª®+¡œŸ¯]»†¿çZZZø%Ÿ>2?k<3´­©‚j$”ÔVÒS‹bCÈ>‘y¯H%)eÕ,…" )&Í/§„Qü™Q¼Zü ù€ÆòööÆÏ›�6íÆ�øòÔ  šP¿�ÓÑÑ‘_ºpìØ±~~~øÃ:çzzz~ûí·ÇÐÐÿ�P(6lØ´iÓæÎ�kii‰Š"0 ëÖ­›üºp£F�ò÷÷o ?#•••>>>kÖ¬>|¸ü¥íò3†a]»v•_:føðáèÒ™ÿ÷ÿ‡Tùü¼lÙ2¼vB^}ùÙÑÑÑÜÜUŸSèG¡~‹ÅŸ~ú©üòth½Jœêù™N§+Ï[T�f3C›ž*¨F5JiF =$(çéÛ‚È|.U ªÆŸ•bRZyN(Å7‰I¬¬á6°@4ägÈÏ4VMM�££#~kÐF½|ùR~i>ГŸ7mÚ´sçNt?<<¼wïÞòóÑ.\¸°aÃ…—ˆD¢áÇŸ>}Z¾8ù÷ß?räˆrÿ6lÀ×- íÛ·/:%[_~Ž��ÅÏ9 ‚Ï>ûLþô²rýÆ7ß|coo�îõë×Õ9|ùå—(K¥Ò½{÷âùùÖ­[£F�Bµ"¨Ü•pÔ™ŸÑµ�ði‰B¡°W¯^ø×�ÚÚÚ®]»ææþÏŸ×ëÌÏ2™låÊ•øYüýýuuu>óªçg>Ÿß¥K—üü|彨Bƒ™¡ÝLT#‘DXT™ŸZJñ�È}™U’TZ],ÅÞMÑ•`’<)”â›R“Ï¥Ö¹@´óó£Wœ8 •zì‡Ãß­ÁÛá°­ÃaÛC'ëlðÐÿÞÉ ßÕ÷òs׿Œñ‡ü @ÃX,–££ã�7H$ÔB·-"‘ˆD"ݸqÃÑÑ i>&?³Ùì¹sçN›6mõêÕC† ‘677·ÿþË—/Ÿ?¾üå\]];wî,ŸlÓÒÒú÷ï�.ì¾qãFgggTç\RR2{öìéÓ§¯ZµJþ¤k}ùÙÍÍmÔ¨QëÖ­³±±™8qâ¾}ûäÇ£œŸY,ÖÌ÷V®\i``@ Ðv___mmíE‹͘1ãÞ½{x~Æ0ÌÑÑqÀ€k×®511™1c*«¨3?GEEȯE¶iÓ¦'Nà�?®¯¯¿eË–¿lt‰¥úòsaaá´iÓfÏž½bÅŠ¡C‡FEE)4P=?Ëd²#GŽ 2dË–-&&&Ê]5L#™¡OT£ÊšrjYfL~hPÎÓF½œÌUI¤bjYVÙ7©�MVX ºQù98þÕ—_-Ò7 y²jýІyÑý¬ÓÉ:=uêl`¾y}·îÝ2˜Iu>;yÚ¤_ü ù€ª©©ñöövrrÒì%AA899y{{Ùç�§Êo�ÊÊJü¤«²ŒŒŒ˜˜ü¢ö /$ gYŸ>}ºbÅ ù-G޹téRRRZœyÆ ò£R¬ Õ`#t:ŸÊ'‘HÞ¾}K ð« áx<^�ß¶ÒÓÓ•ÇÏd2ÃÃÃÑÙlTŒ�ãr¹éééø–ÒÒR…ñH$åÝUTT(Ìû£R©ïŸËå6° Fjjjll¬PXGé›ÍæñþË–¥¥¥ò ÑhòËþ°) �@øàup”µ|fè8SÕE,óiEqa¿ð\ÿLVbq#§4=„ìC¤…P|ð¢-TÎÏ$Vª¡‘Á¡ŽÑYÏß~½a•”O;=254,10,1°S§Nž{¡ûè%«Ö}ÕÀ)åÌÂ东(üa}ùùð郋—›á÷8î´Úöá1Æø×—Ÿ3˜Iñ9oê{!äg*jÉß555©©©#FŒxóæ�üö‰'â×”‹Å›7o–ŸjZ�–ü´tØ©‚jÄ«­È-ËŠÍ Êy—Oˆg„æxå?2øe”ïæ�V¿]ÿà¹Ú÷²{�îéÌDôpô¸QžO=Ð}bfø‰óÇÖY¬Ù¼Ó*€ø¼áüLH Ä÷«P¿‘@&ÚÞ»ÎbÍOž7¦Ïž ù€*Zò·ÀW_}5yòd|Ù \HHȤI“æÎ�kjj:iÒ¤“'O*œ/­D‹}Z`ª zI¤b¯ ½8>Œê”ó4€ô(0çéÁûTÌŠ9ìôé³§Nž6éÞ³»“Ÿ£³".ºŸ½è~ÖöÐnC#ùüÜ­›¶Éâ/nÝs;qþX�O^?@O�;ÒãÑ­÷8¨WŸ^YE)è|ø´YS÷±¿ûä—ç|Þûsbfxù™˜Žö»÷À®a#Œð퉹1FÇ®³XsëžÛ»­ÝºiC~ ŠÖó[@ 4örx …µÌ§¦ 6«*a%¹4- û‰_êªççz¼ýá½½úô3~ôÍ{nMËÏøíÉë ù¹ÿ€~$Ö?sÙ²ûÛu–kÑ};§=¨fãô¥ãk6®Vî*­àíøIc¯Ü¼Ð@~ÆoýïÉççïÎ8O›5õT×*’H$VVÍ{Í5˜*ØXUÁ9ϳ½�دz~F·TÆÛç�õü\çÜõïÕ›ŸåëŸÏ\;=û‹Yè¾oØ_úƒsØé —˜üìõ#ÞæYÈ“¯7¬š9oÆ¢e ìrùDòó7›¾¶=´ò3€Ærrr’Ÿ @}˜L¦��]óõS›[µ�ŸOÌñ&ÒE¡êõÏ ·Ã§˜-5m¾ü¼ÿˆý²ÕKð‡C õŸ…<éÛ¯OJ~Úò:úÅÀÁz>¡OÐÃ%+Ëçç XUó³Å–�›wYC~ÐXÁÁÁ‡V¸TÊ<==ñˈ«Lln©8›�œó,˜ü,»$-­z~~èoƒõºØìÈvz:3ÑlÙÂ�ÛÔ›ŸuzêøGú éÁC˯}·uïæYóg~ùÕ"|‹ûï×'N™€Ê{þÔÐÈ@>?ÇåD}úi'báƒùÙí7WÝ�º¨vúYðãÞ}zC~  ü¼¼ììì ¥R8õþ‡T*-((ðôôtppàr¹jï¦ 6·ÂJzåyl~XpŽO��oW=?'Óâ,·nêù¹Ž¾Áà>}û,[½$…ÿÁü¬%gÊŒÉ çç1ãGa6ì„1½úôÚµo»|ã?_xiii]úé¾%…?}öÔ¡Ã §Ì˜üõ†Uë,ÖÈççvú·;,{õé5aòxùò åüœ]’f½ÝB§§ÎøIcÍ–-œg2ò3Õ‘H$777'''+++Í®ì Z!;;;�æÏ0U°Yñj¹1ù¡DZPJaL8ÕŸW[!ÿ¬E#ë72˜Ia‰�o©1�zU£nÄÌð¤¼XG¥…&�‰õ=CŠ”_”£�[%ºÎ“Õ�ŸЪÀTÁf%’3Y‰¡_''–ñnågåÓû�ÍÏpƒü M�©‚Í“a nn(Å7“•Èá³ Ô9ì ž@~†ü €Ö¦ 6+® ŒH ŠÉåÕr +é!dßb¹‚g�Ÿ!? •ƒ©‚ͧV\“ZFy^XIÇd©$94N6†ý—“™´²/Kå‚ç¶ò3€ ~ ¶' M˜*Ø +éa”ç©Eqµâ|#†a™,Tð\©ÑÑ5#ø¯@‡¿Û“úŽ&Ll¼ZnL~(‘Ä”ÉoJjbß}ïjܸqaaa'N\²dÉÂ… ãããe2™««+z¹¾¾¾|c‹5uêÔE‹YYYéëë{{{ãO�=š@ L˜0aÉ’%¦¦¦è¬5ƒÁ@oËþýû§N�*ÿ#«h·ýN˜*¨Fe|VdÞ«FD}50y!dß’ªQð¬ò3€KÅüìáááìì¼oß>ùü¼}ûö-[¶ 6YYY:::ÿ\*âúõë½zõš3gÎÓ§Oñ~Ž=ºdÉ‘èÝ߸ÙlvÏž=åsoõ‡R“B¡PKKK¡~©3?Ož<¹¤¤eÚO?ý”Éü'ð---…ú�Ó§O¯_¿]ƒÏç6ŒD"¡§Æ�7qâĬ¬¬:Çéàà ŸŸ-,,öîÝ‹î'''Ë×ÀŒ=zÒ¤I e0¿üò‹üyûÖ�+;ë~¦ ª…@ÄObéþõeã ž_Uw˜‚g�ŸtX*æç_~ù¥´´´ÿþúúú(øéë뇇‡ãÍæÏŸÿûï¿ã¹\îÕ«WÿncjjZ[[‹ò³££#Þ`áÂ…wîÜÁ6k~Æ‹Od2™®®.:Ï\_~ž}âââð‡S§NÅ_;zôhùÓÑ“É;vì¢E‹®\¹’œœ\ß^‘æãI1)¥4#„ìC)Í�ÖS=^+®‰yWðÕ¡ žÀ‡ @‡¥z~F eìÛ·oĈ(?ëêêFGGãÍ-Z$Ÿ‡�g``€ÎB+äg“»wï╟E"Q“óóÀ�ñtZSS£œŸ'L˜pðàAù¥<ð*èqãÆEDDÔ÷F)äg<¨Ëd²9sæÜ¿Ý=zô›7o”{�H$ááá'Ož=zô—_~©°ÀÈA¤ùH%UÌpª“(ñëkSQà £>§”f´ìÐZø°è°•ŸËËËõõõ���Q~^³fÍÑ£GQ‹¥££“™™ùw0&x�„T*3fÌóçÏQ~Þ³gÚ^XXؽ{÷œœ|/ׯ__¿~}�PÎÏ2™¬gÏžxY…¼Fåg™LÖ£GùaÈd2;;»íÛ·×9’Fåç%K–üðÃè~AAA·nÝòòòÐÃ:ó³üò×B¡°G�iiiõí«Niš¬ZÈK`DDæ½*ã74ïòß‚çÂZ+6V£ò³L&sqqÑÒÒBù™J¥nß¾ÝÅÅeäÈ‘xVtuuíׯßÖ­[Ož<9gΜ… ¢šç£G�<ØÜÜüÔ©S#FŒ8räˆü^222zöìyäÈ''§ôôÿYÍ Îü¼gÏž3f¸ºº=zÍU|öì™���‰‰É€lllvïÞ�Z6œŸwíÚ5sæLÔ*Gáp8“'O^µj•»»û?ü°`ÁüwîÜýû÷®Ï’�� ¼®²D"ñóó»téÒ£G�м¼ú®Ÿ’ðþÂÇ�Ë~H$___Ô~X(úûû_¼xñ�?þ�_:ÏÇLJŪ÷üdll¬BÝryyùýû÷oܸ!_È�¢>šÏ¨àï¯$¿ýöÛ… üüüž!Ò4Aa%=Œò<µ(®V\Ó@³wÏô�Df”¸®%ì:&ø°è°Zò— Bý3P;ˆ4ªãÕrcòC‰´ ® ¬á–\A<+ƒ€ òs{‘F"‰0“•Jñeps1Y½ƒ›BöeCÁ³ø°è°à—`{G³a˜ cpsC)¾™¬Ä^bäéÅ ‘yPð\7ø°è°¬­­›Pg Z!‰Dbee¥éQ´^\A‘“Ê«U¼Æº²Z±à}Áó(x®äg–òb �b2™vvvšEkT+®I-Š £|¸ªªJÓËÓÓÓÃÃCÓ£h]0 £q²CÈ>ÙìT‰jg’ÿ)x®.jþѵm�ŸtX†yyyÙÙÙâkÍ�¶B*•xzz:88p¹®Lè8Êø¬È¼W Œ ˜¥ÿ<@Á³* ?èàH$’›››“““•••hkììì<<< <ã"~“Nõ/©bªø’Z± šœÄ|£âijù �bRJiFÙ‡Rš!ÅTýcJ¹  ž ò3@[WRÅ §ú'1‰_õW1¸T(xnÈÏmWµ�—ÀˆˆÌ{UƯ÷êêÊÞ<ÇGåð…0¶Ñ ?´E©8›�Bö¡q²1ì”÷oÁ3 ž›ò3@›SXI£+2ïU#¢ZÈkZ5bþ»‚çÂh‰T¢îÑÈÏ­…@ÄObéþ%UÌ&wÂá³C)~y’Z‡þù@㤘”RšBö¡”fH1i“û¡—“C)¾eÕ�¸–7h,ÈÏšURÅ §ú'1‰¿É�H1IjQìÚk�¨Z­£Š ?hJµ�—ÀˆˆÌ{UÆÿ¨3Æ5"(xn9�ŸZžD*Îf§†�}hœl kÜÅü[𜭾Ñ�†@~ha…•ô0ÊóÔ¢¸ZqÍGvE/Ï�‚çù Åðj¹1ù¡DZWPö‘]ý[ðÏ-ƒËåÚØØXüËÆÆ†ËmÊ!€*Da&+1”âËàæb²�*Øø·à90¥0F‚AÁs˹ÿþÁƒ-,,öîÝ{ÿþ}M }Âdƒ›JñÍd%Š$Â�ï�Ã/ ¥øÑ à¹Åq¹Ü­[·ÂÉg€æÃ”iA1ù¡¼ZõÄ-*xþ¸õ:@“Ý»wÏÒÒò·ß~Óô@Ú›ZqMjQ\åya%]-J0IJaÌû‚ç¦/ >—Ëݶmœ|P# Ãhœì²O6;U"«¥O�ˆÿ ž[:]=_ˆ€L&+ã³"ó^%0"ª…<5öJñ¥•稫ÃÖ�Ëåþêñë^Û½@5vö¶×®]-((Ðô¡P•@ÄObéþ%UL5vKãd‡Rü8ü5öÙÊq¹\{{ûo_�J #±ÒrØépûà-.ûÍŸ{»ví‚ €ÖOŠI)¥!dJi†“ª«[TðL¤Öt°‚ç_=~u»}C㉴-ÞîþùëÕkW5}RRÅ §ú'1‰ê�Ö'U¿¡¦ÅJ;^Áó^Û½oÒÏ¢mñ–@޶³·Õô¨[µ�—ÀˆˆÌ{¥öÕäʪß<Ó;RÁ³<+++RqªÆ³h[¼‘XiÖÖVš>€Š$Rq6;5„ìCãdcØÇ^LPAÞ?ÏlõvÛ†XXXh<ˆ¶Ý›………¦ Àÿ(¬¤‡Qž§ÅÕŠkÔÛ³D*I.Œ&Ò‚:ZÁ³ÈÏ�ŸÐ>ðj¹1ù¡DZWP¦öÎß<¿î˜Ï ?C~@['’3Y‰¡_7“©¹`C®à™¬öžÛ¢ÖŸŸI¬Ö[ž ùš…É077”â›ÉJI„ͱ‹<©ƒ<+ø˜üü4èÑE÷³÷žÝUØŸóæú�+ÝÏ’å·§¼ýÙëÇ‹îg}Ãþ’ßîö×E÷³nw¯%ÓâºÚºwsï>½Ó™‰M¡Ûo®úƒõéöü\ò3Ú® ŒH ŠÉåÕr›£ÿÿ žÅºàYA“óóæ]ÖC õ-¶l3~ôâåfYÿ.âáö›ëç½?_ºj‰åÖMºu=ÝBÛ½êÔ]°h¾Õ6‹¡ÆC¿;㌶ïÞ¿Ã`èëíKV,î¯Ûß?ÊG~/�níÚ·=»ä£.ìò:úäg´'µâšÔ¢¸0ÊóÂJz3í‚/ªŠÊ{�V§ÆK®´MËÏ^O=úè›™ÃNOg&Ž7ꬫK;=,1°{�î÷}~CÍÞ¤‡¥2Þæ°ÓSòé}éøß‰}Ø#ÿ(Ÿ7éaŸ|ò ÊÏ(À£ÛÑï›-5m ?ýþð̹Óïûü†nûœíÐ8!?@äåååä䔞ž.‰4=ЮˆÅb�°k×®ÌÌÌ�éGŠI)¥!dJiF³–"¿/xH+އ‚gy©$·,+„ì›V'U7¹~ãë «líÆ^p;;eúÿå°Ó·ìþv½Õ7øök·/¡\êrùÄäi“î3�™húå‚ Öë>>?Ÿ¾tü ³ù äg;§=ãÿoœÃa[üvíö%ÈÏБH${{ûêêjM´[»wï.((hÚËKª˜áTÿ$&QÐÌ—ü+­.!ûæs©Íº—¶EŠIéåäPŠora´|ÁLÓòó�_¯a”ÁLBç™Ì9tÂ1‡�þèÕŸ÷êù&=L!?G¥…jkwEõè†æ¦¼ ŒñÇ7ønßò¯—~|~^ºjÉîý;ð‡! ÚÚ]廽uÏmäèM«y†ü 퉛›[`` ¦GÚ9???WWׯ¾ªZÈK`DDæ½*㳚g\ÿ¡¢‚gAis鶴À0¬€›K ¾x[©¼6`ÓòsvIÚ|Ó¹óMç^t?»fãêQcG¦ÐãÑS;ì· rüÜÑﯜš6kªÅ–�hûYW—Ï{¾ÏÙî¢ûÙ¯Ö,[¼Ü,‡�~ïÙÝÞ}zoÙýíE÷³N'ôéÛ_»£±ù¹K—.+¿ùÊý÷ëÛl·èÔ%f†ã¯Ê*JѤ»{ÿŽ[÷Ý=Ÿz k²,\b2wÁì[÷Ýï>ùåÛ–�^ýù: C‡iz �ãp8ª·—HÅÙìÔ²�“�a꿘 Â¾’˜Ähzp-<ÿ«¨2?"÷eƒPßeЛ–ŸÑ4½3×N¯³\{ì‡Ã‰¹1òOýîýëæ]Ö¬×]½yQþ¯Oè›=›×Y¬9wýûÌÂd´‘�tðøþo6}½Ã~Û‹ˆg {‰H 9qþ˜üyoïÀ‡9ìô“¾‹!E&ÓâÛ¢ülhdðèå} sÛƒ»£Ò—°{åkµÍÂrë¦û¾¿£-$VêÕ[—,¶lÜ´eƒÛÝkM»Ê!ägh묭­%‰¦GÚ9©Tjmm­bãÂJzåyjQ\­¸¦™Ç%ã ß<§CÁó¿XŲ¼€hzp¿¤�fMÎÏ­ê¦P¿Ñb7ÈÏÐÖÁÿä e¨òIãÕrcòC‰´ úN{ª»º(„ìË€‚ç÷J«‹‰´ 7´×ìªÂ6†ü ù:2øŸ´Œ†?i"‰0“•Jñeps1Yól Ô²Ì0Ês(x–Édå‚ÒØü°ˆÜWEiµâšÔ¢¸0ÊóÂJz‹�áß‚çÜÛc+ÄU¥ņR|ó8$)ÖÄ›7~¼ñÇSÏH›íïvÿéï×o4z-G­ÊóóË—/utt¶nÝŠ>|øøñã ´///×ÒÒª®® Ó§O¿té’Z‡¬aaa£F�’Édd2ùĉýû÷or„–ÉdyyyõågµØ»wïíÛ·UlÜ·o_Ú¿***”Ûh0?cFãd‡�}²Ù©©¸Å€ ž[ffbëT#¤' Ë8Š?î�'‘H¶v¶©ô�ÇѶuK¥'ìµÛK"‘ÔwTh€*ùyÅŠ†††d2Y!?—••;vÌÌÌlÏž=èYùüŒº¹¹­]»ݯ­­½|ùòòåË7nÜ‚6zyyùúúâ»#‘Hßÿ=ÞþÒ¥KË–-Û¸qchh(Þ& àåË—ùùù055ussCÛ³³³·oßnjjjaaáãヷ¯©©¹xñâ²eËÌÍÍÃÂÂÐF|Xá]}øðᆠ.\øý÷ßóx<|üG�EïOTT>NGGÇáÇϙ3õæåå…žçÏŸ_ºt©……Edd$Þyß¾}јäççÛÚÚ.^¼ø§Ÿ~Z°`žŸKJJöíÛgjjºyóf´ >ÿÝ•þø|þ¹sç–.]jii‰�G&“¥¥¥ÙØØ˜ššZ[[ûûû+ï¨Nè“VÆgEæ½J`DÈ_Ì®¹‰¥âDæ›zH‡-xJjI%ÉÁägÙìTu™{yy�ÐW¯^µ°°˜2eÊ�;w‘HDg5 ïܹC£ÑÂÃÃíìì*++Q?&&&;vìÈÊÊBý B…üüâÅ‹áÇËd²»wï®X±ß>gÎÅ“““»wïnaaA$?~Ü·oßׯ_ãÍ”ósee%á½[·nË?µsçÎéÓ§ûûûgdd899y{{£÷gõêÕ¿þúkZZÚï¿ÿÞ³gO:�Žz&óçÏ?xð ê0''çÝ‚"ÑܹsmmmI$ÒË—/�ŒŒÐû pþ¹°ðŸµÈJKKõõõ�=síÚ5”Ÿ1 ›2eʵk×JJJöïß¿jÕ*� ‹…Bá¬Y³ìííI$’¿¿ÿСCcccßeQ±XWW÷Áƒ4-44ÔÎÎ…íÚ±g{“Nõ/©bªÒ^]Þ<¿J/NhB•o; ’ˆrØiÁäg™¬$¡DÍëi;;;[ZZZ€±´´tvvVï! ªäçùóçóùüAƒeffâùùÖ­[sçÎÅ›¼ÙƒfÏž�ç瀀€û÷ï÷ëׯ¬ìŸrÓË—/÷èÑŸÔ6hÐ ôÔÍ›7ÑÉí;wî|ûí·hã¥K—Ú›šš¢§®^½ºeËå¡&&&®^½ºÿþ‹/¾{÷.š·xþüy¼Ÿ�.Z´H9?ûùù�1¢áü\ʼn�-™Ÿß>½o/^¼˜0a‚P(DcÓ××—ÏÏÇ�_·n:Ó+¼›Çf³õôôþüóOÔ ##Õ½(¯¿�þðúõë¾}ûfgg£ûŸþ9ÊÏ|>àÀ�ø|O\II‰®®î£G�ÐÃôôtT‡“‘‘ááá�Šd¤RéŠ+.^¼ØðGi±üü®à9÷UFñÛUðŒÉ°ÂJz8Õ?ž^QÃÑôp€öL•õŸ×¯_�î×ÖÖN›6 _ÿ9$$dܸq†††C‡½sçÚˆÖFO&“]¸p¯µÈÌÌ\¼x±žžÞ°aÃLLLRSSñ½�H$###<åâí-Z¤««;lØ0SSS¼ý�;wœœœÆÉáp:4zôè±cÇYXXàë¶¥§§›™™¡ý.\¸0==]~ýçñãÇoݺ•J¥¢Æ†mÞ¼¹sçÎÆ »~ýú‘#GñóÏ[·n522êׯŸò¢Ê—.]êÝ»·¡¡!¾~’’’"_é�ûÚµkûõë7dÈ�yóæ½yó�6ß´iÓ€F�}èСS§NÉ¿¥¥¥ ,èß¿¿±±1~9%%ÅÔÔ½?‹-ÊÊÊBÛÖvvvFÛÏŸ?ß«W¯aÆmÛ¶mûöíø(+W®ìÓ§jAK—¨W |ÒPÁs‡:ûÊ®."Ò‰´@vu‘¦Çt�ŸU¤PÿÜnxxx,]ºÕfTWWŸ;wŸ×©^ÍúIKEo ¢bòC;NÁ3‡ÏŽ¡‡Dæó 4= c�ü¬¢üüüýû÷kzê'‘H.]º4}úôqãÆÍ›7ïÌ™3UUUͱ£æû¤U +#r_e²U\ ¤­«¨áÄ3Âéþ…•tLÖ!~d U±¶¶Fë¼Ð|$‰µµusô\RÅì8ϼڊDfTå9ƒKíP³#€VåСCEEP9 šWQQÑ¡C‡ÔÞ-¹4�Ð1 ž«…¼”˜PŠ/�“ÓÂ× €777´¾Í'00ÐÍÍM�¾/xŽŒíÏ?½8>„ìC-Ë”HwÍG4‰doo¯âd4Auuµ½½=‰DRW‡Uï ž_¶û‚g¡¤&“•L~–ÃNID*¼-ÄËËËÉɉL&kz  ½‰DéééNNN^^^êê“Å{Wð̬ ©«ÃVH$f³SƒÉÏH%ÉBI­¦‡€:;;;[ZZZ >–––ÎÎÎÁÁÁjù”b2ìß‚çrµtØ ‰¥bJiFÙ'½8¡F,Ðôp@[%–ŠÞ<‡ %í³àYŠIò8¤PŠojQ,_Ô,K€¢ª<'µË‚g “æs)¡¿$&±J¨þ+?€…Å+h¯Ϙ cVÐÔ ŒˆÊö[”Z&ÃrØiê‹v™-‹xŒˆÜW±ùaå‚RM�´yï ž#âÞ<··(ØU…oh¯‰´ ÒêbM�í‰Drsssrr²²²Òôà£888¸ºº4êPU[‘û2«¤½<—ñK¢éÁQy¬*¦¦Ç€vÃ0///;;»ÀÀÀÂÂB©.Uܶ•––ïÞ½[õ]ü¾à¹°’ÞÌCkQ\AYƒ‘û²¨2_Óc@»|øðáª*X¿«]ñóósuuý`³vYðÌ«å¾-ˆ$P_psÛÙét´NNNT*UÓ£jÆápn#’ˆqù„vSð\-ä%F‡R|éåd)I@³°¶¶–H$šP3©TjmmÝ@^mEx®?©$“µ‡3´QuZQ\Ù7·,K"…Ï3š‘………¦‡šEG¶˜Çh7ϵbAëmÙ‡\š.–Š4=´�ŸÛ«:�ìû‚çÔ÷Ï\M J�D!©$%˜üŒT’"’5=t�ŸÛ+å#+’ãáq B[O›b©ˆ\šBöÉ`½­ 4=t,�ŸÛ+…#û®à™Úæ ž%RInYVÙ7­(N ªÖôpЩ’Ÿóóó‚Îò …B&ó—¢((( Ñh<ï#Ç6bÄ£÷^¾|©ülnnî¸qãÂÃÃ?r/ªc±X´÷D¢FÔÙæääŒ7îÍ›7Í9´:ÈÙ¢÷Ïmz%d)&¥—“C)¾É…ÑÕÂ�ýh4™*ù¹gÏžû÷ïG÷ß¾};|øð†Ûëëë4ÈÈÈhàÀ�Ç�‹ÅM�N§Ñh3fÌøë¯¿”Ÿ¥Ñh_|ñÅGæR2™¼nÝ:/[¶¬ÿþFFFúúúãÆ� TåU eþüù±±±ª4ÎÌÌ477Wq< CG“aÙï žyµmµàðn.�úâmAdÛý)Ðn¨’Ÿ{õê5tèPtÚYÅüŒâ"ƒÁ˜={¶��ÝÇŒð‹/¾¨3?«EddäܹsUl¼lÙ2tÿåË—½{÷®­UóÊÉ¡¡¡&&&jéÊÂÂ<Ç3ÂÛnÁsQe~DîË8�+(ÓôXdªŸ>~üøÞ½{òseeåîÝ»õôô Ž9‚‡IùÕ3Èçg¡PØ£G�äädó³X,ÖÒÒÂO½6*?wíÚ533S¹‘Hœ={¶•••››Û‘#GfΜ‰?¥œŸ©Tj§N�Lÿ:½lٲÇ*•ŠaÿE„…… :9ŸÏ×ÒÒ*..–ïS9?GFF¢û±±±ò/¯3?K$’?ÿüó›o¾éß¿ÿ¢E‹Þ¾}[绡 måçÊšòF�ú‚YAk£'è TÏÏ2™ìܹsk×®Eù¹¨¨¨sçÎ, µIOOïÑ£GMM�B~¾{÷®‘‘†aR©´S§Nx0¾|ùr�ùùíÛ·={ö ÿ›ïfbbòðáÃ:¦�ŸÇ�wÿþ}åfD"Ýþü¹|~~ùòå´iÓä ‚=zP©Tå~êŸ�Öµk×òòrô0>>¾W¯^ KލžŸ}}}gÏž]狾\œ?~̘1õ5�×Vòs•°2‰I ¥øås)&Õôp> Qù¹ªªjРAxý³��ÍÒ¥K333“““gÏž}âÄ ´]__ÿæÍ›ÁÁÁß}÷]¯^½‚ƒƒÑöÉ“'ÛÛÛçææþöÛoS¦L‘ÏÏK—.}ûömRRÒŒ3¾ûî;ù½ïÚµkÆ 4M>‚" ùùÏ?ÿìß¿ÿ“'Oh4Zxx¸¹¹9ª£:tè/¿üR\\0uêTùü\TT¤££óêÕ+�#•¾Ëo...S¦L‰ŽŽ.--%‰üñj\g~–Édæææ+W®$‘H‰‰‰Ó¦M;wîœBÕósAA�ŽŽN`` �F‹ŽŽÆ0L(®[·Î××—ËåVUU?~ÜÔÔôƒ‡¬Mäg¾¨*µ(6”â›Ç!I1‰¦‡ URÖž={𺋇:;;£ûb±øâÅ‹óæÍ[¸páíÛ·ñö°yïĉd2ßžœœ¼bÅŠ™3g^¾|9++ËÝÝmŸ4iÒ�7Ö­[7{öìË—/£‹c±XæææS¦LÙ¼y³B]ñ±cÇäû—Éd¯_¿^»víÌ™3×­[‡_Z%>>~åÊ•3gÎüî»ï(Ê÷ß/ÿŸ%K–Ìœ9ÓÊʪ¬ìŸEÒ¼¼¼–/_>cÆ ‹èèh´ñÚµkÊï�H$:sæÌœ9s/^|÷î]凖_TäÈ‘#999è~nnî¡C‡ä{{{ùå—3gδ¶¶F§µSSSmmmçÍ›7gÎ{{û’•Ö£hÍù¹F,H/N!ûPJ3ÄÒ&. ­!eÉ×oui GV™PRK*I&?Ëf§¶ÝU©Бµ†”ù¹9´†#+O$å°Ó‚ÉÏ2YIBI�¦‡ÐD­!eùùùÂJ¿jÖŽ,"‘Š©e™!dŸôâx�ˆ¯éá|kkk…¢bÐH$kkkM�B&Ť4NN(Å7¥0¦ZÈÓôpÔààÁƒ$IÓ£jVTT¤0-±…a˜”Á¥†Qž'2£xµ €zy{{߸qCÓ£jèææ¦‘]c2¬°’Nõ�g„WÔp42€æSSSãèèˆ.E Ú‡êêj{{{�üY¡˜W™CáðÙ-¿w€–Áb±oܸA"‘ ºM‰DéééNNN^^^-¼kvu‘H¤²«‹Zx×-¯¦¦ÆÛÛÛÉÉÉ´e–––ÎÎÎø[‡ÏŽ¡‡Dæó Zr¿´-5œxFx8Õ¿°’ŽÉ0M€VŠW[‘ÈŒ £„ìC-Ë”HÅš­”PR“ÉJ &?Ëa§‰$°B :.—ëááagg§é%"@órpppuu-(PÏR"‰0›�L~F*IJjÕÒ'@ëÇår<== ¤R¨YmÏJKKƒƒƒwïÞý‘Z,SJ3BÈ>éÅ 5b�úÐxxxxzzjz åøùù¹ºº6íµRL’Ç!…R|S‹bù¢*u   °³³c2™šh9ÇÁÁ¡±¯Â0i>—JñKb«„•Í34€6ÀÊÊJ"‘hz åH¥RkkkÕÛc2ŒYA#P_$0"*kÊ›shm€………¦‡Zšê½ˆÇˆÈ}›V.(mæA´ �Ÿ; U:»ªð í5‘TZ]Ü"ƒh ?w@ ô2~I4=8*/€U…ñŠÚD~ær¹$©¼¼£ßòùüfí¿¾ƒÎ”Å1¹/‹*ó›um×ó3—Ë%øC�F¥R?ØmJJÊíÛ·ÿüóÏÒÒÔÍ###CCC---¡P¨ÜÀÝÝ}À€¦¦¦&LHNN …„ÿÅb±>8žÊÊÊŠŠŠ6k1••u¯bqìØ±ž={òx¼æÛ»òAçÕrßD¨/ ¸¹†5߮ںæç°°0--­{÷§N�:xð`Ã/9þüСCC%$$ô›Ÿ{zzú��ðñãG›ÍÖÞÞ.µ¼{÷Îf³½yó¦ßqú] oiiqžO\\ܺ‰IGG‡ÍfëwÉZLÉn·»>šøÐ;ìí�š«o7üú÷7uÝ=ìaàWòsppð¦M›NŸ>Ý'?_¸pA¡P¬^½Z¬6‹ÿû÷ööNž<Ùh4:UUUåíí½bÅŠ ¬_¿þãÇÿÜÀ®ßü, OOϨ¨¨ÎÎN©OOÏèÑ£Ÿ>}*¥­­­îîî÷ïßßvìØ‘––æp8ºººT*•4ÛÒh¡¡¡­?×ÖÖÊóóƒÜÜÜDÍùû÷ï5�ÉdùyäÈ‘'Nœkþ+W®¯Ýé'þRßZkïî§Ú¿Ï•ü¼hÑ¢ÏAnãÆ�'OžLMMù9##cË–-R·Ó§OJ‡¹¹¹*•ÊËË«®®Îápœ={V¥RýòoIIIRÿï’Ÿå•ÉÉÉ111Ò¡s~.((˜?¾4Ÿ‰SƒaéÒ¥ÎÈ[·n]²dInn®¼;??_­VKãìÛ·oíÚµ‡£²²ÒÝÝ} 2f×ósrr²´îp8rrrÖ¯_/òó”)S¤v�N—˜˜Øï€Î†Ä¦+ÿŸ\ÏÏ555sæÌIOOù9))içÎ�R·+W®øùùõ¹¶»»;<<<$$DÔ-øøø¤ÊäççK=¿{~NMM�ŽŽ–�óóñãÇÕjµ|>â”Á`ؾ}û@ï†^¯×|!¾dggk4ù8………‡£´´tþüù½«®ççÝ»w'$$H‡&“iÕªUÎùùàÁƒòn¿�ü ðÍ\ÏχcóæÍ+W®ùÙl6ûøøHûÚíÞ½;22òs®¶ÛíµµµÒå§N�Z·n�Ãᨮ®ž>}º¼æYîÇÆ sÞ´í{åçøøøC‡É/¿{÷î¬Y³úÝiy ü,~A)DFFÆÆÆŠí2fÏžÝÑÑѧóË—/G�%•yˆoÒãèèè”””~_WŸü\PPàçç'í)!ê·ÉσâåçG� >\äg»Ý¾fÍš��³Ùœ””¤P(^¼x!êuÝÝÝ#"" 333§M›výúuqù®]»–,YRTTd±XöîÝ[RR""___­Vk6›‹‹‹¥Fçüü9i‹eÞ±cÇFEE¥¦¦>|øð«ùÙb±L›6Íd2‰ÆˆˆˆåË—Ÿ;wÎb±$$$ˆß÷ ”Ÿkjj.\h4+**Š‹‹½½½Íf³8îïïþüy‹Å²gÏ‹Å"ÚÓÒÒfÍš•““séÒ¥ÈÈHù¾%ׯ_Ÿ1cÆÙ³g¯^½zþüyùõÉÏ���þþþÛ¶m»xñ¢^¯W*•ÍÍÍäg€ÁòÕ(õüùó¼¼<é0??¿¬¬L<¶ÛíQQQYYY¯^½’ú¼~ýÚh4jµÚäädùZ´¨jØ»woLLŒÙl–¯ÇŠ�ît:]\\œ4þ¿î%ýæMff¦¼›”Ÿ%"?·µµeddHÝ***JKKåÞ¸q#..N¯×ËóyIIIbbbllì¥K—¤Zåû÷ï_¹rÅù­hjjÊÎÎÞ¹s§^¯ï³éôµk×Ä8—/_–×·oß–rûW‘Ÿ¾Qê'ćð͈R?!>t€oF”ú ñ¡|³°°°>uÈø±uww‡…… ö,†*�N'ösÀO¢¹¹Y§Ó ö,†*£Ñ(ßï?¼²²2£Ñ8سªêëëãããÛÛÛ{"ø_hoo���¯¯¯ì‰ a&“I¯×744 öDð_d·Û­V«^¯7™Lƒ=€!¯¼¼|ÿþý¡¡¡Â*44tÿþýåååƒý·CÒ?5Ü endstream endobj 97 0 obj <> stream xœí]ßo7 ~¿¿BϦˆ¢~A€8N‚=l@»Ûë�u†µ]ÓØŸ?œ�Ôw‰?ŸxVì³ç(Ü0%Š?‘¥-çÅe”QßëÎc¶êþCó¹i)Ö{£Øæ Sôêá]óËwêcó¹aMÖ/¾»útÿ¡!Õþ}{«–Þ7g·¬ÞiÎ~úôñç¯ÿÜUççg?^ý0WF]\ÌæW 6‰‚"ãCËá�æMó¦ËÞš¬Û¾¥aþ:PªûïÛ[õò‡«~Íîš³ŸÿþíãùùÙåý×~ûëîÝ¿_ÕùÍõÍ�5v~¡..TÛɳ§Èª»?ZJŒTˆ¤ƒÍQÙ¬î>4çÆw¡îþl®\êîwun /µ7>ù쾜7ÆÍŒqyñ ºqõ­}&×wÛô?ÒÑ‘á��7†âžúHI[ãÓ��=ã.÷ÔG¶šr2aHŽaK9>[å«Ò,>¼½UËc´Ÿœ"Öl—›DhjUfÍíŸð$Z'…ô¸rÉÑj9X�ͼ$Ð5"\!YÌã5åõÊÊ›ŠRfÎÒùÀÏ`«bBæhj~JWÎ\¬»Páð|t¥kƒ]/Ä.¡7À¡Ë܇¸žy�p)eÞ[jeÝ�%ãèõêºdeÌÑ-ì 55Gß0€@hpj ‰¤7E²êõªG@<°H ®Ö]8µlK˜b‰–d±¬8µ˜9â¥xh/éÍG(]ùÎÐ[]�B,G°#b Éßp÷”w2—û/!œè6ÕEq ÑhѱaKr¤A`+k¿BÄkê.D£ C±Cé¢#¡3 J/¥«l¨p`SòÙGæ¥<ŽI•«^Å['pßq6>’lÖ1)pò;VM0Ã``Ì(ÊÐ, }÷0P‡’ 1š˜­'0Xx€â4WúÞMj3”®-™ùÍ8ƒ0͵,¥ªhE”:öÖI õax­f†˜]†ƒÒí5|á©1ÜK&Ã;èÁmÌ�ƒÛ&¾oA$È xE«‹ 4J˜Í1LÔ’Û7¹É¯xOY|Íiš—¤G£ÿ»N8ÃXnÿ àt%¸ ʯî Ë^f\Ëî[Ë/{Ë ¸üÊKQ×–7‚‘Ç ;¿Äꃛ’ç•ÁK2rôPï~ïèK2œÔfC¨œ�äÁ¡%& D%‘%‹‚UÓ„‰UH$¸WâT,+QžÇ^²¡LÔ&'g»:·uV¼�³‹ØqøaŽ!Ž�ã"¨àN)–²íô€£ë!ë˜ Ù—“ÿÚÁõ]„O²œ*�·½TÖÔ”ý·á±g)ºWÛðˆÑF!Fjpû‚[ä#g£ÁSÙ^ô¹0=™ ©'¯^³nDÎÏKüÁ··w—Ž[Å®Ž�óOFWH•isQO8—â“ÉÃàp.§Yda >ÔÁ™wJQ“o½L-9eäVtDpÒÎÅ�–áÁÞ�±ÞiçˆÃh Âþ'¤Aω�xø ŽšÂã@H+ü€ÛoÂzÍ>êØ |мìÂŒÃmy¯Iy:œø@-Gh# «4N:áR=ì À¸}FÀqypìKÃ{‘kÖX?¬dx…Õ[HXºò"æò9/bYÜ´¨¾sQ-™¡}ÁGyŒ2*æ`T¬ž�'äUÀ‹¤[$D<©k‚îÂÊ0Xº`Ò^ÅÒ7(ÿ¯¬’UQBNYÅ¡^LK× ¯Yÿ¼hEmW¨”`HBMM6»’âÜÐË#¾i�Fr“¿ øº¿6®�ùÀÉäðü”5qûÐdùœÊ³Tv1Ũc°™ö€=ÐÂÅa#± "� ·Þ>#?5b‘Ƚûðˆ$ _ð+&:ˆï#¿®Â3ë( ›êz¹{½Ô<¢pÅWO*¾ý&_BЇ#vqÔ,1Tp¦ÍíãÈT|->8hG‘4ù”]wÎOõѦ ½ÕŽ�ã¡õY/.3æ:¹¸–Îðq`Žôã2Õ“1X.ÍÞòà‚‘ì)®,!Oª«ù ƒ<Ç vW|cu¿`Ä#ÇKh¯éGÿȱ‚™ÎØS�Ê) bÖäML½9yí"•uÏ,Žy8üO-¦I>·�¯5ÀÝ[ÜÝ�ßo/"œ´b¼&ß‹Åm¿妣(C¥ìÙXë¦èùs“ܲð" iƒjE#JóÀ[÷òWGñû/â°¹üiŸ²ÊNEaZñ-zñºìÁ!ùKš°þC‘•¨am®.�²èxÑë©EŶ|=&>ô˜ïàõT\¢æP ¼ž:Á(¿syã5/ñÇ�Øäw8ëõªb,íX.iÉ}P5“†!ÛEqM°s�x0l�)x\ñoš7ÍçÆ(6Ù(ë½QÖ�¢Wïš_¾S›Ï k²~±¼WŸî?¬9¹�ݲzÿE²‹DüŒKÒÆÚHŠŒ%�™ÙoLƒ^‰7Q[JcÍL=#Ì�aSsD€ß°ˆÀˆp�u𬻠‚øH$�¹AMa±C”UD#î.šALæÐ­íHo­Y Úº6÷ȦÅr VûöW—Ÿ:ë.XíÚ…–‹bõßUÙè`ýÆÕxö«5jþéwr�´qXYbÒÖ+²Æè¶+¶Ó‹'âraZc:ìmX¶1ÔƒžzЊâ?¡ð endstream endobj 100 0 obj <> stream xœí�|ç™ÿeSÜâäR.w¾»ÿ].w¶/9ç’‹ÏIð¥�ă4«¢ÙàŽ{�ÇqY[»3³«‚U#ŠÊλ»êˆ"„ B€�Vbwf¶Š(’[\ö3ïjµ*•Ý}gVÏïóýð±A–G3;?ž÷yŸ÷y(JÝzI÷˜öÃçãçÇ‘¾��kþ¢¥¤/R„æ'ÎO\�ˆY°0qÁ -X¸x¡üë‚E‹†é›2äw,LL\0~¢�ľ‹œŸ8/!!�¢¨$ä4é8ž~âåHßÂÐ*ñ�Ç’¶5¾¨ÏIH˜Ÿ0ÔN¼yññ qññ ó0óæÏ“ßv߯óæ'$Ì‹‹�Ì›?ÏÓÛ¢Fò�)H`�À²èÕÄÅñäì$TZúø+Ͻ¹&%·•‘Î�»;šÎx`/‡(êõ«Æî}òKÌ䶦˜ìƨˆ“Vëe6žKClV«J=¶¶¯ˆl€óæ'b¿šŸ¨>¿rõØ �éÒ{̳&‡!·5…´»_IkºµZ/‹D i…Γî/‰f€~5Ÿ¸ÿŒ•êN³tÐ/Yik ¾h³¨ÏjgÏ Áh� ŸÿÀAü~¥ºõ`ë¥Ãf‘Ec²9GDšO#�6K‘kkNFüÓdé�¯TåWîÞæ2Ïz$0f‘ΉÄÌcâiާÍRdŘ…½�ÿ¨qTš¿ª=WŠÓì™u™[›V�v— + 9õœÀ˜xœc/­»BüsJ@�ù+þÊ ‹˜,½ÊN:ûTJf]&iƒ ¦èü6½Ù™„œØ¬,5ˆH@!øý*Q=~U~f3®Ì‚9iÒLi³D]ž“ÎoÃf•UÑEüʡ߯¨Ã¯N^¨ÀfU j-Biƒ ¦¼^¯å@—6KÄfµ¶¬­J­ uù•³§¡Ð%\q"mt¢–´ÇSUMÝ^¯—á$³ZQ讇R+H€_%·£k²¿Ã„ƒ+ÄK–EÚ`‚) 9•í¬Yúñ’óÅ:(µ€!øýjÁB¥ûUËÅ\jµÌ‘Up%•.p¾Ý@‰‡ Ô †C-ëAwOóv÷Z9ÇΚϤ[íÒ41ÈÑïWf¡²éc⟠P&jYî*ö­½uGN“'2’S9 Ô ®‰*ÖƒŽËÇ,‚‘‹“A]È‹HÛLpÄJi8A²,Ù¬ÌPj#¢ ¿ÚÕ¶QÚäY“‹µ8Ò6i‘M�N³È—¶Ú ¥Vp-”ïWÇÏï–ÌJ`¶v&ç¸#$m%•ZÕœÑ"+›Õº²3Pj×ÄïW - nMC{ò�©Rš§ó\ìÖÎdÒNUÙ.J¥V²Y¥¹ê]Pj×Fá~UÙ‘+7a`8Q²,Ò6ÑHÈ®l—~$$$[�G¡Ô F‡’ýªéb5ÞÌs8g„\1H”ºZÉ?˜ºZÀXP¬_¹{šJ\«åŠ$foGN^Dd®ú²ë¾ Á èjc!À¯÷¨@jºòqpåõz›º«H;M¤C‰þ ÁÒ£—‰?}PÊô«Ó—�šƒt6ÅEלÍ÷z½¤Íf¢ÒfÛ“L‚®oÌ :¥V0fúýj±‚üj—\1y‚¹TŸfÏ̬3nmÑfÛûJ­:mmä=¨ÆWuçvàs‚Y¢6[ý®¼^ïöýžÌÌ:J­`b(-¾®Ôç‹ò¼f“Ëë³Ôßáê€Mîj%7ŠI/tC©Œ¥ùUÅ™­¸« ç`‘CõGoh3Ÿ]y†–sìÉVg-ÿWâOÔ‹¢ü —7‹2\^6& äåR+¡úÔ§Ä7¨åø•«ÇVäÊÀÃå9õ—g-vÆÌ3¾i§Âž(µ€‰¢¿ªî´à‚+ŽgÕ>\Þ�çf9�µØY_W+(µ€  ¿Š¤áò†¢S¬™7ä¹}¥VÕç‰?eˆ ”àWîÞæžLyê £öáò™™u©¹Í’eÉfµ©J­ h(áü`àpù-Mé¤-gBZ±¥É_jµº´­Á¥V4ˆûå„5R†Ë3œ�œÓJËǙӊÜ'œ_¾I÷«ˆ.ÏÊ[�xÚ©Ñê<â€R+2dý*b†Ë³²MaË’K­>!þd ò èWòpùòJ�1‹*.O#É}–%”7ô¬‘ô«Ãå‘j§Þè­NZªcwáê…bèj!ƒ”_õ —gT=\^[Ò®Ëwé­NlV¹ûÏ Áñ«È.��7ÝzN[ÒŽÍjãî(µ€�Bį"c¸üzÔ��o&WFI[ƒJ­ ´„߯ðpy$¨{¸<‹ø¨�–»Z­(p¡Ô BNøýjWÛ‡¾àÊ¡Wépyi+P>•-•ZYD(µ€ðf¿ÂÃå%lZԪʂ+SáêƒY¨j�R+áô«Àáòè´ÙÔWpÅ �xlY vÕ÷‚0y§_©}¸|Jn+k²K�åe³*Ï¡3ñzÒ>4*Ñœ�³·�å¤{²J­@L<å.ω4מ–çБ¶¢k‹5KÙuZnÃ"ñ ”Z€˜¸_—ç.®'mE×–Þä¤9ÑoY{>"þ ô+ÇåcVQMÃå V;ƒx½ÉW½PR{‰ø#`”L°þªüÌ& —×fÛõœC¶,颹êóÄï?£g"~uBUÃå33ëŒ[[´Ù>³Ú°«�øÍ`LŒÛ¯Ô5\ÞëõnßçÉ̬Ãf•^ì†R+Pãö«}í9*.ï+µ’7�V±Þ¥V >ÆçWê.O#!»²GV,ŽB©¨“qø•»§©H\¡–áòzÎIK5÷>³:Ðò ñ{Àø‡_Uu µ —×›zNÐs¾ê…�õ0“ TÌXýêôå£f)Na”?\Þ�çfL‚ÞäÀfe�™\ rÆêW.yþ)Oç :%—7�bͼdY²Ym©ì"~«˜ £ñ+W�íԥí—�ìi߬Šáò™™u©¹Í†¢SجÖmo³µ‘¿ÕL�‘ýÊÝÛ\{¶Ä"­Îdy(ã`ò½b‡ËË¥Vn©UZ�«Á¥V ŒìW;ó­Îd_;†gÌN6«]¯õ*Ô¯ªš.J¥VòäƒE<&~Aü&Fð+ûå:€³X••ÚÒJ ±ØÜþ«º»€: º_yz[vx>�,K¤KO((Ä¢sœ´\Û°²X NBáW�ÝûqaƒbWJ-VR¶ ÍÙ²Bˆ*$~%‡X™x£0GHÒzbi³Dùš6¬Ý!¨�ùUÃ…Jœu×zµkº•’ÅJ-td”Ùqë@ó'Äo>c"D~åémÙîY‡-ëÿüJ!!VF™=Ít ŸÐY … 6BçW'/앳îRˆµú¢RB¬ô-¶ÌÌ:þã¯øò-²¥åœ” „JÛÇÄŸLNèWõöàóΨ}ò¢ XÖìÙ³çÎ��Y#tÅôéî»ï~!!!ë‰'ެ7ågnß·*§iå:~ÃæÖ›0.+ ô+±§ÁWèîE¨;3ˆ~åWbbb\\N¼_-Áå·¯¨¨(/BÃð,+0L¬�’ÚREï>èWžÞ–žõxÈ×µ*~¨¡5Ôµ²_~ÙÑïT¤¤5; •„ eúU�<­^šó%Œy‹p"Æ5èø¾3qM«^?ŒY1Œ`0´–î'þ`’ L¿jºX�æpÂxª&¨Àã?ï<òˆõÕW4=¼_1Œ}‹‰øC€I‚2ýÊÝÛœ/¦ ‘ErƒÏ0ûU kµž´´«™•À0–×ÿôæ»ìVkÅ1X@ˆQ¦_yz[öœÙ‚ä¹Ïœ@rŽª'-ÍɲÂUâ«Ó4ýÚCáûÜK¯¯Ýd©¬ƒc†ëWGÏ•õõ–!_EEE‰4í’ÝI°?Èð†d»©øèé+¦’êwõi‰‰ ýùù‡}"ɸڲãHƒûsâ�"Åú•ãò1© ‹7pHj‡e94¡,z½øiQE=»âƒ—>ì7®ÅK|WŸf*©>æ¸j~ &' ÷«Ã]…òÁibi—êWÁ¡NƒEò«ŒbO°ÄÞ£®µ›,Ͻôºµ‡ ºöo#þ9% p¿:uñî…Åñ4²+Ųª›º½^_G÷cb�+¬Žœº´ÕZñæ»lâ‚]슊*ê=Ð@˜¼(ܯܽÍÎ4ÉìAkß7qy½ÞìÊvìWÛ�…jN}½ó³¢Šú”Õ›}ü)¿q-\´ÿ©³C'y`Ò¡p¿òô¶TœÙêX:�öÈA—‰´Ti!dîlÃcòtÅöÍòÿÙUc'þ)€ð |¿:~n'îÕ@ü`N ŒÈ™†<¾ŽîîðíèõÿY°¨µøÈãøøÏI×_‰¢ t(߯ø+Çž /0È¥”%aò°rÕ(ƒ„ŠFyÃÿI˜7ÿ9Ô|�øG ‚ŽòýÊÓÛRâÎÀf…œJñ«¨¨(iÏR.ÄÚ¶÷Ú…î!¥ª¾tÁñ ²Q…_UuJýÓÍ"�Dù•Þ,ê­N©Ð=ßik#ÿ(ÿy ÿøÏâ–â‚.8þ¨UøUc÷þ޼‰x&û”yÒH•Oz«“î[©<õ)ñGˆ­í+8þDªð+W�íÖoÞ¼zÿkÈ“¶í”ž´Qõ‹–¶ĉº‡|üçÍwYÿ³†ã?€JQ…_ñN~ý[_û—ÿøû�ÇÞz+û Ò.Õ/‰zÙ¯2ŠUÐStIÇ–=â7®E‹ðõsæáø tTáWuöýS§M½îº¨ÿòö{þðCÒ.Õ/=î*s”WS+Ñ‘Žÿ Ú!#.ªð«ò#ES§M�ŠŠºé–¢¢¢®»Ž´OHnÙ,Ê…î—‰?ÍqÇ¡ ¿B;¶\?åzìSúþA!2æ ¬YÚ%ü ,…î¡£Ñý.èzü'Ë´óHËEâWªð«U›ÔLf�R ùŒ2»\/žtIü�…þã?±ýÇü]Ä/˜´¨Â¯þüþ«¤méªÊ(³-Vn‡µ§!ÒRÖþã? .ÃñŸ¶/�z<û\÷¹kêþž<5Rj¹/E t]Ô3A@u~e?w↛¦ÿaÉÏ‘œ1"íRýJB­Zd“;º‹õ‘Rè>&6æ”j4𨨨mùGÛÚö»ï¾øöóšXM^qñË"Õù•§·åg¿ýñ·oû†Y`><ö6i—ê—Ùôœ¯Êz‰?Ù0³v“…¢¨¸¸xTZøû»�QµäÁeЯ˜8jô«×™g£¢¢Þ·<•Rùò"ÒFÕ/Úì¤å!›÷v²ádźl\î^°ûØÐ?}ý/IEW~Hü:µ£F¿:ÐXµäõû‘™/®'íRý¢Í.:¿�A‚Ñ"N†Bw\yÅ®ø€¢¨yó‹*ê‡ýšƒ�gçÍOŒ�‹ÛsD ~Á€ªQ£_yz[þá{ßýѽÿfé—RÚ¹K~•߆{a1H¨j‰üá�ž/ßcVR•¸`QYUË_¹j#GQÔó/ÿ Ú/A¥~•øxôÔiS2ý%½üÒ.5@ÒzP^¢êóÄnHiô|ñ滬ÔQyɃå‡ù‘¿¸Áýù£OùÌ‹EmÌÝNü'Ô‚ÚýêÝQQQomyä�ìÇI[Ô1œ€ûl¦¨²Ð½tŸm~⊢ôÉkC´¤Ýuð´F£I\°ðpËdÒŒµûÕ®:©ŸLâó¿š�‡ì4i—êW`Sà#•ºçïªKH˜'ÍçZ½9¤ÿ#|\ú]ý â?2  ÔîWîÞæÛ¾÷�»îý7d§7{‡´K žpÌ ¡àÈEâzôXv �Yáy÷‹? ÑhJ*ˆÿà€òQ»_yz[â�5uÚ”Uû^7–¾@Ú¢hêbÌRÖ}u‰‡øƒ%¹…ûcãâ4Íú-ag³)oEQ�?ùlpóù@D~•aÒEEE=ú^ljÎÛ^¯—´Kõk=ºˆ�/ O¸T° –eÚ©‘µ1§4lÿS[ÛWϾðGŠ¢2·¿€Â‰¿jî:rÃMÓ~;ÿn¯×Ût¡Š´Kõ !ï ÔŽ;øí<¡ôiVýÓ"¬aþ_ïª±ÇÆÆÎO\PÓ¤Ö½T >Á²ã©k¨³÷,’ S¯Ö"Ư¶Í‰ŠŠŠ}ò7Ë™yÈ£ Žî¬<1[VeÓÇÄ÷ lm_Ò7Œ<-"llµì¡(ê‘Çž<éRYù6"ï\=¶¿ÿ—oÿç/¾�ÿi«SOÚ¥È?�b뾳ğ¸4-âOïŒcZDx8ÎüÀƒQeÝu”øÅJ#büÊÓÛRäJGcuê-¢‚FEEe .Ú,ùk!¼$>!>>aßñ6â(‡Hò+áÊI³ÜAëÕ®¾ø>i— �‰gð’Xné~üÉg}Ó"ø M‹)«²(Šzõ�w‰_  "ɯ¤ÂQÏ:$0&§~C—Ž´E �ÎÄk³í8ÄÚ~üÒQ>|«BiZÄ#¾iÇyÅÕ¬^�zñÓe?FQ”¹ì0ñ‹B„ùUM—U²žå”4¤^Ï9u&�ANÆw6G0˜Å »ÛÃдAš±ì‘àN‹\ÉAŠ¢–>ôhP†ò@„ùUÓÅ*ìWÈ®G6¥¤°hNÐsNÜ Ë‹„U¥ž�*Ü{Ôµä�eEýEkPiw©×þüEQik·¿@ D˜_¹{šóÅÉlZtJ)KByðhV~vŸÞ@UçgÍÂÇM}ATH§E„�õí óâââ÷SMÏC tD˜_yz[ÊÏlö…X§Q58îy"k·UžÝ]ß[}ê“ZþóÏx­S‡O +V ƒáW­Ù[¼?qÁÂ�N‹+ÖeSõòko¿€8‘çWGÏ•ÉUXRDCÚ«¢°_efÖáqÏ£ÁhÓ‹ÝëwœÙ\ÑÅU�/ª½´³¾g_ÓLJNvÂ9L˜tzG5ϲ~³Â´êõo=üpʪ,µ›•”xw~†§KçW¿€,‘çWöËu}¯>�œI¤íJޝrZéᬉƋDÎWê0J 1%ß¹¢Ðµ¢Ðµ.û8Ï 6+Ì)ši?%þ »�áÓŽÇê(ÆBDäù•t0ǹRz³�Iœ¨ˆÍñ²)‰Ċ×VVê šd·L“ãb-v©k–TO&Äfƒƒ4´±Ü·õ+;k@–¸»½°öREÃG[?=&~ak#ÿ‘¯ÿ%‰¢¨äŒMį HDúÕþŽ<¹Ð]Ú—#íUQòìT^² O#�–{5Èá–˜’ÛJœÔVVøâ—dY’¿9� £Ï´Y¢!ÏÍ Ë ûWn»Z|eg“s6íž±f!5ß¹ºÔ³qW{îþ³EG.íZ.eì¹þRм牿nÀ‰H¿ª;W&-‡˜•Y`8�TâW�&&&fîܹ8¯ŽcªèèèÙ³g“¾4E(11o�b%$$n=МHË'Þå]Héñ¯-ƒ¥ª'"ýªùbµu8¿BkuêÍÊhÚ0²ð›¨‘å_òÄÅÅM¶eàÈ Ü'õ§õ}�¯™�œl'þº$"ýÊÓÛ’ïJóumñW}ûEV§Òý ¯øbccñ›3gÎ�F“˜˜HúÒ'�F˜ÜKLL\¾|yàdp�4ç+^%þº$"ýÊÕÛd–ä`³âY…4IAÑ}ò¿ƒ3gΜ={öœ9sH_š¿dÉÿ½Z¾|ùâÅ‹¿`=w!/þÔ;¡˜AÝD¤_m÷¬Å«¿þÞx<[fÏÈw$#ž%÷n][8ghVZ­vñâÅ3gÎ$}iÊÕÿTZ­ÖÇæÍ›X–†�7�kgåÔǯ〉y~UÝiõÅT�”så¥.éùŽäBGj™=ƒè‹u ª­Â/Ý}÷ݧÕ*¢å b¥Õj—.]ê7ù¡e´ŒI>÷Ž„ww〉a~ÕØ½¿oÈJeíulFEEá·,°ÂjÆŒwÜqéëR‡¢££cbb�Tòÿ©äWy’_%[�Äß8`"D’_9.³8�¾ÎíÒ9ZE/ý…_´¡–EúºÔ¤Aëh¼I�ÿˆÉi_!–pΪ™ˆñ+gOc±+C.²¢‘]Ç©§'6«ÀØ`Px�¢££g̘�o�F£™3gNtt´ÿOå£Ó’_m?v™øKŒ›ˆñ«Šö-¾ÓÍ6-jU͉›¡9«ÉsŠ9èÂËçÀ+..ÿcqàê–Ë;ˆ¿tÀ¸‰ ¿:,w?F“ç6p=²©#A¸ôó§_À¬&¢Ÿþô§8—…OèøËk«ÝPt Z`©�ð+[÷~³¯I›�Ù<·�ôK3*ÝqÇ3fÌ  Ê×'(lV�ïø–JfÕ×ò´ªåâï0>ÔîWöËu1ùÛU ê0«Ûn»-0¾šlýaBªÀû©Ñhî¿ÿ~\½æ?Hh=ÔMü½ƇªýÊÙÓXê^ƒË×9»žS|ízàhÿY¾�ô¥EˆüËjüëÌ™3gÍš¥ÛÐɘ$ËZ»º`©UûUÅ™­¾j+›�RAŽ}Ðhv0«àjPeÞ+LZÝ­Õz¡Ë¨ªQ¯_ê*ð™•�F­:åçØ±;šήDLvE)::w£( 'µ¤þðYíxIXÞÐKüÕÆ�JýªáÂ^³ÜÏÊÂ�C²,ÒïÇ5䟸!‘Uè„û†ùo2þUîà'- s`°—:Q£_�¾|Ô×îXôYé—ã:-¿�EúÒ"Y�KBÜêð%Ö¢C ©0Å^•¨Î¯œ=�%®Õx„DA³‰Jϱ���*°ú ª™5kÖÒ§ß’'…I!ÖÌQêò+wos¹< le¥¶ô¸Òsìx ïßaǹ_ˆ¬Â£A–ýƪ݌Üݽä(ÌQêò«ƒ]ùجr[S èÊJEçØçÎ�˜õÅÓ"æÈ"}i“H�åXE½¬ÏaÍÒ¨ú�»á`ŽúP‘_5\ØëÛt0&»!·5…ô«0’üÓ"¥P`ZD˜…w`ýEY�<÷NšœÂ2˜…F8˜£6ÔâW§/×Zå:v³(õ4FE§­ð ø×:L‹ ¨øøx‰F£yá½Í¸ªa3ÌQªð+±§Á×+†gP{ºYTtc+ÿ´ˆÀzE˜APþ¿,ü}±h9…ÅU] þcBù~%çØ7ÉÒÈ‹P÷zÒÿ‘äßûó›L‹P‚c]Š¢X“ôyZYU *Cù~u°Ë‚G�润˜:V#/"ýÙ¿ªüÝ«üïL‹PŽM||<^žp}AüF�Âýêä… ¹.”59ô&;«ä{à1[á:L‹PŽðÑrÿ’r H(©½DüF�’ýªõÒa«€û±K“¹LåÎ9õ{”?²º÷Þ{ï¼óNÒ× ¸¸8âýñW é°$TŠõ+Ž]Ѿ‚”›c4–šY)V�‰wŠÒè²›¤¡Ïmä_C`”(ӯܽͻÛ6ùª­¼ˆSpŽ}�GA3+… / ñczì%�¼KgŸUƒ2ýªªÓŒÍª@Ôš»Ò›cš³³R¾¢££çÌ™ƒÙ[ëÐHظ«ã4IV ô«ç˱YY쬅׈ ÍWÍY�Y©BOÿ%cùë)<ñ EQ‹~6šEh2£|”æW§.¶à^1‚4GÞbWhÚêÎ;ï¼÷Þ{ý6CU$Æl7Xí´É±pÙ“Ò‰B:×6-âÎúâ¯$0Šò«þ;Ïdµë‘Rgžâi04PEÒ[�´Y™ÊIÒœ4ŽðÏ«Ê5MüüEïokÄ–µªZ»+åø•»§y—g#^ j½ÚÕÝJì㟸„¡�ÊBÞõ¦‹\-ù’o½¬ z«S>z*þÑ£/¾·è¡§ßÙxÿ«Á"%�PŽ_Uu ߇ˆg7vêµ^Å¥­†�áŸp ³23ëÒ·6§fŸÂÌ ÔŽ�—Éõfž• ²Rƒ>ájèrZhÎáÿ×d«“ø+ Œ€Büêøùݾ�Œ‹Æ–Eúm,ÿ™åÀÒ˜e”ÙSŠc>ßgM²·ä´ffÖ1—o° ™Á—À‰Wûâœ}�rW4Jð+)Ç.×±›yZŠÜ]ŠK[Íš5 ÷Ù ¬ …ÝÀPˆÉq1ycêó%N^¦YùŒ2{€5]Ñ’-âÊbχåæšîÝ'{ÙÿÚˆ‹BJC?,ïüOX³�–ï:á„ㄊ†¸_ Wꋜéòg�­lÏ1óŠ3+ÿ´¿Mù›±“¾4ukXk’þ5Ç%î3Ë�Ј¾d´J¾´qW‡©êÜöº+ûš>>Ê>úiíå´—Á"$[œ\õy0+åCÖ¯Ü=Í;=ðÐëõ6uW‘~‡köìÙ111qqq~³ÂÿGúÒÔ$ÙšÄ>kâ}5FkZUìÉ*ï4×\(;v¥ªå“z7Ì<�t�õ«&üy̶k«;¬^¯—ô‹5@sçÎ�3gÎìÙ³ý«?˜1²†Í�û­‰E£J4¥X�ëÊÎlÝÛUpäRyCïÁÖOO‚52ýª?Çî`L]¶]Y‚¸í»‰oQ||>^å Ø¯›2uúôož~ã-×O™øÓ§ß|Ë׿uãÍ·þæÔiÓ¿õwÿüï?úߟݷ8æá·{{Ûk«ö¿~Ç™ì}g k!#Ì~uüü.|œËd7æ: [;“Ãþò^UÔ@ÅÄÄhµÚå²H_ÚhuÝu×O�6}ú�·L¿ñæ@kºþú©7Þòõoùú”©Ó¿þ¦[¾ñ�ß¿ëG3æþ&ö©øåzÉšVïOͱ5APáô«æ‹‘ÈJ©Y'Ëñ¬Én$ñN¯AÙu\ ªäi}‰¦¯ J4M�:[ÓõS¦þ>¶¦ÿþuüý¼¾äåÕϱÅÚÍ'W¸Öïh7UAPaó+áJ}¾3Õ¿�dv*è„àÐÝÀ3fÜqǤ¯Ë§«Y“/ÑtÓ-ƒMþ՜ߚô9-¾DS äÀ¿r÷4—yÖË9vÚâÔ›U/ø�Êÿ+ÉÎ{×]7eÚô©ÓošhÂÖø›S§Ýðݺ}ÀjnÕ>ƒÙ±ªêÀ�È$<~µ¯#çØKÚµùn5¶:á”x罩Óo¸á¦¯M™r­DÓª})VgæÎöœý犠˜„Á¯Žž+óõcw1V—®¤])¡¡fŠSÌþ:ðWVì¹çw Gþâ)S¦~ûïþùöÿ곘»ôÍ¥¯­)u§.»9­Àµ~g{n€5A˜„„Ú¯š»šq»S/-]JY -]˜ø2ðš½Pî_ò§iÓo L7ù5ý†›>¿B—s [“©ê<äÀ`A÷+±§¡ºÓ²Ý½¶Ä½ª¢}‹…7âÒPN¤9§R4ßqÇ3fÌðTãèi<î^(¯®¬Ð<ª½ãÇ¿þÇïßõÍïüônôÏ?D'ÿ<€’ ®_IäÅ$ðÛiXœc/?³‰T{]ffSzzKjªÀ0˜Ì‡òÏ9 Ê|µïœ^(¥žM{¤øÎúžƒ­Ÿâx�½w³¥ò¡å¯ÜsïÌïßþƒ¯Ýú�u[·ÿH€b ®_áé6‘Z†J½­HøU]ffêUu™™Ãð #²¬È²Ms/¿;pºMPz¡°HL±:×–µI½P�9^~Ĺë�@ü#Š%ˆ~Õré�Õ7:p°eYœLMWÁÍG‹lIy§oÌs§!Ïhþ[zºdV,ë®0š®|óÍù±±zÝðFÆ®qõB‘f¬ÞÞ¶yOgþ¡‹�€0D¿²uï·:S†õ+N`9qü¢Ú,Q—-$åÚµÈÆä¸Ò�ÇÀ Ž7šì#ÿ‡-©©<ËòÍ Ã³lcêªQöB1ZÄÕ%mÛ*»Š�\‚8�"ˆ~uúrí°ñÇ3&Ѱ¡kœÉv­Öûþú.m–Èr’ñaoaÍ¢Ñdg9‹xÿWÍ�ï^ƒ†5+ÌÉ”ÕCÝÉ`Ó ]v·›^(?Ù{êÀ@17Uæ^ç˱û%ó�æŸ^Ô�ϯ’Vwkµ^ ü¾fQþþš9p»!ùj~ÕjHa��^ìÎ;p¾ÂöQ½ Æ €¢ ®_�¾TkîÛôcØ ˜ªÛÐå[µ ÂÜWE0b¢©>míÕüŠOIm&}ÿ=A¯¿:t¶(`g�Až4N4˜„ñ'¯¤vÉ×*ð%š,ÂÊ"÷‡å\Õ…ÒºË{?:lÿì„y§�¦‡1+ƒ¡¥†�€šº_íjÛˆC)ö ÈiDž´q›•ìW=l|Õ·0ÌÙw¶Òöq�0L¢éHËÅ'ž|nÓóÏÛ™•ÑØºýñ›À˜®_¹{›Í¢TОç6LdCp€_™EÖ<¼e¥æ;GøÑ6ž}ä±')Šzá•7N¶;¶p|ÚJ>=Þ›ßr²�ø�`¬ׯš.VùöeË Š_1�ß6ÌFžÅ¹×öÑÕ~®ª“�=úEQ/¾úæ áâ÷€‰\¿Â}c8i1´£‚t~mi‹ˆ«43ÏšƒE(ª½xµª²ÎýàÒ‡)ŠzíÍ÷ë�Ÿ¿É…àúU�ÜA9“‚éWfœ¸—±ðvu×^¡=fùa~ñ’)Šzë=c£J r¢_IíÙ}Û‚zä ZS>éüa_ýy½ëgñv<½pÑŠ¢ÞÑ¥6ºÁ¬ÀkkûªÞõedœÈ¢_UušñΠYÚüSÚÌÓ}³ÎóªÎ�ü³”T6ÎO\@Q”>y­­ Žò“�z×—›+º Ñ` ¼Ð¨ò÷"ˆ~UèL—Vl",¿òz½ù5�´\j´8G¾Õù»êæQ•²z3ñ» Ä9.~‘–ï¸E%nÚÓEüÂ&B°üªåÒ¡þn bpüªÊvÑëõâoºóø•~ ËŽ#ññ `VàgSy;¤ È`+¯¾«®|‚åW5]VßÎ œŽÇÚÊÊmÕøü¡°¢Ð5Âê;§`_l\œF£ÉÜZHü~1Ú¼ÇÄÏœútûñËîì¼Z‰õ¦òNò—:^‚åW%®Õr—;6X~•Tz\[Y‰ïðžÆ«þ��eÚ©‘•Åí"~3 DÔ»¾<âøl_ÓÇ;Ž_±îÎÙwn㮎5ÛϤº’-N�êÀfe±‹ø�3n‚âW§/Õöß>eíÒ€†â&Úw{ÝW»ø�9¥�&66v›µ‚ø�€qpÒýe-ÿyu˧å'{Kê.›^ØZyvîöU%ž´B—Ñ*²æ1x‘ï -âÙ«ÿiFÑd÷«C]…rëÉ`‚[E¥Ê3eäÛ»¿ùãa¯|í& EQqqñ¨´†øm€A4x¾:&~qØþYÕ©Oöœì-®½l:pnëÞ®vµ¯.iK/r-c5¢¾d”Ô™„g‘tNMú‹Ý�çÖVVê šû¾LªØf9qØF”,Ô[Û¿*u¯•k9 ‡&Üô8Jî{ÌXí´ü×ÊšímÃ^öŠuÙE%Ì›_°ûñ{L6ê]_JFÔòÉÞÆ�ÊN\)<|)÷À¹M»;Ö•�É(ö¤æ;�c І1"Vêà�ŒÙôÈ> Ï Ì¢;XNÐÚt%õÚÊJÿKÄú[šp<=Üÿ´Î¡ÊF”÷+Çå:|¤¡ÝÕ÷«$®U²,ù›VŸútÐÛÚ¾bW|@QÔ¼ù‰EõÄo I4x¾:ÊŽ�hg}Oqí%sõ…-{»Ö—I ´Îd‹ՌՈð9²>#’ÖkûÀn“ŒˆÅ‰“ çì:“Ô|ï^-¼A*b”Zòj D½ÉῤÃvõU›¸_>[,·ua*Û³½^ïÍJ[ &™í¸߆�ƒ»(4z¾|�YIQTâ‚EeU-Äï ü«³}Mï¬ï)­»l©¹�{àÜÆÝkJÛÒ‹\)Vç¨]h�IÍl�È�çöz½9•íÑœ\rH˜tó…°Y±r£Î"è¤>'Ž”ÜVÿÅìo>Ù¢X&îWežõRÔé 7v޳ãq ’¬‚¶ÀÊ:=ÀÿÝ_¼£K¥(jÑ’ËóÄo úÓD-Ÿ”7ô–½œ¨;ïÀ¹Í]v¶g”xd#sÊ:pu&ÏÑìKi½ú¬@#êƒë3"N(¬éªn¼4ñ¿»C¡”ÜÖ‹]Js¾+ßy¼‡øC=ô+þòqü¸¤í&zfPouê,¾þÆYªDNºþúÆÛzŠ¢–<¸¬¢v¤¶W@dhDRšèØk€­)mK+Û>þ¨óÕÃQršhC—nÕ%­V‰F4ze”Ù‹k;¥Jì¾jRsõ5Nº)‡ úUí¹RÜí*ëÌø;´û¥·ˆz–›…£ü_ýY/~úÊëoSµìáÇÔC«½pp¨¹{ùó¶î>Š“˜�ùê�õ=%G/£ƒç·Tt}°³}õö6\SD6_Ùòz½U¶nyÅê3ü­{»Tqäv‚~µÃó�üÌ™ÂÆ‰.uVAoöµbØ\ÑÊéÿÑs/½NQÔ£�?Uc;GüŽMîúÉ=·~ýß¿ý¿¹/Ƹ:çÈ©Ë×üOå«ñê,{ÿÙ�»:Ö–�YYìJµ:Õ’¯ŽxááU¬Ù—�_¿£½~Ô³ÈI1¿®Ôãa€••ÚÒc^ Z�Õ÷á<&ú6[ëì=Ï<ÿ*EQ�-æPóâ·kR‘_^ÿÍo}?�©S§Ýö�ÿ|×O~¾è‘—2­µØˆLUç6í¬‹\É‘˜¯ŽxI÷�sM¾ZÇô"÷Ç_ÃðÑ7ñ«£çÊð‡¨ ™®¬œÐbЀ›\Éö—³ï,¾6iZÄSÏSõôs/×¶^û/w`¦‰vŸìÉÝ#®AG“ÖïxYŸýÈ+é_ÿæß}X7ÜtË׿õ÷1¿= óÕ‘'iîpž4¸SŽW…d«x Y¹ýÃ'âW»ñ('‹ìí&Ê"ߨBÖ,w~�§E<úøSE=ÿòŸŽ9T|¢œ�FTr¨ãâ“ÆMJÎ[þÆêOjç,zñç,ûɯbïüï™ÿïöŸ|ç¶ïÝ|ë7¯»îºk>©ë®»þ–[¿ùß¿Š{{ã‰É™¯Ž<19.}�M:®+ou±fqç …nŽÛ¯Äž“òàÙ´èô„’WRþ«ï³�ª¥E_uCL‹œ¯Þs¢Û\áÈ´Ö6ìø#³õ±×Ò{Ö‚ç9gÙ�~qÿ¿Üy÷wÿéö[¿ùÝ)S¦^íÎßtË׿sÛ÷ÿñû?ú×þüŽÿê?îþÝ�~1ç'¿Ž¿ç÷ 1ë�Ÿý~ÑÔ©Ó†ýÿkFÌ“ïqºœS“3_yÒVV&m?®/höo¹š*1ý2n¿:~n'ù‘]�lZ ÊD¸ŸX½ëË}Ç<¾i~o²M‹hð|UÝt¥`¿°© .5k÷_RóžysÕ¢§´s½ð«èe?ýUì~:ó¿×­ßüîÔiÓ¯v?§N»áÖ¿ùÛ¿ÿÞþý®{xÏ}?þ_ê~—ø‹?øú²×Ö=ý¾I›ub"Ïy’;� ú¾(kmYÛ §‚^Ãñù•³§Ñ"ÍEeKÚµùî í J;ª}‹ÁíZT7-bP}uñQ©%Hîþ³Yå�ëvœÉ(òH퉆;ýúwÿÎ }ó»ßý§ÛÿåλïüïßÞý›y¿Œ~ì·ñÏÌZôGê‘wæ?mXúZæãÚ]Nƒ?_ýËß¿ð£_̹{æ¼²_ýaá+ѽ5ï)vÙŸ6¼”¶ãݬzÈWƒ&"=õÈ©Cüb®(t¶+eÓp|~uâ|9~í,N}Iû˜ƒZdÓ¡Szt:pŸèU:[QÓ"ÕWo?vÅ|ðBÎþ³Y{:×—�É(õ¤ä;‡í×1ʲÆ77¥9G`¾ú׉�üô× ÷Îyø·ñÏJ~õð;óŸ1>øÇuϱ…on¨aL§!_ �tÈ£CÛƒE¬¸zÏLåûÕž3[ä3ά‰óÎ mæuè´Ù$÷î+}-¥_Fʪ¬0üÔê«OôÕ^2U�Û¼§×W¯�ê«CÛäýœ–÷³›ßÏn†|5H™Ò"[::ƒ�×·iˆÄ⣗ÔèW®›UZ 2Ùvm?¶ä•^nêçOèI'y8áµ´b�&–¢¨äŒMüq†öAÕç7ï•#¢bOšªú�€@d…�w=ê^�ÚýoÁÖÊ.²½þÆáWõ*ðå›x}¶}l‹ÁÀTžoh´hbc)�&aþ"ÛˆFäÏWKG_k.æí?·¥R:q&uŽÍwŽ3"‚újhDõ¿&}5ð'¯5¶XQ~µ·}Þ䜆±þìƒZ¾¤Ï¦(iZÄ‹I[ŽO-teíîØRѵ©¼#s×™5xi–?¦ƒBÿjN¤Os"‹xƒId�C›m×›EDP_ ]C²Yõï‹­B-O¦=éXýÊÝÓdS¤Ë÷¤q.ã˜ð£Ðå´Ì[¸TûŠ]ˆFÒ*R”2Ef‘æ´ELÉm틈úûW3œ@Kà^Ö¼>Ï‘”g×fÛCóHA HŽŒý‹#žH㬱úUÃ…JßõŠ,ò¤�õ§ؼ½¡æµÔ¢~_’,HŽ‹¤"‘µØ�HxÐCpÈ }È�^9GáÁŽƒ ç!"�B'#�È™†<þvmi[S»·Þýå^ÛG{?ªý:q¬~UÙžãw—qüÈ,ç¸jÅ  �Ûâœ<‹xº¨Q_z6Î@ %( yŠjÎz½^Ú<`½c0‹1ïÀ¹ÆP#�ɯÜ=ÍÎT9¸2ŽÛ¯üÍ+­ø2Ê쩎Üc4y½ÞMÝ;êαf‘”F‚ÑâÌÚÂùÑcò+[÷�~ƒÇœ¼ò5¯@†w½^oÓŤïR„²û›?Qˆ_9[Œw+Ûs Û0ª²]�ú_É©í“îð�ËÙ¯vxÖùFÇt­"}‡@ �RTPÓÉ ©·yZ�+lf5²_ñWŽûN]{×�Iú�@ ¥È?Þ+«<„Ý�ÇäWGÏmÇÝ®¸ötäE¤ïRŠ¤Ì•í ö4„©-Ã~eôfi†˜TkŸ'è³DX ‚@ Ÿ´¢¾oý11TspFéWRvÝ®÷·jÏsACÔ/�EÔÈ=E-ákËpU¿jM’,Kö«­�É9nè& �ú¥7‹¸íÕ†ÝákËà'aÞü~e×!Ü‚KdMNvkg2éÛ�$ùxžä…‡/ð«„y~³zäåÅy‚¾¯’�E<,A ÐùG£†³-ðñÕ‹Ì£Y};ƒàW h�‹Ë?µÞ¾¶ ÃúÕŸ×<ÅùçKó ø ƒDlY+‹=á7«Aùöw?| oTšyšƒ¡ó h |uHÈÞwޏ_eÖeâà*·5Åd‡�A4@Ò ٯʎ]!âWóøýÊìd}•W6·5…ô½�@ Rff]rN«¯-Ãé°¶e𓘸°¿˜A.kG< CçA Ð ­ÜjË̬“:L™ÃÝ–¡ß¯øüJ«ÁÁUžÛ`¿�@•–Ýb°ÈmÊÎ1«@¿zò�K}‹AQ²,Ò÷)KR…“<}ž«w[?óûÖƒúœ—å3δY€n¢ h°Nš=à ¡<ìmúýj¾œo×P[êßCctð+4P�mê„p·eðƒëE}aI_•=m A $«€Û2°f�”Y5�ñÆÅÇS¥ýðyœ¹z-y9�@õÄi¸G_Z�62~ðŬ*ÿ3˜[p­«�@“T<þòë+JŸx-Ùÿ;I±±±q±±q’âããâæù‰q£À÷•rp…ÿ¿=½ˆÜ��@ ÑêÿÀº endstream endobj 101 0 obj <> stream xœí� œŹÀ{wYNA®g0*xf5‰ŠJTj|T⊾§Cܘ§„DcðD"ñ‘€ $YÁ! rÉ!ȵ°À.ì}ÎÎ=ÝÓßûͱ03Û=]_UÍöLmýþ”驪ÿVWWõW_HÒ Ý¨ª¦u=ùß ÔÂø½^¿?ð¹êtpÔq£Q÷ºÜí —³¹Ùår{¼^Ÿ×ãjªÓ<,2K—Ã<…}‹a?Ki2ž*'€—íµ}¹é貊yÕ,Cñ1úðÁýÜtd/…R~5ËLX}ÀJn:”7 NåV± Åþ‡š g07SÀÅ4” › žæ¦cŒ¦6ñ¬YfÂØ?öäòÒq�K¯ãX¯LÅà§þp0x-/TA׊e(L>àM^:ú„ržÕÊX˜|Tô䤣óF¨æZ­ŒÅ ü¨wqÒ‘õȱ#ƒø”“åpð­UæÂàÃy'ùàM¾’ÙŽðÐΉŸà¤ãNUÕ8×*s¡÷±-‡�Ž<'Ó H0¨}hWñÑq~%¸¸×*sñ…=hx‰�Ž3÷@3÷Je0´>J»qÑÑq58ùW*ƒ¡õ1†‹Ž¬…²wÄãR|l1Ê‹àNA�2:Ž\tLdY;:¿ä¢ã5(ç� Pùø2‹‡ŽËš¨§¢âBã#0”‡Ž³O°F¶ˆ��éx„‡¾%§åÉ@ùàúœ;’‚ñÁ!<ô>]N<’‚ññSf7úäÄ#9ìá¡Cä A È}°‡‡ö?.W­¬ ÷ÁÚõ+¹¦k ±æðМ�el�5¤>TæðÐÙ²w@êãeV¿•c „>ŽŸÁ¨ãž œx�@èƒ5<ô¯.—ØI óÁ:¤FÞ­È Zog í{XŽå„ù` í²Û¤2@âƒ1<4ûC©ƒ¬á¡³änfr|0†‡þZ¾ñ@`íã[xèXM¥ÙðÓ^±ò¡3†‡^ãÖånf–ýãoL:UËEDV>ز‡ö9 mWHîCg í²IæíAbÑ?Ö²L=²—ÈÞ�%©�-{èërâ�&yÿ` }<2˜KÒü Lá¡£5U¾ò@“ć¼ŽAÇÕ.]®éâIÖ?XÂC/¨’�V4$ñÁÚû Ô¶qMÄ ‰†ðÐŽkdþV:Ì}|F¯#k‘씘úpžKïã%ùŠSOÒëx<2a(%f>ÂCG©A¹#�c:Cxè÷œrÕŠ“þAzÎ ¨²¡¢`ìƒ><´Ç(³£¢`äC£Í-‚{*">‚ôá¡YïB©\DdÁÀ‡ÞDúÔÊWL´öá �y­|TÓ‡‡Žðk‡l«ˆ $ú¨õùiÃC/m‚=öUDÞ׺·Ã(u (ƒ�6VDâ}¨³¨ÃC»{í¬ˆ ÄùÐ|Ô᡹«`ŸŒ^`'ÆG¸9ÕQT:²æC© å@«xŸŠl¿‡ºö~’<Zùp]L¡ãçºg±mUŠV>š¯Ä©8gÒS×ßì >-7yp¡•7îùêE�ËëVáÉ5¶Õ@,ÇsÏd”ާ"ÉOÜngD"®°¥#7š›ÒµÅ¾ˆEüýj_“vÆÇ%Ñ�P¿=8‘0~¬‡w1>Gä;^$øP�Ú…Y‡#“Yy‘ø|U�;ßcd¸ƒæØV~Ñhõ¼ë\€2¢ÊéßY2<”­|h0ãCɾèòEð§Ol«€`´Þ¯¦ù¢„(Êù~×d»Ê/Fûÿ‚ô¡Ìƒ7eö7>øz±ñ%ýžM6•_4 ÷×¾†í s`…-¥#ºû,¤�¯|Ââ‚ñþóØò&ì°£ôâaèCwýÒGO@®™ðÀ$?ÃóØ2ØPzñ0ö¡;z!}ôs«r�Ìò—LÃv�WàHÛ—^<Ì|4�‰ôÑ·Y•sBvLóû<ƒí /‚ ¦fÇÔG=vËZ‡&»2cžÿj*¶ƒüQ>b±c+ÒÇ™ šNtDúèV­Ëíµl$Í/ŠÞhû´œƒ0’ÔDZØR%C±ØHžw¶ƒ<'Ú²ôâ‘ÜÇlé|’à8*‰9ùÛÑéôŸ€Ê6,½xXø8€ÝMØ©,I¾k‰%VçŒÃv�Ç@¦0aÀÊÇ~lÉ= ò==–çÝ…í �È„K»°Ù~rKäöz¬Ï»�í Ê„–ôXûØŠõ‘sPŽ ÔœÏyVÈò¨ j|lAw�ýDgÜK 9ßùf¬�ûd>}ZH|¬ÅúÈÞ-;%DçÑ߀r·<%•"+±>²vÉB‘@´öy$d>–c}([å2/d>àj¬�ÑÐÔ¥B¢;È�ÇAR@èC¿ëãvyÄ „>à_è²§¾øÂAÚ?‚—b}ÜårÿÒþï¡;ÈðQÊ‹/¤>4\"¿×C™ÌÚ€…¸À|t)‚©r�'bT"¿0ׂ¦k2<±¼ƒõ1-4EW¥ ä÷+oà|œŽ!‘ä£Òr'à¯8�G“ÁÊ•^ä>‚^ßÙ(¯¶|0•å r°f¢|Œ�.`Éh,[|Þ�˜$]kÃw*·<|ÂGð#ÐO�Ç+^YîÐdª} à ýËUˆè!¾ã ŽLiùEã#uè�¸g)‹à—òù ÆG„àlŒ�{ ðxªÊ."xP<¶¹�~çª]H(|4/y�8#l,IIÁï£nòòЇvÌNô¤õ$¬LUÙEçCpþ@QºŽ�Ú$X½p\wKád*Ë/ÈþQÖ’è2;oúÀ[4ù\ !ßÊÀH^X}º¥¿3¾0´$²oÆÈdiþ,³b!ÀŽ~·ØÆî2rVYèûÂñ¦ùH¯ƒÒÔ_8°>ÐêèaƒÚÆ‚K }dWÉ^rðÏWF‹¼}Ç- …‡–Ìi�2kAd¡EBÞ‡É ž†Ï¥u-Ïï—ðî–ÒÉAûPá<³‘B4¹( í˜ž;59Ã+sbC1?ŸhêCQ”Þãæ†vŸ›³¨"'„äPø° åÍÉ›:œÅ]49ú~w–|eK …�† !Š¢\�ZT�}3†gåüS¾°%‡f=ñûÖ>”ð¢Jy(Íõ.©��çˆ|„U 6Ê·Q(h|l õâ_j .(4>4ÌY-½åí Õû(T޲ÍòŽ…€ÊÇ[ƒœR9T>N`|(箑Bˆ¡òƒQB”ì.rŠN��Çq>e’ÌŸA���±>èò(#"è|¸r±Bv¦¢ðBçŸë ÃÜI ô�>oøj™ã’Jè$°Y'äC/ ”>‚ØÒ•¹2)/ ”>à^¬�12,ŽZó°>º¸åÂ"´>pK&!–ñ/¼€PúpÁP¬�Gä�Jn˜‚õÑ_—3k(}è°ëCÙž‚â íø¡{±§ +Ódfkh}à¬�+åb ­ va}(r£­5´>TÐÆb}¼%SýXBß?àØw�>FÉ–%´>B¬G½Ö©Yæt·‚ŇçdIeþWŸË•,> â8§ì¥”/¨ëA¶aQû¬ß¸çã¬T5™÷K&CëÃÿþQ(ÀÙz�RØfB¿j‚¯Ð>~'§è°Œ&{_˜ËRóÄ+д†ÁGîDw�£œ‹ª(aðÂô|…Š«ófjÚLúƒIx[ªŽ•Òu!t°ùH²Ý„Ž)›¢ÄØäÎæã—è"“Å%‡ÍúàNe‚<[Ñãé£ÉC¥’Áæ� XŠ¢läXxaôñ'´�� “Àèc?ÚÇPùR*Œ>‚˜­èä)‘É`ô?EûxC„eñ”ÁêãŸh·B¿â «�z´�ÜFÙ?ÌaõCÐBþÉ­ðÂìã×hÿ%oXæ0û@ï$Tz«"¤fôVte=·Ò‹³¸íc*Ôó*¾p°ûxíã"9€˜Âî£ íC9Ä«ôâÁîCGoEW^ƒF^å vðÚÇÍòÌ38øXM` žœ:" Snä¶EQÞ—‹î&pðÃÐ>îƒ#|Š/<|Ì@û83 ÓÅÃÃÇ´e­Ì.c AôVtåWð5Ÿò‹ðc´�Áò‰×.>>BûPÀ1.å .>(–L^†s)¿hpñ¡÷Gû¸¶É×¶pñãÑ>rjµu<Ê/||¼‡ö¡,„·x”_4øø¨ÍFûKå"okøø€ï¡}ôð{–røbÑàäã·h?UÁa‡_8ùX‹Õ1"œ9# ·£'ÀLJîÇnEßù S&UŒ‡Sÿ€ÑHÑŽ¡õã7!íõNÆËÇ,œŽÜøìH—Ósëò–ˆ‘<‰^>"ûÇÖÈǼs§Ï*ÜXãÂ]¾ëÓ·[ö.ò([&Áɇà|Œ �çþo;DþØkØðq“g,,ÚWw£RW~x°}u^ýAv�»Ž&ï}[ý÷ÎòÆ.I,’³¢¤øXe{ØxÈÍÇHJçkǘ-CÞÑò6×÷Tb§ 4TÖ:ŽNáåCoì€bNöΈmY‹»ycóG¿Ó)^�áæ®åçC™¾¦º¹Oëÿuz¤9ýåšG˜ÃE¸Ý¯à÷ÜldÍ׋Ÿîøà'É» ;MÀ�ÙjøùØÄKGÎJ X_ˆœ¤·¦Û8Ê|‘º”EŸžê4W¼’Ö Ÿ¸ùýäi ßekºž[`ÿ^Nqá~t]×þSßÈîÞ4]@æ÷|"¸ƒ©áÎú¾n½‚ÂNÎ-/ÿ_þ³ðu${ڔШž®‡‹ñõ–›Mÿoa[onÉÙ �G~w×~/nåXkŽpöÑt=}ƒ <ëºskþÖ\tœZ0Û7q¬5Gø­—D.‡�Tlá¢ð>PÃß`~Ëo§Ã³éùØËˇ3rµUÔ�5´>éÄ©áMèS«ßýíõðe%�js‡“_qè˹Ÿ..J^¼Ïq…ؘGao4»GNƒz€CµùÃÉÇNØ6}ݪû©ÀopÀÛøG,Ù[NóºÒ3²…��R¨<›¥¡F8áMü.]Z`8K3�ñRì ¥b,Žüæ|¨áÒ~¼áâÃ…~{ǽ}*§ö¶¢W5Üù]1—æãn˜ÍÒF¨ú“œšÛš‡àPd�›Í§ýxÃÁ‡ ›:2´ÐcA Ÿ…š¬uÑcÈ~œ²³÷˜àÑ?*X– 0Ž[kpiÀ}~è×îéËÍ!ß’—þm^8�û]ü›„7`iø×ôÌÈì#Ó·MÖëàþ¿¦&¢{y$øû¹µ!OX}èð}Ód½É´IÉýp¤shy1-Z`îèÇòœЀ?@„�50-4Y¯IÇWR¬>JñÙúZ踪.çÚЄ|×ç”®y²}ø®¦n•®Ÿs�\ å¥ðÁW§ãy·Œ>¤n“n«áè ®­LN×c¡8g§c ›�W©›¤çf8À´ÉÄÝPÚMQöñlHN0ùXMýÆâ¬]°“~äaç3xAQ^çÚ’|`ñQJ Òoo*#âõ_¬Œ‚ôËÈàÛGÛÃúTF.ð<)]<é·dBïC¿�¶-.*ƒ©�\°¦K ŒSŠx·&;ô>¨ß -‡e)Ž\ à¨èñtúå-§öñoôQ©QòjaqÊ#X¯\idBëã8íX>ÜsS¹@Ày.õŠ =ÝFJ®K)[áf'Ìn‹Èž… a[ Ú”:ú=”m0ºÍ"¬éxæÀò4[T¤óñt˜NUõ¬×À}÷eäyK¥Òtÿø„j2—õpŽàß  ôþàóÇ£uJ£;ÖÇAª9óí‰\0 çü[}yéö4Ú•ŽôÑ<”¦ :~`SäB,¹ƒFæÏ(Ü�õ—Í-(ˆ<ë¦S`”=8†¦%:} ”Ïd<è4hdþ¬¢’h'Tüê‹õ›¾ÞWÒà�ã!;þtZÃÂøÐáYšöèVÇóofkzå�+˜[T­Ÿ§¶²¶ÕÜÏëVit·Bö��hV{njóÈ…ˆˆ–ÜK¾&GæäÄÄø8Ѓ¢mzo…]m¹ÐkxhˆhŽ–×YU›N·"">†P´P¿=°Ý ëgâÇj­©¦!szD<Ä>‚Á;)ê¼Ã°ž¦W‘�Õ1q¬VõMiô¬D©�`t[Ž ŽÂçü#B½á�¢ÿ†Scµ·Ñ‘V£2=„>tXJ1–_RË:sÑýÊ»Ÿ^°µ&¦ÀÞ†Œ½3CÚ?vwÃ7ß÷já¹\D„˜l�=bÕU/fVdBõˆkêáÖÈ…^Ãó_þ¬8fÚ 9ê>D$…ȇ¦�Â7åMÍðW¢{Ü­ ø�Ìå³â˜tÍéð¤¶)Òø5^Ç�²È…«¾tÜóÇð�ikUü‘†ûR�¼�×qO€(aõ�Ï«áPvŒˆØïu¸D¾3cí#ßtEë¸_Õ§Xÿ­~ÿ �ò|8ÆÇcW–¼Íí¨C$@Ð?êðÛ˜&µ‰–éÌ… ñ_¤¹2h¡)EXúÐTü{½ßèšÅ‰¶��|íôvc)âÉ}èŽfÀGL€ß4wxt <:0ƒío„HN2Zh^þÖFÖ«†‘ ‰kàÍBN瘱¼_ _'É}¡Y×7ƒó–8±kàZ}Eæ­�·%–>œWëØ´Èáñkà�Úc¥õòæd‰¥�¦±&Íß±WÂÊí´èí{!v ÜW¹ïñö0³æƒuÿø¡¡�γ½>ÿЏU­ñlصv嚯ëS[|áHâ#|wÑ�. f¯ýÈk�çE†ˆÐX½ñÔÝH-œ7¿pC]›ÕA$’øM™½MWv�‘‘|Ôêú˜±ú”�o7µIÑ…$‰�àÚþ²É®ý¿Çͪӫ«7/Ž^H•O²ô$ñ±»å|GÿŽ6ãï‡OB‡ô NÎ@’øpÍóTþ.ºþ·?> ºÛ+×=ØHö|µÑT‡Ò'rмl}Þ˜ûh‚_™ûP&€®zä­‰;æ>\I�4_ó¥eBá 'Éýj{7@ùKm\ÒöAÏ$ñ±>lウ?ª¦±?é›úÀÅæ:ÆÀIAâù½dö±.^›÷�½æ:²v‚\ I ,b‚õÇÜG’}´÷B•ñgÚ%þ’MÏ™}¸ÑO²]Ì̇æ‡,w8”–©¶Û_å�í×®]¿yבø[ÅAÆëšõ�bóî1* ?"<î“Å{vìøfß±ºØÑ3X³ÃGó¢oÔwØ~TM}üÙTG§ÒtL$œ*‚�åGî?P\Wgož¢…³¦O?rØ€H²»Û£7¬yã™FSæ‰À§@Ë7fÍUe¥ÇÊ*ãâüû6†ŒÍ`t†Ào¼~hv8áóWY¾ÙÌG™iÃUb.[¹k+++kâ‚çC –/œ1yüØáìó \øÌk÷õ¼ôì^ÁP 3¯›~ísé—’Ý]_[×àŒk€†�‚Y!h¶÷ý*’šù0=&¥gCf¯"ª®¦úW\�½;–‡ƒqÇ `OµÙé=pÑŸÅjâ£Ê´\3Òô Å$]�uµñ [�ÇüÈš®ëÕ´e5ññW³/ëïÎŒÁÃëh¨oŒKc5sä^/ÐÆÕ˜ø¸Åì«fÃÊoJ9ª»ÙÑì¦�9r] 8è*aì£Þ¬ôùÓiøº ˜Çc> >ty2�}Ì3ûžPBÝxœzœ ?|Çc>ôZK7i6öa¶}ó"Õ–w‚·ÛÓ:I•îX=5ã1:Ì¡Jsfè£Ùl¼[Ç ¯ÂÍëvy|q�ºê®?þͺç>?1tÐPýÖ{Ó¥/˜0™fs‹¡�E&ß�§§ð|Íëöxüñ ÍÕGw¯~ofÁ/FÄäüí|*Š®m«f¥çgnüJ†¡³eWÂVÆF�'à ˆÿþ@SùÁ­ŸÏ›6ñ6Óñxrí?’…Z¤Wž@¿˜0òá5ÙO;Ê©ç9§šÛQSQ^팻µÝßn\ö÷?çßH6_Ý‹wÃ¥Š³¿äV #…&W_T‡¸û5å'+âó¾DçÇ¿™�¶ã1ÎX>T�ƒ‘£ƒ¡Î=n*”“>SµÕUÕµqs¢6œ§93@kbóá7H 6ÆápAMòLí­//;YQÓ”óãt"?€YÒ0ð±¬õ5¯ŒÞŸ�ë­¢dñ±òš&®ëÕâq[ìiB |Lh}É%‘¿£.ztÁ¦'kݱŸ‰¼?~ñ© £8$U¹ù2šËŽÃ^Ò-J­}¨[pZ-±7o^>ÿÕ‚‡rýÅ}e/°¢ßWpò9²ˆµÖ>V\°Ålj™ÏNúÙMÃú‰üH” º‚sB!É\¤µ�|ƒë-‰<¬:°¡.B�õ'Ð>%É[ÔÊG°ŸÁ凗TýGí?V3c¹/OjµÆØÊÇ:ë]µÓÝà[û�6¯…8dE±,f‡­|öÙ]f‘yva}üÑî2‹Ì{@ð¢0Ö‡ÆÉÇ$\8œÜ„Aÿ8jw‘E¦7QðZœ�—ì.³ÈŒ"ŠíŒñ„49òWL~O”D!¶œ”o^SÈ ¢øêX³ì.²ÈdÕÅÅ�ö¡Â�v—Yd†�%µˆéU9v—YdHoÛ]d¡™D[™Nù¨†Ù]d¡ùŠÄFØG8ða�ÚØ~‚œm £�l;¡ aiýžÇóa¾ÝEšk –ÀFØG�Þú4Æî" ÍÿYHuÔGO3σ˜%‰,"²qÊÇxXlw‰ÅæÎÇ'p·Ý%šžº“Ì‡7ìã �›â|s 1·ç¡íŸu¡®Kí.±ØL#݉îû(„ûí.±Ø|Jf#Ú?:7ûÚív˶¡š4uFØÇ]ð©Ý›Aà"p-ãù"xÈî‹ÍÏ�4Ï~èy7·Aíkw‰Åf&¡�ðö�ºQPdw�g3±�@ÝÐî ⌖Pâžmv—WpzÉS¬‡ÞZØ]`Á¹ Ö�NÏ]¡<ã�u’TÒäwÕÕÕ7469ÍN—ËårÇàŠÁínN§ìß’ÿ °Wã endstream endobj 102 0 obj <> /StructParent 100013>> endobj 103 0 obj <> stream xœí]]oÜ6}ׯàs�¥ù!R`ˆ=±±] ‰�öµÈ¦MºIS`þBã‰=ræH÷Pw4²“h³â%/yyïmˆÝö�qÆ™ؽ¿6]0o?TŸª¾%¤äL ]¶m“ÌçwÕ/?™�Õ§*ZÒöÛ‡ŸÞ~¨¼éÿy}cî~øü¾:»‰æý_ÕÙ¿þüøæËç¿ß~1ççg?_ýscœ¹¸¸Ü\mÉ´>ïRî)ü^½ª^í“®³ýØÚiú6û.›ý¿¾1ßþòa\—·ÕÙ›ÿþöñüüìÅÛ/ÿöÇí»ÿ}1ç×/¯¯ƒ › sqaúAž]ׯsû{åï8æMn¼Í¡kLèÌí‡êÜ9W_˜ÛÿT/¾›Ôí¿Í¹sñî—�M.µ©«ïêä\}é\Ýmÿ‡‘a\ÝcHäåíœñ7ÎÛ¦ö.NLÀ'ç|{¢1úÖ—Ú)&§è\ýâDcŒÁú®uyŠ�Ù9ßÌã#±�K¥ Û­_çÐë}l¶RñÍ/K¤ÂGã[›ó#ɰ¾ØÆxmÓæœ›¯œñ8ãîVÎ{ë»Ø¤ìï[B‡Zü5üÆ¡–QËnX‡ZjH§`ÔÒ �NÉLGøör¢7ÑÞÄ,ÜíU·Ý ¯oÌÝŸß3{ª6>ÚîØX±ÝQíîÐíºÜÖ¾~Ìæo¢G_8ÔÐ�‡ºòWìá5¼`'‡®é™oèy@h<¡G!½Ýöµ.ycS®c£ëÚí�ùøwܦNhS‡:ZûÎ÷6u<¨@v3�¡isÊ÷ —п¨#hˆWè‹KÔà@ƒƒ]uˆø5K#EfÍ¿aÜ_óãY1zërÝù‰#+òÇIˆ¬PÅ@K›žàBâðœÁ3ÏãgÏ•SCc¿Ô¹±Îû0¥áð‰Šv>8QW˜ÿPÉÐ]íð£áhE†gÎ+K4ÜE&»‚ó€_ðJ‚í«‘ =�˜êQâW \K•B¨¼˜ây°;,òò‹ q@#Fzkâf()´Ðy¸æ�ž\úø9îj¿~hp7åæ0K –øàhDH¼A4®ÙQ…€j4*/áÕ‘ÖÃ!âp3 QWƒ™ºjÑ—ìBA^ap3t¨+´¼jÁ˜%/$l—íDHš¡^ +¬!H€J aš�~“iDÈÝ�„W’5� Ž ²nÌí+ŒJ'ÔÃD=X�5;¿E÷i 4;/Q5ê ® íelŸ ÁÀÌ#ïpX º´yºÐz‘˜ %�ˆ€zè(Ì >ÙØÿ¸¤å,úa½PA¼;�FE¸ŽŠ·¢ò0­ù"†eÑC{‡L­Éô6� eún=f =\ÁU=ÌialCÃ-X(QW"{ Þ‰W _@àpÆÄÑnǼMpe.%_ˆ,º2ÃÔ€¸èö£h˜:€R Ôq` ÇAÑ+û¢ôÂv HŠ@´ªÄІðÜ¥#%0<‚L„PëòPò”a8⃷X‰/2…!²jÉñ•+V´�` /\�¿ æÈb¥‰P 5IÑ¡§‡ixð)ƒ¯à±š�gI�§�ïŠß 0¸: !Y"XŽ .”èþ&2®`9:Ud`G¤bôÔX,ˆjгxáàzÐnˆJ‘Dz€W‘ž †.4ÌC¼Q|¼ÖeífC9°ùÔfbe• ÇÑCuÍà”tÐâÃÞÙ0`¥DG×C5Ve‚h(Þ@•�Š6]ñk®Ö„·(mÙÁÜE.YÞóº˜`waëy�Ê÷´1R/ãhĉ O ~;ñi*Ю¹@Üx E÷5ª%CŒLP/ „g"6âA_ ’†�8"—¬(b cHܳç×züù•aFžßfpúVv~a«><Éõ.º¼—ewâ­&N§n£u15BmQ‰"æƒÚü”©Z+uùhb%ÞnÂb%Íde Qé‹Öq%ì�E7šb¼ˆ™–?°à-Oϰ ÷dæáãÓ`WüÖCg�–0 Ôai¬½€lXÇñ¥”¾b ¼( Gäðƒ¶,‰^Pr=ÏDýy¬0�¡N£ÖSèƒ/¸Î°zZ3Ë×!|&Hëǵ`-×h*ˆ®±Þ¥�§„®Àw ¶EˆÐD¶2uLɺ6ÇÉéIAô’×È=»Š/ù©½ÉU×N-òJãÑøCYï•LŶÙZ¢Þ)«‘èG±¬F~÷Pãø›ŠÁ4‹¸ÖV/¢—tR¢!wÕŠ8ñ"´âbèÉyAJ>�‡ºNoð"eÇõ|ÔÄx—SóŒ„AlÙi_ÏʼnG"Ϲ¤šµjú�âÓ*´­y Nø |~Ñ‘ŠÅÂ'{dïδ™‹žÖ›9A‘×c`�m‘W¦ ºâ�Ð|Á>hǼšH*]á‹6)ŒGNÓN=þ!Ž“ÆÍ€„ãGghÝE5ô,QŠÏ÷iæcЯÜÃw9—xÍwõÜëj®Ó±¾HQw”rÏW‘…¯ è)ß™p•­ã�¡$ž9ÿò Dü“0K—3�Ù,äº^L Ëïè¥Wi¢‡ã{xU˧ëÙ´ L%4n‘‰…ÒI�s97fk(4¶ÝfÇ C%E�d#ô¼‹“²pYÄ«‡jh*ú=ÜDF*Øø'¤Ie#',6�uMnýÔ²kpi<Aúä;mŒL}¢Ó3 *�ðÞR½(¼æKȧ^IqY€8ceÑž<Œ…·  æš·Â@Å”ÊÞb>iU \ᘗ³-rò˜MÑ ÊȦ}êx—èUš]¼ÐÕ<Ñ̨ó™VŒS&xÈÞz“Ô,()ÅW_\âù»%,W•¼DeÄŽ•Ióʈí?f]špx‚I²‚OÄÔ,VxŒ�Sç�+_·^ñ µ\„þin1KÀ#}Ûã±o]7�Í0!t¸ÌüDTâjÂübì¬ëúpbªø¿ÁÍ?EõLnåØvË?ôµ.aÉŒ¸¯"2µÃx'€ž3ƒ7žŸönºÊ¨ççòØIÁz¨›hV#¿{´Oíã«&ðvtXJ|�EÇVÔŸCÜzæüBAýK8@ ü^ü<ôªßóAäß}ºØšY"‹Ð…–#T~¿ ôºdOËðõþž{8›ƒµ6`ýEj¶RW½`Ýÿï>¢Œ !³ÅJ Ȭ¸"K® œ0¢lÉKûºàëióï ç‰?á8˜u4/1ëiX v¥—]ˆÓèÔ­•zyîò©tô¨øúzOËÔ±ÍCŒžvtÊRM¡[ÿÀûsê‚#Tè ƒxÜÓ5�–òËæ<žvø„UÌ áG(å£UëÞ«êUõ©r&ºÎ™�’3ÁeÛ6É|~Wýò“ùX}ª¢õ!m7àÃOo?¸>»‰æý_Ì>o°+´µ.„Æï‚·]Œ1�>ßñÀ÷Ö·õA‘Ôp "ìjƒà5DÔp ö¶û£á¶¨!Ó_ –@âu…Ù ¯Ôàèá¢Ä 5'kòHÖv‚C'”4IŽËÙ�ïzá ¹ÏÞêl2ªØøÝÏToväƒÏ6Ô]ךÐniä`S?Ò»Ÿö“ƒ­{¹Ìw2ùðׇ.:gsH£‡ÁÙ¯Á™ÍŸ;ê­w¶È²Íý$ºÝ8¾þ÷a_³%ÿõ/÷=D—jÛt¾™ ïÝ=ý~þ|‹Å endstream endobj 105 0 obj <> stream xœí]ÛnÝF|çWÌs€¥æÂáH–ޱYÀŽ€ìk u ,ÖÎZq€ýüŹ(:´X<]Ã&9rŽ²Æœ;Ù5ÕÕ=¥Ýî�±Æš¿•Gm:o>_Šm‰�њ໺l›h??ÿ`>_ŠP:wÏ>ÿôð©pfûßû·fÿÃãÇââm0/.þñÛ矾>þñðÕ\^^üøæï·Æš««›Û7»fZWgc½má×â]ñî¸yo»rÛ·ötûeíºÚÿÿý[óò—Ïýº¹/.~úï/Ÿ///®¾þñËî?ü﫹ÜÜm6ÞúÛ+sue¶�¼ØTÆysÿkáö3æLݸ²ö]c|gî?—ÖÚêÊÜÿ»¸ûq?¨û™KkÃþ—MmlcWýYPEk«k«n÷FºñæÏnô¹»ŸÒÿƺ²©œ 'ࢵn­>º¶ô6¶§&9k«ë•ú|éºÖÖ§æ±¶Ö5úøÍk!+íî‡÷oÍþ‡”Ýï*ãBüþ#Ñ J·ýecºP†íŸúiÜÐ,´‡×¡ëê¶rϯƒ· àPÍÀ5*èPÁ5(žn|ƒ (poتpãh®ýÄv•‡«ªô¦Uåõ6\A¾*wÇÎÜWV… z½òµÞ>ǽÝëf¸ªã‚Þ”ôÚØ 'Í<“€{¥+`U´9†såàéã¿ì> ÍA¤¸‚g8@¸Ö<½¿ ¥Ìf£aµvœfÒóÈðh3yƒ�ÛÐs„aOSYü �Ÿ€+¨Fû%¸œ’¿ÕÌû çj&Çä4?v9ñ~"hûQA¼ “A.ˆzD²  п ÏUD�ŸÕ2â ‡¨ªž5è)Yྪ%”±Iô…9G‘.E¤ú9LIŽÜP7ŽhyP‰†º�RPt9)âlhYôŸÚ g)¡»´7PÏߥˆJ\²ô8xS‰}¢ÏÍ4H‚Q‚ö %Ú§Å r ù±™&B±®bgÛ ¶ˆ1|":LĬÉ͉KKW…éI‘n«çõ�oòôñJ–$1‹É÷n<îæ{?6Ã"Û“pžV 2I˜v=ãÊSkù¨Ld �†`²SŒÌ„>P ßlt¤ÅЍ>D‘:ÚÞs¤8>¨AÔ]žÆ€q¢Lt ¬ˆß�ÑJ"H~d�I0[.e‘ÔMÙva—Øý´wem·ïÝ ë Åø,³µh*Œ`z�ùƒ¦5Ø«¢ V–ù:èÃ<>�Ñ®|•d&’¯J[ <¯‘ÝxðÁr¼NPOû¦¹—õŽE¯ÌKÍß3ÃS5Hø6`0ïGeã¾_ ‡œùk'q¦RŠ”\Bt&\(QPD¯€o�ÜAæsîaçlòGÀ�˜Í• §Qž†Í6‹BeÇO&ç, rã GŽˆ]Š4ìë:,p©Êl¬±Œ`ËñVŒÀKÀm�¢@þTP;Ó8�ö9ÁT¢5ÇðHñ9E2´Ó|ˆƒÈƒÌä." ‰³šAm˜¢SH::KäbxÇQ¼Á_?©xƒˆbºpE„ϺŠUñ  xÊGQ'Ž@BÂBÁ|èz>Î�ˆ7ƒ§Ê%´¶ÇÔ€NÇØ• u°è¬‹Ó |ØTÒÙ 4¿Ù4­$‹�CE÷5Ÿ9#ÏL 2¾ ®à´´=§Ã4õ:íö ÐW{ê¾€aEåÒn/ÍòÌ®˜JzñÔÅKw7¡ð÷Ú)j¸ó¦‰ÎºKdmJ JÖ Š[$±Ä\�¢3G¶æM>݆’tÖ&zèYvžiù!DŒˆ¦6 f¾†¸ eŸ:¬`ް"ŽÇŒ­ÊVð¦`š”H6šøH¯æã¹xéüšy¬×¿ñšC:ÃéÄP[™ãCmy¦üœ2jÔNOt§óân½õ€—bb¤wCœ,$;²¤FpÚaUüöA¯Z‚Z‰Öo`)Í›ñ•Œ-ÍX\Zˆ�÷æÓê¹M"ŽX«"@( Bß�Áβ–Ѷ§…¾®¨ÞµêK�F4þþSE%œj½NËÉ™µ8?u¢* áósô "¿Ä4§a‚AçÙ½¿TF€¥å@°*^~¢™/ý´‘P•è­•¥÷T¼² ð”¦*CÌýh.M��‰’Š™„4›Ô—TÈÆÍ1 ® ¡Œ›økq>_‚Œ„Ì[B�T/œ+Xpf¬^Tµ&cåøÆéh}Mx.rÉb(‰‚òÇ‘€Í½W0Ñ�H%s¶‰ø'™€öŠÎÖùÊ&1ßÈ©X�GN±wµ¥À 7ÑÞD4Ù HûñŽ0Þ²/àž[„ˆZ3Ÿ8Ö¢‹]èûÈì¼2^àœ¿š€yÙä¯î}‹^ÙEy= "’€É@‚H…_5™C�Ï_MsAe›!Ãd–±�ÎÊçÂò‰&Ÿ®J1g¥žnk™®-Çó4ùxöd_G½ì3|~^,�åi =¼�ÇÁk¸E·¥Ë*Kï!Ÿe`‰¥�K«7¯9fÚ1Ÿ*7Ö2�Ÿð$åÈ¡´£a[ ÉÇ 9Ö 2¦3ܨ*‹æº °-kt!`íÛÒùQíÑ~äΕ® M¬Ý·+5TÒ%”XTr°CÏljƒÏ†?T’2Ò„¾¶øPIÊ*àÚîä›OÔB—Öõøþdã1‚f&>‡„ï|þYøATÌî«wë¯ ÔÌ šg Æü ÊÙÊñ¦–s"§ÐL¢¹<=Ïš÷®ñ·0A<Ìç¡üÁ% ¾‚]2S‚ÊERW@Q)ͱÇÛ§ü¦žOZ·Þ�'—€¶õ‚ ¡ZJ§Ð§-E±ïüÆVŽ'Xaèιžèíà úGsY9=w ÞÍ1Â�§ˆ’UtÏj¦Û\Â7,2M²Â}E«×pü†Q˲ë…y —¢§—Nþ—ð©¶ãž3Íi”&Þ!ÇŠÏÔòФz‚N‰ˆmÏÅU×Ï€–]&ƒ¶G佄x –D꜉áUÐ +ƒ.¼í�ë�ìt€€Š¶¡ô­!šâ.+ʤ:�à•ì²,Þ2ÎB”\bZòLÞ˜˜$#5ßZŽ˜æÄ}†zL‚bÎ%ü8³¤1xÂ@1±ÀšÚ÷uS“*òf¼´šc:X*!Óš„fvØ»�G>›z·†à‘×’…ʆCÉÇ2Wr1QBð™Š"#‚½*"† NÉ4qhc…pO -G'P3.Š_5úÙ7>‹#n Y"ÝæÒ¹„òQŠäŸë]öU]°*3|¢Ûåež$úhžgÆË„t¼ãK´´‚ɦdÍ¥}J JØ ¼ZþœÒS ˆtãjyè¹àӔêxÓªjùwÅ»âKaM°�5>Fk¼­Ë¶‰æñCñóæsñ¥¥óq7ÛÏ?=|�,_¼ æãïÌ¢6hQƒmKë}㌳ޕ]a”Q³Ï“Õº¶|¹¾)¸Vu‹ àT°G_�oºÛ¢‚š~M lÜ¢ªð´Ã8W *°twÑ â‚Š{×;Ò{×¼«K_u]kvQ#ÑÔ¾ŒÛºÿé轫}Ym_ŒzÿR<ÿõ¹ŠÎ–µ�£oãÅ?½5·¿Zﺶ¬B�wÁ—�«ãþµþ¸ñ§ßîšÞ=?YÅfÿäx³•jv;þÿåÙ endstream endobj 107 0 obj <> stream xœí]÷WÏ×öO眄²,ØSŒIL1*ÛhŠ]lˆ½¢Ôݙ٥ª€€%à}òõc vqQ÷9ÏO†C.;wgîÜZW÷êð–4´ ¥=-�, Y@Ð@Ý%h ¥€–H8h´ # %  c-…©c„ò_ $Yh0#£•?VúÐ0ø �Lùû Í«þ-+ÈýëTä�¸îWX×-4Зtã-+èLXǰ.™¡+l镾Ç©é¤mao`%7¶q0í;š �Ìó§«(¿Šòëba3RÜŒ×ÅBù/ üé\èdÚw4¶q0°’³-ìQ®ä×áxK¯¤g A F34²øû54V0‚Åè æÐ³¨²Gå~6 îŠ*¶QÉ*NÐaBä�¸Úõ 0°PO#? DiWrp5築ù²ò<.×ÄüLàxp%G»’mQ£otFé ¥�ÊÕ²PO�VS¢Í”¦¨¢ÜÏLÁ­ ê ¾í iL|£¨¢Žé(@r� …÷Ž05�Ý8X†gÕШÛpž�n˜¦“ïúÂ-YHЀèUlb¢ÒqÂê“û)*¨åycòiè –âU�A� ‚ šm"åJMnm„ réÕU\— “Þ#Ú•l¶Kx3C-ÍVÁòú‘è’Èq¹Ÿ«‚ºb±8éI›ÝÛšWQ­‰/ŸGŸcý+Ù%ùö«»r œ9–³Ÿc¾#@ Èq„,îí©Ít±¨£2@Ý%h{„_ÎX±XT› É!‚í±�•ÜjuŒ«§áª˜XɵÆ›ŽZ‹Å_Θ¦GPw)wÒ'‚št%và{"l¶ŠöÅÌ*zƪUAÙPÞ¾�i¶IeMSw :JÐ3‚Žâå^�— ÅëiìyP3ØÕ@0 Ó¹=íÿ-»>T•Ó¾ß?Ƿ˾8ü`u'¦<)å}\hh^Çzè(ÞÀ"’ƒœ;õÂ6®ë¹Šò¶ùL½{zu&¡X,ZÜ �IÙÓ:Š'JÚ¥¡y’Ívi`%Wƒ—ħáF¸0°’k²I$ 5&ü@ô Й;íž ^ÏâX�ŽâI6Z¥áõ}ÙW¹F8¾yØb— f¼§‘ X e Ü+öœ f¡Ž)‡±v5YEE»þ¥'\ZÛo²ˆ+A”»ç�PQ5í×0!5 ¶»+YOXþ­YzÂEÇrÖÀâÀ½ºK0tšn¶µ-ʽ’5 5tPEyô¬@0�žNU)Œøò¸ŠòÔtRÏ@’mm‹õ]~ ä^ÏÚ‚ÊU[E-‡44°àëplž?•}ážçù“σ1 5 8ž0•ÐgZ¯a¡Ê%Í8x=¸š“}±ž5Ç6pj «OÇòjÓ«¾ 4;‚õVÞÀ ZO2 s|ûU¹¼ªÇU”ÿáL�,P› –©i¿ŠòȽÚ2€è�Nhvõ,4rh|óPö¥ya÷9H2@Ey4Tðµ¡p®2ΛÂ6ê—áØŠ²}U‡+ðìëpŒdpŠ ±+[î• ”ÏG£E(ņ`ßrVö…xñì[Êêˆ-4–WÓ�—}n¾¥$½”ÎGÐhçB'²?ÿWÂÙàI£U$Y¨¢@Ð/Ç­AÐ¥ÂCZÐ3ÐéQî�2sÌs€³ïhü¾Ô³?4Uª¢ú}šø'hì pù�e 7#Ewð¸ÞŒJ0MÆ\[ϸ^€¢ŠÍ_öUª"ÉÂf»´”ðP qQ8-å¡áz�÷þs¬îTQž&:JQE?öG”èv rUÌtDHWw~àâÍŽ ÜZs¨:À›nœAA²¸{]z¥i«µÏu©ði0ªgJ%ZPu<�Ë&öÀtU8Àýu8öjó¢Ÿ 7Â…/C8[CÕ ßýµŸ{†kê騊òXøm4îQì9Ð.tŒÆI¶µ-˜e•Ó)·]‰sëQÏb/«¢`ψžp±c«™Êé|Ó Tª½”oÁeL9"Ÿ7Â…öÁ¨ž…Øãô!-·6UAÓ$~>:"Š‘ÿL¹.>:"z?㺋héR_A×?*nŠgÍU1ßl—tåÐ S+)gÚ^GáÖ—F. Š£õÙsœÍHËðå³ÜúUG°AÍk{x’…3%TôBèòëYœ'££ Ñ-ʨ`mm‹ ]^‚ ê »_Ç<Ø0ë5THÆ´Ær¹(ÉAó¼’®ó‰�8\ f²(˜ŽzdÉ&ûÓPX%~Ž“fH°<ñä9� éhܯ¾É**ÉÌU1ßhËNƒ§L6kvI³ ¡�ž…JNþ‹çlð˜,Í(wŠx«·òXÍXàXQªŠ^{³dÙ0£ŸÂ0Óšpe7ÉÀ/ÊöŠøy(¦gpw÷j77ÀÝã™�ÖÄ×›‘Rxûª¸ÏŒT› Ñ#VupaVÉ¥uÀ+¤ÓsˆG˜ýˆë»ÃUR°rÇ!= ;Ç·eÿ½ eáOgBÏB½I¬FŒ©dï5x¤Tºë¼Z®¢¼‘Ã1¦ú_�Ÿ1[î/¤gáˆÒšõusxm¿œ1Ûôcó1¬KÐP!’—¾ÂÍH±Æ?ž^7›ÐÐ|³MR61…é ›m’΄³Ëî¡cS\�kàÀèÆ�ì¿EaÍrx}ŸÄL ¦ï\(guoëL¸^Rö_¡°ÆÙh‘Ô¥!¶wR°òTe‡”É2 oâÀrÖÀA‚t=wP3üyŠ7rPi[¡ðFn„ $u=ÂíCKê.AGá¡ðJj…·¤e6m`�žHîVnmŽNê ´ÐWxK®¢<Á’ ·°ü‹Åb—GÕ*‰ˆ ïŸ΄ÖºÇ£7vÉžôüé!æòÿ–]l…ψӾ#’…Åbqr3u½Ž™ÝÛjl²). …wf£UÒЂe6q�‚áA‡4OrȾ˜‘]`…ÏŽ¶ÅŒ�ƒå©ÊWéØ[ʧ¢<”4…÷à <#h ²GßrW¶“ÒÐxZkû ’P­ðžü4Õ™-‡*”�ÁR 8\Q|û ïÉþ•,îÁH ªÎ SKÞv…T�A=­¸ÅÞŸ«"v”©:ƒoº*8cµ&^g>+¥Â‡±} ¦5ñÓeg,žÑFÇŒJNµÂÓ±”5rHû-vi�D•ÄóAh°ÎdRá³æ8%f] çZÒíÝ[ f–‚·wol-ɺŸÂ~ŽZæÒOP`î Æ<=S;ïz¥z3ü>í�ß™ò¤Ü¾½>;ïßsm¥—v9c-v±Ñ‚:Ç·VsOÐÌvåû–²?ÆâF3|×'uOƇWvg¶Ò �Ì Ÿu{÷&=)ÛÜöסˆÏ“ SÓ»·\ˆÒ8fÝ©öA¼ŽŸÃÜLb|=åöî-‡2‹xÓ£«Ij*ÞÖ/9Ø1³ÎïÝrÆÇÄÖ¡�ƒZ�;ü‰.ܵŒ`ÀõÛŽ'\Xɵ Dšlhd5)ÄON Åkq|šçc‡CË»�VÔ>ZÍU£üd ž1®d£}‰Îû÷{Ç×KU,÷N×AŽšŠ×s°kbÛ]�é“[G?Æðaqoo‰ûûGg×KU(#Éß.oúÓ@¸Å.ZæÒÕð#­K…¾¥ÌGG¸µW_OÁÄÑéÙ ëøû$ˆô/î4XÐ×áèÈú %ëR�`„‹¢i©Ðû¾ðÕÚ…/ -6ñ×xŒ�n�¨ò…B0zðs,Új—/{žõLíÖ›áðòn*wrg±ŠÅÃßg³¾½fú6Ÿ >Úf;å=jŒ¾ï“Vøìñiþ‚ÅÓÇö¹�z3äÜ©uñqLO¸Ð»˜i´ j*޶�î!ÕY¾à•ö¿G>8Â×kZk¯¤3 jžc hW²â‡gÇŸú#ßG£Ñäï{Hu ÒÎÑ×áÈ—¡è܃Ô±”m° á•äÁïö‡Û<ºÅ ~øŒ+ùÀ¡u+(ß=±Ól=(w�—ñ2§¶Ùíf›xãÖq#§}GïûÂ]±í[ìó7Bˆ~�_eÜš¦’ƒ3]ËI‰Ý1+Ö¸õ.f,h d.Õ9 …âR­céž¾¸U”ÿ6ïŽÜæX¼=~ŸYÝÛïû³Á{�“Þ£f›8¼¼{¿½ë*ˆÛGRÏäÎýôßƹÐM6ä•öQª|¾àöîá×|­B‰÷Èú�ÑŒÊ:6µ�“ ,ÿÍ[ÝÛú‹wt`®‰ùŽ‘X§3š»É¼âéã÷}íJ^²´—Á™žz¼íq®„¶XtI°/C1v&qV�u,ãä¬@MÆ;Fb··7¦|¿­håª'Uù¹5ÙPÿò¶Yn6õÁ!íTå}<ÇŒw¯Ù.Þ~îÆ ®‘õý÷}Òï“ǼÛÞ;™ã *;¦\þc#I+”°&æ×¥BK¯ô4ÖNEx¥ýŽð¿×̉­£w½âãzîj*nž­°šÝ“;ÃOx]Böð ¯æ?öi zgæý°ʶFÿä+Ò€¤yu>.ˆ+7“�K°2º'b¶¿Gún„ ïú¤§4ÃþEæà´ÞrÙÌžöµØåÔüb±8È|ýg2šizw`Q6Í/ï±Ñò‰‰{$vù‰ÐÚ‹ Èz3ÌÊpJ^D*wÒ`AÓKÙ¼R‹ÅéÍô¯‰¿n%Ÿ‡¢ž*»PnD¡Plë_œ]5ÏŸ6ZБ§äED“¿›mâF¸ÐÒ+ ¯£Áב8ëNÉ«üç°În[æÓç—ÜV»$íÜ'²ö¸ø}’¿hüOù~¿ëóOlRW‚å¾ E/ßž§pV܈c)ûe8®¥ LÓÉz ª’?ÿ®ØÉ`EÙ*Y?ø>•[¢?pnàŒ¯òRþK<ý%·" …â»^±Ü8båë9xø„^”k n½ë“LSI�IÐÓxŽÛ¯qùÏ£stŒDœžÃÒRÆ×�ÌçÑ9R¹“F+VþòRÊrk«ˆÉ�åÚ-73—Ý¢¾c�ÞÕÓÀh†Ÿ"°V–²t1ÉüšØ./¥¼Fõ%|‰:=‡8½Ö-�#¥"Òû§%å/~Œ†¢r^Ž.aÊ“îŽÌÈh†F¶V6Ø22§¥¨ôA-XûáÚJÓ®äOg¢ÚÓ»¢­_šòXxc¶áS"–:nµ‹õfH² } ,·8—ñ¾Oêt&f}{r ò"»¿?ö‡ë-Hö ø%àò‰í_cµõJ Åz *�UrÔÆ�ò"¬³ÛïûjâFyùBAÏ­½¢Ü‚\Æ&ʽs„'6jâFyÝñróê…@FnY.cf+màÀáq ce´ØQW-Ý�ʈ¥pN�ìþº1¼’$Ðh©VZÝC°rÈ-E´„å‹]…ãÓ|ƒÊ?º Ë¡¬‘µ)Û̵ØkîH*‹_‡ÂÓ›i¹¥¨£Öˆ‡ó"¼Ò~¾W‚ÝÌ}*zªŠM”kë¯Eû6™ó×ÖM¤ ’O™ÃvK±Ã 4rð~UcUÅ&ʵ÷KrKQßG"‹Áš3_Ë:vT{æ+L5Z`½&Ò�YÝó(ØDÙw½µ¨c_‡¢no-ž•fkî¬ D,°Á‚ÄsàP/ÄYërKQ_ÃÎÚs`O”îÔžÍãA¹zÖs°ï¼K¡ Á€'Nù¾ >ôIæ™ $•±wpZ½²»‡Àµ•&@0`²6²A.bd5Ùd“Ùš{1ÌðËPDn).Cˆ¶Ø¥ôsZg· OP5MÆå–å2~9cŸ‡¢�[×üpì�9|Kªµ vο÷y(fŸß‘[�Ëhëìç7ša dÛý‡³|ÁÈAËlºFÒ&ϱ‰r?ÇmýáðnmY°=“ñÞ…Ì» rç 40ÀÈÁV»TSnX˜8j”–Q䃣¶®–½ó;Ž•mÖ½]„]#(¿’žhº±fMËðJûíCQ‡Œôc,1²’”[¢ÿàXØq¬ ißÛÒ+ÆRµâW9Ë-È»ã[DÂÇZòÝùÃ#¢´ï¥f"®ZŠA0Ó‰žÉ]# ´Ì§›¬¨²ÓËõ¼ fèßñIû^ûzÊJçëá ïwŒâ¥”ö½­Xùkeç§§ãN_@Ú÷.KÁ�5³óãS{i‚’�Öù=\wPŒ>û}L*/¥oÛ×`A5’Õüc,:é”ë_™jŠ/!½Zo�BÆ[ìC¿(c…ìE¸¶ÒÝS±Y>¬gqÍåJŽ{Ûú%Ùw²Bg'.‰Áò“ö½=Óȵ%ÿþÞ=jíE(÷G*aÏ[oAµƒs,ìØ—Áùãšô‡~ŒÉ_esrVh´¢õX`5,hL‚–�“1”í’ìYý‹ÁÌùyT¦'ák´ Ù£½ßF¢ã¾ÐEÁz—€ìYý»\ŽÊ§}çR‰9ï»>${Vÿ”'Ý=…£™¯¡ z¦¡´ï] ‡š¬HƸêþÑY£­G—RÚ÷Z桼žŸU!ûi‰¹¿¤‚o«�„œS§36²!\z\ ÐjOäKìOçNêÍлã—ö½ŽU�`p/‚ŽÑ?r2nÑ&Ÿ™AOÇ­ èÒÃSÆÛl“-P’)…iÖ¢þs ¹Z—àô?>ûià²æ—Ù5‡er”›½ ®Á²$�“! n² -þüÝüØ/ÊRÒ8ïÏ´ ˆ([á‰IûÞ%Ñßd•¡R#_(|�®ñ¥*½•�uÉPÒ¸½wÜ`�ž„¯¢Tüž¯ÕýaNÌ Oªcä?Íoíš{AƒÔ[ ÊýyO=1ƒ=q±ˆ6Z¡w»Â^qÎþUáëpä‰Ë- ;?Çá5RÁŒ÷ÓzâÌØý£³w½ât x�`+’¿Ñ ·'ó�ðJûÍ6Lúþgú�l°’Åá$ÿίê<6ZÑ“‰Wî#wñ.yéðkÉ ÷¯^¹µžs:l¶=�ç&­h-öŸ9íÛ f¨gnÎO K请u*€íÿÈnÕÝŒhû¨ÑŠÜBèÆ'V¾4uMÁ_ÎØìf£«ÉLÝ,•´ïÝÚö5ÛѼ¿êi¹£³Ïƒa˸�TÒ¾wl“o¶‰�Ò�ÿz”rÑ¢ø×}m -�{´¯¡ùþµË'¬l°ëxÎ�UÐ`A³¾½ÇZÐÝÌI§3úim^q‹¼ ƒ)ïw§øi üˆ·9œoCܬè s~œÕc†o)BÅm‡YJ^¹ Ï ¡Ö^Ô={ „0qØéŒ~pÜí|¼Š0ãí]Æ :º–|HŸä“³Â| Ól{¦ÿ»=„[ ÿ·QñƒCZ¹‡hZ:wÒ;¿Ó`�#BE?Ø]95Û=`@?=艴 ˆ+Ò•ëÜŒfH2à3¹°å?+ø?ω²Þ±-¾µWì‰,‡2w þ>[ f¾ EÞ÷¡q�ãq�Ó¿ëãfqs‹{[¸ãLºxúxx%ÙdE¿ÆÅŠ^Ö‡p…:F¤»8éIÝ)iü,_ð…÷©©xƒö.�;™…7f¼C Ù†~ŽE×@öNäÜá™Û·÷i ÜÖ/Nƒ×«ý„ ôŒPÖ1=µ4àæ®s•)æ¼n>Ø=%9øm82±‘ò‡v2'—ü gùÂöÞ±OÚ/µ‘Ç£?{¦Å9x”—±"Cißð†Ð>ˆ•�žŽ/2 qø¯]txœïþ^²¶¹í»Øj‡ö%°µý˜‹x‰ëQ¿y5Yá‡Ô¿¸³sÑäïK+[(àô !vèöíuOÄð@ÒQÉéåot›Ü›(ë�ò?ÇE q>‰'ˆ$³'—rÈOÏ ‰ô±WÜYM~ ×›!5#.¢ËÁ¾Š4ÏA…£HÿÓ1TOI�ÖÛވ˯Ã" Ø—À¯ ô¾áa%¥¶ ¨/ .ùà€¿&`ß²°$ù¯òÞWƒÁ¤o:dÝðÛ(j²A-%Í É ë-@K õfðyQ.8ºzˆyse‹ù†6øž)ôiP4°@G õ,žWK -vø} Yæ…™Pàq7®ë 2¾y°-�ŸNô®á�‡¥ª[¼ˆÚúQ×$r¬Ë’ÿö�¸ïm°ªð¶ó�ŽÕS’‘Å?–Oßí^|‘0ã ¥0ŸR£nCa+ÞS.Ü­V!‡ï¡Á¤¯z›Õý3ø‚À§}YÇ`R0°HgªŽÿFŠ—6"a‰÷þZ… Ïé‰: Ô VWW×B'4ìž¾Ãq©PáU윀Ú^Ýž¸¨c©4EI¢ì­,:… ¯"ÊùI3P©ŠoZSuŒ¢ŠÍLÔÀ‚�èu … oäf ’Ôþˆ©Tź¿A°!-Í÷.)&™Â±éh ¡ƒuÿ@Ç«¯Þ¤\m]Á>#Š9¬B*Êó–òÿ«c„Õ§çx6ã7;c*¬HO 7K×1!åùWÇêêê4tPGë¢r\*¼'­ Hkâ5ª¨`uuuÿ¿¿©(É1û1k…¯�b.`à€Ê}sµŽ©(�–‘,\’$ÙVøì¸ñAÉA•=z•Ž•þZ|S< ïÌÎ ·º×(X]]�–õ`` Ÿª�«PáUÒ¼�…¥"ñÔõ:†�Ð1`h]9.Þ�£ìëÇÝ6nÔ1�IPw z ÅòWx;¢\À`*¨¥ø¬®®NÝ%è(ÁÀÁ9–]x…Ï‚ó@2p�`y UÁ½_ù¸¤uO¨ÅDÅç¯ðFæ|-½@Çõì­6±?[YOˆd’ƒkaÅ«ð®GÉB’tÌm7±2¬îA Ÿ‡�¾Tx=¿�Ár=ø�¬®®nºTwI²p#ª\0^IoXœÿ¯¥ï¬cÅbÑâNhLüç!QÙÊV¤¸ïý:µ&ž …»*Xoä€�…ëÅ*SX�ë<›˜éÖþ%´ 5ñmƒPÙÊ^¢˜óµ  ûYb¡5ñN0p` )V™Â¿¸„Â$ ÷²Ä.AÇ5…ësQöV]¾й@³ ¨AÇ>TÁ°¯ŒÂ¥—z:··¿Â?œòKØ'ÆðjæžÖþ%èY�äBz i%C¡WØãñ)Ùå'M¡GQ°ºº:’ i­[ ·b•)ôÒ3’–†Æ.¿¡«BaȽñ¶oEåtX¸QÔìUs-ŒOɶ¶ÅÆ[�¨`ÿ•Ó©µyJh´B¨ÿ¯•0j²@-ªÿåkk[|\þ2J ˜Éû¢bü¿RÚ—% ÜÏêÑ,±KPÓ¥Â%lÅ”óÕq3.êY\v¤±HUR°ºRá’† êLB³M€åÄ|E„™vˆ™ šE×—=:“ÐÐí'iÀÌJJ€éµ0çãf±W_Ç„Ô&XU+£ùÇf[Û"ÉÁ‘ÿç+¬>çøÉBåQ3�'P°ººº¶¶Åú.¿†$ ƒI¥9Æ g`é¨gx-¼ª‹E5 ap}œŽÚÊ)mñ^,Q&Ôb‡î?,è™û'ðÜ:Fh¢$9Å0{©Ìù(—dÀ½‚CLà¹7šlaÃŒ…® b˜½@Nø£†’¦¡3ft'´µ-ÞR’7ùT…Õ&ÊM„I�oмOË­M•Q,GÜûx^ l‹Jåïs"Ê(W„ä Êé|Ó þßP; ¨â§_RÙif[’”¶?Ï‚b.ÀºÃzg·˜e•Ó)·Ý,çw¿ªG3¹YQ94kœb.@»qNE³#ØdòV#»µPu€7œ§œÿor!1§¨Y�RÌ»§$’mm‹Í&o³ãnÍ�ä…Êél¶�Ò,9`r)7ÍZ$Ì„¾�áqÏçŽÜZsgP¾”L�¯#Š{¶¶öøö!h`àùMMn}¹'ŠÅ¢k+͸b$[ì@éÇ^# &a“ �,`¦c®Íôm:Q×8H9@Ð°Þ ½ÛJN£ÌôÄðøx V3¹µãÑ@ÐPÏ‚H3˜J73y(îû\Áˆž�ÃëA÷à~;µ\žI¢[$Yh]TnOM” XD’ƒjêp^ëS'µ> ˆnQCáɆ Û‡¯thy*ò)Ð6õöQ»üj¶¶‚Ý� <¡•�fž`€Ñ¢ôf .!‰4ãiYMT éçæsôQÜD)u›g,´,ˆÊМ*eÖE|>êž`Ýíͼ” )%ñ’,híÞmešá#s+�Z{�žÁQȆ.ßÓWÕpM(í'X\zL²`pMRÊè…(è_ÅE¸¨¿'ÐT*í‘{µåÄy …ò†¶U6´ÑG-v@2à¼9‰Ü+\PÙ£j‹¨7C‚ 8Å1¬4½A&Ä͉h©ÁËM–ä^ÛÚA ¥ÎiZ<1á“Ú-)æüÓ<ÝOGã$C�m£zýÁž;pÈï›Æn?É…H‡8W$%ŸöZæ|«’ØÚ Hºü:óV¹«ªÜ+Yë()˜@r‚šµÁ͸b¤Uàf~‚Øu�ëÂx’ =nà5k�f £x ¾�Á�˜â°ýCß6ü1Iªiž4ãA �Õ'ÿBGñzZh0 : 9ømy⯸=çÛˆÁ/#xœA õ\:­¦_£ãëÑ¡3‚õö4øa'o¼ª�˜ó/‹â®’Й„z3ÐÓ8P"÷ʼ4”÷4‡g�To>$ì½ðôÚPŠÝ�V`à †B¿nŠ×«ªP÷„t” ÇãÎCZñß�pU_XeŠ˜ó¯ˆèÇ8>u4ÐPA‚«™Ü+ðZ@r!‚á»'¢ÅbQCãØº�öE´•ÏÛבómÅ�cÖ[JÇ"Å7X€Ž´¯¡žSÑЋA±XœÜLYÜ -Uö¨Î$̨Ñ& ¬ÁÍ8|F;Ê<1Ø»Œê9`Äg¢POI$úÕ%KÔ,Töè[NÔpˆ`q¤O©FF34ÍÀyùt-Úlâ¾/”äçÔY: ,ÔR8ȨcB$ õ¬§ª8jAÁ½¡¢
    Ô}�©TEœàÍB#‹šl¼e. ÜdrêöÄ›ÖT-·1Qp#°mc­Mqë6Ô[„·Ý!�‰'hÞ`FF6ZÁçaÞ<�^´ÑzëŸÁLÝdÔ‰Y?Ø S¼7!¬Eà,�†7 3? â;¯�ƒé( £!Áë-XÍp0î�©œ†/o»Cêž�Æ"ð…ͰɺüÚ^K Š×38Njä ‘Cx¢1‹oy V¡Á"Í|³�o¶ VÁhÆÿd`ñÇŒxz;>ø4þ‚Á_ØÀñ$ q­ u´ ÃMM_ãÝðÿô^Æ endstream endobj 108 0 obj <> stream xœÝ�ÛoTEÀ¿¥´Ü /"UñÅxWŒ¥RH« �´¤( ¾ø®P(•‹—¨$j¸I”DB@+ô‚P+à�"UÀH‚ ”Q(˜Úp °Ý=3g÷´»cNÛîvÏîžËœ33ç÷ì÷Ë|3óÍåì8C^á‚eë›[;¯#&$ŒÑõγÍu—-(Ìsè'`BÙª—ìïê&:twùeåòþ7K'°Ž3#JÖÅȯèI$¢ø%tdMñpÖë“5uí9ňF¼�ÒöÁä,Ö‘`Ô¢}Ò­°�¾œ  ý¯Œd¹ Ê+1òOå#X[€¯¤ÁžHLgo±�­I^U‡?bßD%ì¬b8Z?^/c:"X®{Œ�IQ3Ò�AìЃN•¹Ÿj¥ç)ô¢�¶9îš�tƤél™{&ù'‚Ι¨�?éŽÉÝ5ˆÒЕš(®vaLËY%…œ6QQPU¶Ã*S.In˜¨H �4¾EÝR!$Šv8W¨Í¸FujÌ ¾ZâŒÉ�MÈ]“^›�9¨<ô—k=%t‘~Yóšó±>ô*]“!;˜4ŠÚF3ÏÆ�fÐUâdZémtLñS/ˆÍ¡Ü¢5ÕÌgÚ(x.•¥¨‚Þ³o2h+Ã^�´Åî"-«ŽBP­½�´œý\$˜†ôÃ*C›¸ith¨õV9är-™ ÜduM“õ G ¦�¾lIÅ÷W ¦!Õ ²âÂË`œˆô™•J‡÷Z¬"U˜Vá¡pѽhRe— ¦�¦˜R¹ÇÏ:àtÜkB%û¤©³:·é>mbq¶ƒÛ΢�¶Vy�Ó!¬´Ø ÊÜ·ŠŠô€!•!çí¸˜!rÎP—ùD€f!­3 2CBPæíÙ‘×Xi”«¯|ÎÙ’%5øÓ *…‚dÉ\Ëä´»x¾b—èÅ´«ÌÕ—”ÉH•iTòÊ0é®Ô.µ®«Ò#\�RåIaưè©T.'êø‘ßS¨<Ë}yœL0ÅìßÂ:0+œÖU)°Y ÌÒQñýÅ:,k´ê¸Ìrð•“ŸIvùM¸AL#úk’Êc‚Mùý 'ºìîa“Uºk¨ä 7å÷#�It©6ÅÁ‰å²¯“u@vèH8a.t@ÖL‹wi`K,5‘¯ãTreÖáØCŽû&èe¡SŒ�®—ú]²Æ.?ô©Œ<Å‘GÅ\ žb„Æ\¾eŠ}n«d µ)¦Oðö†©]¬#±OW�æ²–ëƒVc(ïj.çXBƒ³½*#,}ãÉáÞ©ÿi®ï%Å?]uyËí¢¬T]ޱƒ¿¨Ë0�W”ñHpŸfJ4à9Ot}BüsÖx`¦TQª°‚�ÿ²Ž�íàóHŠzÃ2‘ÐèÉÆñç—{`ñ¢Ñ5¹gú‹R±‰uôX·›uô¨ù•uôøùëèqÎ3Ã!7»™”$ì‘k2Š §úzx¨Yˆ‡šÅ[.’‰ }€œˆâ‰MK ì‘Ý1ÿÖУ³•uô8ÓÌ:zªg=vm`=>öÎÞE¤b�ðw.b„çzf‚Áùyž™ø•;À3ý% p™u ´hØÇ:ZìX鑪?R Pê‘4à^á/(j„Æyë®e«.«=±G©R]Š=‘d¨Huæ‰*&¬ýÍZë8hТݷ|ß&òŽæ2ÅMº}×ZÈ^ Äþ.®‘u$öÙ»ÏÿŠð%.�¹Œ¾$“sû>€ù‘u,v9Ðÿ]R¹àIÿ~¢û†ãßÃÚ#ôñX´>þûÊb¡wÉ´º²�ÖñØ!ñ^X!p±¬,OP�<�{¿|g¢ Ô »µÙ9@¶að#]à똬r8If :,£âdŸ Kå3É*s„l4CÏþ`—Néªó/�ñH:½¥—ã¬#3MôX ˜(Ü2?žÊª¿Yc–îm)U`Œ`CYptj¨*ËÐÒ4*0øoÖñ™áŸô/uÔ0©ÿÜò6Ÿ sÁ?¼)ƒ ä^e£Q®d~Œ|º lä ÅõBtü¡Èn`³,Úf숨1¥û ©,â^}`+çý?dâ¡¡ì\Çöœ2ó å¸[¬ãMCôFš¿×!Ÿã.#M6¥PÆí,ƒ_0©PÁéZ½aZ` —-ƒ6[Pß—ÊàZKoØAVwõ¿|ÀÚÛ‚ÙMœ�0…ZÇ~hW€ÜdçaÑÁõÉàFë­¢’µ‹›WÛ{»ÀÇËÐŒ6Û}S–p!ƒ_·os9¨ÍÐóTT n2>dOI`ì)¦³fèäÝÔTr¶2Ì3ü™½±8‰ÅˆÑîLTz™® <ÐÆ$ÏB­Fw\Ì�³žAžÉQί%W]®5ÃW¦;cÃÝmšÐö\AY¦à‚kU€|>ÓùŠ]²+ƒ®Ðv+¬.»L0æ †gy{ºcUŠLüÝánƒ�¥>·§NÑq¿Í@êÌÆDe̲%ZƒîX>ðr®Ëø¦í–)LŸ×ø5ÇþÒ÷![[OXþnÞ0Ö}ä.lJ–ÎÒ"rpïGË. *x·E1÷·Œ=R¸åíIÖ6»gØô•¿ ÙÈPA²Ôüæ4~2KŸñsªÛCa$ë*Ed)jÿfÅì{XÇiœÑ“æ/ÙP{¸å¿ë¢ààõŽ–Ã5ë—ÌÏw¬jü¶û4Þ endstream endobj 109 0 obj <> stream xœí]÷WZKÛÍŸîZ7J·kbŒ&1±pUT, Ø{¡„sfæ:ÒìÂ÷ Ü×kŒ%{í_ny×}õìÌ<ó”ý|øÐpøHóÍ×Bq2ŠW0 •�Z `¼-�@Bð (¨Ò"•Ê( £€”â%¦”â‹GÉ@ •¤Ò¢â¿Vø€ŒàŒ·C [i¨ €Œä¥Wd­ú¿¨ C!é°O:*ÈH  @«~¤ùkL¥�* lgà×q‘¶„gWŽÖwŽí©C{†wf‘+#°YŸ+ãg³Á[ °Y�¾Â¿Ø¬Ç™qÚ3{ûéµ�cëÊ‘Ö4ù:‹¥¡ŒüW`šÂ_R ™Fÿh„&C Ö¿›¿(‘ï#Žºˆ�Œäj¤ 5«¡œJ*)øÍä›XŒní$½ŽŒß• U�W–w¤÷w“–åØÏI_+ƒT ’‘¼„M†€ŒArt«Ã}êAäký;û‹’ÐôËóqÄÛ¢æ:É A䥤WJ[i ±†7wŽ�+¬¦¨g�Í@gfk'©±DZi ÂG��‚ÈwRAã•2‡2[ëßâ_܃&Âþ�šm!=R‚oú呪y%ƒO­±éÀÆv>n­tõ Þ\àÊ®o'G§ƒ _Ù’“éXÃÉÇÙˆ¨ Õú÷úòùü‚=¡Y‰´�\a—¨9•‡@ú…¨Ãž¸²5R‰ ¸²¬=3¹m×âG„”Š¡�‚@Ú•ˆÍ‘Èçÿ^£5@ó/ã‡-Á|>߬† )hh°EY{&ȾiÝK�=3µk-<$$Èçó#–`Ëß<Â×ú·Þ(h¦x)¤$háe$�Sðûd`w?xãÒú“Îý45je�¤ðÃÊI^Nñ³U…”àä$PР™â4leàüZ½� ±<ú\Ûz¢]‹c)ÁµÒ@·¶Ùã/ÐÊ¢…ä¤ߦR‚SÒ¨W/nï&ßßÁõƒ®ÌÁAjÐäÃJSóù|^»nQÿ=Ó*)�3¥íZØBr ü4œöz|$¾íéasPAÃ5×®Áog©úoœV&d'§ùöÂÙ¥` 1ä�µÿÄuBΕ�(5øLkc Œ Öú‹½%4ÓPJÁv ”QX]£Ó~î£×™š(,0¥øûö|M„½™t7SÞf\ñA£f?çH×üSÖ9é^½ d`ó¯9ìüéèëÛ¬õ—¬S´°…ô4v9�ú&ü›ÛÇAgfn1úkÊGÎÛ‰âou}3ñk:Ðc¾Nø&"‚½Ñud³+›I�4èëÛlfeÄßí74Í:A *iðÙäë5Šëîãú5¶¹àÉ—jÓ¢eöœ^‰2‰”ާ/|±3ãz´Ç pû©šèšSd³†…îëÀ�EœLãù[ú,B¢æZhØd(4¸x=µ›Öo›wbù|^½RÒàâ2—/`‡K Ì?™ÄÓ‹ëü-,9ß§5ÿÄuBÖ™éÒ rÈt¬”æšÕ ýè4yZuœ’á%jNA�_ÖÈ.ºvøóÜe» šý]¡Û(Þh‰ žtJçÇu.ש<»É�+³±~42ìÔ tê…‘ÙàÆf¢æßý•peÍ+G8Y­Æï¦ÊÝDØkýµkÙT2|§É#§¡Jƒ¬Ž‡?Ã]áÚÆží‹¹n£XÕÅenØl× ñôEþ¨BÖ |šõOùöA:™½¼¸Ìg/÷øTß„oÈ@�÷vð8³]:AÉ€&Â^èHi¬„­œäe��A §C;…ãë^®xλ�bï¸ØÊÀ1[ôˤß;ûScƒÓøÐ›Û;Êåîþ£\.?½û2îó7žÌlÖ`‹ÊiX,ÃÉiPë/ÿè4yT:N¥)Vx¡i'õ�ºns�»Ø°5« ãzôŽŠÂ‰óV×"jïºÕˆÎ®ùG¯ ÷Ò* Éi `¸êð}ß› Q¡�&�ŒzaÍ{QŠÀîÜ¡ÝqÉ‘¸þß�Nœ÷NϯÑXöìªUÑAƒ>?{òÙˆk�ïûÞ”� ±Ìh0`Ï¥2¸®g‚�z4¶˜ö·kÑÈBT»òØ!V½¶­Õüs׊6«ÿß½)#ø÷—@+üP¸q]NíÚqyêºÍ îbî ks�ørÔÒÑ*{ü¤Æ–œ ÃB´æßº¶\ÝIÊ)Püâý¤5d$”“øç’SÐb?y¹Àî�\:Zs?­±öX»©ùW®9]ά’B¢0øùöO³¦¦|soB6’‘PÅ %÷yÅæðç ɉͻ�?aX�šWãÅß38H9vŽw7îݤÏÙpïMÀf»´HFð¤-´ä|Ãó‘ïÈ45å4ì4ˆ[à²søókÞ‹=ººþ#mq —W¹vZpžR‹±nƒÐ¡CS¾Ÿ³�Ï㢒†ß¦Ö¥X ‘Ä&²Ù~“_Aãy�™•Ì[œîìëÛü2,D^Á€Ï&ÿ^¹~‰ü1ûïŸÇ‡0o�÷Ž‹íZ´p�&ÏïÈÏã϶P·^X[‹×üë¿ýlö×t@Áàéξañmuk4}Êî¾¾M ¿LöÅ\Uæðç7ùËr ™{¶Ò* d–Ã�ç7„Èi·A˜°5PÌ`³„5,g`_ßf§ÚÕiòÔZ;%¡¯oSùÃÝô (h88<ðU]`E®žwýj$|üß1JœkV"­8³sôˆºn�=»0û§Jf®¬v>¢``§ÉÓ¡vÕÿivsê*iø}.l-�¹'\kW]¡M‹>OˆmZT¬CMnÅJX™Ó«.ƒ°µÑ@—f�ÍàÔYá4SRÛMK­uô òùüt!z”²¬¯,°ÛÜ�Wkž‹xeµŸ|ž¯ÿ¬b> >xÒk®zÙ¬n!ª a“ÅòÏ/ÐÔT§O€bÔ-/Ä`¯vE>Îþ)?ë»?H{¿,Á¥•Æ* Ù,5‘Ógœ>%j­¦{ §�[ ág“ÿ‚üR¸®Ú´è¹‡X0=2¬ùweØìðtPÎ寰”¬¯*@!‡�ëD]z±ÚiŠÒ9¹“.¥Žy/Nϯ•4¬ùG}úÙìàd@JbkYÝÈLFq2ÜÆ«4h“¯V¢µ 2«‰…ÂÌ~yhÓ"Ô�Ó(>ö¤S'*€P6Vû–3íÁ£8 —«R**›êÅØ–'Y¶Æú&D¶Ð¿Ý€ì ö{+x×е<Íð˜ÕˆKF{ä4¨F±û…¤WâË�&ÿG‡ñ�ÚoreÜάûÖÂfÊSöÆÎ!<.ª``EÚu*NãVÒTB­ü^\]çä46ö|úænJIƨÚLNòmc‡ §Âj.§{Y˜ÊÓ˜7�ý6å¯ùW®9'£÷xNF½v`ÖB ) ä$ß¡êç!ù'»Œbàèž“'aX‹L/6zCc±Ò40á“Qà•›Í:M…†o!�œ†eôä¿&Ç·’#óÁç ì(uѦE-Š]ÙvÏž�"^Gc­:ËŒ%NÕ�v_®g\<€wÇ~ÁÕuîÇl`ºÁ’ü�Óy�Qæ4›É×ÌšIN©á˜®Ó0ì×<í:$DNKX.‡oÉ!K˜ã/{šßOý=ÍŠœZŽÉ)(¥8 YÝÀ¬`¡àm&¹V Ú}xð¶Þ8ïõ¸ÀNϯG¬�.ƒÐcå4^yÓ¡G­¯Â>¼é&´¼vÔ€ƒÀEØl§V�à�BUÈ/^R@�;ÖõÏ5ïÅg“oh6ç0OϯWÙc¿LŠÛ\2r|~»sûò*Jœoz’£óÁV ÔÍGø†´ ÚsftaqÀ¨¯Jk¡€Œædüe�Ô\3eÐîËOî¦?›|íZD/‡§w�lŽÄøFôûŒ_Ž-ü¾ØÓ÷iêäjfç¨U‹¦c�–=óyNZ *$!+ÿÆ,Ä{ž ¨ø†nÉ{¹Á_š÷2†�cµ-Ö©~ÌúéËR¢µ$2—Öà·)?l¤B@À™Õ¬bw É+H®•ðVVcͤ»àpg25IE¸rxÞ¡ÖÜe4s9<‡Òm½{�RÓœ_Žý˜ ØQZÅ€V«¨¨ÆšGø« ùÁ7ò–|’ÜÅ#3&¥cã0ÙkäíiXˆÌà>–/“>)ÉÉ ^NTì�)%ð² ×¹ºÎ¸–È}1×;îÛæžxf–ˆéíØÐ”¿b³ù½L›ué…þ©€œ‚r'ÿ+"0 UXCÆr)^syT„j[Ìð¨‘Ô³�Ë凭Á‰÷îrÀ,DzŒ‚f%Ü©è•8±tTØÞÈK*qcÊh(¡ð²·ê¹ä>ïУ;޲/Dêä²M‹<ï70ÛÙHôMø.¯p>çüòºw\\pž((!¼2ê¥L ÉËi¨`àDÝ—�Jä�Ùж·üÆÅ‡°`OÐs¡š‹¡Jœ¶EçöþP�ÚŠ7“¦­¤’A­ x¡­±Œ’Bs…ÝW{y¼œE7ãâŸÇÊâôü{è½Óàiãxh6PüIs¹ü€Ù¿»SìáÐ$lV×xLµ�œœÆKÞ§÷ßI¾B³š0o?cž÷YЬD¬K±šë¡ôò—ÓÁakpÅ•ø9žF—+ãrœœB �ªË þñöºÕp ÉuêÅ÷qˆÆ-q-©Js ™á™w¸&`yõè“ɧ ^À§È¥£„Ë[ÔXÆåÒÎb�ÉÊ*”Ûì¸^É€Ùƒl͵QÚ}9ªqQ‘>½jÓ šK¢²4Û"Ÿ'DTèZÉåð}�QXZáo4tò vh@3ùl�YÝJDª�±æÚ¨×¼½ãb b)ï,$cwS:”9½ºý3g.Û´0¸ÏÞÈŒž…Í…%¶ÏXÑÎ]É@ónºæÚ¨ç�§7�k•ðeÂçÚ9®¹6*ÅñÅèÜþ=ª›ÑÅÅÿ®Ë€ƒS2°�á¥cÏ�™ŒÄ»ÑU ¬ÛŠŠpΞ]UUcƒÓþƒ­÷³:‡´„ïmº[sçÑ�Æ2.ׯI,°ÒKKÍ#¼”ÀKáës¢­lZ�'¿,Ïîí¾Núïé³E¬÷œc“[1˼­1~ŸWRHEó ¦¤´¿d W'å(ÛB¿>¹|xÞ?嫪Æ:õ·ÿ~²ýöt‡�œý�¥N.۵ȿᆳ±4Ë~Òc�ÉJˆüóùüˆ%(#ÁÏ·Ùˆø÷l“R–‹OI8¿¼V¼ý±_þ 5½ž LúÌÌ�þ ŸÿóƒBäô“I´.�Û+rgƒ—¨Áè|àI—ì…BÊBAÃ%÷YÍUQqöÅÛNž•� N¾í±ß©ÅX›™6¢n_Ö;ó²s{G­ئEmت�Ÿ�h{Ýû§À2.ױ˭b°Kö‚#þ¸Æ4+‘f5ìпŸ”Åmªm±å6’”‡Ù½£qÛû¥­áï3þÔÉÕ�ŸëìâšY÷Où½‡á{ÕuCÝh!yíjø�6q 6“5×C5¸à:ý2Y•�,—ÃÁØÛõù±­õOùnVÿ j1l\ײã|—ŒÁ[•ÒØG‚m"ì2 ¼�6ž{Ù;î¡“ŠkÌ�ÒßÞìEtf:õÂ㦠Ù3lJ¾•zý“i–íÒðM†ÀGFxHcÅ­sýS嵐ú^š÷2ƒÓþÊFþW×¹ÞqqûÍ.•ÞÝJ LùŸü1 kÑåÅÃÇ�²ù% UóÝQþòHÔ8a;µó~rû÷òëT`ãÞwÂrž~Ãæ±Ö¥èäæÓí(;\Jg��kÌïÀvšr’oúuÏ:‰�#Þ¦_9ùÞÒbr�Ö)Áxe˜¬˜éÒ ozÎl‹ZöžÞ‘á@ibî‰�,ãruë°Àþ¹'+QsR5ÿõ]_”7œÙÏvêQ"}ñB�ãçmZäØy¡>»{<¹› Nù&ý#³!£-b/T%¬ë M æÌ+®„qAxRcóËP¢æZÔw“±‘ï$ƒªwÔSý$' MB´üv2O Û¦Eku¿‘do3ñuÂ×m¦·c”"§bôÔ%f,ûñ¾ ¼‡eb'Õ®}bq^>Ÿÿ>°oÜŸ»MÁT ’þÞY$ÑGáý $ØW5ÿú¯ÆyçI»•áKœËá­¾:á`»®«“WZg ÷zЋ žôOúº Šë±Ì!‡w¯ ÔS˸\)ÖÝÊàE{~KÆv!)éí45ÿî¯Ìuî¢oÒÿs.à�•j·Ã'fÿ·)?Wß1XÀ•þ9�ž=5„uu�£—"*>”Õ‰¥ð†Pç¦çI�ÉÌ<ñ¾þ–Œ-4ó¼Ÿ ÊgÑîË›¶S]ah6°Ã¥Ò$º‹8Î\nz’ƒÓþ£hÝ|˜Æ�–ž¥!m¡VÎÛã·5yu�ÛápP±±úô-yCû.*.ø¾˜b($S#œ§5ÿâµSZnö ûËnÓ¢£0b ê×"¦�¨v%òs.СC­ ì6 ½F_ÿT`p&8l élëj̱s\Õ:¸w?¹±~4³›XŒNØ¢3K±µõ¸ç©‚Âöæq�Qxò»�ëëÜ€Ù7`¨84`–ÃÃVì…õËŒàÎc©×?qq…„?ºIøËF°k™Œï©#ñ%\õœSËñÏxP¢S�õ6·wä2 tâ‹�úb§ tâ@éeWB¿é›[5pd:¸²RI<×αÎêÒ z424oǬûqëA|z;¦^u„Nb,aû-‘¸#÷ùnþØY§^î€}Ë»¹ÆÙ7£Ï�Ö —«í÷„¿lIo︯æ·æÜWÄÒ‘JGæƒ0}§•ý!dN¯ð/kÑ/üÂÍÎ�ãŸflç¸p�%Ì®ÄÓKŽD�Qø6å?ØþMiŽ�dÙ“ ¿æ‚››¨ ]ݡޥjþfG ÞvDrù¨æŸ¸†Ü®ÉÅX[acoêäyvd7H�\Nïµi Þ.ÃÌ'àJæ#:´íM=™I(â:—Ûé=ÒZÃç¿ÿÅñÅèl 9Õ{±éIÒ–§“`OroÉ(ÜéZlJ�*ønfÜÊàô~¦]‡Æ7¢wz>ËCöìÊ´íÔ¡Õõg˜c öôà¤l!”}þÿ‡Ó‹kz)Ügò:O wþÓfÅ2m¯‚ñó~S4æw\T*hlÞ‰¶e4؆ ”»á¾˜]ˆ~2‰þ²VE<ì¬w\d,áR‚4dO6г»e>E,:Ýq\õOùKOÅÜAæôª]ûDQ²&]‡r´2¼Œö0+á�4®cÖüs¿>wàUߤ_»9¿¬¤�Ï ŠÝ}_'|�]ú鯾{§Ìž ›=ñe2ðeÒ_Þv•|>‚{x* ±ŒËÕ§2Ú#!½’—ªù/�Q¦¼ÍMþgºî›»©,,ñ^£À?¹\aQuië{n#ž¾h×Â#Çó²ú1Ââö~e$6ö©çý€•åô~æ“I¬R�ÿ8Î.°Ëåòú½@?g‚ÏÚV:,ûxäú™=åäbÈbã+"0Ü€árËH  aó¶¨ù§î ×:Tñ4EéðÅÎ:t‚X¸1{ZÅÀGF�^‚ë\®•�“[Ï0ô[q÷�£cGeVd§–oa|-è2¾ÏiÊ?I,ÅLen®ŒëQMa ssýhx®Šþ„ —5gvŽJ9ÌVÙã. íWR`—kØ e'%ÁàL¨æ_ÿ¸®Ú4°"™ü— {vÕª�NöÔ¸„ËÜÕû­¹�Gcƒ3Á_–@8ñàðB"sI-†ûM•XÆåšXZðrU@,5D¥’X:šÙyQ"½R˜ÞŽQËG#ó‘=P™=÷âПý1 xC¶e¾C ÇB»|*š¿¼Ž%/(M/…Û´pÎÆWöмáꆯEÍËI¨ßxWP÷r_Ì©4°ìbwe‘Ì^¶jà�ÙPÙ™ÒR FO¿ši?v}©ç|Ÿ�B«ªøi�ΠÕ2¯È{¹¿+ÊIœ¸˜¬û�Ê}17gÏRËG?fCŸM¸ù¼Ë ôMøZÂÌjbÞyjªóͼ—)c±xõ0l ~™òsÁÊO¬ß ptöeÒW=ý”ÂÃA©A­4g¯ßŽ‹UÏÅÈBT¥�Öà¢3qèÏFŽÏ™ËDæ2?+× NûÛµˆZ>Úz¸¬?4ªR– <ìƒtϸè*·;¢ÀðÉw³¿¶ƒ¼ÈXÉ@[�6P;ðj¤ÐLµìL<ÙîO_Lï`#f%¾/Þ=Óì¾¼JKl8|¤O¯T XsW±˜µÒd #·UeÀU R2pÍ[wÛܬޓv-šÝ;zVú(}zU¬¯z~û‰–Üç}ÕuP,zdX«b"evïhvñ3º×d”Å9X9·ÀeÍEu›¦­T§¾œRHû ݦEó·æ_&¶SúÊ-z«[¨ÛXfU± šý‡›îWÒ#Œ¹q†_FÁ�zêN4m¥zŒÂ ]„Èi»-ÿÏ ’Z:Zq•Ù‡P=,9íT%_Çdö²] SÎZ ,ãrÅYNAábeý˜¨X'•°¡ÀFþl§^(¾~ZÂe éTN!óiÜW¥ýM6{Bÿ”ÇÎ+0Áze4�’üŸArM¸¯Úu¨‚ûŒ–œ‰/“~»/ÿm&ÈWÁ×î…à‚'ƒæ@›–ÑÀÿ8Î/qYÖ·[ÅÄW‰.¨d�J‹æjí¦Ò;.F6Az9œB¦Ç(ÖUoÏHÓO¤°¢®õe5‹úÇQ+Љ&% ¾Œ#j­,{B�ný¨"§ bð]YU/k»/guœK±ï³¡Ï¾/“þ¡¹�f5¾äþo¢ó“É©Ú:¶|>oGéþÉÀˆµŽzÍ÷Öêñv«,D%ÖЭW¥×Úîà �záû´™=ö²áãóÀÑÙ¡o¬ëû&ýÅæÀK<ÌŸÄ–'9f‹©40™­—^ë6 HÖº`ý <ØóÉéjÍŒì¢ësph.ðˆ�Œ _a¹ž�ìƒ*^dæí˜q3B/‡+^«*æíؤµŽ²XÕãú&ž‘•Ÿ}Û.8–Ìí?=Ùwvq=:ülòM=gÚô¹𠬣Cwì°èç"Sˆö#õJU„æâìº+:Ã{àË}� ÌÛKÍwårx»t‡U雞]àÏ0é3.ÍšXñôsaX�NZë.‘U%ÓPBxŒ·²^úõ㱅г~í§ç×í:´_�wß>Hÿ²úÄ ÖwÌv葯\�Á—Ã;íÒÁDu†ë�½:¾•å4_AO•]áºM‹Ê¨»ætª’&0û—< ¨11ãZ<ä{ÇÅ ú}•Ž¢§ÊÞZ½¬«Í4ËÊ)ÐJÃbªå°2ÞP“;xô¸ŒßÁ΂p…»#ýÙÏÂ�ÀŠ$—E¦r¾…¥ƒ^ - êg½ØŠ.zÜ¡JíEš =²þéq˜6b}“eºÊß‹óË룰Ýw4“®~³`y]�»¹ý£Aj„|Å Tj ÷]à2b±2é‹n£XvÔ>HwÐZ…ü3s9ì¦E-Ã;+Ò›`{MèÕ¼:W\ÇŸ�°ªSÿuHû6”�@J Áµ�\ßd "SÐàÉJîC!¼O­C‹<� ¸@ÌÛã3HHÝ#°"Ý1W� ½Âi6·ôÉXWœ:§u HÐB@ÍrHJp*¦2OK9 žÕ—r |ò}FÜñq¸MåoÌ\.o=ˆ÷‘'þ ÀnN³~3¢—ÃUzœV3 N�v‚94Á$ÄfÙ ‰,)*Ò©Øe™2ë5ØQyÇçöÐaÏ8šÝ-ÉœíÎ/¯ [hpyŸØMlF¯ÂÞq±â _ì´w\Ô[+»aÊŪhØ®� c�ZƒJº2»l¾Ï†ÊÞ¢2½›ÜåþMd%ØïshÀìÖ§gÅL·A WÁ#Wä½\ä;ôȸ­H szeXÇ»lvÖ%×ú'ƒN¥Á�Êÿí䨢¿UKÓVJ[nÇi�Q°c…þ÷éçÝž.¶]bæ‘+øôüz‡KõOù¾LÂMáî+²DòÇ.íhÓÀéíXÙ¥ódöÒ¼�{l¾ÆI´ÞËým$#�œâ‹“8þï)w·à�/·æ½XbÏ6øËmxÕªEÇÏÿF¬˜ù2y7‘%f\B +íû¬ ¤áϹÀôvlã0¹R»|jÍ}lÚŒNûU ^@küayêºMÏ[P¶÷A:]Z[cúäj¤†-x· ÞÚ%Ëú V(%¸æ‘�¡VB”Qà¹CpüåhÁì³IœöwêQ·Aœ<7 {q•ûdסç±s&éZ幉]D¯ŠêE?±èÓ¬ŠÓv°%¸Ñ3oÆR‚´EÏáÈjՀϢn5²ìL8PšÿߎT>ˆw¤.8£óÁRаÛèû9™ØŒïíúâò·»L³lš¾��¿þÕX+!*(œíŸήç9{¶M‹ì¿™ƒEŽÏ £háàs@ÌrX½$VV'¡�víX+Ëé7ù±Eô¾šÅ/S�Þq±Û *h80åÓ¯F-ûسŲ߈þ˜ (i80!Ú–¸J-Sxs ¹x%�¤j,³ÿvÖS@NódÉ[“l.lŒŒß�¯»“* ´9ž–ÙåUN·0 ?‹ªA”r™vÄv"±•ëC™À«ë:ѬDÚ´hr&Oi;[BqSÒ‡[è"Ã-ì4¥ÌîËõEÏ£~¹ãѽ@.†Iû£Èé×)߈M,6ÞÔ9÷|ÞÞq�°…J¯ø'³—úÕH—ÕóXG586%c\sø¶Æ> ‚ÈËh¸ žÎ’ÍÙ³OŽÜfÏ®T Ô¬·ia í<\“>½Jf/}±³UöøÇl Û(ØÜ\ÍÅS ­,lÓ"gYz|è¤S‡lK�’ÇHº ljÊÿÓ¿­1‚Èw�% &¶ŸžQ/ÆÖK02¶Ü!oÜceÁ¨Mø2…:t°Ë̵ ×ùÃçf±jÅY;~Ë<²>þI$³—}âÜbC4]x%?‚MMù¿CF{%$÷µ„e©%Ë›6£3v¾æ y!m‡|§¾üâÅ ²gW=FakýýŸfã6AJ‚ÒóáH™C™Ž•Q`=ѯøÓZÒX·~-beKGÔ?w›…^ó,„�ÏÛ´ˆßyÏ#o)—[I�&Âþ‘pÿ©1,0šS2àÉ•ÌjÜR¢Ÿþ)ߎXfÖ½N88#¬»“X”îG©Z+¡zäìØ)]Bz›ûŸûðáC é‘’ ÿ©ëråð¼Ë \]?V±ÆÏ:õHH×^'esÉÃ}�ò•Q—#ÖàÒReÝÖ!uV$Qs- ºW`>|øÿó­‰°cG²§®Ë¡¹ð#GÙåUnpÚ?븿?ð­ðË”P�}F�£³nÝû<ʬWAƒ&CàŸ‡5ÖDØ[H<¦¤ßL>®±xÕm‰?ÿ˜ŸF&Gê1o_:÷ü™çŸ¬¿Ã¨Ì±‡�$ l2ÒX1á/!A‡þÁ‰Ë×é·iÜ ¤d`§^ødwùT,u‘9½ ÆÏlöD»iÖDô–oI1ãÒo êY¢my’L}xW–?&‘”àt+áGöáÃIa´’‚‹î{–(Mn§º ‚SÈœ]\Ÿ^\Àt»õOâú]»öM"͸ӟóFÙo„r�<‰xú¢K�j.‰Ê2äÂÊ)¬ˆ?®1œÄ pŸÿOkäŽÀ6ùËVíÝ Ñäy«9CÁ𫢂Ò®— &”‚V Œ½¯ìÙQJ‚+.=©±5ß<Âÿ™(Ó­ß»ð5ï¿íðþÙ(Û©¯®ïâ ÙïÝ~?!Ù±Û« @ á‘Ü“ûðáCóöRS0@»–¸­±1[t‡»g7ñúaR»^áÓ¿÷ƒlÿdu÷Ä�XƒŽwöïîâh_Fq-Ä=éýû¯K’kóªxpk¿-½_¸/ žÙ=šÜ{Ûùü;Üó³SþªjŒXí¿�»ëîÒ)å‘Ó%bÿec^É+˜ßÖ@/¹qêõÎ*�Ós¼šÇ~qþ aö“©’ëâç\€Ýx'cp»¦‚æ¥T©‡Xr ÈþNC½š ܈�RƒÓ~ýª¹**K>éR2°ªëý{ï!æO»Ø’�@F�dõd/§ðktfÿ·™¸±…˜‚�=ãÂç ±M‹ÞY´ÃNzy¯ÅC¸¸Ì)hð>RýœCTÒPEã´ês5VˆÊø5סo–v�ÌGú&|ãÑ£829ŒÆj.†*qÔ&VÏ>”ž|Ÿj.�ÊbP¢æd$_†À I ¼ˆDIÃ齌ß·ØO̾b)¼8I´)¼ÏC �v²^Âö<§¾Ò1¾�[ª¯¥3åÑs (¨b€DýŒhÿîQFñÍ$צ쾜v-a½UŸØŒÍ9*0ÒXŸä“®*­ ;¿Ä6€õo­ÿ$S¬ûËx™‘Øm4“œŒJ˜¶S3û¸�¿X¿¾Î}™ô•=”ý&¨YGÕðÁ^v³bÍòr:ö}Š‚÷~y‘ØïGh&p𿃮¿Ï„~Ììñ³Ä毹 ªJÏÛ¦E±—íû»ƒôéU»‰{o~�<ÉvhA3ÅKé— eöÁ“Ó�°Å~Y#R ôÄéý4J½�‘¢—pÆÎ›ö_?Ú�Y:®s¹akprñ=Dû«…œÉ5SeFûw §yã•‘`À쿺ÎéW#¦_Íð:üiE›•±[7oÇ~˜}íázCŒ²ÿþ›Ã2.oÇ2}}›íCÎ ìÿÑd±HôvÁ+è &jþÝ_™BÊE­}϶[áÓÞq¡Ç(ŽÙ¢Z[ÀºÄ{6Ù·{]&YO—Hoë0Û×·YY�«KR· ‘+ïª#±t.z:ôˆ^ ?d&sÅ­J0ËáEGbÛ›ZwÏì}�ôµià䢘xƒ÷æÌ ®É¼¡¦â+¢™ÄƒK °‘w›áœ Éš¸n#ÄÞûGž@6‘¾¸¸Ì§±Ž3—|ðÄrï2Ø ¥¯ï ãâé íJ¤SÝoÊkEp"yaì¨E+VI`ŠƒK„Gªæ¿L1ý®úyžËÑ=¾ã² nT–äÊiЩ¾N;õ‚~5òøüiÑ+¾]‡6߈glÒuØ£ÍjØL£ÇÇŽ^©šïP*H0cW½¯!:ö LfwK­Ä’í:äÞzo�©Eì”Ò6vج†UX�C޾¾M%¡¿2û�†MÿØBèYYPpŽªs<÷¾P|Kvþ¬ð[ò!ôõm¶ ³2‚o×�|W]Ö/¡'îÂs[Ïï:Ó®Dælõksq­4¬Þ[ò!È^Añ2’ž‡ ˜Ýд LåTâé‹v-¬Ï„FšuŸ€R’—‘|õÞ’ʌ亩C'wô�y‡_Í–»±ÒçÙªÇT†yQPj ŠñJËíB|!:‡œ}}› nÁ÷ÖÒÿ\ i—œeWϧwb ¶º‹ü÷wñZ„&ÂÞBÖD`ÿf¿e£‚‚®F͘yxÄvêÊ_‰Ž÷YXë«3ÖçJÊ !=™‰½d£‚ŒÀÅ…6-àï¿Ûç!:#lï vUïp)Ý\i,Ær�ÐBáW9Q�±BBxå''¹O¥¥ã_8.g³ÇÍ õ¢±cÖóňե ±Ìj­¯!'9•HH8¼…Ì{nÀ~„mÚòûÿ™åðúj]$üS¬{t ÈHÐʼ´Q¿â���^*h ^DBºe¦^„ÛÞ{ü@žÄõu®U#µOæYÖ`ÅÎ`m¿‚²wéWKN¼¼F©�̚ЀI³Þ=`.ljÅÓßÌ¾Ú Ìå2Ûpíµ©)ßÒ›¨µšîöWYÍD^AÝF#ʬߌèy“¿—W¹£°àÈ8í~û¦n³µÚÛk]A âm ™?×7Ô"ÿeXìëÛ”3д#™Æ’Ù®�mסÒ*áHl)Ükò©4ðˤï—%Ø?åkÕ@Ú*÷_5%k[EÊBEò˰Hõ+°"úú6;Ô®N“GÎÀ‰]Ôh2³²Þžq±™åryÝJD¥³»G™[ËX³gW–ƒx»¾Ú&¯…•‚»¯ÉÓ©v½fEò%è4y>iB‘WÒ�ZE�öÒ´º¼í:dGéG0™Ë¡9¼A˜ Þ_~B‘Ó6-B{Õ=ÍÒ.ÖlƒràžŠÂÉPkí<‘ÿNb3Œ-Š(ÝXy³ßáW3ú:åÛö&o'4Š«-MÑ6-ê×[b²Ã¥¾OVÑš8íb�¨¤q ÖWˆpj­šgƒ ò3+x­’œßfl¼. UÞM,ƒ6-~¬õŒ :(§À€Y4lF—Ø“N=z¼¾™Ëå{ÇE¾:¶±)ö�œJ ç�gV2õƒ=„|>¿èLPKA»�€K¼ù5på³®67¸ù;æ8^B#ÐÌîQ5ZËâ.Ïà8Nãk—‚K…uɵVÊKQXV$lÓ6ò·uS·.,»žÞ…�·E,++° “ëÒb“Ìv†WT­¢N ! nrã”4\ƒo{ÍMEh܆ ö§÷˜¬°ÇÔÒ‘Çß\«Ë^vóð…­Œž}ØŠÿ¼{'#jÓV=HÆ8)�½µ• Ю �ö ¸ÃEïáØÂÓzôrxÈnÕ"r14¾0ûúÆ‘°[NÕ)íbm+PÁÀfJ©4µ¾ZOë0ÎÀÈ(øe qñƽ7ù¤«MŽmþOŸâ�ìýS¾dö¿ÍÓ�:²?¯¡1îòüš„x)›ÅÒlp4Ó¯1[T+à í�³ƒ8͏çkÜ{sb×;:|$‡FØBJÆÓwÓ¹³{GÌb$vˆÐ®‡Ýö&O ÚA§È)Ðjt5›vš,–Z«à5P°5ÿPACÃR —Ö(¶gY½þÓªåâ p}2ù¾Mß³Š"”8ï5ù~̆zŒÂ�™@‡:·î_ºšr¹g–ðý(§8%��Êkýå_ÿØ\¨PÙÝFà 5ÿè¯O”r1«|§Ùì 1zšH_øb§‹ŽD§^µ…-ŽÔˆ%ø§Æ™Ëv-¢ÃE£9íÐ ÞÃÐöš7pËó?ââúÇ�œÂUȶVN•o üv�ïÍŸŽ65=VÐÀ´+¢†<ÐöƒnÍúj»�hÀŒ4kp×ç)¬ãÛ´èò�õs{ Õc½�ÿv6 íZ�\ á©ó}sƒå5ÔÊðx¨ì°£0ÚSë¯]KÜX((hС{¾F<Ðâ¨MœÚúm×^êäªË ü˜ -»Ž‹çôüZAAuá•jÙ?úi‰(i\‚l"ìòPª~o ŠòÐd4kñC€‚Úu�Ozkþ}ë�Ü1Ûo†#óA—˜"§kîãšÚ ]çâ{ 5`ö«cí:4»wÔ®CòB^BBzŠ&Kµþ¶õÁ·¦Ý%j ¢á¼Ë×à9´"…”Ëâ:ü5gµ ÷ÿ6±¸¢¬~“[ Nïgv…ë_sQ)ÉKIg'tï5ýõr`ÈŽÖQ·‚ñ*hءۂ¯ûiK'Jòã›)%ƒËîÊ·„q|ßn�ìÄKP¯ ùf(ôe :B�>‡~/½qïO+^ÙLñr’SÞÊš¿{4ãµæ¸˜.%8% ¾ÏÁƒ`#ÎÜËÃ#žZÅ«¬šI®U‡1TÊ'¿!%89É·ix©(paíú„Æœ­Ã±YÆåŸóX]…í¢|q¡U­¿Ò{€T�§JUÿži°ÓÖ¸Æê­ÒîmAø<�— IÕ|»–—“àý5NÔÅ3MNñÍc^%…Zµ`Æ.zãï¼ï‘‹s3¤Òb‡“)iüÇíoÖ«ªhóJñŽ`¼^GBà.»/Sh�÷¡÷•RÒ‡;²àkQJ‚Â#£x…eVë/Ð(Àû›(nt>�Ïç[H¼¾GNͺ`Â7­ ·=u›‚’)\‹צÅY/I¡õ®Ö¿õFD>Ÿ_pĵ+á6R5¯Ô •·{è-‰MH»íAdØÂÒRá;‘o%D d$/%þ†ôu�&Cà##´0HJyq�NÍ©Ã0kü¶‚d�¾¼qn•G¿æq]C‰}} EFÊ« ¡œ€­DW-üEÙh"ìÿ¨ÙÒ#ýljÊË^FC�>Opã;`×ÏÚêMH³î#~ z vè9%�d$�ŒqMMyé�` éù‡ø[d|3hjÊ쉷 „åhcð™ Uó2ŠWiP‡žžçfü®xã^¡zyÝ4 ’^g¬rh|}›á•4P1HNò-$¾ U8ÍšûÃÿtÇëÙÆä/žŽmÔØÚTN•tèù�£^) ¥…Z•’�í:þÛ §YXh×�!p\‚ƒÇ˜ô éÃÛD)Jza’ ž‹CwÙƒâ¶à[áüs.¿aKšC�z^FâW¡ŠÁ‹Ý¥$”Ñžv¯øŸæßÛðã㨷EÍ·¨y åĪÓrÊ·Œâ$$ßBpr kOÅ`yà�Æ4”QPVHLI^B`ñ࿤ð?*ªHÅ@¥_|-øÈË(®…Á+ÝþOÈ(lq/¥8݈oÃÿÿ›Ñ endstream endobj 110 0 obj <> stream xœÝ�ùoTEÀ§”¥…ZĘhˆ¡”#…´"ØÑJ‹àñ€á.ˆQIÔpÉ%¨AÒ@KŠ\*).iËÐB,§°;3ï-»;æu»ívûv÷óÞŸà}?™™ïœogÈ^4weEuÝÍÛ©„¨Þ¾Y[½måÜ¢ì ‡>éOå/Ú{ݯøp�èÄPñ_ÛSòJ_Öq&¡KÞÇFº±J]œÛ™uÄú¤ŽZzÑï3 %äó_ølD*ëÈcè6c�Ï0ãÑìáÞé]YÇßLú´*Œ¬xDÀø@qÖ€”¼J{"��¹)lM2Kê†ì›„un–d²3T�ý”Dñ+Û²1É©6’|ÍÂg ܯjù—!m‘0ðÂ$wMrÎPhïñÀµî™d�rÐDžâŽI¯2ÅY \êBNëð¾b©7K–xVy »a¢�¯d;iÒy9¤Õ3}ïÜ@mÜ-‡Û|,jCž3&i«|îšhàPyî­ÕÐÖÌ47Í¢G¾K×$m“B ƒ¾¥YÏzŸshðe \Go¡cÄýG,U Ü£ÕÕ2¬_Ð**³™Ö¯èû&í¾á T4àz»“´ÔrNTÁåöVÒ<{¹¨`aÐn;#玹) |0Íz©ty,™ ¥Êjɤî⨂…ÁûÛ[RI)媂…AÛÚYqÙÈ¡ !h�•y^Öaëç˜V™Ì][‰€^3©’Åe G˜RésŸuÀ‰¸×Ë„Šç Õõ{ÚÏ™˜œmâ¶±„Q6V™Éi k¿cP¥?祢ûRI»ÌhÅÅ ¡‹†šÌW !ê2*c…P!æ&Uéz‹u�FiHz$`gS–ø 5IT† RÃ4³ªt¸êæþŠ]BÏ$rYÌñ�²-¡õ T2ªa¾Çã»”»°CLµ4®ÊarX84žË)‘~#ÁqT^â~xÜgs¶†u`VøCW%_Àb!MÐQI¹Ä:,kÔé¸LxÈ:*k ±m]~.‰5ñ[•�‚uù-àb]¶»r’Ê Be1*™Âuù-(1?n”[Åy4¿uB¾É: ;ÜhµÃœ'hBƒFG»T °$ŸÐQ*鮢t%꟠7…®b„à©-.U¬ƒ±ËÏÍ*ݯb„(Ý".3¯b„ài—ݬC±Oe“JªP‹búx›Ž0ŒzÀ:ûÀ¦CŒK¹Þh5FpIØå"ë@hPÛ¨ÒEe ÔÆ®ÿÅÿXÇAßÍåC)Ê%¸Hs9Î: :ѦaÏ(£ñiWHÐSj >HÑô �“X,AO©XÀ^ÖAÐb×YÇ@‹«HÑ»h(B/X¶w.I#Ä›U,Áä% ,œ'IJ&$0gëè±l;ëèQv„uôøõëèQ#ôÆKknÜc=îyØBŸÂ/‹·¥é* ñ ½¹×š L.2Õ1™Ú¾L9Y¦¾R¦1Lëèq¾šuô8TÁ:zl]Á:z|)ÓÚE‘4kJ¨P¢µ¾¡Ò¬Áª�É´6®±Ž�W¥8¤f' %IÊÁùäK’ÈÐËô•d_é-ÏY¯v†äë(èpXsY,E(Ñ\r¥hü0Gsé$E¹¨öI±S>où©ø8ì2R‚) ÖtÖZ‚õ¾‡‘ëâ~d‰}vDÎóOþßXqé*ü9NoþæÖ±Øe_ËIÅ‚W2øº<ÿ¾¡è÷°v½Õªˆþ¿2WèJæË‰võ¬ã±C}ë[¢<»TçµR™·~ܳµ (ö.‚à–0@ØJ†ž�uGE½»ãp0^дìÓ»ƒPЩòy0IÈ)§çN‹ØbÎꪀ±þm¥ÛZ4N W0¡ãqTÀ`áö.Ñ x. T°»}Wd6*óöˆïÖÕbPÂKTÛßaŸþLüRG¶@ÍŽܲ‰µÂȨ«’¨€ôÖ1åßä�‘�$—!#O(.b;n@xjHÌ¡:c¯ õ`ºìKx¥uÓ¹Ïeèmƒ*là¼É(É®€�ÂsŠëõåàY3Z>Áõ1ÿ; ®×a(ÇM7¥@>·2øU“*ÌæT¿gZ€õ\fðj * e3‡2J¹¥7ì@j%wÓuŸÕ÷8=Uœõ™êë¯q¦UqU2j•õ·8H­à¨Í(»ì¼‘ @êVnR³RjïíZRÖq"ƒWÛ}S0‹ d¥‹lËæfp2†Ýe¼É¼›l)Ì8=O2ÍÍê3V&ó�a=Ãk­=$—·|ŒVgBpš�ðÌñô9&õL­{–º že êþÂ^_—¼—Çšþ†1Θ:/w³hBèëtAY&ûŠkƒÍÐ?ô:}<ó½�Ü0QÕÕ”3±›¡ãé9„6%ÚV¥Èà7|<þ¾=urN:x�ÓyšÊI&Ô:T6¨f¼»&9‡õô:]ྉƀ2LµóTñ–þlL42æþí¥•ÔPý¼ØÃ¹.“2z;¦Ðr ªÈ1ð5Çé<õ'lkMâý…�X[4“>­Ò-M¤ƒØ»³ÈÑa—Úe/©ñ›Ëlè¯ùh˜µÅnÇé4fѤ`BAˆ}Õ GóS³ôyrâ‚]WU*ºJèU”¿*çOìÃ:NãôÈzcÖŠòÃ57n{¡Jˆ ½·ëk—-ŸU˜ÕÝ©oþi@5¤ endstream endobj 111 0 obj <> stream xœí]ù[ÚÚÖöOçyNB@ÑÖ¶Úª=T21)¢àˆ8+ˆ(c’�„Eœ¾o“^¯·U뤾ÏûË=·¥!{±÷ÚkxW[Û_‡7$£Æ Îèp%Y”dœmbÔ«ÁX Æ «§€ÁÂ( ¯!X„`µ£Á µ#þ=PèÍœÁ‰¬þX5?ÁX”?ŸQãt;A¿!¥¿ý+ôkFû#¡æœÕÕmã ÉhMÐÆ -™�x;* ¸2ØBÁ¶vàôMo/„OWâ«ô¥Ÿ«ø¹J€¯î$k;ÉZ€¯Šÿe�¾\‰_,„O§·��¾#ÛÚæ- ¸2oGŒ1˜��„Ÿ¯Æ¡�!$|Á¶SÜ?f^eO)ýn^ñt`X­+¼Å2Î &ýši7ÁêI ÃYúœ)Ü[˜ð-EÏ·øŠh<Òr‹¯,FÏ'|G¸·ÐëLÌp£3PœŽ`58«²§4$Ðaì;S¶×TİšÒïì‚ê{ìÍP\m¢»ð4†Õ´x\‹±(œyïH` …©íãMpÕ‹z}àjjûØ´PèK 8c ‚³È‹aµ."…Pq-E¬a¥ßâ+n� þc «ñ˜£UßcZ<œí¶ñ˜w~÷t;QUÊ®îb@¨Î‡Nqo¡Û.ÀýÍ 48�XÃIëFxdH@¿f”~¯¯h«ÕjóÁ¢y)§ÆiÔ˜hñ<ú<‘÷•6”Û¯Ë öʱYú<‘FàhqýšALœe)çÙ)Öj¯Ç¨hb4#Ì�™t­Vk7”â‚ýäL;}GþÆ8WòÐÏWœ¾£Oi‡®£gkµÚ�™´z„iz½“Ê„v‚ÑÖC08ÛÊÛ×ýÜ 6­[Œ�«Ø×»m‚hiíCŒct£Åh¥W •¡Åh#í 5 û}&·9SÜÊ…ðÙ·Ùœ‹ƒo€`­KYOpÿõ•jœÖŒŽdµ­'9”ÔÒ~‹m\÷ÓÏUl«‡féÕš˜Z­fYʪM¯{šÐb4R·.5N£$Ûmœ¾£&¼$ÊÃíDÕé;ê² ( Ô&øBt«5½úiOBÐ:æz´�RÀh\�²â«Ü$œÝ9ykôf¸§¡‹�¬†J¯ØKB; ´„˜"„ÖÕeå_­ëwµÉ­r—…×SÐÀœÕbìëÝó�PaÁv<¢&âí$ÐÐïrøJÁ„ò Ú´ &jŽÍ’ž„‰ûö!F?íþ¶ÓÛ»®ôJ6)ÔPã1Ô‘ B|a¿AiÄÖ£Ÿ«` P’íí]ïЍ Véõl.¨ì©v+¯¡85ô$;àJ¯Ò—Š/Ü‹ã*}ñy"­'�š`ŠF̱×Ô§�‰V“@eO¡f˜¼žð)¾X/šÓÛǰ´ƒdkXKÒí¦¿ú.ÐíˆuXi=ÅhL4J°ßgsUÈ«qôs•¯3Y”dÛM@ƒÇÛñˆ *½Ú zŠévÄt$0PÜìΉâKÓbœ ž(€¬ ª±Øß–„‚µÊ°n ú¨ý®´ïuûj }àjÀ•F ˜„BpÊVzåå€x>,L=7Æ6KŠ/DËsl£¤#ôÐHº�¶ö¹ùtf¶~>²F¿¿Püýÿ%\Ž]­íÝ}ÁýVëî/«T5”Ývaƒ}M5×™Ëzìp/•_bw§ vá) «é)ðq<ùšÝnBúùÊGG¥`wç*Óíˆ)m5�€j�ýgVP $lÇiÙjó3 Tû&R:¢PÂÕà˸lÂÌpL5Ü®ô_[ýR¸�¨öOÂj Õ «ÿ7Òüµg°§O©° ž_¦2ÁW{ &ªƒS”½½ëzbS53£´݉kïQGÂ(ë«�½ µA43ÕÌÌ?ßY•ªI¯â-XôÁ^�ÈÇíDõÓDJGqúPTÚšn‚³¦yøCøèH¾:ù/”¡úÑ‘ÔQ,ò-£m²,€¯ë â°ÿñ5Lñ¢éç+ÝvA+¦fˆf)9ÓŒÐZ J_(°Î´l 5˜¨n²W˱‹åØÅ&{ÕÂÞæ:{e0s‚SÌJÛWBÆ´8­¡Q,F[-U´ÅWÜ�òÈ|¾w<�¬ÑÊ}>Ž F+‡lïxbd>ï·ÞÖí�œëHX'£Å2Ì+h`½½ë�C!„Œé¶Å’Ý˱‹áù¼Á †çÒkÑÃTáìâªZ»�‹Ëjªp¶=šKÌ`d>¿k©r¸éà1t̆y5W°¬QlE)`^m�r¸šË­œw·X>½ª=åÓ+ïNÑhá†çò �JNXDÁv€v"ªˆ�i ¦s$ŠÖCaŠ¿ ©8<6Z¸é­ÂÙEå!Öug•©­B—…›+þE¤â€+ƒšBÒˆì5�jŒÓâP¯¾ËÊ·Œ72º~Ømã{§�µ®›ò§omÜØÆ¡â_GúùŠÑÊ‹A9‹Íº1Ǫ̂1NG‚–©Éwl~p‡Ç—Ï10Ç—ïÇÇF‹´Ã,ÇÎÑú¬Q)Bë°ÒÐÌHÖák‘×8·{ÚeãŠe LD±|ÙeãæC§Š5I8º^BEÇ —Ã1Ó˜`g7J€~W‹¸a[|¥ÛÆ3é© L�>é¶ó×£I^:?O¦uTwo´¸T�'âÝaæZ¦ñÖ²R´,å¤50ÔbÖºZTü JB¸2P Ý�¾¡ƒs±†Q‚mf逥è¹ÓwDx Ãóùo3Ù‘ù<±XpúŽÖnÓ &ªF+·Wºh„�å/ŒîVý´Uú>äba¤þ�ÃâCÖë(þïâLðŽ0ûšÑ 'd`¢â�ŽßgsŠßß¹;Ǽ{]V¾gL°,å–BÅ-¦Ê[Li1T¤³0JïH86J7Sö³;'_\ÉF˜ˆWrn÷¿¿Ç€Pul”>:]VŽZÌ.ÞxÈ¥fÑ3Ê×g£ì-7eD÷ÛLVG�‰oDŽ©îïÅÔp¤h6u�Åèù—©L·�›îîÞ‘ªÕ—;5yàP¶ë}ؼ¼?·½ß8› ì›—‹×öüÖÎcž —;­Vïü+…ÒÅ|p¿ËÆ Nešm[óssL?¤¯˜õ…t$p7“4k@¨â {]Vn#vxU¹{ÙþLæ¤ÛÆÛ깉ï3ÙîH2“ú ;Ü‘¸í[Wºm<›yèÍâªR]‹­¾°×TµR®­²X1ÛõuGJbÔX%™¦ é¯Ä/zÆëRîôüÑ1ù£“«ÞqÁ¶z0àN3^÷'€NŸ|q§­«ÅÞñÄÑɃ2S7qz^±.åzÆ„Uº‰ŽNqÔŽa(ªÃ$ þkÅÁ1$hžo:¿{j´r>¦ôäÕ?:¹ê¶ñF K?ùCþˆhòØhåÞÚù£‡¥>o…�)­œ§i¢mkôªO–ÄÀ4D} ÅâÞ}Å¿�HOè´ÓÂ�ìs÷6s¢Á˜Íøá3?çlÄ5#É£vZ¸…p³˜æ-è) ƒÃ¯ãÏ·1„èÉfqõ×èK£•{¸cs?ð…ÌØj^’�º£«yÒ›•䣘ô‰ÑÂÝ�‘Ÿ[|¥€‹#Äs“˜P…(Æ›#m´�¨~p$Öc’í<ɽ³wvîž[ÞsP­ÖÞÙ¹TáLª\�öŽ'š¤wl£¤¯Ï­~fä_ÔÛé²òM2ˆ�Z.bžŒTK&¢gŒ�$â’…åž1^ÚÏ4Íg,+M‘;&jF e�Ÿ+Sã´Ž„“:›d”Ì:{Õa¥É2×"l+¹/î”´Ÿ)bÐ�´­Hœ¥:<¾ì0ƒ&1<é?ÒœŽZÓSœ8½n9«Æén›Ð$›˜iaoj« í’Õj5?SÒ`L\êÛe,y¬Á˜-öé7ß»àö0ïžâË!neÝ6Ak‚ÕeO°1O6äê)vj»)ª:BÕ`ωÜ6sÒa†á…ÓÇ×¾Þ…ÓsXËÑa–ìnr¥¸•5I`Ö(£ð‚ɶã�n”³.å´&Ø/©ø·øù]¶ÊÃsiÉ׫V«¥÷ÏzÇ“¦…=ó¢4@XqáÍbÞ½ÞñDz_2‡ÿ&†fÓî­¦p`v’5£Eh¯±}”�‰S•õ˜lšÉ2#óùµhCY…ÌD÷RŸ&’œÅn_áÓDj7]~7*Ü“?}V£‡#ž¦8.w’5çfIOg´#�03øç1Ú@�æ‘­øØ°=!U8û4Á å] pp¢“ðdÌ÷?8xz?"”C½N¡AÏœ,À½WñE¹�¨¢ÐŽ0O-µ1Z …o*jƒœ<>/ùÄSÇßf � åPt/Üëäm˹‡gدqU©Z—s}|¬?íë4OK]^+âäìÊ`Š/Ê5-ËE=Áép¥ö׌À줎`›JB_‹3 Š”nÆKø"­B(‡ØÃð�9¾2™)ž?üCÒûçý“‰s8 ]îå|´ô÷J1º«ÅÅåš~®‚,JÅ‘xþПœ�YõoMVˆØ8]Í»ƒôµaˆœ 1F+pù lã-Ÿ^¹6÷ŒVnf—ûåCÜÛñ±µ†$ª*•*‚³Š/ÊM~›ÉjLìðlê�*ÙóÁŸbÞÈ™â�}“F+'yôUÄ'gb+ýÅ<„r(¶¢–A‡Œ­å¯*¬T«\îÔ±–ï0j…‹ïÿú×…rh+þäL4â™�/»¬¼â‹r“ áS”Ð#ÝÙ¿ßÆÌK¹vè²5KÈâš®t#|›ƒãËN àK·XˆÈø~hÜï›à;-ÜÐ\ʹ±çÜØšMwšAŸ“wøÁ­Ö%’/…:-œ$=›¿ ž:p7Q-ŸH£UPãŒe9{��ÁA‡8�Rœ}½éÚœÍËE—_ú ÿân‘XúõŒ»•ѽð qïDÝ;Ñ6Ý ?äoa‹Âbø@òÇžÜÜk’¬åMÚÖõ§*ßeco°° "Û$e<7¹¿0Z¹'\÷îAµZûà6ø[J©¸ÁE>Ž Òz’W•j½È§YêE¯éWΪì©7Ô�rRjNký4Ñt›°ÈݙՈ”aØmpÔ?É7ÎÀDö»ø �²e`9|ðïTFñ帕}ΔÖÄh(îöƒò{¬Þ&|MÛ÷s•ùЩ+PžÜ*ÏOVéËåØE§E2Å€óËJÏ(¿!4p¹ÎG{Fù‹Kiö²bù²Ó­Ä/ÖèËÙà‰+PvÊžÐi“=ã¾Ô`ÄÕ÷[¦–¼Š«¾Çt¸Âa1?_±¯ô9“ º’¤7K-f̤»l\—•ï²òý“‰'7ýÛr÷>È{>1/g—¢Èçì¢òy"a¬¿‡.÷c&Mz³¤7;肯«Ï™´¯(¾|Áª¾Çþº%«1ÑZóY¹ƒr;Qµ¬ f`YÎ�ìIå7×k¯t1Ø7Pà‹;y|ö¬Œ¥ÐÁÇqŽ=|�ßþ|²‡0Kµü<çÿøìjЕì ÀÌö-m¤•JdO,K9øW‹ &?9Ó­6ýŒ…3Úð´A¹šê•øÅû±¾�9øÓQxz^]Ë÷Œò±äS*¾ªÕÚÌöþ{ˆìÉa]׌ì…Þ�q³ÛûOóÿ£ÉãžQ~l-ÿÇF¿bùód>8JÉv96JŠÓ|Iÿ2H¢+Àù 8»Á*P`9» ›nUÎçgJÎbžLîàŸTálÀ•pßÔjcû¡A7t•(Ïœ›<gý�iôó3¥N wSA6n°—I¼éùŸ`ì[,£ÅãÝvBdz;ÐÀ„ü£Õ £Éc gN&}též*šý£‹ÍxiЕì¶ssá˜üÖu“³¡x—�ûâ†Ï|Ïý¥P‚Ï<àJj VG²OØ´ùìTDý¦ËÆCM¼ÏÿŒ­ó(ÐA¹;š�‰ØGïFW üc.÷ÎÎuPàÛtŠôfÇÖòŽuØtöu*Õiáºm܈‡[a¢ü‘’ÖuMþ(´DG‡=Ðo7Z8øÌ‹YÇz~l >ó·éTÞÙ¹¡ù´+P~g‚OUKò°ÓY~ÁmÌ[€³¤o`£_3ˆ‰C)0¿+k‹h@¨öŒ ÛÏ‹9Öò?ærÌAB<ŒÖùÈB<2½�Ú‰.Ä#k\$Z�ɱ#{á5.¼ƒ<½ Ÿy��Äþs”ÿ˜ËŒ¯?+«`�Þ�%d.ÌžÛ=ÑS@Cq×dª–!+óe„X,PÏ.o¾¼ª¾µó›«¸µHÎ ž~gç/¯žX#½Yb± óî�ÌÍ€?2Ìi°øû±„œ�±FÃXâ3C"¶ØÒ€KPÜ$$ççÉçnò"ʧW�f sƒù»QAkbÚIpíŒ!8‹{e5õ¡¹Ü3«š¯!¦7…ˆâV!!×¹X¯t‰Îùíý¡ù¼œëkòVºŠE‰Ãsi=äìqóq•3x‚¦Ó]X É% ÃÒËFÌË/G$+Ø8=‡/\Î(îÀ±Á̉6æÙ†› B²r>€}íж,euéä²ÓÌrw—�½,‚ÃP§™}‚^Ù=°-çìkò•lm²W:œÕáì›á8åÍj†Y=ÉÉö¯ï$ký®ôÓ¢ô÷ 2¹)4õòá܃R«ÔF“r—5(ðf8Þ>ט5Æôɘ¦ ðU= .ž}]ú{“�†QÈCçV|rsOÚ÷sq _»œAŒÞñ”&.ãÁê—ñn»>ëŸ�^J:À�x[Ä%ö€'Ç]ïÁ'g–¯M£‰¥öQêÍ`BÆ~pÇfɾ"}·›9ù2%S­N£9èæ@öY£Án…m%7¾)_̓Ó¤'á0Ùx©ääÔè6/çƒÒË•g‹ç½Î±±�ãÜ£rýÄl`ß²,_€7rn JÀf%c䜈y +ÒÝʯ‘;8ÿ8Þ*6æùCé…2–Ãrüa½"΢8Ý>�KÙþÝ�d ÷žY­w+¸Ü逻El¬òéu÷`)$«�í$kP#q(‚Œ°ïFeí¦¤–ö=;ÒDøob‡;šoŸhìòeÉ_‘'¸O-ÉZZóv”GZ‹³nY›\¥ÑHI�¯ïMnÇ7I8ˆ97$Ž]üôùå­sîwe48£ÆYLÞLå|èTòc¥«/¶Ó-ƒÝN‡ßÚùß;ž‰WRf…“§ 61:ØÖdÕ€ ÒÇ`ìÑ—©†wJÊÉ/n^’¢‹kœ_Vô¤Ü‚r–ÕÎÌÀ){Cå€+$ó7NÏ+ïìü:¯pµ´\«weJÒå'b—/Ê.‘1¾YÒ›¹37”[UØé?’PÜö`.·Ô&&’\æŸ_Ãy�¡Ù´œ‘v‘SÛÇf §€GÆü‚ÈíDµÛÆK2€ÃÅWù–©¸¸Ipê›à§¤P’Iκm¼üM—žÐ©�âôP¤o|6 UžQ„W©V'6öú&xú E\ýßIÃ}Nnrsï9ÅŠ•juÀ•T¤sv%v�’@G€ V™1Oîôtà‰?Ò£Ó«¯Ó©§¹6°k3û2 {—þ¨èx¦¶ ò{b"×™K”| Fñ�«žQa1ô¸˜µ \»¬ÜØ&h’^¶F“? �ú˜.+T—}ì†æÝ-öŒ >…W6Ù+”€SHTáØ`/?8¶•ÜCf|TªÕ_þ<‘pñ�TKUï?„�t¸ßÍõO&BBù!>ÆéEŶœûèH¬+Ñû/j“¬g”�вÅWF45g>;ÖåÜt 0½U°.ç¾OCåÕŽ¹”ñ%þjëºI_‚!—²‰N3ø>�†ol«0€oì³3a0ƒá¹¼œõZw1˜¨išÇÆ¢ÐÆ:(Ð?™´¯æg®ml&m´pPÒÇ[Xc3ÂQ‹{øäˆÅÜû±D§…û>óÓÆfûJ¾2ÑA�s¹¥X³Ø˜âg¥Ÿ« Ïç»lÜRèàÖ–^ñ¬ô‹ïìp4ƒ7Ú‚-áçB,þy2ñnž•éýÛÏÊ㳫ÅÐA—•ñäå¬ ü�âY©¬Ï¿Î\¾KŒ®æ’4�>¿PîŸLôÿ�>2Ò? eáDù!·Ë³‹ÊèJþÃXB©ØÔµÏ¯xìbéñ± ]2Z¹Ñ¿)va߯'Å.C=£‚RK »,aS’r1XWz:ðÄÂþòéÕ·éÔ—iž.¶¸‡FÃSü÷™§Ç`§¥Fˆ1XÅrI>(àöœ\Rµ G!ô:[ÙÌèb¸wœsù /:—d €Ìuk񾀤ü…¾ þæ´µ–!̉;ùi)ƶ*•Ÿ�ê)Î`á¦eŸ.mmµ˜%[±¶‡Xæ-K’©‚ ͥ埼•U(xVÊ¿‹J\£xk:’F~®q±¨QtÔÇ@ë)Öºúâk­·ÁÑwKmeƒn‰'àˆµÖ2ÇB­+:R‰ž‘Ýמ‘?0�¿³óϹÝŠ~WÒR gDƒµRï[‹$4'×û&£ÞtŠ&3jŒQ¯=¼MÇÖéáµÁ^8ž¾%´øü逫u´{-¢E ¦Îj‰VÐTÉ¶Ž¦ÊØkM„( [,åÔ†Z)ÎmK¯ •)ž÷½jCÝ‹™À¾UÆ ÑÞÈ™ž‚†’¬ÌsQ_5îþÈA7h„Æ�uYV½ §ïHo:’…âüƒ-´„VçB‹øüÃVÚà˜ˆÏòjuš< Î"«Áh5N÷:S²ýÓ ÒvnìMZ$v1±“\sXþìÇñ”j ˜3ZŒF)Y¯–ý®tôU;ýnn á�—¯�Ž’à &¨1ÎS—fÕ¬œel¯3 î'8 u´Ä „€fgÙ̦õ䋟eC,µˆÃ/óòKÒEOή:Ì@ÎN^÷VÙ`â,›úL.èùËœµšËÍ¿Î些ë|ü£t3¹æ‚ûÃòÎäY( 8«#ÑÆtÐàl�¼³WéËN3xrýðMl1¥WK]ˆìŸä¬t³Ùg b0‹ôã:0!X™ ?ˆÅé•fFê†@+n’sCˆI2#_È�‹²¦)aËΪÙ7ßÚX& ,Vœ“}Ö3Cü¼Ÿêèj~h.ËÁÅh!¼ "žíÞa]Af>B¯²±p¾©/›á|x Db1W�žÚa<z…�Çöà¹Ï—Ã?沎µgÅ«ýLéƒ#!s•õìä4#ÐÌþ;³ž`u$ƒËkíbO�Ñút-ú gÖOn•¿Ïdºm\§…û1�&áÌúñõ=j1û}:Ýeåºl`hž[nš™õÜQh‰‰yàƒuYá3S‹Ùñõ=8³~άï4ƒnÿ}6;¹gÖ?Y–gÖËÞdò´‹`ÿ5°¶¶¶·xV��n;/óÃ@›ß9é´p|îÑfM×óìwÊÏ”ŠGw&‘Ê—>ºôÅ�ê¶�Ù�ÂqÚÙÝe_Ü)]:8¾¼ë™÷�.|tiÐ�„ž3É>!œÈåN;-Üìî‰ükj´šºýSö¦�}ÄŠVCH ˆŽÐÜ.|>¦ôðècJZœÁ2�ªOHïŸ º’ƒnÛWÀºâû¡77èJ¦÷Ñ�•?<Ç<ØÎÿ˜÷³I—:-œÌÎ�È öRG²*UíŸwû7m Ãj]xJO²2×I^s%~ñ~,aòdŠå;Ú"NÎ+£«ùžQ>–zJ¦ Z­Ínï¿2ûiá\øý?»½ÿ´pD,yÜ3Ê�®åÿT,]˜æ3‰UZ�¶Y±Î¥€æß´JUkû_ d\ƒÓŸe–ú ·Uëj±Ã ,K96{òû„ÜÁùôVÁ@�Ý©[ÕWŽåðÁÇÊdfìAøÃ÷ÌÊÌ㳫/î¤�Ó�Âï»*•*›=1/å:ÌÀºv”½•òš}i-ΪñXÛoÐRQÄFÖ¯�®£H?_±¯ôMÀ—ÙïJ YÒ ]w£•{kã�V(*"IG˜}%‡-ÊT§1²ÀÛV$È��]T>O$º¬|·�ï²BU(Ò›%²ý.øºú&’öµC…—�ƒu‰*,ø‹üncÐÀHZO±ò�„¸Ëا®@Ù(Ï3—˱óN w�Ÿü(\\V{Fù ®áÙØ)9&\\J²/–/;-ðª¸Î\Îïg!|ª øÒMŠ •<®Â‚¿ÛX[[›�iqö“rÇåýü2•Y‹J²R"¶ÁÑçÆ'>O Òn^‰~™’µ•ìáüèLiL´šân5°¶¶¶ÿßßTX^aÝooåJFÒ®$S%&:7„6˜¯ºWº´£ˆ«JÕhå”réïá&€JP*{ꟻmL…Õx%�m]¾"�Ò¼\tK1qã,î<°`#²^f"î�¨{'ºLG"{º/`ÞÄbš°&7÷,2Væ?�¶µxP’@eOÝecbÀ_ƒ³]6Y;.ÂWŠNŸH¾X‡Ç—�Àß]xÛ�m²}NÎháàÈ¡�=çÆÞÐ\ºÓÂõ9…±MîžP_ uX¸C‰È›ˆ§Ž\MçÒ­0n]ÊÞc`mmmœ…¢dXˆÈ=DéOÏÏ•N¤_¬Z­öÉ™ØJÞ²)Å abI0˜ÁØZžÏ�þrÞU«0�îXËw˜¹ÌÇ ·|ÂV2üÉ™hÄ3_vYHÊÜCOè%�Ø)|¿�Á Æj öÛlNñǾI-ÎH-ÿð£«ù©�_LS;¼Ñʹý…?V•O¯Üþ‚ÑÊÍìþ*†ìަǞ—Ѿ • ,lP|QnòÛLV‹³C³©Zí×ÐëïP›˜ö!Fñ@™l6æ£Kø�@{ù>›èŸLf‹�èpÌÏû'Csÿ×5y��~Dèá¨Vá Q|Q® Ãb«ÆbŒþ£�µµµµAÑ~=šÊ«4˜Á‰tµÙ7O›ýéö‡ó°úÔ¶’{ÂöªRµ-çz�|4ÿ3æöï4ßR¬�6˜emó¹Ÿæ•¢žZ‚Vc·„÷o?.q¦}$.¿\Õ=ü8ž�DÛów¤ gŸ&øzùÝ3Æ{Ÿ§÷â ß� ‘œ …{�‰G¥¿Ždá¬w<©ø¢ˆÜNTQh`1ù MìçV6Gp¥}GæókQ)°×(”.zÆ„pn¯o"ñd�훘ò>M¤‰Ê»Q¡P’^¶¢V«­FLž=ÅE¤c³T Èh‰‡nb"¬KYcš'ˆá ”%”�½‰ô>ÜLž= ÅWÍ‹YÓÂ^ïøãÊx޳iw ¬ø¢ˆÓjŒV^ì”�µµµ-Ôû.Q4Éw UƒHÛr(‚ÉœÌÜ[»”â«§ç•nßaæØLCbzæfqc\[e=œ´ ê�µ±Z­fYʪMt—Uh†¡]°‚waoJ !ñ_àgJŒ‘Ü9�§Ž5³õ˜ÂÂÂå+àò6*ÞÅŸ›˜‰Fpæ±&Bm¢u«'�k«)¶² 6¢J6·.çþ�JIû™"¾¸“’”ôÜ„¸‰m(4›æNøŽôT}3=ÂÛÿÎhLt§•W°æí&ÍËE“'#íªõŒñ‘„Äâ""‰ãž1^ÚÏ™ÏÈ©!vƒ‰Z§å‰žØMÀm�`õëP¨û·ïUýèHHxÁLî�½³s ŠîV«µwvNÂ�ËJäðãx²I~ï£õšj„|Š'ö ´ÛŽÁ$f“TÁ­Ò—F+ÇHä>á ™±ˆl_ct5O<»OY�>é²p2·{ßE?_A)ÐN0Zò¹ce‹P—[h–€ÌBö1=ÿÊÆfN4³oHØMÄFìPƒ1lö¹�Êd`‡à‚Œ u÷Ó4Ÿ‡11œn'žèíÿÉ T\G(3!îVzB°;uóÙÀÒÉU·�3Z¹§õ7=Ñä±ÑÊuÛøçD]6ëó:å�vWâôCÔ—ÄÀÚÚÚP*®±î"8«`×Òï\¥a|Þº”{B³tró’kƒî4Ó€Ö5èôÉwÚºvÐ;.”of'çËRîý˜ÐTU¯Ÿ&R~DôC·4†<oÆ|ª™™æ‰cˆ U ëjV£‡ÏbÓé“ng[ƒS¢¾Ïdw$-¶ÿAîè{½JʶzÐmã…»ªTW£‡F+‡{ Mn9é?BIÐÛ»nüº+¡�ý?T33[©×c(58ø..ÅοLeºlÜìöþ=mãÕj dOFæ3ïìÂu‡¾yy¶Bîט ì›—†fwNÞŽ #ó�ýµâñ&ò‡³Ûû]VîËTf)&Ÿ¦ýCèã*( 4X¼ãG¸·w]Zƒ±2ŒÑâq”`¿Ngÿ²¿s%v�{ om|Ï(O-f½»E K¨}tÉ»[¤³F ÷Ñ‘pl”nn ³;'ƒ“Ò‹l_cÀ•¼)ªŽ�ÒGGÂhán}Èw£ü[Çd4�ë{“ÿÎdõ$¬Ø×`’yb¿ ‡�K(ÉÎPêx —c¾#b *~›ÎŽxòÄâþ„ïh�¾åÖLT�®C=D© £…»5·F_:}GÄâþˆççC’Kð!WbÍhZ"§ƒPÄFeO©-Bƒ ¬Ml\ÂbZ£'Á¦ê+� eµh–®ââ&ÈŬ̳AÇMpe @» ´“ÜýmGχÖÄt EQœý<ÙDwÌçp‹¯¼µI_° ov¾©Üõç°ß•†J)8Ýn 50Ý_wz{×Q Œm4E‚éùœ�vÙ¸?J=Åòe—Mi¦Fо~ˆ’@…Û‰¨ ÖÖÖÖÛ»Þ1Q¬ŽËMvñy2‡ïÇIÄ4Ê—ïÇ¥T¶$çRì\GAkðØ]*�€š€ýqZ‚1Zù&Éc>Ÿ£ë‡Ý¶§ ‡ŠàópKk¾Fû§ÑÏU:-†nÆÊì†ýŽ7˜P¯„¤u$ð6™DÆóà«SÛÇ#Øa„’,ÌŒ Ç£…CIVìfšÚ>n™Å5½‘3”ÈÔ?×aÊœ’7Q?¬-Á¨f© kƒ‰š\­Ä.Vb>pÕ$}4�à} %ž0€`,2¢¼�‰Ð ‚³ZÓmZæšùwÒÏWº¬¼ŽççÊn}8´&Æ4—FIö£#ÙzgÇ_Â_}ïHê €|ÍèºHÞï.TŠ@ ÐçL½šÙ‹ãv¢úi"…Rp|ƒú}QikºµZͽTưJ°ý“é&iŸyåCLÔÝ”ª™™¾³¿�oh`X­ï‡ ͧ2¯fö"LT§2: V·ê‰MÕÌŒÒvôÀçü7¢„írý®´ÌSí^ùX„êçIXSÑíˆu™B�¨nmTƒì?TP¬ÿÿ8žÜz½i6+BµÏ™‚±¾ÞõnS¨Ûñ8q'e¡š™é¶±Ð7£àMó5 Ñ„ôó•ž±¤ž×ŽÒVóh`¼Ô¦Øn»°ÞºáÙ—È5ú²ËÆë p}SSÚ^žˆZ­æÝ-šæ3( Xl¹dÓ ¥7|f0”dMóQ›TiKy.PÀäth±ÔùK¤˜ìÖÖÇû¢R¨U4  8‹`ŒŽb©*zY &jÔRQG˜bÆí³õvš ÆÀë0�’àÓDúõ 3ý\e Þ÷ÑNm½ìPi‹h�a^�ÁɆ ŒV¾ezšŸKpô'¯£`ŒÂ0i'›+Ù--à„V<ª%aí.B‚Ñõi¬hfŽ®B £;F¢]ßv^bŒâ €VwÏPôM¤Z¦¸Ù¸ ®Ä¾NtÀ6h¦e€`Œº^Ä‹’¬Á šYÜà…r:x\†YÈΡ°ü]EÍØŠG4x¼Ýc5ßf²M5ìåÒ®þ�ÎêHX5jŽvÕ[{”^m%q-¡€’P§½y¦ç¼Pºe”(Á^‹“(½ÂM•=Õnáµ$€úfŒl4•làKáJü¢o"¥'Y ×à1QdIéµm. ÓYWNÓ˜X”€ǯ1´ÒÏWLž=Fïa‘¡Ú¶Ý8}°—¨ùïŽa8‚Rq8rš„²--Üô|Õ±õ’ž(Åê‡"󮨪ªôJ6;êÆ ÓŽ±zŠ3ZøIÿÑ«¥ýf]PšµÃ‹:ù:œF±¸´"À-�v8ÖÎâÑb´žd�6Îùjiÿáôöq·]@IÐŽÓZ’Õ’¬T:ù!´­Ã”`µ&¥@—E÷•þÚúííDuÜW2Zy}ý~£ÓŽÿ��/É¡5Á¼úsO(ÈÅýVR/ù#ý\Ŷzh J­ þètõD‰Ò+Ój÷4DœuNpÁ~›Í5Ïô�Ñ:ý:›­OFjŒƒ9¸zK¾Ò«ÑÊh‰k1¦>î<®�OÖhåmk‡Í65à™ÜW¶ÕXMÂzBMÅ„€f¦ô ü-@©8BÐÃsp¶©gêó¡Ø>gjÜWzÑ )?Wß,õ:S:6j1%Y-Îh0Z�½¤¦¡–A­V›ßÙ‡3©I ²§ ¨»ž¡ŸœiÇfiƒ}1]*ëÌ¥c£Ô7‘FpÖÏD¦ Çõ÷K4-TöÔŠWSœ‡5�m 8„€•�ØÂÞÜîIêo„êìî ç= (Î &5xÅ�XG-¼âÉPaÁLa5Ó|I«T5XàMÉ!ónL0-Ü�cËÕ6Ù+w lZ(¼‚ѓЇ׌Ð*UMó%­Æcÿ`¯IÆ•ªö¦g_ÝŸ…Ž ÷­ æ fNKÀó¨wpåç*×¢ [|ÅÏU6ÁÕ}¹»ð„N§¶�Ç7KÖÕƒ‘…€+óv”‡ÿzŠÓb¬ƒÓfëòqða^OÃÖÅ›áxûH\mŠÃì1(NÄò­Á5Fë`0 Úž�âàÿK„€ÃÙṆ19aáÿ$€˜¸7Ôÿ0¼nÀ ü„€sˆ$¬DEp Å-A#äßx7ü?¬V³Í endstream endobj 112 0 obj <> stream xœÝ�ÛoUÀ¿¥´Ü /"•›øbT„XZ …´ ÕˆÜ!ÁÞ•{¹©D%QÃM$ŠPZ„‚\D).Bi… )„‹ÀìΜ™Ý)»ÇL‡mwÛÙî\ÎÌ9g~ÿÀ~¿œïܾsf€;ääOž·¦¼²úîC$G0ŽÈèáÝ+•ekæMÎÏqé'] Oñ’ƒ·TYÖcꃂ¢Þ:°h\Úq¦¡SѲS2T#‰dTAB'—v¤±1ÃV\UÍh$ ©5_É y3ºÌØ/=‰Xñh̹:0½3íøÉžzD ÙñˆR~›Ò‰¶Š*œ‰Äuöèšä”Ô Qç&1ñn ÅÑz@¹"“Ñ‘•²þtL *‘á â„§èb±÷©6î:�^b@,T3Ö[“‚ î˜4 ])öÎ$÷œèž‰†xv�7&ÝK¡¡+51y›cZÖ)춉†ŠJ2]Vú¯ä…‰†t#ßM“Ž«PÌ+Œch«{ µ‘ˆN�é‘ï¹cÒn-òÖ¤ÁfM– *¯]ó¬§$‚n’_ÖÌr 6&Š>$kÒn+•FÑA›IæYÏKºJ‚L5¹BÇP�ø‚ØêRSÍDª�¢#�'¢2‡ŒÑçÎMÚl¢Øë‘6:ݤe”1¢‚1Ú鬒–u€‰Ó‘·s Òþ(3­¢�޵·ß*Ç<^K¦C>jwO“±—¡ÓA‡ÚÚR üÈT‚éHem츰2'#m°¡²ÀåZ‹]¤¹–UXX¸ƒ>°¨2˜ÉÓAC-©ôhÜ�{XPɼ`é¬Îkê/YØœme¶³è M¦Uf1:„5�fšTéËx«hH¯˜Riw�RÅÅ Ñ«¦ºÌ·4 Æh¥ •‘\¨`ŒÒ—g;? ¤Yî§½ðc[–ÔÈëÓ¨äs’a8ýZ&«ÖÃó§Än¶ºË\Êð’²%Ò‚VTr8Ê0 é…Ô.;=9V%Gd[J•AÜŒaqЛ©\ÎqÔñu¢gR¨¼Ãüò¸%bŠÙ¿Šv`v¸d¨2ŽÃfÁ84Ú@%p�vXö¨6píâ-*7ßnéò'wƒ˜Nì�*ý9›ò›@o4wÙõ”vLv©/m¦’Ãݔ߄Ò-Ù¥„ÛÃXN^.îÒÈ uI'ÌEœÈ:¡á‰.”ÄRý)A%[¡Ž3”„o‚¦q�b'5¹¡ŒS7ªtá<Å0VºÄ]fpžb‡¦Æ]~¦Šs*ž©dpU3F|v…aX�v$Î æé.+˜>h5‡º\w¹J;\iPédëOÖˆ4Lýo1}/Á,ÂÍå_´‹ºXs9M; 2œÐ¶aï(‘à%Ì”¨7À»¾èú c–ù`¦ÔPKÒ‚ûnÓŽ�µðIŠaæº`™L¸ëŸ c ¹S|°yÑ Nœï›þ¢Î]K;r¬ÜE;r”ž 9~¯¡9ª¸>xIæÎcÚ�ã?./[ä¾,ÞòÍT‰±Êõá^2Q?¹ø)ÇüÔ÷ý4&ûi®ôÓ¦švä¸\I;r+§9v¬¦9¾ñSíb²jJò}TëËñÍ"&üøâä7ÔÆáíHQ °Ÿv ¤Ø°Ø'ƒ²º`œO2a À‹>9ß—{ú뮜¢Žk.K}1ÃDJ4—B_t~¡@séà�vÑÿfÍG0Uú}Ë/|Ð0êgºËPlaBƒŸÝµöA½/ÿ»¸}´#qÎîø}þéÜ›œwéÌýÞRÉnüæWÚ±8å`ÓwIS8O²`Â_øñþ훜øÖn®�ú¢å‰ßWr�d¡‚D¨£�’¿á……ï.åùI*ÀsùRy>ÙÊøý/‚íÍT ·w{ÑëÍ]à$¯ÿÝq¼… ŒâtX [º8Ý*_n©0–Ë-™8ÒÈÎóØc.ªÀH¿¶2ê- œå®a¢§S¨À@îæ4 • lãì¿ÛSª@7ÎzŒØ5µ ”p%#ÎiEÚþÍQ÷�ýÓúKyuÿÔnùŒõÜlÊäµiT û>íÍr/ýcä#8É2ÿÑ °Š‹±LúÊ„ dVsP,‹Ö˜{âUº¿ô²)€Ìg™é7 61Þ2²…‡†2Ï1}yI½håAËžOhÇÛ ±G­ü͸¹ g™4Ä’ @1³2òûUæ2Z–A[VØÈäÈ,­³¡�”‘vÚzÃ2*˜ë3è ½·2�2¶f–�ØÇžµ·8�:yX´m9C2Ò>û­¢‘±ƒi›³·k¬ ÍÒ:§o Àl&F3ô‘s�¨Íbè="*y�)oÔG¹„Tz\¤ûfý…îÄT²h>d‹68‹[0QªÎ<•¦‘5€Wj¨äª6[q±B�" ü5áüŠStß㵦|o„;&Ðq•äáTS¶d›Ê6y7l¯Øí:F,>��`¢Ò¡ Hª\4œ�Ì2¦÷Ø’}µaEÎ>jP‡k÷.Ó‹vœæé:xâìÕ;�WÝy(¢Æ$>¬«:^ºjöÄ\×V�ÿ=ù2 endstream endobj 113 0 obj <> stream xœí]ýsÛF’ÍŸÎ31€”m­’\…eo;"‰€¤{]u{»«½dm×Ué6ugÙ–Eêƒ&o/ö^ÝþÎKw@J¦>(~$ñJår郒hLO÷ë÷¾ø"Ç(6T¡¥¸ MpZê×綠¨9rŒ�á…¦«LˆVür•á…i/*GŽc0ŒSüânÈ]Žož¦½´9rœƒ)K„†*ü+0f›§ì»žñõ§Ba�ösäÈ�r°)ÎLésWQÀšÕŽéRäªBaÀöm™'Æ9r¤�Šü$å6S–›>—¡”ƒ ç”9}Ó–¡%|ÛioÔÞ§½Ø9Ööîá¦wféS`ºüÇ î‹nóE0X®>ÌnÔÞÿFœQh§½ê9Öf£mïb<ú­2„ðtƒíߟ¾;þÇ»“|ÿçn¡¥’ÄXÊÁ–ìs¥½ð9Ö f]™nÀ%W¹ ‹^ÀÜБ%[¨Á`ðÓÁ'콆†2©0`.#Ó m/(7ý´_AŽëÓ !`eÈw!* ­¸Ð$#S¨ïÿöö¾øâ &Uóå¹Ä¸ÜôãvóÄ8GŽÀvD+¦¾¬±F„‰`Øu•ª{J“š`«}ó±öÇ^ùqÏÁ01=.òM6GŽya0´^ô!`eXxÚ5ZÇÀhzØã¼*a4 ƒ$Z åÇ=»zlÕ#;nÎrás'àNÈjy—'GŽÙ㧃�ƒÁC2(>îžv�-üõÇBa`JeákÈpçOƒ1‰®�q „ ¡7bV Yó­ñìgÊœsäÈ1¶Õ÷èZ2°dP( ~ Rý}øÿ'öÝ)o¾:SµÃ�«¸ý­õÎhb\ØÛ3ž¼6E°˜’#ÇÊ£¸¶ñ��‡½ ÄBÞ|DZ›)ñ•Ñ:LŒ�¨äÅ^S<Ì Œz~˜Í‘c*[É 4u_ÜsؤÆ+ý{“Ç,y�åÂN�$ÆFÝ7ÄQQäÁ^DŽkÛ…>)Ñ!¸Ÿ²r¡�,Aì¦Ð¼Ù¬«%BæE…§]Ø^q“-È&Ú–ÈGes䘖ôªC6Ç$«pöl¾3œS[UæªâÍÈK…§Ýb³Ã< vdSrgnh4òŠqŽâ”z¬�µ^²±þ°_ØÛw-ʈ‰ bM“G¦ðŒFh5‚�–¿õ¼=»W“#ÇÊ•"ÄU±Ö[ë²4ø‡ý�ÚûsóéNÀœ‰wFK„%¡îÉ“$1ÞzÞ.5|žWŒ‹ÂN»Xó�:¼óúã8¿_ ªÐ.çuhÙ^Çt#S*.BüÊO1) °·ÇžP¨°·W|öóe¿¹Q{_rýQR«…¼~›»'OJ"2�4? *Æ!1§z=9.ÇFí½]o[Ž�‡¨ÏvÚ¦p—n› ¾è?Pl„ÒÔjÈR™^Ç’ ãZa¥1¯í/Eä-àYR»WsÊÍ`s" )Ä_Ó𔌺ÏhëP[¾êŠÕBj$Ýúas�’À7â#’?‡;¦%|ÈŽt|x×µ°’÷a¼sÜ@Ïéq!Ý4!³!'Ü/W7½©TöÓ~­ë³Úa�w\ଠÞ?¯þýÍݰ܀¦Œ }ÅÝ䮦îTöõ5#‚¶2jáL|mQAI@èè;'׃o²)}»Ñ6Gb֤ԯ̄“óðaˆŒj&‚ŇJG–Ø^þaͦ�x‹ ™3Á±Ñô|Ê…l ÇÏé—Q©ìo>zS®¶ y¢ï혛Aç×Ë7Ù‰a9á¦èZ£û£«à4ꩌµÞR´ZnÛn\_Ü3««ñïÎLü¡T¦hÇ� 3’¦ Z/ûD[]ÈK\;@Ý@(ÓU\*õ¢›C’Aõ{ò„KV<Cž0q9ìòpO1Ù.Ê÷9•â†àžâ¤à@ £ëHÆîAñw·$lQ4¦˜œV8aŠ2ŠãN¸8øü1�Ùy>J¯£‰÷“”v­†®51yÒ/y3Øaõª¤.1vC|Š#k·*GŒ Lb½XœGh 3¡¦7Íã ãë�ƃ> Ua•úwRÛ`âCt¦˜m½ê›^®"23ðXðÁ”�ÉLT,Â�/ÒG”¼ÛëÌpm”oT�ìúñHYCqØygùD«Š#ömú,z'UГ!°µ%5_à#›Ó³¿úÈôðcŠô¼ˆ»Q®;=Àçû°OB.[ÏÛO&+Å‹Jž²æp#µë0`åIŸ•¸ì˜^`5!ŸùÓ-)ŒFXümrT7>Eî–šþF+¸çuJµÛ9¶0‰š÷J,7j�WáÍSîF¦›W¦Í«rüp�Ï&åYø‡£ÑjºóJ{xÜWJc{÷ÐòÚybL<Ž|0J“l'‚Šôîf¤"Rßû êʹê¾ì~ƒêT–´ì€wrûǃ'½½“>‚%•-",b`yPž˜îoÝÀO~ö3{òŽ5¢ä ÆõüÝš6è¡�*?mÊ®n0�Ìôm'ýÓ"Q_,¡˜ˆhm¨‡Ùã2'—NŒ’Œîa£Ä–!¥.“>‚-"æ*’'å"øö÷g?üï|;鹡O̤r|Ãñ‹u¿°³^—Aa[mÖúÐNuãÊùv·øÕÇL�05(ÖˆPÜ ä² »í„D5<+ÝzóiÝJÍØÐŒ8Í»AÃô–ù$È“zµG©n?ã…^“?wL+ì´¿ÿÓÙOoÖ¥kPh©;p½Pu<„ÊfWš5¢-î*ºòPŠ»Ž�3Š’w‚„ @€Ëìõ‚.³Œ€IbX žŠb@³U–[/{³[ã5Ð%Ðï>ðæ)Ýs,îÍW}¶ên•\¶ \t‰CT¢ÇïÍjvëä”±ß'ª† @zZ„öuÂ# ’f.\fõ õ¢?çõfPW�k5Ì .›µ™à5ƒ4X<‡ê�ؘ°c%æé±‘é_W6Q�†|ÏeÛšÁ`0xöç“¥ éâ�—Ö±Mƒ´Üëk£#$@ã™®e¼\@:üaTjjq$K£ "JUAü°3ZéM�bÔ�JcKl»»zn••Ê~iç  HЧº×].ÊMeÆB‘…Ã\×ö‡Ó"d¸;ß„*¹ò´EpÏ9›¾2c e‰ã!÷Û �4Š~”›ÛÐ5XU·JÜF�+•}z·ïËîXÕ¬Œƒ ›– _ÿµ®û€¶ž·õgŠÿÚ�6ûá¿V^ꓨ#ú¬i–júÇÄI7d¢JÝPZm€®�Ä®Á*ºUR ;˜ž—²ØÏEÉ Ou¯{uzPj@!”Ëð›çšÕFí¼®:Å{J¢@¨AôfÒª†³ª{”�š PŸöŒs¢s«„‘™g?»§é(Iï&íuÝƃÞp�;õƒÁàÇ+» 6Þu¹ ¿ý×S¥‡! Öz›ÍøL€ÄÇWCýžÉÃÝ#(­ r£³ªrÒ3â{|îVù¥èß¼™pGO€ÇU¼¥(£bM-ïœ>u„-­;àmPÝ;»¢Ü”DëÎ^·õ⿉7Î=e#g`±Ë_JBÓ!hÊi†� ™çîk’Vƒ\4ÑJøÜ­J‘2X"·ÊBKð‘):ß™BNøO·ÒÕÉ ÂðÕ'ö O:ð$òc¹¾Q»T*$‰V8ÚÔ�qÀ3¤‹­,ÒgmÍÜà b”…)ogÆ·žnFk’Æ÷°Ôn•EûªbØÂ(ì´ïT—ãVs-HºÍÂÙê¶*Ï�F+65Pp†Œ–µznhÀÖÃ�GäÌåvD§ ¸í$[vJŒ«{`îCÍ;�ËÞMú})â4ÚÃYoC^™hEV¡â®Ööaµ`ì>r!Zé\„iÍ�æy¾ê9U÷C}6wƒ9 Ò,¾¥mj‚ÏãY¦·ˆiÉõÀ,ÊrfØ­Ò@¶ J†4øS Y]ííÀ]E“—�Ñ>�VU¬�CJì%'[»Ã­Aƒ°Šh0óx­ÿR¾­g¸æñ\SÂÖíæ%p«´�Fï-L°‚JlÚëš1ÀÈûÉ[b �½Ï­èÞ&]ë’Ó¶VÅΛNgÔ|4d{N´@²�NWF#Ór…KáVIüIº ¹ Š7v0Y:Ÿý•ª”Dvºðӱъ¡ {+Lc‰U šÚ»‡›Þ Àâqr^›�5’^&�×,GkâViÖ#òÔKÜ*MüB? Ï'Bái—‘¶*¯L²7…½=[þ§.¦Abvî¦Ä[o“««<2²C‚�ˆÇ¼ÄÖ=SXÍ#’%$ë™ù=‘-C¶ÝµdìÍá(ŽXó{ÆY�ÇÂã£n•`a)hÔÝç)eYFóüø@”£½zø›�*•}ÜV`êdôG°íâž[öÂ’nĪ\4ìlb�Šmw—šnÖ•I¬i}_šï'n nLY€|â�ºb™'!àLhÄE³ÒÜ*cƒZˆÖ”î98Á­ðpá[Þ*o¬„JeÿníH�Ûe×�“�‚±ž×6dlje®Uõ¶q—’ŠI 74¿€[мŸ(ô_ý�?:C‰iu «E¶Ôzˆ&L$yŠ7:ÆÎ)‰åŽÌg…©D«é�ÏH`¹þ"§†Óé™h ĈXM’öPÀŽ–¡0TµŽ1{¸¬s¯à€àèâ§áÁö±˜çe� TZb6þózI�<±¹«J­ãsn/£—G"X›“Hfý²ø¤‚{ò‰è^gŽäf#ÕËÀt ·¯X¨íúé€l„—_ôɲ Ž�oðG³Áfãè´uOžØ�g¦)h@æÎ†q¸euî<}{çÙ(üjó—DwwèÄd7Ú¤�bá�È–×ÏsÍ•Ê~¹úžÃ°¶ÚÙû°ŒWà­ÑzÑÇ�ôœ œˆ0€ò ”^°c®ïl?¾ù”ÒÂošP¦´¡ø¸WxÚ]ØSoz“r`éªÃDx'½ I±Õ)<íb±>ý_ßløèu8Úo ÊÒç�N™p-S@¼bøZüxlRo!ü?{º K([h:IßL:ßþëéçÒ[X'Ä÷€bšÒÂo‰Â¶úþ]j€‚‚ú× =zo‰‘y( U6ÿsŸQ Y|HQ”áÁeRøì��=W �Ô@-$ö›À«Ý_ÿRôB;J·#pwçЊ]ÞVµÁzƒD]=xNßÛo…¶ýj~=Ê9�lOI Ä@ý“E>»æƒÅÛ–í†ÆöÙ\׃6"4ªØP¤ ¯h¸�‚ÏÙ�B?Ëó±õŒDއ…Âàνÿùï -Ø°Šžf·�Øô•–ìÚ› @0úÝaâ]xm´ \·_V_&Ïßr“Š'è¢ü„Eܺ´3šLÜß�‡½™ô�`ÀS(æuî4O(½—r°éõ -ÅÏ— G‹ºšŒ—ÈôüDÁÞö $ÙÃM\šnDî]%ì›L¿ÚÛ¡°­X]¿{–·úmÖÏQ‡¤™€¥�ÎM¢µØìPµyªKs‹³]˜Ü$:D:­‡º"+XÚé,-ãï›Sç–6ØB(1�Q¨�6Ñ“=5±„ýÂ�r*âŠCf¥�ÁÇ'– çEæàBñ:<Ë4K�Æ÷ŠR#°Y­° 3A°……ÚƒÀµÑм¯ˆ¬~�úrD«…ô!Êå0:R¸3C¨Öš;XQOâßLuë^y ¥×mЈã@ʈfH<¾ú¸Wûc�êÜI˜„áecAPB £sÝœwÒL¥XUiÿq×_[[.¨'ˆ€ÔHn­1§:Ä?YžÑ]wšÞ3ª÷�Ú%Èêt¯zÏÉXÐxÐãHü+5}»é—Á…¨N³á|ªJ±.ù™×6�¨üxF•é1¿ÿC7݃Ö«•9ŽÜ¾>€ÌÐÕF7�ÖØ:6 Wþµ L!A`*;]Ëkß­‚o2ÕŠ9ç/ ¿óõ/`{‡=y´õ¼ :Š4)3Z2¢:Tc¨+èôÛ Ø$<½{ò¤¾÷�*�t{™é«ŸxM*ÊNw%)%Lý„šrÃh5QÊ>û Zyr@­ÂÞ^1câ�è›|©}xÉKyD_†Û¶‰<öè”Ň\"D%‰.��]’U$ÿ£™T®:Z®JøÍ—½Ô?hÍRž�ÌÝ2¢ŒÕ`<¼øµ÷í­ƒÁà/ißr¯F'©±ž£}NÓ^Ñ@¨bI–ˆ¤Ú•å*ÃmsŒP ØÑØ@ïüb;Ê,7ÀL‡NšÓëÉØõc4µ�†þ½ÖÛÃŒçú­l­ç ¨ãg£ö¾,ÚI´—ÚÄ P!|’aŽRÓßqäç`Õ%»ý&ªsò†nî$:ç"ÔÕtÆž]¦¨0T´Î0GÂt"jš0'µảPÄÉÍÑQ.@ÁŒéÙf Zm¡æÊÅB§3}Ó0D�]š¤ëdïòß®ËèÍXèkË ¤ T|WÑhi|©\§%nšnW.r‡šŒÐX\ —pàîzŠ�¨nZÍŽ…z&ðž·l¾. @_ÍÑv ë]jVî]3XOó´õêoT�&ä·Ò^QjØzÞ¶ÍÁÑxEr22ÝÀ�Gcÿ*æÑ©Ì¦—6j€h©Æ…÷…¡a$B«Ö±j'5ML�”!l›Òx©Õ\è´šMÓ§ÎĽkzpζv=ˆŒo»Fî!‹YHc/ ´4�?ì0ÐÚß²§.-ðN3¹·b©_—ÂÀq±Â•zÖÌ�ã?h9Ñ ð“7ŠÀ�Ï8PþÊ]GíǶ‰êìØ?q7Jò= g–"Sš9ˆè®²¨7çRÌÙŒ7O™7þÆŽ¼ …ê™;ò#ÿ¶Ï‘Ôºõ¼½ñdŽŸì Fò>í�t?�ñh߬0SˆSSçøõà£Ý»ÜpKfÅþé"ýC‹O–²€b•|šÔhk€ì#·ž·K-u™ ¶I…ˆLÒ™Š¨ƒDM¨ú�g[Ïç’ËÁ¦Y;©ýœ)vö>à (ܾî‹3>¾¥È ¾öQY‚Š!½„y,û @ ÝñyÌ{1³Q Fk¼ÀŠU¾a¾~le^Ûj`NÈœˆ'„UWOcb\q�›8¿OV‹]ò5U„Ç=�¾ÖPoØx %�8à;§‰t§yþ@a¢qjé:Û/Tˆhc]ðì-�ÇsÀ‡Ì’­Æ¯§ÔÂN[WT ÷;§$¶>€P1— \rü›°#F““¬Ek2"d˰…–LS> K%àvÜ|°ùè ŒE;Ñ(a~¤+ RW<&3$†P8å¤.ãá ëÀ" 9µ)—}‹—iÂÄ|Y"[Z‚Xš¾E ‘šÉRÉbPÖb� ¼³)Oo­Éu¸ÀÅ^Cž^‡KM{ž^Šy€Gv†Ü Jµ£Je˜EçC•kv.r…*yp”Àƒ?Ê{ºAÌš -'ú|kàzSVÄÞŸrÙ·åTD’±ë ÕtMZ"ÍÛÔa»Ú½TÊAÅýåÆÑšlÚ[™Œ |-·˜µ){¡åZ)©vý˜ «. ¹hø/ BÚ^¬8‡GÉ£Auëµñƒ*>9+¶:ÌS Û®Wÿô�ÆÖè—-¤ZáÜ\�ʉ•‰ˆN…\%\T¼€›@¿ù(ý—öZRƒå*†—Ü}Ù•r0I´f‹bmzñÜ MÏŸhÖ†˜Ïe�FÅýØ'å[�åxMÙHöŠÏ5”Í—–>,×gµ†©ãŒw04_õ‰&”¸º¤rb…úóƒ>ìüKèÓ`è.±ÆÑÊ]�ÔÝ|¾5Ù[q'+.T!@…µš—ærµ÷É}è1z‰n'¦n,Šb�K)~ÑF<ñ�ƒ8uB«vÍÍ�9ƒgWHsžv|dËmcÁ­-Ù5GŒn­e¡'ƒÁ‹·éë¥#爢õŠd’×QRL+sÜ�X ïT±Fî¹haóeÿǃO9üh5Ë‹kDS§a`°øìgÖ|;tpÓÂGáÆÂ£•†ßIä0ã³-0·“Ó¾t³;ù5?|ã&¦0JyÃh- ­�“‘iô¢x¯8"0ô̯ÿ·$#åp·dÿ›�“ovŽïJN}Øå¤Ô„Û±]?&�5ŠÙjÌuÍ(‹¤Ë°Cu¦Å–ììF›É#ª’qáÛ^¦£Uš TÙan,[²Ï½ÄôKr%êߟÆ#n=YQz7¨âR vÀ¡è~¸�8Uö¹ðq=wԤ¦jh‰ýÄýZ/ûÈÈ håÜ[´¯«é䣱,Ì[ÃÅš0Œ@Y7X0np2JSòNP1H#Ÿ;kè¿JHÅ©v¾ìfdy*é@¡Ÿ‘o9�Mr[CåÞ$<s}6è»Ã»Nj7œŸàfˆäVnvaÏnÓ–Š’kf=ZŠ©–¢§ -¸µfd”o‘…[¡E îVu�t(? ŽöAëÅÅB"ŠÐó·S¼ eÙ®²› Fóعg·Õ¨ª}¸à.!Ä€ê¢hºiUèføÛßëB“âßž=¡CáyaÏ; -ŰÅŠUË� ̉�)hy=~«¿yNÎ]}ÞÛJšƒ¸#¤f”f UŽ•Çh©+Eq{Ô«ëÄ ™B¿à„N¸àa´Ë`$‡îj‡×´¤áhžòßö&šÀM4ÐGn8ke…ÑŠMÆrõ°RÙ×ߌS\8Î@cL´b»'åÉV[„Ö)]äLh:~¯¢Ïv8‘9Z&bÞψ׼¢º‘ÆÁ­Q”Gts›¹Ëé(+[&•"T»~ëy;X ôçC2©a2�ÂKó½².D« Ü_ßÖcÔŸô�é,z.s…)Oà>ƒ¯¥ä€Gª9g褄3ïú‹çcLdn·M”$âÎBÏ)"9¶\pš(5üDÙûsŠä¯Hºgá«Y Õ¥Áe`æ´›/—Ò~ׂ|þdxÛiDsmOpÙ†­Êàê O�,#9‹Á|ß º"Üdôc÷õè�€í?#�Æe'ÞÈÂËôš‰˜+ˆ”xá³ùç�ó´ÌFxÈÖœÇÀ¹ÔŒ �¸\ήå�§ Êçþe²œ+|¥>— äë÷×s?rƒ¸ûy´* XÔBÌâ˜Æ2‚É£ó)ýe$m'Âl„ˆª”y:Äe Oðu¸iöS+Š´.Ê×›0»>ç2á16䬇+C[¨&LD&”Ù‰æ×ƒ²Ñh|)Õ·kaǪŒ`t(ÛÜ[Í|˜(µÈ VcïK¦Ò$Ëh´µu÷5™,—÷¬êr´ç–ô)¢Íëh|,çå¡÷t´7ex·ztµìLöA|3¸P=µxïìÅÀÐ,n ÇX ¿ð Ü ’‘®ä›¿fËè&ƒC(õε疪Džt>Ÿ)_Ê>ê>a{ýÑ›™?Å‚îÒ­·ÜU ÅÚØ}]|öÙ´:š é,È�È·b6ÈXV*i½öh•‰£‘"±&,Ç_Æ*âR@ZÅFÊôøF~¤ñ KwwÞ%íõ¥FñwdI¦+Ÿ\ø�ž¯Ã,°:¤0`u­ˆÆWLÐц¢•,ʼnJ Š=ËYw] X8øƒÌ“Àt}Þ˜³ÎÞ=ÜôNiTuø—µ¸t`÷Ùz{N_× ÙùÇÒ�k=„˜ýKgóK¬ˆ,ÈÄbó_ÅÂ&@¢°œŒ*ö¬àN([v�Îð†_jù³’q°m²›d^¸bG¼D³t”Õ–ö¢¦ÂgÆ‚êŠI7Þ|SrÚIt“\�æ!dFÔeõPÂ;ᨎâÖóöÝÝDkQF¤®Lwiæ-÷Å|dމ²Zè’™aµ‚XÉÞ (—G+‰�p-)ÆTÛ ©¥­$J55j —Ÿ×¾÷à ¢•IUÄñÖˆV¯Ó¡C•Žx$›“y®éÀ¶K`iߥŸ/73å"Ùˆih[Ëüò—ví•ÿ‡R33Ù[¹ŒÈÛ(Á^ÄæÌ@N–"€™z½¹à>›öº&8†âí‡hÔ¢·Ë+þd”Wc¹ƒ¸ä5„j=^2ï7¢ò•Î&7ˆ ¾ìsÜX O»Fs•Ý(Hþ‚9¾–@�ð´5`vú´&–v¯ý«¡v.n©­—ë(W• Á�:]o¥©wçøéÿo½ÂÓîŒVšQ€åeÅÚ1!\–ãôLE`&¢a7>xÒFŒ⃸ÁÜ\ŸrŒ–MkjÍ«{ò¤¾÷�.ÝõùéÔf�\óÙX2?ƒ{â´">ÞZæº$´\•%á£\ŸÏCU�Ÿ˜"`¢Mó¼i¯k è.ZÝëÆöyaMs\�Ö+ðÅCëy«ÿÒûp™’ù�dGaý?0Åd&#+.;,.:™"DuŽ#k|ÎiÀ›§ÍWÃÏZ·JùrÇÖ­—=låèiq`54&®5q'dµXŒbÍÔÆFÝ/VÑxˆ*NNÈšo‹Ïþš1ôe\°2§P%Õ¶ÌSQë rHÊòL(Ó›,Ü@òÔÑ”c E ç¶ØLŒ‡ª!«Çd<‹øÉë+Ú— €Ÿ4ÇÞJe¿¼s¸VŠp+ƒ Ä3˜PÌ-bcеo”ÇB~¬� jcÌ .cÞÎ`¦ÖÓù¡Æ¯ÊÕ÷›�Þ¬Æ�Å‚»>÷üD yRé! ÞÅ]uÖz»n'Ö± ‚�©=¸¡Øn4ð-‚$dïÍþÛn@lí„YZjøÙ/Yç¸ÜóéÎO…}ÈŠo,ëW©ìßÝ9$8hø<[îٱقÄÄ@¦#nÈ’QBâ³ð#½MñqKô�ÞÂÈ”Ê êó”úº âm{ÁÆ“™MmäHF#4MÈa²}óîåTt)²'¯3RQÉ@¦C¼/ºm°çˆY@ÊPǪùnßú)hŽoÈòmžZ UQu�$ð\_&žUŽ«Q¬†PÏD•°ÊKšÕNyçgÇ6€òëa< -e4BˆYye�s¤}J% ÉŠQÄC»+OùÙ;!-C; Lšüµ-ú­0 Û ‹™@Õ6��}ùÕ¼µ*P€“m'Ö,å°‹ò° ¬‘yvr“!é{Nš�ñ¹úÆšôŽ” Øp4ü- ¢ô;:c"X _°·U†­øsG éOWü>öUÁݤ'pÚn�‹]bÄĉ 1 µÝQSB[DŽ QVE!ÓÌÇ 8Ê; «‚2$�QúsË [¯ÖˆH¶žHKcÓ„ÈxxÕx…% Å‚sn-d#ídt—CÏb%å`Sv‡)±Ä5¨‘žÚy�v‹ä\UB6‹.%yƒõ$çÇŠãœ8Ýä/ïœâ6Y6‡¶°Z~yLšøRö¿‘Ÿˆ˜mÅõáX5%ø,`Ï}‰gŠº!T%•Ê0ûvó9¦xV&£‹˜Üšõñ}0‰{اkcëy{£•ŽräX(¨¬DuÅXq}ü,yñ«ä7çdz¼…—#Ç‚�e¥�Æw] I)=*UOÇüš<(në¶ûú ±æÈ‘AAåï@áyÿ°¨� Òz‘×säH¨ÍVS…ískÈCúfBÂYå5GŽc�õ?ŸqäÛh¾ÄˆÄ(“‘«CL) “#GŽ)ñãÁ§Á`À¨©­vu·zHÓU¦A‹'¶áÈgmräHÍ}˜Fa×T*ûdnßDãN—Hß§>GŽ5‡áEÚ3"ñ+<ínÔÞ'¼qîìÑé-„›räÈ1[›�ÂS$¡Õ0ܼN¡ Æ»D§FOÚËÌ‘#Ç…§].OË�{t a¢¹$£¸kƒò›z×ÎæäÈ‘c1 “éàÈ*Ò ™<Š5—–@Ú:GŽuƒK¸Ó%œX�> stream xœí�y\TUÇÏ ‹²˜¸e’ûF«K¦â.Í¥(-­73-³MÒ42\Æ-5\33{1•èMS"MCLA–EA”]`†Yæy?w†;wîrνwGýþwî}ιϜ™;÷œóüžsj\ÂRθ4Ë™î7~€ƒ–vÂ*9Q–vÂ*™yî–îngi7¬�±9#Û¨}”–vÄÚ°IxåÑBôÜ…è!–vÅÊøà,BñƒRxå¶·´3ÖD«Ûƒúz µé ñ±±´?ÖÃúB¯ß˜¢ ^ ˆˆfi‡¬…îù�r¹{u/^9��ZÚ'ë h)Bè#-À-Û†Nª¼‡—,îYŽ¡W*®+÷¹�üw„e½²çߦþ)ƒÔÕsi»=Ó;ZÎ)«`F¬¾ûÛ®¤ }¿“Jíck!Ÿ¬‚–i/4nþùªñ¡>ǯ�³€GÖ‚ß/†ÍÅß2z¦‡tin‡¬…Gó{¶%˜vTªì›Ù%+aφ¦m÷ÚèY&½C“'4¯KÖAÿÜÖ†mÛk9=Lmüe&íðo$}š–efZü3ƸåPîõÆÂ"s…�f.û‘9YõׇyÊ¿^�âdrxx*ÉÇë~‰È+\6,a´Ü¦%¢ë¢ë÷ñx:.”µßUß} ùÄ\0M•P\z“ä$³ä³6âý£åf‰®‹®ßÇÄN•C›XQ~w-n|‹Qªsu¼÷¯‹D]§õ²ÍØ1ü"£åÇŠ­ÊX¿�˰”@CØzV5@yéùUcfÞÊ�áœûtÈ Ë‹=üº·„i[Ìh¹Öe"û ý>6­v§Nþ‘ÊAtû8ruÁ‚V=¹½X!(¿3æŠèù,~ Ú·R“ÜðiÌç�ó2± ôpZNðW™Pó³�µk>áœh¶«XÇø¡D»S/ÐzVçGŠªÇT¿��c6„Q“¶Ý¿~W°�·o aõ¥fRÆ Dóòj#›$2¿¿ÊkÏÅæâ}ˆ(Àý¼p+}ØQÔ™i=£³è*€v…aÇ>Ó4J zI œÍ*;Í©ßarú=²ºÛíª5ÏÚ(-"?C‰ÐÔ‡Ý"j^˜E¿ÏAÿi&]Û|%ÕÔË„×S5PiŽ¤í–‰uwWúiã›BË+T¼%ØaÓï³³±¨>‘ªŸxûz²O~‘гr€2stK&—”#¯hÚûö%BéPFO´ièfØd#€!\¸‘…ÇH]û£ *Ìqs}® ݸW²|%y5¬ú}#œBSÜ»Î>¤©€mF‡&áåÚ¨‰cX�¬¨4O*ÃÒúÜáÆ-·Æ�¸Gvý>�o¨‘hN —ëû)·£3éZ¦Hü‹i«eÀ þd)Ñdufô„¿Æþ­7À¥ß§‚ÒÇN¿ŒìQøŠ°cø¢vÛæ‹)%H¿+Œq«ˆ2›~¿ßJjXîêKý¬éÄå]¿4êë¶T©çê~_º‚ý•sKÔ" ŸHè£ó0ýÌ–‹LXÅÀÓáÍ[j(üÖ?Fók@û­­ß¥ãÔ4J Á´ e,¶©ãÂd,]Ël9 ©02Ü›ö¢½î—Hy ŠP ·#Ǹ‚ß¶>šuYEØ)1ïýM蘞EfÉu;:�Ñr•„³LÓâi—Ûþì¬í½hJà¨`ѾEuxš„œ³ÅæÔ'˜#ߦ¨£åÜcÈj0Òï-¨- òv}4"5c¶ŠR‡àŠeÖì#s¬‰€/Ä–äah§[’‡/7S¹†q¥þ†K4˜,w®A¿ îVIäúIUeÁ¥Ÿ&â.B`†;.Åò'{¢ó“r Ë í•‰±&€�'÷ÆnG¨×¼bj5yÊ=åÂÅ<.àÙ É2 bsØÈŒîyvŒ\ÃgÓŠ÷ÈHÜ�šQ …â&$ìKðòt#¤ä¦O%K–ÂA¥[‚ð¨òžk×_ • ܲñ öéB(ÖÂQoÆI™Øµ×È.fJÖɉZå�mÜ“ÂLæÃó@‚DQß²³Ï Ù§HSDHÒ±0^Ÿq8Ò Ã’DTÁº¸Œ÷ÍGïL(ø\ÐÊ÷7igéš/.wŸ“p½Lpø?�{‚„ß…¼PÉ®‚ò¶©Eû–J¬À˜á7õAù¡‘ú=O©›eI$ÔOe¤�Ñ®o¤žÆMÞ7vrŽ~ãùÆO=h‘œõãà|®¬l’€Í“jò¤N&û¥%ðó¢!=k ^?(GB§I,/äYœøDúYÓÈ·8›}’a‘¼~—uÿlãfò0iõIIr,=ø™È4–6l>­“¨#ÿÙ*'a/¿xÌæÊKrœÅ6>(r­ kL]4š&lyòõwJ†ežO3“_\ü‘L“ë´P)]I·²¢²žvŸîKÅVFª TöròÎÝpA\«Û2-’ó“€8ZkB@íM/{ÝDhŒÚB‹æ·OHæ0lü^¦ó¼X¥­ý�äZNÖAUÓçl»üN¿9jÉ_"YP€î�—€‡ƒÇæì�%W2©:•¦ ?X )ØITrã” p�ó;,§È·KºÔE”zß6š  r åº&D0àÏZÎÁï0Ì> stream xœí}W"ËÚõýé¬ït@Ì3£“ƒ �"æ€9aÄÝÕÝ4AÌ"á{ gÎG»%õ^{ݵŽÌ�z¨ª'ìý¿ÿ50 ‡Jq p Ð÷ zŠ×‘¬Ž8Å,‚�á ü_œæQ 4@) '8=Á!$‡Qð?qšÇá?ƒl¶’ÓœŽäPÚ«Ñ䑯¡Â�ŽàÚÉÈ;2IùJ¿*T¼4„ç⨉ð"$À¨ ѧ'¹f Œ†è°‹GC¦Ù¸uåĹ~:¾}1³µäM¯²·Bv³ÀÝ@~7�ßöçŠÿ¹ÆÝ®°é¹ÃëIÏÅðÆ™}5E-&¾NFº¥føk9 ¿Þ ô$§£AäÛ¨ d³ë÷ú+ýÞ¨P!3òùüŒ'iYŒ Г> áÑ…X`xz4ßí ˜gcCë§ ‡×›â]LÉË)·ìK�oŸ3KÉ�cá«€Pœ�PŠCÌœ¡ï'YŒ:Fh²ø5ÁJ¿g*T”#áÇ#ù¾é`>Ÿ×…«ž;þþ™ØèÖ¹Ü*h¥pK̺ö.™¥dÏp£��æ ÇQ^3ÔÓFqÉþßIµÒï¢ ¥¢Ýém¶² ‡‘¼‘ðëHîn$h± ¦™Ø”çrK™}í%ôHù…£ëÊÉ;g%A³E@€Ò^€4ÐS@Kó•~_U¨ø+ô&#9œaÛ�ð*‡30×ñn(èp§VÙŠínÏå¦�ß¾øîŠb€{t!î ,¬Áâkwªû Šj�Æš(NOŒzÛ\X®o‡N÷é:Ÿ©x(½`+ÌMz.¾MFPƒ‚Þ ¿R ‹Q,B©¨¢’Ð>”äô§±À,¥�æ[¬¢u9é®åˆû“;Rnlû^ )Þ@„ò¢g]ŒÌxù¼ZžPñªÐ>ŒâP’Õ>ŸÇî½ËЇ‰¢\eo©ùDs¡È¨3³ù|Þ46�‚‘ðWúQQÿ@ÌZ(Éé _s¡:`š�¯�ºÚæ§GÊOî\t Jx!)j$üÍ 0ÚXõ¨B! &€“�ˆ™Ãx¶t§¶ý¹ŠÇB¥èÚ»z?*6´;½F«  y¡£BÆš@3í‚sýÔ#U~ñW�n>�‡ñ©»Ýé5Ïgw“êPÅ a$üRÀ(^G¼tC0èw§ûç®{F‚8 {Dóù¼u1¢'|•þôTÔ$"ßC$:ˆ�‘ðã4l÷²¯¤vÔ {”3ûW� vŠÂ4€ (Tú“TQKÐR\!ˆ<,‘S o&¶!T] JuÒ#å‡6N ÞÈú¦Bsj BE èî^kû¾gè?ÒR0—òn8¸ä½©øz®9n‰Yb>�RŸÉæ:¢\ÏXsܳ°û…á›ú}ˆ™E ®ÒkAÅëAKq(Ⴢ$ß3Ü”¯f7½{ùu"øHÜ1µ�`–�‚ rÐ}ŠSpÒªØZé¡â5€@I.Ëv ò¦îÔ°;þdèí‰ç?¦"_ÿ•¥kïª8úÑI‡{(U™°Î�‘pä1”âǶ^šÉü“«©Ñõ§Cï@:ÿÞð¡·ȯq·í~œá "ßE‡PÛA¥ˆ E€äa ò)üÌþ•kibçÂ4~2ôæ÷“äüqñÿ²!d½7®½«%ï�BJ€ÕÌ-1û~$d j;@i¯ŽPÓžu…|>?·—4φ1†oµ‰«lZ¡…´)d� q�y<ô>ŒHc[çôbâ­S2Zøžaéûd°Û µj{†¶•dCÅ GÊ}ŸŠ^GxQ‚CûÅJ¯ò€ òc‹çù|£ùN‡$cRåAóqçj쑸ÛáÏ:üF«0¶_ÿþP.—¢W+±V›0è–§ØQ+¤pïë13‡™Ô½¯æÑݽÖÝë‡�* ÿÎP:îàÆ'f»ý û'ƈ\63ü—‰@êâö‘ðŒ§ÒG½®hC�) ¬¥ 4ÀL^”P‹µ Ø™Ùë/´Cƒî‘ૉ9¸Ám÷�dš â¿6µäYzt=Þlä\ä‘‚û=n39r.üc:ZñˆxM:ÖNaÃ'Áa«î}5Š|ž3 "�ÓüÇÑÐ+o;Rα–z甌 ÿnÈßjÚlBÏP ß.%îî£ïÓXÀ±ÖX'ÏáÍ3(¸dò¢fV߯–üj ù|~ßw¿ë~½ýîOn ÙeoÚÍg–}é«p•Ζx?÷Ê«°Q_žOrhã §€¾¿P�U5çk óe„âß8ÛbU\—z]ÑÅ¿\Lj;N/6\ëË@aÔH 4uï«  gv… 蔪Ä[Ä#åš-üùÕE‡NÞt:ü ¯Of)‰Ñ|AW:£UzY©xYð]%¸V›ø ùÌ9³wõe,PFÜÑnjÈ0EFöÏÆ ´ !<ÌbPx©fè)!!q†_Q¬n^‡7ÎlKѲCïÛDе§HûM•Ó#å?Ž…p†‡-@»ÉJ¯/CÛÇé  §xœâg®+¾l~§}õd|ó¸ìУ"JtœÖ·ý9(2Oñ&W¡Ôb_ÕνZ=Ú>£ù‰�‹Š/˜ÿphýÔ±òX‹Ëãø1šÞ­s/•G¸2-è@�¨þbÕíà†fj §yz)Yñ¥ò'§<—}S¡²Cï�Ó¿ä­¢óóësÑ{Å%(/J²ª´Kõ!XĶ�Sàãh¨:%¿6Ål3çoK®¦ÿ†“‹ÛV›P�¯ë59Z(µ#k]Œ¨)—j€žðÁÐ#Ø›XÍ ÿŸÆB{ây¡·°Ò?«øß_ 쟉á4L¹Ìí&*½îðŠgß)(üó‹Õ-íÚ»zëôgKo#+à:�mµ ªv‘ ¦\0’ë› "&5åRI4®xj¢ÑñóxhÆ“|VèÙ—£&uËû�+ì-Fóˆ‰Ã ^u³­‚Õ[÷P ¼ V|I” >Ó> î g¥5÷’ÝCÒ¶?·)fÝ ³)dU±b‘§ n¶¤Pé5؈РuŒ€,Îð5Ô]¼xtÓag=ÉÇž™lιk³‰oœ~œF ßfŒ£A§Ãÿc:ê\?­ž^�×ç—Ɉ�æqRÐšÕæê׆Ö*j‚8ÍOzª®Š÷8×AæÓh¨gX:”.2ÙÿF`:“Ûgmv¡s@X<8 %®on ;d³¹øizœ1 #Ã÷º¢�Yt€c Œ;ŒÔcçkBK#à ø:Y«º^“ž‹#A£…'f£ëñÙÝä°;Þ;�Yß9ÅÿÓ¹Ðëtvaÿ¤Õ&˜çâUÒ%þšœò\â4¼îᤪåòJ(d5=ZÔÖQóA®ó™ñ­ó�ÕµpÜå�Þ9ý�«µ<‰«›ìÀJ¬Ëá¯ò¯ü2Fi%­I=v¾š×5SSŒn�UüÓ—…ë óvP]�gÿ8–ˆ]á¬Õ&Ì4X‹õŸÁi^kâ­ QµÈ®4t„W³š\­d5Ÿä¶?×=˜ÙI”t÷à#—­6aÙ×XW¿¡õ3Ã]‘]�kPÅê/Nñu³Æ~LGí/˜'ú™A±ÖáÏåg¥À�É æ‡ÚY­‡Bíh`ž�Wü—…޵ÔçñÀƒN|åabóøkƒ9ˆÍÞàÐüðjMj[µRÀHÛ¾š{5K'œ…± ǧ�9‚=™lîÝ�¿æ ./ä÷©Fóz‚S‡”B° ?¸~ZñÏZR Çc%x£<ÞÀE÷�TñW÷štƒ VjÀHµ±S~`$üN3ZÅúh¦ÚöC¡¤ÓËÇ4¨ËFϰÔh‚äBÂ@C/U8W^ f€S ™æë¦ 0ºu^Š'QyX:l¸9£M1‹„sqR=sʉ¢)^›M¬›‰Ñ>Wtƒ=U(ôgév»Xñ×øÊd“Í7Õ¯A.Æñ`ïÊØvýHu:ü±”œ –ÿ Í.¬q�¥¸)dq†/šDWzÍÖ P’Õ¾6kýÈÀîH9Œe÷®”‚ÆTR²,' �Rª\¼ ÐQ¡8œCu’Ø,fäÚí‚rqWœ±Þ¨“{qéܲX!îJ ½—¡�Ž8ÍWвDv®°é7ƒ~ECoج…É}Ù õ[(^G²ªVüK #¼zŠÃÞR•es�»í =ÇJÌY/Ðgq…½E)^CxšˆƒJ¯ß†ž€›(6êk"{KÌ›~•1ßn¬ž–{~ Ãü©øÊBr ¾Õì<ì#l³ ÕÓ‹¨ÕÜ)7ºuÞëŠ~ ~ ™fcSž’GÓ»—°¼NqzÂWé%\“У¡qÉÜA6f|�ï—0Š^®n ânM·ýÌì]u ˆ}®Ð&w*Æ®øÈÕÊQêãh {8PÊÐJ‹EÔ>”RËë塀ޭ¶ú, ¬¦^âÂð8v…³/“5<¿0é¹hµ \øòÏ—¶Îž–"LjYJâ @Í<þ-\é…\cÀ¿…Q³€3¼½NÓtn�1ZxÇ…~‡i&<ºY«•…µÂ@GðïB»ÂYç€çÑ=Ý 2(à*êS•[ž´W„ïYo –ßùm2¼æMÉw±ÔM«U¨ÝZŒy6>õÔ̾y6<è~â;ùýpÎ2˜T­Îç3 z3Û3ªøJPŽó×ívñw­?Y@̆í+'uåÑ#å[¬Bê≺ü8ú„BÈðÆìl!Õ!¾gµ 4k°ðÃ5{j*‘}3±¡59Göüç�Ž'cÕÌû|`ÉÂ?þ«¶Ä,œ­&jÞL;€¶…¥åîæµ`$¨�iôÇ—Ç[§´.ÓC<•nµ óUæ¨û,.ûÒo�O÷ùds9”Oþ¶c!„„¢"Ê­U¥�SBr:ª0ƒOrFÂ� ¡QÚ§'Ùu}Ú¼ç ãEˆ^½0î.®3]q´|Ÿ7øŒsý´ßû2z?ø:6ÏÅ'w. »„Ë"OÚ1%ÏoK™ŠÝ:ÇAÏš� rËUQ $‡Ãå=ùæ^ow÷šÏEù62h ÁPÃôAÍì_µX…ÒmPþDôä¦Ë!ÚWª½Ýn�»ísE�žYˆlq§\è2p|í \¬žü˜ -¼m9Ù=‘Ê ¿cõ(Õïzz¸ØM­þÃÔjž!�Žü=ô¸îî5…Bï‘$ˆ²ñÝÜfÛíb‰çê·C’žZ¦Vóœz „€üzxß‘B¡×AFtͰ*½T^™BöËx¸{Hò/J ºèÉ�y6ÜåðÏV»ê»c-Õé#'7O¾¨pf´ŒºÍäL3ð€ZâóZW’ Кž-Ä@( 7s(Áê)AO*õZP `4G.$*¾Z*ÂÉ�‹wN©gXZ><ù›NàÅuÆÃŸõ»B­VÁ¾zRýùÌIÏE»],½guO<7ZxÓL8þïwÀ»ú8ø1-½Gnñè§y”æõT­n|0î ûbæàö§Ì Á¿…1Bh¦ùFÔú]{W¦™X»]lµ ß'CÖ¥¨s5f[ŠöM‡:D:Ä7©{(ði<ô}*BÌÅݧ³ûWІá¦�uí]:ݧ¶åËrÒ¾z2ºu¾ptóx l‰ÙV«ˆ?ÏÆeÆ“xã”Z­Âû‰ž�3á®A—Ã?òüzÎÀ¸Ó5<<û+ôÌJek‘^ 6±P v›1äåwk[J¾ ¾Å*|›ެÇ=àŒ ]б«àñ5_øÏ—OWcŸFšÿ4tËi|éæ3¶•ä;§ÔÌðß&‚ƒ«±©íc×Nbbó˜Yˆô ~>ß¾xP´ŠYJØ—Ÿ­lŸÉæºâÌÞÕÂáõØöùÄÎEÙ†òŸÆÃ:3@H5ôÒ/jÍügc)¸>ÈM!k]I¶Ú„Ï£·7•‚\.?³“h·‹Oú>[–’_ƃ/$ôÇ®Š>ïs»É²É׉ ,V¹äüq�6sêI€ÀôìÏ]�X¿ü%u(‚D²ÝÃub[:7…ì‡Ñ e1ª¨(.ì{Ï[mÂìþ_óøÖyç€x~%Oøoq§­VÁù‚ÑŒ®Aÿ*+ƒ†öÈÆY³EÀkP�5tVON›œÆšhù÷n´ –O4XŽeGÊ} ­Åžì– �‚ e>7x8J”™ØyÄløãH™i–«›¬‘áe©T.zo ŒÐláÚ�µ'SVˆ;¶˜áÔ¢Oö§À öyeÔLkšß'#ÌBäu⮈é¼Í&ü™¾0ÍÆÆ7�å}®Ëë Nƒ³²¶ÑþL.1:�”CIw¸­&5Ê”®ëá4 ½–¢j‹öÕ“/ã�ŒÂçÌ?±tpÒ3ø½ ÅÍgZ,üåµü7Íï“Á‰­r2-G2J‰¶ÙE-Åa–š›U:ô0šCI°Uïã±÷\8¼nµ=-† ˆÙ0µðëlo[>yIàŸ¦ ÿÜZÉ68{?�ñÝþ0*à(±tŒ»Ÿ%uÄÄ¡½òßXqƇÓOLý× =RÚ.¿`Fï…¸¼É¶Ú~]úº‡$1öÒqÝ¿áó¨Ô3ì/½ZIÞ´XyÏ?¦Ù˜ŽH­Õô—Þ4C¢½<Ò¯@š…à:õãäõ8îTïTH¡¥^"6¹ÓžB>y£0þ·>±—c œ¾ô�^”p •â×ívAv/Eûj £@ÍYï'Óï‹ z3gø¡Dq|«aáÖÒ¹íϵڄh ÃkJãýˆ4é¹pí]~› *÷,±ÔM× ß²”èÑÜNßÂÞ›V›P¢Àû³8±sadxƒ™yE+ Ð_òWè)SRo”Ê‚Ã�"f•2RöÅó÷ÃA§ûT9)ìâBQÅhfÿª{8ð~XšÛMŽ¯Ï®2éLîäü– _Ž®ÇÛlÂ�é¨,…¼?¹xtc k/ôʇÒÞŸõt!Y¬ï¨õÛ®¼Ï‚SÀV³’Ïâ›A¿r«g!—Ëw9DÓÜñÔ¶Ìe…ÿÀ@ó÷ 4×Þ1Ü=hµ 8:Ä�£AÛr²3…²éæ3ú§á!_Þu«(PÚ‹�Fù‹{ŸÎ Zt§%åLÕ¾ú�Pw¤Üôî%½˜ø6 Å:ÄÎñÝ�ôu"L-&¦=—ON.^+íkù,Ìx=ÃA×S‚Ï/D‹U¨lk®GÊ!$Èç󳞄Œ‹ö€Q~„äè -lZ’…-©òM-ÂdÏ,¬°·æ¹¸Ñ*ÀÆBOâ@:'o’ç·ÉóÛHòæPº˜ñ$¿M›-¼i6¶Âþõ œZ8žQx�? ‰3˜üÿ›Š\@)Pq! ØœO°–ň\+ö•�þ,íÁíÏÄêÌ>!OsŽ�áeiS—�›b–˜�ÃVü�Ä“e¸ÓËÌÌN¢Å*˜f㎊¿’ž«– 4Zm9Qî÷Ÿ_ÁµŠŽF‹ § º—,˵"(Älu†ÑGx1Æ'Kkœ�á=í—ǹÃëöѹ»*ybö¦³Ãîx»]œùw¯ò¦Âiüò@Í…ß84˜æ#—G*ßßáðl5–iùt$«ý,&^Ú�^ƒU†Ö8ŒâÝ@‘ìVÙ߆­þeб¡ËV›ð»ß–kïê븂iüò°î;Å ×ÀŸ˜ñ$¨ÅÊK̽”t÷–#*‰ºMöT“JË`*�R|U ÉNï^¶Ù„ðó'µG,•n·‹÷s÷J§ñ˃…®ë>y¬þDϰôȤҫ±{8 /(9ËÃHø‹”ë¡?ãîCÔHøu…¹u­eïÿÙ65Že áùï¿$<ðçŽeÍÔÔú 4-IHM­&“e_ºÅ*ƒB>Ÿ'oZmBqF•ZH,ì—?:ªR·F‹ðq4 Ä/_wT‡ ñû‘¼+)£mRpÈõ4@Ih¤7m?×Ô{æ8Å¡$‹>D‚¨_³?ÿ>-œ ‚5÷y[¿î–R170í©¥‹6(àÿ"KCxšˆ#äçqærw“ß§$}SSM6�žºkþìî^kýº‹~?„ѧÉ7½#$W%€Ûþ\§Ã¿dÛöÄóŽqKÌšfãë>ùí,_ˆ›[x}3èy(¿ÄlØQÖÀÇÂz3«\è! @m¢>¬kê…yÈâ3"[p-aõ°FãNû³AEK°ÿ>¨}Tx¨»{­åë^)OãŽú‚ ‘Ž`uPäþ]¡¦w~‘'ìC£øÂŽÿ¼ îÿHø 5Ã’ýËå§d!½�°,>[:òq8VbÔüqŸ+ºÃW¬eúoÈåòÉ�m�÷ KòNʃðeÇ€X%ߨŸ'"¡`èé)ð¯¦/ò.îîHüö�‰+ü¤$÷ËЄätoè=,ñ’3@mjö§h§¥¸»Þ3ÈßD]`�~r÷÷ÜMCŸ´JBo½àr^Þtç#¸¸†qß§"Uz)ÿe"<¾![[ËÅu¦Ó!*Ñ�Y¥¡÷oK Bœ{˜wÿò>‹J hKÎÁ6‚Îì+nvw»ü_ð“ܯ¾kÀíøá¿TÉ�“YJ »©/OlwªöÀY¬}¼ôËbµ™Íæ¾O-KUä;vwàTÌdöîø÷S3ó÷Pgætf^W|ˆdÒW·Ÿ[a¡7¬°m�&3£¦„ �&�|ŽtÑb{gqëÌçó?¦‚ð7�,j;øÔðÄ«ý*ÝEÉé-÷Ñ R%i–Ž�’ qÊ@â,ÝLóÕ™f¹wŠ\öA«MoÉnG"“ÍY£ße’w�‹ïGB:Þ‰” ½¢÷+ÁjÍ@Û{¤3A‡ÖâC…¸ãtf_AãHÐÃFh߯€5³ˆÉw÷(Áé( 5³MýOìþé„%èCD(L]¸'Nû‹Mª…¸óé{…âN Ó)]wtz m-Íë(öòHKøª¡¸°è½)ÅP¸ltØEÇrÕøÈÕÇÑ_%ïùÃë6›¸¸RÞo;¿Ê|~ŸŠTÃæw‹ :%‹ ÁÂ3ù´ý>mïÑïú¾|º»k׿܂“OoòéÍ>ƒ…+XS¿O×Ïé{ÿj*ó3Ÿƒ°›š`Û�^Œf�?Úþ�…qו«›>Dþy‹÷ii^KqMÛDzÿ!�ª¡¤îXK)¤“P„e!òiL‘þK°î;5Íüˤu dÞ èùÈsëì¾àEÇ€h]®¢sæ=‹%u�bŽ!/G±Oìî¤Ú+4ýšÏœ< ÿàî4«±Ä¾°�¬ÉL³q·WÁ»ØÚQÊ@¥õ6Ÿ ÇJÌáþoþÛŸ£F«0µ“(%é$D¯z§C�ÿônµäUþÇ_obµUzŰê� ÞÕ >ƒÖ¾AükÊ #†§–æ›(ðry@#ÌT¸çáëDø…לÇÁG®Úì¼TeíÓ]ño_z«Ü­y6Þláû¦Cˇ'þØÕý>x›É%ÎÒG�‹±Íã.‡øÖ) ­Ÿ–n:ùú4Z„^GV»àlA¯»¸©Dþ�ù×”S!WB ¯l/Æf«Pq£“�£AY:Xþ†PâºÍ.¾Ä†@vŸ¦ÛlOŒlûsãÛæ¹øû8ߊ’i :þ/aÛròAMÝj#JÔvÀ,…^¾VE>Ÿœöww¯Áꀙm5‹=*0?ã±wðæÈ–’-FFÚ8Uî�÷H°{™œ?þ2~7-Y¿N†é…ÄÜáõ}=ñÓX��(z�ãë·ÐUÁ1�çö67€.ÇÎÏQÙ¹ƒ˜,ËUQtw¯5÷í¡¶ä®G…½KÑ¢¯˜§Õ™eÛ¾QZ)��Ýâ:ÄOc�¹Ý¤/xNÞ„×ÞÀ…k'Ñ=$½uBu Ý@þÛdøPRðÀÉ….?�‡Þ J¢’{ké( DÔÄžõBºÔÁîwÕŒ@¬PG:Â{W}ƒÝ)>�ù®§“U B!Y¤M!ûy"üy,àÿ»Š/xÑ=äïsE‰ùøÒA™IõR°æM™gãƒî”¹:d‘öÄóU0I÷ \<ºi®5E2w$‹Ð°Cì§,§eþq¬ËûDˆ™“] pS̾”FÜñ'§SÓ™³y;(Ñ Îk,ÇœîÓ¢à Ç‘^Ž\.ÿ~XªžF/E9¾}Qs¡W¸ßý«+æÿ.}š©©) 󫀸v9%p=RþÓxèYª#ÌB¤ÅÊ+7DÞ1p—Kt§¾+)}Y 6ØÓ÷�±åÕ°.Å!Ì/Cg]¡ULöЃZ”œÂïN÷é÷Éà³âè6“{3èŸÛS¤×KŒ^½”‡ž ¿_gî§�¦™X±çJÞE«4`Üݵ€²Áa°Neò> õe³;)ûPç ^´Ù%6>z>âXýU¹ž/Ø�œTÈîÄ<¦ë?±yÏ¢ÝI-j"ãîÞiS@[‡âÀ¼\Ù¶ñ­ó>W™¦oÅ-Nfµ„HaV}[üWÅy`-õy¬&_‹ûÿ5ùª{¶ÚDØØL•°«¯á¯gäRÁísE7Ê~™ÙIt2¶{årÐÜé~ jù}*B¿²µ¥ÿ¼Í&®ýamYÇÜ‘r(Á$”XºJCéÐC úrÕº‡¤²Sˆlè²s@Z“­�z|óøóxèÁAà‚¡sȹúJ†Î\Áй¡üC¡â÷Ñ��áÒ÷§pPõí~ùë™eÐûz8oËöÈdhØbJ±”z‘äÍ[§ôvPZ=’¡•z‡?ëtøEܳF‚ÌBDé“çžµ +Þ(ûúÞ<3ÐÐßAöE«4Â�˜y}ý…¦ìu&_S¿gäIr¶X…²í‰£'0ôVÙÛ6›øÂ »Û{ÚjžœÈØ‘rߦ"ß&‚§—Šˆaæry—'Ñn—&¥ù;‰ùc(VkéÍ¢µ%Bø7ù*ŠÉû,Mý>” Ö� ³ïœRÙvlèòËxŽ­q·ÝCÒÀr¬Œý(›Í ­Å‹!\âßl[I¶ÙÙ;Ù’ç·ß'ƒŸÆBŸD®ß ’Çù­�•ÔTù·ä‹þzEŸ¯fF�żþÇTd”Y5›ßM’?¯œÛþÜ÷©È;çó„òøÈeϰôu2üÜZÉܬý™f‰³tyüïHgr³ž¤Ñ*ØWOªArª"ôHÐlÅHøqâ¯CßU‹âOOÜ+,±“ü®²…ÒÀHy:9G7Ïʶ�ü4ø�WÂäÎE× ÿËx`‡?{Ä<}›ógß&‚]ÿx¹–Ä)g_9i± Ö¥hÙ÷U:»°Z¿OE*>û_YÎÞàð¢Ç—¨í\U(höB=Oh«gæ°?Â(²wcÐ6t –ÙNæ‘r˾ôüÁõ {»)d[¬BüôÙ{‡XPAÿ³æå‘`à׉°�濌‡Ýñ•£Ô&wºÅ�®¥FÜñoAøÐDxlûüå[Ì–˜µ­œ´Ù (ôêQªÄMð*�=”.èùˆ‘áû\Ñ%oÕÙǼ>k)œæṈ̃QÐÑý™á$6 ÈFFÂ�>_p dL³1£…ëô t ˆívñÓx¸ÿ™Uõl6÷q40ºõ؆µíϹö®k)b.nš‰õÏĈ¹øÀjjzïi_ËçÒ#Aë‡~W¬Í&v ˆôBdÆ“ððg¾à…» _ƒðå¾x¾x�$çÂoEŒívñóxضr2í¹”åÖ\ëü<†3§5˜c¹ÇÏÞiƒ =<�“ ™ágžãŽ1½ }¦w¿køÄOÓö¥¨Ñò<ÓÆ¡µø× ™§'äâ ›Ý:g–’½®è—‰ðÇ‘`Ïpà�3Ðéqt;ýÌBtrëx~/éÚ�R¢}S!£ʹ[–«�T@ÿ›þ‚oªeo/ݽV­’�p PŠ#J½îÍ\·X)þð,Þ&wÚÌð“[O+*gs¹7LHÊÕDª4G6Î:þ¯Ámpö7ï¿\º�Œ®C_Î>Wt­ñ6Á…£›âióŸLoqwÝ# Ò¦ÞQ|!:‰j÷Ь�Ó#åß:¥}ñü‘˜šØ][ßà3ŸÆB=ÃÒ{K¥Ï¯2áäÍÂ~²Ý.˜gã5}Ô„]+›gäœRRÕáäM—CNíÓ*¡e)‰ÑbñoáJ/äÚƒŽä PfKëçœö\öº¢]ƒþV›ðnH2ÏÅëÃJ o&æVÒ~½µ“-F«¨5ñúš­¤W8tyæ¾U™%÷+óÝ�Ý"^®ÒÙf†¯�w•YL`M`”Ú´)ôfn|?²Y'G£Ò¹ptÓ5èW(ô¶ÁÙ·É*•�zá–GózJ@iµ–'3°B ºÑÚˆß[§Ä¿xBöA|�–-Õ[U$8PšÓ+9ÎÖ˜@Ök¾Ö‡^ËàÐÆiït™6��@ˆ^uøë yµ2(Í£´£Õ£¦"@àÌ gh´æ�”ërø�r&[r¹üÇQi´.ð_'"Í¡Œ¾J/Òú„Ž0†^ÿL¬â÷+ÓµwÕnN/e«2Lí$>�=­~Sýœ=¸Æiؾ‚õ«í+ Â@BexŒ�拺ÈÛWO>ŒHé[ÊëþóŽq½.<¿:J²ý“µ}EQ ¿Þr 7ƒžá'´#ê’}®¨y6üÂèa¨“_ß]Cë§8Í:Q•^›õ�š©)œæë¦£tîH¹¾™Ø‡)uQæÉsù0U7žÎë S((ðÖ¥h>Ÿ¯ô¬h¦¦´v�–âp†oL›Ô�Õ“6»pàZ€ôw$ÏÒß&Eóó\ܺœœôÔŒöïƒü<Æ^ozJ­å½´[†ðe¢A§hg÷¯Þ:¥o“A6tùdoµ»ú0*á4èŸÍxnojÍ›šÞIü˜ 53¼i&V‹6(“ž Ík>mŸÚ®ùª0PÅ| ?Q_Ö¥Ó#Auåî¡@»]vÇ÷ÅóX*]ªÍdsgW!zµtpònÈßÌð‹û'šá^Þd§vjÏJEY �®h>«¡÷ª€qGðzÛLóî†W(“-)z�Î~‘j¢Shxã £¡�‚�T{Æ*íàz!Û ì+5°f^““ž‹7ƒþ«çˆº¤.naÑÁ[ÕE‡Uö£y-Å¡µlbRÐLMéì»zJÀ)¾>¤ÿd¡GÊ¿sJ¾çOù¹½©ÏãÕÛâ²#å tÐ;ÒRêP^…¡§„„Š‹F‹Ð˜µ†?YŠãçƒÈfsívaÙ—®øKx�½ÓQCA©fn7Yéu§BOðíTc`‹Kô῜Pþ÷ऌÐËçóÃ*½‹W<Í/3V èÕƒ Ú@ã4OÍ×�®]Ùì ”­š{à?¯ÂáÙ…£›B>SК9Íu<¡Š@ù2¬#¼8Æêböó%l³ gWOþ†Àñõûá@Å_Âï\£EÐS,B¡f5«:«'|Z“§A}ô(–Í—VÇR7o¥Š¿„{nûs] JüÑ@¯Š®T+´&_Árà ¿ÂVi®àØåð'ÎÒå…_~ªš$§GÊ a ßjöªÒšU=P ²Å&6Ú0û=¡~`¹#ínoÊT5“Èý31œâ»»×Ú¾ïUze©xÐÓ�á1šïtH› }«)ÇJ™Æë½S¡*i‹e“x!¥iø¾ßݽVée¥¢$`4Ŏ ß5Ø.úÖ¸Ûk9ÞëǧÐw¾&‰ì+)Œæ1èÕ”f­¡h>n°ð=ÃÁjXK¯Ló\|lãÙ¹Ô\ľr²ìKÏì_Í^oVè[˹qŠS ‰æ�‚�B¥—’Šç…/�Š}àÃh¨Öm�ŸËu>ÓnŸ¥¿zxÒfÛíb× ÿÛDðÓX ™á¿L„ç^U~¨P:×S‚¾}•^G*ÊAä{zýÝÝkº‡ƒÛbcEßüÁu‹Uá’´s×¼)£…'ç±ÔÍýo3¹Mî´Í. ¼ÖDƒcž3Q‚CH ŠÙÖ4º»×º{ý‘Çh¾«ñ².³ûWP‰e7y›ùëèÐU:;ìŽ-ü¬'ùà?H]ܾô+¯Øi]>1Ð3yQ‚E u¿«yD~lʘà4èpHõ¡€W:׸Ûï“‘Žq~7ùûŽ–ÏçC‰ëé�D«MèÐó‘GöÄXê¦Å*(úÅE.@³-Í£$‡™Ô¼J� ŸÏÏï%‰Ù0N�«Xµ�ùÊqþ𚜋w8ü(:ðB‡QàÍ D/$–¼éV›ðd ~`9¦�åúŽ”û>Ái^ÇHzZЪ~%uœšÇ Æ ®½í4Û‘r«ì­ÜÞ»Æ,Ýô K�Ç]>Ÿ÷.¾(Ðå²)d»‡8 4A­Å¯c¤J/Š£xèQk†Î)£ i”ù''=æ™ð“¡=¹y딹·s…½m³‹Š×hòÿ|‰k‚•^ *„ÞÌêͬÖä3ЀœO¨ó}Ó{—?¦ž¶1 _÷È:Ñ0½{‰3]{—�â#r�ˇ)Yg U~¨ó@xt„í+½ TT (�‚U4<|Üà¶â�PZ–äù.*+‡©6›°Ê½è�ñHyËò F„ÅjÉ# á©ô‡¯¢Â@¶“ŒDÞ@œæÇ5ó9èN­Â°;Î…/�OÓáäÍ{úq4Ð3|aÜ­²·o†Â$JÂè«ôg®¢Z@ù÷d²�êM,Fƒ�£!wCæ^ÖAƶ’ü4êrøß I½®è ïw)g_9Ai§  žm1ªN"¨øzküqÛ­I8i;°–jØÛŸ,\ôÞtÀ4²ÎÄöM‡Šc\•þ�UT) Á·½æþC„òðf0PÌM1kž�c¥œæ‚Ó™ÔL¦Š§�P^ݧ°F“/ʼôNGU]ëé‘òƒîSÍh^Gx’EU9#Ï�F“oz“lúÒXNŒâí+'�6oû\ºö®:ì~œæµÌ£$«#Ôå@cZèHx^2Ð|³Z@zÔüƒ³×ÝÃAœæõfƒõ UÓ)*^ � Nn¢ÐRœ�š-Â຀w\ôÞ| ÃÑr @ã'›GoV¯u*ä„–‚*=…¼Ï@Cc£�µTÊ�Ýsz÷²¸Ó!О&«§ipC35UéJE}!}ÅaÐS|3¿êûgã Õã‘rcÛç�X5@HheÞdò5‡jwŠŠW€žâ G,(œSè4ø4žÞ½¬ï:à*›&8³—zúÜý˜5õÂè«ô¢¢±]5)øÍ�,J²-<³”¬³MpÛŸÝ:ï â :ÔÇ�­‹Ñ¢ŒR¥?� „`‹¡ÐLœaQÀ*3<”‚fZ@IÐfûfb£›g/Æy ·Äìôî%³˜x7,vZb ¯'9Íg 7„: ¨º|*j…û ‡‘ÀØÔݽ†œçŒE=Ì~WÌé>�?¼VÈpÛŸ[ö¦Ç¶ÏéÅÄDZ�Ñ"¢$0@+4ø� ïPîqZø§—S3–*êp2âënsïZp(F)NGxµ$I3XœŠUûv›øa4dš�Y—“N÷éøö¹kïjñèf•½]™M!{ï´íÏÁÿ²«ìí²/={p=é¹Þ<X=!çŸ'"�©à8œ�m(Éé£X�&¯ÿÂ(1}?Ð÷ª*0ð!$W° çõ´“CL\¡f0xFå›-¼�á Œ€Ó°—ÎS� `] å¼ÐŸ³98 ÿY3#ÀíŒâõ$«'Y�J äóy“+„ÓÅnVû!¬}“Põ÷Tñÿôæ©h endstream endobj 116 0 obj <> stream xœí�{tTÅÀ'Ù„‡<$(‚E*@„*Qž–…‚Ñzªí‘—…P¨MápªBë*m ÔJyUR¤é)º¶$-ƒ&1Ò(9 �„Bv7÷ξ³Ós³Iópï½»;÷Î7så÷ `¿ß™;÷›7BæÐ{̼U¯½s¼øò5{ ¸ñõ«¥ÿ>’µþ‰&šô F¿‡vè‚ÇëtùH8Psü× †Û ¿( �î[ó¡ËãðF2Ôž «ÁWôÚ£}¡¿1 £×}âsFá¨Mírz/ï˜qô7gI×yûë]1Ij}}gV„þþlè<çˆÛ�¤°§ð§ý¡£0�q{Ü®�¦fWgw†ÅDz­(“‚Ô–ÂHrÖèxLâηܲA–šà³3 ƒ2ž±Ù¿‘ššh¸’Ñ:0c™\ Ñ·L‘�êWZ¨±špB6G“‚\ŸaUÃÍÔ¤ ]]d�¶ªÏvlÔ‹NùÓ±ÐqRb{Öå6]!$ä>Ð:VRK$š|ÒÓÂ>Éëq#+OÊówn8tÄñ1áf¨IŒÁÏ 8Èg{›û®‹>ýMè¸cep³Ö©-~ù1èÈcc�a�ßX‘w ”~&m1´÷î’Û ã�–¾y �] ×ÃТ#µ6â„ Cp´ƒh˜fÒ8AL¦þÀÿìÖ�'O‘Á¹= Eèð*`3ÞOI ´ -v‚6ãmñW €¶¡Žm?'õI!Ps´5’ßã¦>)4Ö ƒ6[íx+�u\Ö©„½=wako‡¶òUÞâÎ!Á*þæÞ!»wêøËzA‹éÀ .=â;Ó ZM;fpÖŽ·‚³yJÃi}R�7BÛiåuðý`uðBh?-$åC�«h#ó²>è÷?x ¡Ë7C+jâ1Î=âµóРßɽ'Bä5ЖJ*‚šo‰< ÚzI€ EH¨zeÞ$n3Íö¸wÂzº©Ú@´àAEm¤BBª ¾Ñâx"î7à<%•òÜué¾LÔZ!Þx-„>ƒJ;S¸šKÐGzHÔŸãÚIˆ£'ˆ§QµäaÜ›ADý‡åJVcÀƒœÉž)3ð¼ÂTÔþtÀq#ugè)ÅnüÈËŠú¹p½—6”1u :X$vÛj§š„ îb&ê°xÝá¶ànŒŸõBé �š\(§…&Iè¿ZÞ˜®j¢iº*I£À� Ð0sdBе9‘w]·Ç»’FÚæ*ÓNXE;[K“iXhÙÏHsEY`kU?å] z¢2­²@ŠjéA¢f9 #4ˆ£tž¦Vמi¾Í"ëÌý™TžF^!$W»ˆEÖ™;gP‰Šbè)è�Á§»uZe‹ÇÇÚEÖ[£5§]f¾ªî“¡Ú%¦X£C}ÎäQ½‰æ®–?hx‚VTÎ,½ŸCi8ÞqàÿóÝ�î­ÐHÑo¾þ@÷zí ’j¤cQXî8«·bÏDL£ô¤¡“X¢_쥽¨B¨rW•ø‡ØhoÞŒåÝ“pº ?Ê)=N+ ÍüûÛú۷߇”Fm‰?cgãIüÃ1…‰½B‘Ùñ’è¡S©àÛ¬³-VŠÄ¬Rn�¹ãIr&4ðÖžúXÄ*Eþfìˆxmœ�Ýu m8%^ׄu·p¹Þá ¡?ŠÖ‘©cš”·ÒG°Y)ÆBBe�¡B¨ �QÒy‘R<ÊB©�Ka¶ëuàuqL]îE<¦Ñµ :þhÁœYCÃ8AªÞë ¡MBôdBå´Ë2¨I* B[ˆLyà­  ™’éŽq5ˆ¹Ü7SÞÀRÍvlá¼™ ]ê ­(ŒíßÛ¥»¡ µ�RËsWë�Ä�{8G�Ÿ‡¶Ó–éÜ6èx?´›ö,á´A÷äé­ÝeÍf.Mù¿ää…׆mš V1ž@�†„ÝÜ™j¬ m%¶£œµè�uÓ�Ñ�|„«n_ðÚ0h#jØörT§5w@ûP'a;7픿\íœ>>x‰“:å.¦»iÐ|žâ”|ŒönkóI“à{Èò¶Dh QpO ô¨ ~ÚAtÜòh“îwjÜ×¶W*wáèøcà{ÔŠ}y'å ZŒ”’¥ûi�®c�mƒÌþí‡ó8-ÐeÜEÆ-U¯æcZ*V’×c–ëa¥|�ÛÍ9fD³DÁëz:Z—8™¬¹w«^L&½¶bó3)4tœp—Ýä÷ŸTÍÑ'©ÇdóZuWÝ­ó²ãþÓ&©’ê–Š•‰ë2&ÛcüQfRÅ3 KXÍaÈlh²àǧ§‹™`êró²Ò£]”¥ß}:3¹÷O²‹þ({òZ¬iú*�f½‹©\aϹe·BGÁ†ÎßÝS犫ÇÜ(yO-ç{ÊhF>—ïuÅ´á/èô]Üöˆßrº$�ÏxßáqD1tJ¾O_žÕ;ŠÔ²¤LÍxç ìs:#ú 68p ÊþÂ÷‡Š0ÿÄ€ž£æ¬|y߇…•µ.ì!ÄïÆ×®œ?ux[fúÄBæJÿì,nÙ endstream endobj 117 0 obj <> stream xœÝ]Ûn9}ï¯àóKóÎ&`°,ËØ‡Y ³¯o&Àb“Ùx2À~þB[݉N«E]âHd•›Å{ž*VkçËê�2ʨ¿éÁ�¹8õô©ûÒ-%.F£¼+I÷9ªçݯ?©ÏÝ—ÎkëâêÙí§§O�UË¿ïÔúÃóÇîêÁ«�vWÿøãó/_Ÿÿzúª®¯¯~¾ûû\us3›ß­Ôô6)kbZjø½{×½ªw¦èeÝúýúu²%©á¿ïÔ÷_në5{ì®~ùïoŸ¯¯¯nŸ¾þõÛ?ü﫺^Ü/θù�º¹QËJ^-‚²N=þÞÙu�Y•²ÕÉ•¬\Q�ŸºkcL¸Q�ÿîî^7êñ_êÚ¿þ2ëhbKx„hL˜Êê&ªq÷Z�±’ûÇCêŸ�Õ9Xã÷4ÀFcìí™êh{íLì÷urôÆ„sÕÑ;mKoÒ¾~LÆØ|@¿YòUiVÞ?¨õ‡šÙoƒ²^{·Þ$ÆË@Ûå—Y•^§åŸðÒ vG/˜ÛÍr(%õÁn—ƒ+@°)fÇ «?1{‡žÈ»¾¢�÷H0#•�`A× {éà»+‡ó …z¶�9Ô�(Óá’Û=´1e�àåÒa@Qv£v ‹Âí¸—8*ê=Q�µü$í¨(лÞTÔ=ÛŽQ—È:‘óšph^Á ‡Û�tÀÙ^1´¨¯ø¢ìé¶¼Ï| FÊGEÁ1G�ˆ»Ý°c>Zj£Z9‚5¤a›ÀX›§ K…qMDZ #´=È"zhÙA­j  mŽqË‘�†]â!¬€€ =aixÇãYR�ÿ`á:¼‡:ƒy"X1š "û†÷!dŽ¡ÃæY+^Ö±¥í°u›-M›h•Ž)d¥½)ýŠÁøö»ç�ÌÖÑÖlÑ&Y†[Ÿß±õÙ—�̻ܧ˜^³9˜á–d$0@àïЬCOÌXåu ®Õ ÝWÔLünÐüp&~O´0·1öºÄö›[¸Ñ7´ûMX ¸‘"¿½ó† žû+Ðl M°­·ì¶¸Cßq�ž�“SÏÓ#ƒŒ"h^D„á!ëÛ-Ø@Øž½âçä!©NÁEá¢ÀåGÓGt~Ä'gèÌPÇ.!R^Ehr„ ‘rž3�áÏ‘X] ð�ïÂ\”G:4" !‡3b}Dd‚ä<àyF×Ê#å3$€ü#:AŒFpÄ}ˆ(@HûŽÚ�ŠÂ]"â¢FÄ,yølàu Üx MjÌ�-X„r2.*úI„m(414pÅþµ†>¼7b§+œI }F�áŠ÷�båô@!¬ì!\…]‚�ô}!Š|_5F §}xØ)7s‘ÇAâ‹xîòK"ôç•èhÎÏDræiå4�Ñ�I¨€G¢�aÔrÈ7í�K¤1úÒÓTœŽy´V ¬hÇoðÞM܉4 ÂÊaï"Ë^áÌ¡ÑCE€ Û&®À6emÓk⦅Œ··×òÃ@5ˆ…•ó¡û cºÐ6…«K/=Œ¶ùh6º� ÏÕaM¶tØW¢'ŽP&Bw"ÚûÚÆ¤_]>ä�>àêò}ú�qê²nou~Øå Œ¶EôåH�PQ‡Ívv†,%tèá�Bí€}… ¹2q,|ó“ûÒ—ÁM†ókÏ–Y]ˆ‚x|Nã&h\+àk;´Í‡5TÞ2þ¬w!�túy‹Ž0Ü@o�ŒÆÍn¹5�qCEÉ®¿‰€HCß Œ`é€ã!2à#(ò®åUÁ†ìôqÂx'4Û±K–ç{º?ž»4„énhuyW&41´C%>²6X�Iá¼NC>¬‰¾åVWy‡wÀ~zÌy&[]¸ B«Ë;šG€0 lȺÀ¾¢½W2ŸÚAž×Ÿ;<÷p$‡žl xŸ3L¯ÂÓ9 ÚßÃßñÏVˆ®L9»Î}DÊ7C{j¯h@—4Ü�lOC�P‘#‰?óAêÍÜ¥.Ñi&Žë·³}Ö6.gXíèÃ^«ðBÁчCÆÅg/h7õ*Y8}ñ€ç«øÄð-:|Ê� †«aâ)¸VÈ}#Jµ"Ò±á�IÑ»¯Ž•i¥Ý­È\Ê^¿[ÙõK:Ùñhß=ðâÌJƒ3â^n–×lû:6ƒ?~òaZüë ¾ú¦¡�ºÝkpÜ)àÔãÛÏ$‹V¼‡6úDað6Ÿg»�+ú&ÿ"SJxxð­„Tܲ„W#á‹>»F 3à¢)z`ÆwØ@Ñ5‚ÃÒʵl9Ÿ�ÿbËÙ§ªWèT8}f‘jœuΨé "ŠÏìÆß*x+iåx„BÃ#Æ_ý‚o4ÁvÞ×¥ì–à�K�%»H~ƒÏׄߨŒ¨+~ÂÉrÄË5ÁD7eÓG”ŠAdÆäÁtíÞ߃CøḐ,M–(&nGQ—ˆPâdfL>'ÞÌiKr¡§ü†×æè‚Ƶa¬Å àju0Öq!±(b ÚiÙYWt°“EpÓW~,OREt&¾Åø®{×}éŒò¦åb4Ê™¤ûÕó‡îןÔçîKçµuqµyn?=}Úñòß«¯>þÉìÑíÑÞôÚ8—­²ÆY]¼Ÿ~ëà•�½íÃÎùó�`5Gø„C� LÅoªÛ#A¢Ÿ@]•Tîv(€}•‘ÀÐÕE#ˆ�[k;+2ZkÎ&íB)½rýj9%§ãòWןë.9– #­ÅöÇmÅèäâäj¼ú§3jþÇF{°NGW’Jɨh£N.”°ù4T¾•­”¿üÂëóÖæ(ÐmMÞ*·fSJŠë=&Ú^oÿ*ïue«|)7&©×ÄêË@}rV÷!†aë#l{·|ð´T¹µ[å¹,›¼jCr^Ç`“W¥·«� *˜¤GuX‰6UØ·E8ãŠÎŦ½5ðÛôÖèâsT.8£ƒMY•—)èóhæ½|¿žw+áëÓÞĬËòé}ºã‹îåüÿ?”Z­ endstream endobj 119 0 obj <> stream xœí�‰WÉïߟÎyz÷d$û¦Bõ(âq‰âŽ"º«šÍÜ7„~¯`~3™ìMÓPŸsÏœ™9“9 ÞKUÝå{ÿÏÿi8X Ðn…áV€œ©nÕêB6^¶ñ�»GµKÈ.á¿r"bxȈ�  (tå2ø×"ÿgØÄ �æPh 3bÌbÑ©7ÿKü ;@Î òèFÂ-°€hز‚FÀn�­A6·Rõ|‡ ìèK¼͸¦÷½ ‡�•ã±ÈÙÔ§‹¹Øõ¢\ «¥ÕŠm¤ô�”I–«ÿ¸¤äë�Û—ãѳ¡ðIßâ‘Ê¿Ï=ÐDó 'âÿ?冯0@@oÒ,¯P<¢xÕ&iF6Â7Ðu}z£à åð‘ÁÇ- JóqšW„ÃGDÎ@Ê=½7¸r<³}¹šø;.î×Öµò|üz,r*Í^Œf[¼*-(Íb|öÙ$�ño†ãÔf�4ú3#4:Í ÉÄò¨g"­ë:%`_­ž/þ¤kzodít"X~ÅÖ¥‰ÍsÏ\Á9”fEÈá›!¤yÔ ’þ­"¯6‘8"üY,¯`S7´¹ [qE/Û%Äò°Å§º¦ö&¢çks¾üŽE5}vçÊ»Pè ¤6{#À&�¤yD Ð&@«ˆŒþ\ uN€” Z^á:'©¬»Óþå£EÙ°Sæ¶¶ª–Æ"§ïÆwY:$üh²Š8ˆìÅá•Û1£?fB]añÀ&Q±‰øÉÏÅ�°k0X>^A7†‡Ã�m]+�GÏÞ|ÀO6»¤ÒŒ�®ë®‰,ÉÔ~€ �ë5ˆ;$8®éý¥ú:n~lQM_?{ìרJ ·$i [Á¶D�þájƹJàØ¬ÞÓ–Ž#ɲáþl”Mnž?Æ� ,¯X@”‘bÍ>’[ | ãÂå–GŒ '£š½j`å8ªïÀµ`¡�«W£Y®RuŹ�LñŠÑ?1BMÐ ’v^åpààŽ²f¯:>Žj�{â|Ïf¶/�øüJUºƒhY]¤TÔ¸ ;ùBŸÅUx·Öô-­“Àù¡Mn^tú“v Ç�{ù µ‡œD ‡UP:ø:îd`ïÔ^X­¹V�Ú´¨¦®W»¾­=Jw0ý‘ä·Ë+híVl.Å*àKˆs(=»6Ü'Mgk‰øxÀŠ8K©ëº/”c9†êÆm=¸å†åVD+džû¡©-»êôkxF (=™�›äªO,Á u Ly>áì´ˆ^�fë¬sÀ(‹jºoá�#â2«ov�éMýÓ&Ü'M¢bí�Z‚Aœ�ÑØú©á^Wg¶(ÿ ¤8 1½ <Ä!@£æ„û�ª4­5‰¿tªàOZTÓ½s‡\¥ÁÉá…¤Àjvð…-¦ú>áR…€óÒ†ûXÝÛÇíË_‚Q{ f÷Æ‘D�)±÷lSÞ¾°I°Ù«Îî\îZ bk‰Ò«±,¾È‰1š—)·l´/n‡UP·÷lsz:œ^%5�?ný‹G¸íÖ-³¥ £=‚ð«ÐXjⲎ…ÙägºŽïl蜈^ŒdȤ›Y,>æDô �ôŒö£FD×õOÉ¿ß;O‡È¹óm[K”B;W“›ç#k§KG¾ùC!”f„Ù~¦ò×Ù¼oþпt4²z2±qŠ]ý™Û/Ž Ç]Ù@a´753• GZ@O©H‚ĶexŒžûæ»'v�ƒ©f²‹È9¨½ÏH³¹Á¥ý`ä`v³útÚ:œß>Äó©Œ /ï{B»ÝÁÌÓ!­YB u jï&ržù‡õ³Òî[8bE„··ðxE‘ÑÕ@0@qOfììÐjP�ýOÚ\ìÚ¿tô~b·£/ÑêU»ƒ™këè$“¿<¿¼ÑïÄÅU)[¸ÚLœ#y×T¶½Omõªï‚¹þÅÙíûl”B¬:äæî-§sÉh·jh¾² (­¾DcæÙ°6õúYïÔ^G_¢ÓŸð/ìEàÉÁñõÝ‚åW8:+n¨'CËû’­^µgrwtíô^¾¸z§ö9 9�Kmï6�ö¬ú‡°DÍcQ©…«�F+Šî=“»z?ž^Ø>ÜÈ�ù…ÓâJüØ5•uHè]079ý�‡gTÓ_Œdp±ÄHgéƒbíQ()qšÞº4ÜŸÿ˜-Ê×âl¾Õ«¾ù�^Ž�^ÜñVv¿\\•֔㞉L³W3û¡»Ž„D’åέ²†R¤ô0àÙ7oÔÚƒ%>>¬ŸîÒÆ&6Ï_ȶzÕ±ÕCΚ_áð¬8Í·÷%ž§Ç"gwhq_�7Í•d™°»¬aK0ȉHœ+îÕmQMY;í hÎAmM9¾)•�‘ŸS.ãR«ÑT§?X¾µRkhçŠ-Ä^&‰¸û…2íûÄ ðÅH¦îçwÆÖNŸ´×ci9sntLÜ…äÞEïd¦³?q[¹ãáðI5ç åˆàÕ}A�8 ·ø´–ºFlúÓE×`êåhʤ�ó9ÚþEw0ÓéOŽGoqÓî™Ü³‹*îŸß(íwõ~òô­W–U¡P¬nõ –”â»`®³?±™85Úñï%sÞ5˜|9–™ÿ5)×u­ü8 1<ìžÈXÒÏó»4Už<¬ýKõ©“Õôþ¥£¯:-oLðƹ-¥ry1†ÿ€Ò\þWúä"+"¬VQY\n´šÈ”w“à³á´á~þÚ¹z:˜zLçOj4«v_œ\Ü3¹ÇÉ�[?Ÿ Ÿ°"ªîŽ1ÚÍŠ¥?m“TÈœ„Âf^`ý=óW�UåØh×þslkgm}ªÊÿ4¥ðêC–!Ç#ÚM®pwÁêMXúÓœˆnõö4…­À›—£™×céÂiÑh�þÓœ]Þ¸§²Î¡Ô�›FVÕR³G¥ÝŠ­KúíŒ&à  MR9 ¾Ïîí÷kÓŸ.Ú|‰©õ|©\‡/�_d©òÿaù{^'óatãÔ—öù±óc¦£…rá;c­�ý-(½ã9îmÖh÷¬ih—Â`�PèžÞ7ÜíïÅVàÍ“m5Æa«ïÀVWš½‰ÛŽŠÔ ­&J]íã9wnÍ::iïK|ýâgó¬ˆåI‰Àï×ÐnÈ Ð!¢:HVG’å§C©ñHÞhO4+‹;G�ýÉðu`V%'±U†(ÌEu)O›/QÓpï'v¥ÙœÑ>hnÆ#ϾR]*"óDû *ã<¸Ç`4bú…VÂìÁ»ñ´)Æ«kÏlîýÄîçŸ->€ðæn™%/ Ï`x™ñ6oÒpçÿMY=y2�¼¸"µÑ{ xS~5šê[8üü–æ œ„XA!Ò¾Ul¤…á`ØÜ ·PìªÅ«î^íwõÃÉÅM{_b"zþχ¼ª–ØŠ,6ÓðÁÐ"´ �‘©eÞWÕRg²ÎF­ku÷¢Í«.ÖÒÓ3¹Çˆ�q«¤ Áb” °ò˜\~ª{b7°´o´¯Õ'ÓÑÂó‘ô?9¥E¹ÈTš˜žFoB îpc6³Z5––H^É“çA(—õwãé¾ÅA/F34YwÂhÿ5šWh¾5óLÜ2ºiõ©™·¨Vnõ©{Gu¾ÊÊ,\\—š=hU-Ù+ …©º[ÃÍ4ãpÜXäôÝxÚh¯!ü‹7´Û¿xôr,Kñ2Í×ö€îMXÝèI@3<î`¯Æ2Qtb´ËþEݽø+ õ/±¢Úφ‡¬ù™Ãcá¶¶‚pÒ€ä«k�ÇþÄÈ®þÐ"´xê<‚° ¯ˆ>üp­XmÚÀò‘7DDkŽñµq6�«?ø¨®¬ª*ִ͸3îÅHz'uf´³¾$“¿êð'»)ŠW¬B=‡dÈvQ5<nkaµä�?¬Mûï‚»4™º~þ`a^v™omÜÈê ˜Îí&„o3´¼ÿ6¸ë�'Ösø0¼Â˜0oÐ3¹–��v·‰¥Ïž¥í¢…¸D�v󇂫¬ï6áŒO«O=$“qµÊu±l D�£Ýü¡àD>ß\VË6¿îô'ŒöÂ�x=–nö P›@ÝNž²¢ÂðpÍl#rƒác’²®q‚‘ƒŽþd¥u§n“oœçDdx8ÜÖz§öVâGF;áGÄRg�ýI (tý†”¿ù¶�8µLþÒh!üˆ³Ë»Y±|Ý 'R¾Í·²¨VæHzujŸ¯ê�\ýÊöR&ÌZ‡bWÎÁ¤Ñ®Aø9ï‚i»ˆê8|8úþ»,¬ömdíT$‹JÍÀXø€®4$íæ…]BCa“}<ó…‰u¢oVâGv q n×f5{Ôq³õZ÷Ní‘~S gÎ[¼ÕµYõ)Ûk—ÐôÖ¥áq+{5š�Ùs£]ƒðsö�¯›=xj›îQ�öôÁ.¡ùøµáq+{âOîqp}SfxÅêB6W}–~X-âáq+#²T&‚k¯l­Óðad®A¹¨¦3,“š�Ihó©€”»NÃÇlšðaK!í„_ÅH2¢ë¥ôc±èMO¨ç9Ž‡Í Ióйô©–”bG?éµ6§7’Œ'A �L¯ùfyû¿O³‹N ±f�d¤€R]íj[�¯Ÿ �–0ͳv0ŠW(A–Bx4Øèø-õÄ-ïct¥ ÿ¹@Ütá3»r4£]ƒðJår«W¥þv3ÅÆ+x„!hîðiê�ÛÜÊ?(ŠWLwy í\=&áSëܔʭžÇŠÅbúð±H»å¿ܲéR¡rú˜ƒÑð>ÃW<­ò�ÝôUÐÛøŒ]T+&“ ÙHé`f?!ç5AX>~ý!Ãð°=³{âæVÅÆÇh ?ηµ¹ØêU¯ŠDºÊ`Êe½k0)ÎæÄIr{ f´Sÿ9šÀ–D®ªf�«Ú»ñÜbìÈh÷it¶µ3çPêép†rË6¾�bçÿcQŠ�;$óÍþl¤ô�Û—�ý‰É`Êë±ÔPø„á¡D¹·Œöè? ëJÐnåépÚðp¸ƒ½Í„e2@græüÉ€6¸|ì�ÅÇ- n'L¿Ó�äÞf†Mx›Ý¾ìèO�ªQ¼M�EΜÃiŠÇ²¢Fû²àØq«œˆú–Ž ‡;؛مò2€-íÔ9¨-)E¶²oš�>X5Q€6^ióš¯~º‘Òçc¸Sñü’ÌÐýQnJå'ɉ�si®`—Ë£f�4Ú‘�ÁÆ+X‡á!ND¦ «Ú¢Œsù²Bë9»¼iëS?n]n¤ô÷» n±† ›4ø( í2ciÕ–�^Œ¤HèáÓY1”ßHéatÃÐbTÌ–þ" )¶úQÍøX¸›½ù��X'�ØÂRü¨k0µ®áˉÊÛEÈÙ«ÏíP<–I±KptíÔð@¸›­ ›6_‚h‰Ü;ÙÂU‹W]�¯qª3QâDĺb\½+ê܆W(·Ü‚ S¾€6RúôÖe«O-œ’aº{ãâªôx 9ùûK•ŸÉ;$„×ܸÈÑó(·Œ  ¯š¯ûó/½ÑŠ7ät”ËzÏdFøŸ&FXÅ+HD $áö X^¡�Üì5ñTÝf"ÌäH%è÷^Þ9šùÇÀÌ�]B4@�H¾ú[Ð@fÄIÈoÎ&ÒªEµòË‘ÌXøÀhï37ó[‡O’«ÿ[D¸¤1½ ¨FûiíB Èp¶I›ª¶ªâ;©¥Þ™O‰Ó6_âs%™×cXN‡LoÂh'­]l@ey>½S{†GÁïØ’RlïO„ÉNºÛOŸµúÔPìß ž·.XYúÓV©“þ;�U|Y†Ì¶õ [�¯Û|‰ •¬5¹(wÑêSg*ÝU‹jz§_£yø~*géOížµN3HRž-Ê Ÿ™rŽûs›‹]µúÔuD"è—ÀûI½êÔæ¦W–�9 éº>½Q0Ú7ÍÁ#Ø r"2£�È6¿nïK,�wÐψ¥ð�íãÖbgÞp²è íêºn´cšK0hí‹Z…“P™lÝ×¶(;üÉ�£=´vY‘�[½êìW×õ—£YV€6W£ÏõÜ« °b%øúƒ)'é¾°0ºy6œî›ß%m¥_ƒ7Œø“óñë/>´ñèμ‚Ön;·Æ.TsèúÉ69~Ó"Éò›ñìû`†È#üÃu±,Îäž§¿®S¬ª%.’ʶ^ÅòŠ„Ï­©ÎCQ.Ù!¢eó_áªI$q6ßÙŸÈä/�ö\ã98¾~:¤õNí­«Éäõ‡,'"Ú]ÿûÊ%SžM–Wê ÷��EÎZ¼êJc«,ni§-^5°üí ¯ÀÊ1W½¶õ�sç·°¬T²p°oÁÄ�<_Ø|üÚ9¨ñ³ x‘».–‹{�ýÉÙíËo~8‹ò5+’kÛý` m}” rú:3c^[×ÊÂÌA{ŸO7кºÔþå_�dïäÞZâÛMYëZ¹£_c¥g"M®m÷%¨4�(€š=jä±?·ÉÍ‹ÒÚ=«÷cèªX^Þoõ©c‘MD¾ îÚE¨ëúÇ�¼Ñ~W?Pµ V­æèþ¦E’øjõ©«Êq½Ž9|Jžvô'z§ö~¼�fhõ„¡å}LšÉ’"éýòTÀ+9 3yÃ}þÞmvçêùHúù°–ؽ0ÚÙï“láêÝxº+ ýt‘úìÎ# Æ…l.Åòž “Þ3è|ÖbœGx0¯�FNÛû`:›-˜^¹4rí›Ûm«¤×~zaX†7�Ê��q‘i¸Ë�¸ÕçDøEsTÝØºVö/µúTq&—3gåO®ý {-^Õ;_ø^Šàs‹$Ë�~�±à9ÓØšÕ�Õ§€BÈI¨ª¾R—I–ûÛ|j÷DFɘF½GÛ¿>æZ¼ªg.¿ú �S-%¿É`ýœþ-Nl”åòBüŰŗ0õPêOm]+­žüк“ Û‡çW5º�øªX ËXë»ÃŸX:º•Zl÷ä'AÜ$íY�#àÓ‡Q§_3ãráÛÚÔ§‹îÉÝf I³¹mí¬F”|Jå²’9ï›ßmö ·Á\0z~Û¤¨0›Ç6ߖͱƒF»UÁŠLgíz<�ú• vØj¢X>~1šiö ïÜî§Äé…çÑU±´“:XÜkõªÏ†S}‹G+ð.Ÿ¾Å#|g�㌯ávûÎLe‚ÆîAO‡Ò&•—¿›­À›�åã7² ½MO­çaöüªø€¡T¼)'v/f7 ïÇ3v½Ëô/~.åq[\9æÜŠ5É,�èº>6wZ)Áç#™o6îÖ·­kå‰�s!”>’¶‹èù�Ö?¿·°}³çÇç¿ÕÆpzq£î^,ÇŽ÷^ޤ8>Nñ3ãѳHâw?ç�•cVÄrmPHgŽ� ?íN:�K¬�CéßÿÉš×¢Zyfë2°| f°º`›WeEøW Ù3‘é›ß[=˜Ý,„åã°|ü)yú�­*øß„>>¬ôÏ﹦²Î€Æ‰°Å«>I»¦÷–�¦?]ÜãáÞ·pÄ �dЇDðÐpœÎ%gw�ÑãÆÈ$ü¢E’åùØu0z>>é[<BùÞ©=÷ôÞ»ñÜû ¶wã9×ÔžkjO˜=ð-†�Ç×ÏB;W÷-ä™;dH ¸BÊ äÜ© ÐGC§ºŽoq~m¥¾ÚJëÆøÙƒj®ï£ˆXh ¡ëúÌfLg9¶x_Î3ÐÖµò›`Žñ>8ŽG$WP›p´‹ˆ­eOnÖgW�élU-uRœˆšAÒQÑÀ4ÚMß…¾¸±Úüˆi—mÕ�-ÊÅV_‚ Å¢Ó/öHìÔ>”[¦Ü²Õ·‹�ŸÉ×Ù|�‰lb㜓íFô›¬õIÁb!#<æw–òÐ&iœˆºSw+‹ûóV“l Nó í& j“a“´a'´Ô,ýGuœØƒÚj¢ôr4ÃIÈ*"ŠW(7ÚwUùB»�©th#ßÂ!¹È=´Mºhñ¨¬�Î%G϶U$玹aðBiê�W.réex÷N-b?°¨Vö̲"¤ÝJsïNÛ» §sÉè>áhê�w€º]€œH2r÷o‹òuçîö±ö(”[¡Ýdð­®@ÆÚù ðPðËÑì2É'܇Eµ²oá�«Ô t]÷Ìæ¬=$vê(-Ý[¸Å”ÇÓvýKGä5ô;Ú¹ªÈà¶Þ‰tu ‹Ñ?dÂât.µ½Ý´÷ì`É ý5˜2ûHCl5QrOï³XG±ãðQH hã`uÅ­Ïs‹^•Mx?±KMÑ¢šX>¶Kˆ¡½g›uÇ@nk ‡Å¢7=)4½ÉX<�­tÊõ-6àÌÝ­lró¼£/i— Þ_ÆËœ;nïÙ6ú'I0 ‹Z%hÃe»ˆžª¬ ¢/íãÖ…s0ÍŠXlo@«@Ææ’ 0þRµ‹* ¢Ï-»z5šµ‹ˆæ+ŠR}™%|…UPèÊSÈæŽÛ%µÙ£ö/5òøÄÆy×>qwpB¤i L¥?ÀæŽ3¼ÂðÐêB {Nïô~Cõ*Dµòhä´Ó¯9ª'Î+Ƚßi{Kº¿ŠÕ…á½Bx01"|9–�ظµ ¹lA¾ægò ÏR¼¢ëz÷‡LS7$[Þwoæð7pE‘L¶K°Ùƒ¤¹ÂR}u,D’å‘Õ“®@š¡]@¶Ê Ö;—›ÞÈ“2(á7¡�\ VÀ7:\%äá“@j`鎛5bëZùÃúÙ›9V€ Ù€bQŠ�ã×Ùt@¸o¬.Dhq ˆÒ@¶ øeÔ5˜ò/™hÝÃj¢49}ó!ÇT¢†áeNг‚bãc�À¶D�þ˜ õŒD›À^Ô%Éí�ÍCNÀU×f¯Ú=µ7=«A­¹ªˆ¢g¾ð$�Âg�G¥ÅZI©q¢Ì qN"Cm„?J{ æðÊvNÓ±+6C»„5Ûú=S{#«'¿#ý›¶–(MlœK¡|×`º&ˆð¶wÊ ißÐÈ8¡¨¼�p9zwœÎ%(TåKžÅí”°+ ¹¦öËÇ3Û—´“¨ª):9CùÊ•áq¢ƒÃe,Ùâ�Tåwbë…Mï’I#Ô&¸£û͆£{ ëЊï”âV‹ÿØ%•UëÓÂv_âùHÆ5½ç�/–�Ç"gS›¡�«E¹¸oVÕÒ?ÛÙ"É2þGµ´(çã×Ó[—ãѳªî.˜É¿ú�û_�FÁZj8jÊ-³‚Œµ¡ÞdXw×<‹‡„ ÁdpRœâ�gXPx¬ U.Åæ†4ÀI<îµCv Uâ r•¼1V«Ãk(šWªmáÕÛ—]BIµKøµEñ2Å˸ÎÛ›ÐuÝ5™Á£7<^[`}žµ>Ém¨zâÿ°‘… endstream endobj 120 0 obj <> stream xœÝ�ùoTEÀ§lË©‚åFŽˆ"‡X#AAP‘ˆré(mŒIDAQ9D"¢Q j´¨„"‚µŠ€PT Z)---°Ç{óö~c–¥é¶nÙã}g¾3ïóì~?™÷�ïÜ„ðáúA�ç®ürïñò�ú ôâùSEß®[øÌ°®M8ý¦Ät=¯à´×çrùY§¬Ü»tBoöDÓ»çíq{�¾x6êr{üÅ+ǵÅþÇœÉøêQ¿+ 1f\¾³ëÇ´Àþç¼hñxþ%wJBê>'ÿosnÀþÿð4ô;Ã�Ž�Z¨÷èìÎØQ€2x“á6­(¹âåÀ¤fØ¡ÑfößZȲ‘(º¾®v<ܼÑÐ�Œ\&@ŒÉÀÊwlõ •\ÆS‘«po4âÍz&‰‡vivSìàÒcÈO:%ô‹y æÜ¾<•DЪ&`ǘ"Ùë)T‡Ó8ú‘AØq¦€cŽÛ஄1f[:bÇš,9'5J"ø=Ӕ蟛/¡aQN"©å`oìˆ3¤œ TFÓ—$o,™oP¾}N¨X×%øW)'°ãKƒçúòH% cÁM¥ìS1£D0ø-¤ör6ƒ¾¥Ü¤ä±ƒK�WYÛÞ‹Zúh38IY \…ßœ¤œÅÌ œæUF(ÚG mä"¥@½¡`,:��Ç­N³Ü9H™lé¦ ø�ƒ”ÝØAYÅ{¸“kÿzÓ¦‚K™êÁÊ2?‚KÙ†’u|Ы…¥‹”(®ÑÀRîR½ï‰ìO_ ,e‰Ü»þ’ã,°”ì€ 0ºƒ:ie‡†Â<°�ò}.ì€ 0a€Ù¢¥°RP)¿`‡ƒ¿ ¤•çÜbp>褻‚+Èñ,”òˆ-ò,cl+ ”Wáï:Ä2ÓnÇŠàíŠÿb¼¸ÕUJdöm,˜“Ê®!7$ü"˜”Ávé|[ &e¢ &S®°LÊ|»ôÈŒ�“² ;8 0)_c‡GLÊ~ìPà0Á6ïØb.2Š 6#©Ìé¸$»úv$€Ü%Å aµ˜`2”_[¯Ã«óíS»1s1„�&·fµ÷uÕ'˜gÝÉuœg¦ÛI ;gý åÆØ1}>ŒUY¿Ÿu9cì„�- ¿iÙ i[¨|ÙN]òrëNi>¼‡�Š7óy)Ä^e¾9JŠ¢‡äâ2JÊ>ìH»ïù+ìH�rBÞÃŽ¸™7M\ûÀ¤xŠú@ì�vB®Q~öÍÃáùí]ØAYÅ{ ¼å§ôwÀ;Qÿ¢ª ¤�oÔÞå¥syÁå¥K•àN)ÃÌ úí|¤ÌWyR²„�ÒNáT«Mç$…lV÷’^7·‡²z+{× °Q´1ö*{ñw{~RîU´Wp}x☚MŸ‰§”QJ®Šx¾%@9¤bS1nä+Eɧlø\oC¡zÃBÚ…·”~ÊÕ*”c�RËǪûx\ƒÞ€lÅf°µIü�’§T>"ä}íÌ•ºeƒÓK¬B“>­øv )Ûêñ¾äi%\ÿtMB…r�ÒúŠwBHûj™Ë}:à !ý%/ë¯á8!ä!i“­¾Ë !3%M¶Þý€ÇâRæ)­N]‹è„�µZ •ó{9)2>—ÎJè<ì3>iàØ&Y¶ ×p^úJ†¬ï¤…ªy>BŸ4ŽÍµ•@eOlQ2ÖK“Wüÿ çØ–IÒVŒâll1<+…}·�mi1JÃꫬ_ Kÿ*ì™*|¢-1mFM·A×Hlñp¬@L,Æ‘ÎØñ7Âx k÷1ý0 ;øFév¥º ¸ÆaG~5‹tñ½�¾¯#vÜ \&8ßõ\ñK©’µ�ŠÜ+¨ý.Å0!ý� Ë,>÷3ØÑ&K“™.!{(Mã3°ëeÐf5åß;k¿ç`Ç™"·ìæÜi�aǘ9;9jq×ÌÀ\ŰÀÐ:ŸŽH»0SÞ 6!ƒ¶zá¯èÑJgÝ¡OÏ�(h5 EÈ_¬%¤õ §äs§t`(äòŸY3ZñÞ&!Yƒóv9½Î$¦¹C.ÍdÙÃm°ÿ±(:ÜŸ÷Õ_ÔïrÅuò8i°b÷â'zɶf!€ÖÆÏ]¾eOqYµ›z ´¦²¤°`í+S‡v‘¾ù+%‚. endstream endobj 121 0 obj <> stream xœí�‰SY÷÷:õFè Ðh’ IŒYŒÂíÅ5î¸ïâŠÝ÷64»‚â.B¿u!“'“cmÁû©o¥f¬IuŸÃ]Îöÿ÷Dad€B»†WXräxd³Yx™rÉœ XݪUBV ÿɉˆá!#BF€P( Ð¥_dȉˆÃC6·jWú€(4�1d2éôÇ8þ$�Þ’�@7úA£?dó„8i‡¾9ZÙõ,.;WÉ­X6v„›ûã®±]Ï̾!7°r<ºq:º˜•ó‹ja©¤µ¨¾ÕW"Åò¿Î*ùùb|ël0xܳxØ1{ Ld> &_vi67¢y…‘MB” R¼Â½‘�³<¤xDñªEÒŒ~6B%Ñu}l-ëžLâUÉ-7úC4¿CÅîÆ«'"‡?êßë^̶ΖÂߪ²ZÕŠÓ;ËGâdæ}_¢Þ£Ò‚b—Ã#Ú¥X$�#@–G,Pí bô3#n‰DXbyØ6Óu�#àE�”¦Îˆs,Ý·|4ó÷áe7Ñr¸0¼~âžÊ¾î‰±"äð&RÚA„ã- @uÄ U‚©>k…–v¼vØAŸÑ$È °Þ£:GÓÃÁ“•pÑ(_û�‚š>±}î™É¾öGÚKûÒ:¡yü½Á…ÐèçJ \�E€´-.hjÁZ%•àëîX×üÁŒlغö·ZR +GŸS¬mv@|å¡Õ­Ø�±ŠÈ,âÖ�”@ú&U7&|ÎÇÐ9½îާ{ÌòLï[EHácÈ $¾P­˜††žu,›@�“ÐÛÞØSîÉP-òÍp%§£yø � gõ¡ëº´qd\Bïû㫤dµJä_Ìq"z�…‡u"©ª&t]ߌ”/RЛžqºêv=;]š—d´5nJ ÔRÕ*ÂüÑG8�€è�ê˜9`ETj�GømP„?CèIpzÙ]¾Ÿ±VD i2ˉˆ²ý˦Ã1g´Y®�7Åß�ðyGøžfÉ=˜ÚGwq}–cîùçu£-‹ð[ÌNDHÙ*¡™ôE©z5½¹/ÎJ¨„HµìãÄ," _î ‡Æ7Ï ·¢Šh%R|Ñ¥±åÞø$¨÷Èp8ælm[fܵ}]%�jJ ðÒîV)A¦±HøGDã§u‡cŽ“�4•5ÜNˆ*®ÉísN@´bx™\o> Ô;Cœ€šû㤞®VÕ»xX¾ÞôN&I?@ÃÁË%5xÉf�«m$mU]×Ç‚Y£íîIc²t pš ‘)5®U­ø¢S£\ðËpÜ,�2èëZ,÷&òÏ“ÞÎOB³rž‘YP‘9³†`�òl0®50܈L=‹‡¬ˆÊ#ÒŒ¶Á'÷)Á8ÃmZ@¤ÙìÓRË×'BŽG´‹ì6®=Â}JXE8<1Ü ˆXKjÁîVi—b)Í‘1ÚŸ PX—Ê ðÓ`Òp 2DƒÁc«ˆðÜ´6âw�ihˆ*ÝaZ%´Hv˜OXx®º„(¤R™~ï”ï0­"ê_& 0Ÿ´Ñ¥UD”€¼~Ò·|Ô9àžÊ‚ñݶ‘Ô‡¯‰7½Ñ�‘&_ØæF67âDH… +B»ÙݨÉ~Ù.ÿ3¾Öû÷¿–?ÿÜ~á ;º£-ñÖá”k|WšÌtÎô.O›g³r¾–ÚòVÄ�¦I�÷ B™ U‚Õ;jÅY%?º~Ú³tèžÊ¶�¤ß÷Ç›|aF€�ê»­u0.M$»çvGV33Û«èp'vÝ=ÛË]d�ò§ç…ÓóÂy¾ ß€üe±üùƒã|ö(Û;Sâ'kêá\è`l-Û;¿ë™Lµ Çß÷E_”þϽ껾ؗá”8™ñÏç†×N¦w.ªÑ—ÂÇT†Œ5©º®{&“4�;"�¿¬5¨é3òEÿÊ‘{*óy0ÙÔaØä ˆy§R£Á̲’ƒÉ“ìáÅe¡xWº?ŠE=w’�¤Oƒè0°žíœI·Å_uEX>÷†[âB`¯gñpbû¼*Äzçwå\tïì†Âêâ²PLfσêáàò^ÛHÜ.¡—�‘ö‘t÷BnzçR¥©,'!VPHw÷;‚ûЖ&´ö.ûN§Bç]ó¹Ö‘T£/ÜàQÁhbjs_Û=3|»øð‹zjÿ|a'ç�J½è ×{Ô�_Þ™ý±Í3cKj�-�T`xâww¢Üß&!CŽ+‘â`ðØ9¶ÛÔ�/}Óée%·›»0Úð¹“Ë�ðQßÂî»ÍîF­Ã©¾¥ÃEƒF ¶�¤2.•¤¯Üs›B…‘gzÿ!ßݼìY:ü<˜´I¨¹/:ºš‰gÎŒ¶îêàøìrŠ�¤Ý�ÝQ÷T&°õ =„gå÷¶7ÖàUûv£»gÅ'wb»_vscÁ쫮ȫΈg:;+çïõ…O8 1¥!£­¸ú-‡DtO•U­8¸zÜ6’²»‘k4±9ªÆ ÿê"}p>¸¼×àQÝQßìÁ=5Æ jºÍ£R"1ô[à™Lšy+¯ø{™SòÂľНÀC²™|` …b(z,ðñùËH*°UùƧÒdÖ*!JRM¾˜Ñ†\M0ÞMZܱаsþ ‚¯c|óìóP²Þ�¾.ííç�6À§ÎéEajs¿É~×X9®` bæYš|±g9åý”b¼›Œ+RòÔôÁÕã·½±—�á‰�ýS²À=&ŠE==þ2á {§÷+Uäõ¦'Fh!~÷70âŽ(ïzïÚÌ!¨;ç;ŸcÛÑcraò˜‰î�I8!LìÝ=­gñÐ&©”K1µ’¢¼arCJÀ iûî�£Ôô¾¥Ã&_¤}$N¢oUÄÁq¾g~×îFâdæ.Áwœ»ÂCSkèYûŽÑ]< É ™;„íƒÇÿøµÑpêÔh;"܆ƒã¼6m÷¨Þ™ý•È-S•ÞöÅ)^¶¸HyÂ�°Ðâ‚ïû·xÔã›§ïzcoºµíè±Ñ¶C¸+™Ã a<Ùä ÷ݪî²wéІl*¤§ôÁmi=6QíùËMæºlI5ù«è�œãj‰pú´¹/ú®/6ú»Ú‡¥p�p#÷ºVRôžu-˜††.À¿8Yûçs ^õëÒÞEž¸\ R,ês¡ƒ�*NdþjÛùʯ1�Q0Ú®;掠…Wš|7 —ÏÃüûþxË@4µn´uî—£ÓKi"ù²+ؼi “{*ˉˆˆßýF€œ€„@æFøÅÃz�XË’�åÓa#|ÔàU¥©ÌM:\¶Î­¸Õ¬#E过ñn²¢bÕ±�ÓëŸçJ¤Xê«IfÉ2÷ä8:½l‰¿ë‹Íßà0ÂI¨NT,<ñ»ßÂü›¦r}•ëôÎÅ+¿Ö1•"§¹'K±¨ֲϽêðú ¾HÐ.…"óÐ#ì0@ùǯ]óGÖO¼ê¢œ3úÍŒGM�>÷ªþk“x;ç8 ’#Þ5°íäœÔï~K¡XôL¦> $~]õ\ã{Ošû] ®–rÁ·¿ ríœ?xÕ9"+áO‹ºH¶§~:ëõ,ZÝxx¢Ñ6þaJßHÂ/UúWŽš|áRN¸ùËâçÁ˜ØûÑŠ&¶Ïm¢…mæ�NDv·úcæùäö¹Ý£’ê9Â_qz^xÕù±xsU+2@1�`¿a´™?.t]wŽÄ­"š }ër³.4ú‘#£_#¡úHíŸ×{ÔÉÐÿ:&5xUZÕñ[F[úãb|µ|™©|¿�jNõÎïý ÕÊ <|Õ¥}7§7½q /S<©=ÿž@’iÛDôíX·|ôº;’¿$i`„Û#’ÂÄ·ƒ^ÛhšæšdiþÚ¥ÐüÎËÎHy¢Üs¯Ý%Ç:Â�89»¬÷¨å“KÇì>)ú ïä–¯I"ìù¦ÓF¿4B-0:hîÇ‘©�•#œ-F:Hÿ—ò€dæÑ¥Ý�H´ŽPŠEÝÑ­ ¯�” ñ8Âû/x\ ;f„‰½þÅ=£_¡vª‡Í¸R/ωµ_•P"f€ÌZ€bq)P̼R'â}W~Þ*"›[ížÏÙÝ(wB¢ä„ŠQ,ê/»"£§4¯P|¨VCçx´�²rˆX€l� …¯M°Ó}Ž�®eu]ÿé·¬²IŒïòã £_¡Ö˜ØÈ:ÇÒ �Cçÿ¯Cx4�i׌S<^ã,.|[B¹d @ª´êYxˆ/x{ŽL¦ÿ¸žUDVI}ÓÝÒHßKB…É�äín¼¡ª•gü¶qþq/X$�â! d àùÈv¡Ë®ä’ÓAJPËkŸÉ¤?{™ùñwYr¥Þì—dáøø5VïQ)°cák­}´EP±ëÅd@ü§Â—TVRý!(�Í-Qê‡Ú¬¨Ð"l!›L½0ºš©÷†i|ð©©”Ki‰—3 p_¶,àŠoìtÂŽ©5TZõ亷‰ï»MN‚œ¤Lmîý~µI8uÚè ›yùJˬRt]—&’–’Ó9s ×~÷ISk¨ÎY:î�ÿí6í bQ½)ñ£ß¡69½(pxî†lµ�*€þÚ•‡ð,r¼ŠñеmËᘻæW^ƒ¬DKÛQÅüQ£\ ã*µ¿`t�ä†î…£ÓK›¤â£¯PBÕ/y¯]YôÒå ¾Ka¤ÿô}Rþª¼)uAÜÛ°ôëPX/“ 9¡ÂŒ3¬P²7^¦Ù=‘ø5’U]4º’×·AYô;ü+NHÿïóò÷ߥ€b÷À R†@¨…b±Á£þÏÆ\²®ëCCÕíwÜå?NG¹þàwt»Bøƒ¯ý×ïÜêyžô/"TŒËB±Á­þh¢&S-ø%¨åÅËÚé?umbÚö‹lù÷!àßâ•òŠÉðÐ?K*¦oq�)%rÐ<¤];æ.Ò«”’ÓáPÅ#ì8¢þäwæOŠ¥])�ïdº/ú¸­¨7B˜Ø#CF÷Bjÿ¼É§ÒÎåÚ¡]µÂãb¢�¨´ä•¡¯»/zÖŠGpâLiçNë`tl5c÷FJù™0wBÊ÷>å¹dª¶Æ�3mîS¢tÜÃYaŒóêCÊ%›Û•o;fç·o›ë=&IüŽp/œç ¥+Mõ�÷Õ÷)Aµ—‚#;åR,¿¬æLé6©5à¤ú‡&36 'gÎný~µ‰¶{VïVi ›ÅZ›’Pr:¹°¸v,ß¶�j©¬ÿœ2S¾�qa§ã¤ÿù�U‚œÁXÜè÷C¨MYV„&_¬Nª5¿+×áR;×·¥¨–ƒ¬ ÿ^ÇKÞO«!'B®Ô@db2á>hŒÓ‚BIÈä‹ç÷í‚f^1¹ŒÐ}s=‹ 18§åç³-®Ñ‹ÎIÑ$Tœã³K›±B��H0¹á3A©ÃQ9È´‡)1bˆ2ガëêñL©¯ÑÛÞ¸g2eô["Ô³Û¿&lnd•žD?1¦=L»p€�dF ]óÉòé¯y iw£“3M T’7=š4™y:~ws(^¦ù��çXz$˜1úEj‡íèñk¿†ûÖ ¤oíÏH“I³ˆ8 ÍÈù�zzAR4 •á}t`åèËhº”'VSÁ»»3ºŽ›Œ1Ï%qŽ¥ûÈDBXE‡ŽžhPû6—ÄRE¯D×õö‘¸UB“Ûç‹j¡Þ£¦H®&áNœç �êøÖYy—¨ÖÖM£-ýÑÁ‰�“Py\ >÷¾?Z Á<ÂèšM;GÓkQ}%‚çN:sõ×�6óGSjÕξÍYþ0� ,„[³=nò…—Ã…µ¨Ø:³ŠÈÞ¾}}’§ î½É÷½ñ²ß-ÀË�J2¥ ·`ÿ8ÿÜ«Žož–m©{1g“G.3¯BšH=¸©ï÷Ù¸c§ ^5sxaôk$TùËbs_´sîà»!¹Æ÷h2Äï®b$ˆ¯4Y.ª…ïOÌ?Ÿstk§ç$¬@¸Å¢.Œ'ÛGÒßMh-ªÿÓ+0ÚÆ#øJs8nÑ`ðøÇ‡&Lì½ï�’¦+„›àŸM¿ï�¯jÅïöÔŠŒPPS¯OŸLd~ô»µ¨Þ>šnŠ“>c„ëé[Ø}Ó[ 4žÀæ™M™*¿fãÊÐíª™—_ui?ù]PÓÛGÒ¿ÆÎH á*ŠE½k&ý¶7º.üd<¾¹2Ùüzè¶0÷)ÁðÇ}Âw�ÀnsŸFF0~â²PtO$ß÷ÅZéÊjéOà‚k’!ö{¸O ¨VIÛ8ýõ®Eu÷TöEg8¹ORYß8>»üø5öy0yåwõZT·Š¨\íb´u?jð s ¿ñ¾«où¨Þ£nGÉxJ‚žÜ?Ù–¦~k-�­3ŽînÀ >I¹ÉþÝ“,?̦ŽðàòI${Ê,Ã\½Gí[>ºÆTÜÓY«€Ø?õt%8@Å›G—×<ÏEµÐ2�øø5vpœ7úýšó|Á7�zÕ¥M‡.®1’µ¨þ²K£\²U"‹Ý@oäqaBÏâáõ�t-ªwÌì×{Ôe%g´!5uú²3Ü>š^‰\} û®%µÀð°Ñ²ºk¡Aô}cqÉ4¯4÷ÇÿèwkQ}rûÜÑ­¹F¹²ðÕ8çùBßÂîsox(xrÛèY<´¹'É�þëzŒÊÔµãYÌ,�Å\© VtOeë=êÔæ>9ñÕ*›ÚÑ _¸}$½¤ÞÈ*Ö¢¸ÖwŒä‰ÓÝ<ïÉQï ¶šß5#_¼ï�¿íÕ`‚”0ÔéƒsçhâU—6ú›èÒÕ›Ì0Þdš@ð™‹ÔºÞFÜ¡�ü¶çF[Í5°|ô¢3òe8##›«Ÿƒã¼o:ÕàU}sÁß„ç~§î\ûCñ;&4Úœ«ZÜf¼›Œo¾©øaÛ©÷¯5úÂ_†ã)a¯NNÎ ƒ+{õn$LìÝð¸ñ“½¸�ãI㾿€ñnÒ¢ÂIø‹îϼ\Ú_¾íìœI“+—*â<_ âÓ:ß]¼6–t�æ”<ËC;ˆ°€øÝßážL™]èyGävOþû&_œÀ K=“©x†ì<5ûGù�%¼Æµ�¤fäü]Þ»4•µJˆå¯nNN¸†ÑR,'¢r?¨»h9\ðÍ4úÂÍ}ÑUtHî<ñÌ™w*es#Ø�Uîäq僆ݭšq—r’¦ò×èºÞ6gxØ:œºã‹øþ:W�ß÷ÇŸw¨£«RÃn8…Bq#rôa ÚÔéœ=X¾Õ9îW O¬bhÄïnåTÌmÊínW®ÑÄÖÙ—á”Ý�'W�ÿ6öý·ZD—Œ- Dñ¤á®0x~¥|Ç€ÂÍÔp}Ÿwfÿ]Þ‚Š�䢜#Í%nHþ²'ƒË{ÿø#M¾°s4=¸z|{•Ÿ$Lf¬"d€l$'ó®P.™ðè„�k+ïCóðÒ?ŸÃ£B%ôñkld5#ÇOHo¥ŸÈ_#éÓÉ�¬s?¨æ¾˜wfÿ�•q×R¸€û9C)-¯Œ)Ÿ{#•½øº¹VµâðÚ‰4™iî�YEô¦[ë™ß]SŸlÕíéy!=\Ùûø5ƉðMO”ßX9º]NWEÄ26 1¼Â:ÉbW(€G–pâ·iAÆ*¨[g¾ÙýσÉ�Úä »'S“ûrü¤†Ýðô¼€’§s¡ƒÎ™´£[³I¨e îžÊެŸ\ÙÅë�µ¨X>ˆÈ5f%Á§<°Sï ß÷Ùüo5#_ô,ò¸©u¼Á£ÚÝxGÚ=·»(ç´ÝÓ*Ý”^Љìù*:\ÞkÁ™öÒÒ9¶Û5Ÿ›Ø>7jãñ;�ÀžUB4@ÏHø ¢P`‡å¡UD] 9Ãßò5Z Æ6Nýó9>°û®oJínÔÜÉþÅÝÉ�ý�ÈQ $8QB˜im¤5íT^á$èÛ5ü]WÀÑ娿ÙàêqÏâaÇì¾0™qާ?%ß÷Ç^ûµç^•!šWìn¼h>÷ª/;Ã/;Ãoz´w½Ñæ¾hK´¹7ú®7ZþycG¸üI_Cáüº¯úª+ÒÜû4˜hMó{ž™}ÿBn`å¸ýëJ�ož²"2ùbf7 ”ß´€C3œ€¦wúšÚ(5œÒ¶¤æÑ嬜Ÿ•ó“Ûç�­³‰­³ñͳÀVùçsJ¾üÉßuN®=5ýE§Fó°u4iòÅŒ6ÏšÅBÏ:#(o{c†¿t"ÃÕ5Ÿã$¤ëúØZÖhÛ¬qêºLCCV >†˜‘�Z€—œ€Ìº'Sº®m˜5ŽihÈÜ4œÁ²pÛ>D5 ÷ý V€'©³{ ÌZ$•ÑǯIÃß>‘! ãë”hþBœîá0{"&_Œýe(3ÑSÐ’Z°á(¹liWL-Äï“/f‘TÈ6 -@²Û|Zúð5Á‰ˆv‘éZ€'Å{×Y’»Í'%ÿBŽ+ï0ÛÈJg fÿ¢ihˆ•`çmÛlU—få V$;Lƒ)Ým®âÔMM>îB¢»kU+6ù4FPÚ†cd‡i,À� XÚ=êbEÛŽ=6}JYE¨ëúøZÆh»#à‘è´wƒЛžØc«O!ª”pjŠM­!)� QòG‚¹ ô¬"'~;bž¨z5±}Έq"‹S1µ’ròÇ>èy‚æ6…Ñ×UÑ«)ÍÃK›[eÈÈ8IYëã7¹�' ±ûìÐHô�Z‰_tjœ¨p"dȼƒG % šÇâ$t½ˆ‰XAMoî‹ã.a¾MNTŒ¶/Âo¡yÄð�Jƒ7\Ù© D¯/#iN‚øá_4Ú²€Šk$ná‹.­R#fˆ^ÂDï-½›–ÎÓÐ�ÑfEø3ëxv- Wþècè2Gô·ê˜=ÀÛKYq‡ñnmP„¡ëúFäH×uVÄA½§Ó÷ 6Ô½�ãœóŒ3"Hm]U¡ëzÿäxblsœ¸^µ¨k!ÇŠ¸ &îéD’Áªô7_"Ç'À7½±›ŽAtkṵd™â!é@[½8so¾DðªçF¯ýQrÃù˜åžÚÇ"g²ÒU7èSø¬ÇˆèE§Fr§§øÀžUDÿ&?�¶ÏµÎ`_ϺƬ„ê=aRTZÕŠ“¸¡=ˆ°.ìzFÛ ¡’°ÂWÓ¸ã4]?5ÜÞˆÊ�R^û£œ„�ÎÆ‡Épäš„åFP(ü'ê_zè)–D?iVÎ7xÃVšL:Ýœ&NWÃP<ö;³€Keù‰ ©×3JÃÁ�‰Ḑ„åUÖd"%u5ŽYP(Y$Í*¢×ÝQÒŽìáå)_]–z0<‰<,’öBH 3²{ÔÀ©z -… ÍýqNBfQ¥Y¢FÛáA@wðÙF!�·:ê˜Ù7Ü&k^c§õ•• Ã1gkÛ2‹d¥{¢0¸^§r"zÝ›#{ÎûQP+º§÷YÒ.ÅîÜ~þyÍá˜3ú匄ò >YÊäijNVÈ=g…5#_¼èÒ8â°¸K¡]$BGø¿o™œ|ö¹·�áûþÄ<™4T µ¢gfŸ pÿ=÷D’„Å ?a ½mÓá˜cEÄŠÈ7w@¢ wÑäöù‹NÍ*!ª¶ ÅÇ‚YÒ�p%ÇÜóÏë¶ömÈVGHê[h)\p�¦q_SAáDÄHµ“2:ÂÀí÷ß%q®w†_FRdÀå Ôô®¹œUBœ-’F ˆÈÆ’pSL&½îe¶îcÜä†\iÛÙ1³OŠg¯×ðúISGÄ*©fA¡EDKªEÒŒ~“„êÃä†f R¸cª‚æÝj×|.H¼ï�mœ¾îŽYEDüE‹ÐL–9ÂÝ`€Âò�å!íTlnÕæVýÄûþÕäöùûþ„UÄaPÓÐ�¥c�"uâ„ÊA;KÞWê·c•`½'ì›;xÊÍʆ×N=1®äq¥f+u¥)F¿(B B™-Õ2˜�È&!V€Î±Ýy˜7Ü L«Z±åèE§f+¯q-�kÝnøDòO÷ŽÙY*` ë á`Ÿ[Ãk'µ/@ cÃw•8¥Y×õ/_ãu_ ™»JxH°Ó™“ªðÅ‹¤º§²5–ä¹)ö-¾î޲"´‰È"àù ž©äØZ†ÄÁ FarÃ:Q±ˆ�pU 'á˜Wþh×üAUWö­jů«Ç¾&YÚ$dŠ )a‡ …Ìå!<p'nü2� …Çé.ŒÿéŽuÎTQ'¥%µÐ¿rôi0ÉÐæÆy•¢yŇž�-ý˜ „+0�à3°iáCx2i ¤yh'@»[mM�aÏ V lž¹§³¯üQ¶ôWexÏ&à!ƒKSe #V Õ�©Ö}�–vz`KqdZ€V 7emì·�¦û–çÃ.B—ÔÂðÚ‰8™yÝcð_ •)•FÈêV¸Rª™M@¨jÌ‚b)ù�­}Ûᘳ| ª¥žäðµ_sŽ¥ý ¹ÀÖÙ=µÕ]‰§Bý+Gâd¦¹?n—T†‡v7žhqÉø^ŸO¡Õ-Û<;�~²ºj ‡c®þÓšíË&-”×A…“v(—L¹d»¤r¢Zþùsoø]_Ü9–öLgý ¹�•ãÑõÓ©Ðù¬œ_€—Kjaéß¹~+‘"þWµ0+ç§w.Æ6σÇ=‹‡³û �iùš|Ù)…¶q]žÎ+øvpÖ÷Ç8Ã+f^yVº’5úÙ'í0ü vð¦—Üâˆ2íT,.h)%§Ù°¿ «„¬Ø1ñ>#B†‡PðÄÜ ÿ�ñFÑ*!›¤Zq@Q¼Lñ2Íï0ía†G¬ˆKzË絺·‰g/÷Hë¼'Îÿ0/9É endstream endobj 122 0 obj <> stream xœí�{pTÕÀﲈR0å¥C%’A©<3e¤Q[I"ø©ÀAZÿhMµòlmkh;jñ�•ÑʳE§I±ã Ê( VE# Ž€€¡yÈšfwï=wß{:—ÍÆÝd7ÜÝ{Î÷�s§¿¿6ûì÷›s¿óÝóT^ štïÒU¯ý»¾Ù­‘¥a�´_8ññöuË”\Ó‡Ûÿ*ÃÊ~³íŒ?àñi"¾-ÜúÞÓsÆ8±(ý¦>ºÏ«w¤”JÔë }þîÁØ¿Gñò#AOàÒŠ’Ú–'дaúeØ¿�Ëfmíðf娫aù‚^�ýûAÈŸù–îÍÅQâ?²pv¼™R­{cV,uª:8·v(üøî¢3jIJ¤8š¶n,v<|(Ú¬kŒ$]$DÎp`ÅœÉÛýa––.âkYb¯þïGuªõ¬”µ}a_ìà˜qÓûKZûR{¤ô±p´d ¶ÎÁŽÑ:ƒþFXuq™Ñê&aÇi çbŸÎÝ¥4¦× ÁŽÕŽ3­z#è{@Ö"!ÿ)…Òd¤©Cc°#Ή›Z %c@�üZ¾&åZAøöré µ#°ãÎ’kë€Sœ°:;ò¬˜«ñ/Ò£m’§>w­ëæz¢×Ë2Žwe­Š§‰Ò°§Û€)&ºC˜šŒt¾Û� fpÈm­ð“~¿@é纣¾{9¶ˆ^q¼€˜Á“Ñ¿¸ÛE/ôÙ„šÁ“ 5 Ƕ‘çVAZ“Aø|!¶� ôÝ)�&J#mEØFÒâÚ)D ÿ–¨{¶“48j„jMѶïa[é�ãÁZ“A¤E¸ vÌWºÌ„N_�-&•ÅBj¢4X›‡­&™;Af r�üÛM“ÌM ´'°ít1¼ÿÕ73d¶ŸNòc¤ôŽú}lCqþ.hOk¢Ó[ ¸&J»˜¯#¼&Jµ¥Ø–W=ÖÌJ6�ñØžVIМ(�5 ¯»»UàÊ)}ª¦þ籘…Ü‚éi�$͉RÚœ�§é¾Öõ„<‡¦ÉuJä÷•îhÅXžª¤èëÄŽ!U›C¤ÒD©z?Ž§šœ¶†!ÒÞCS±<}]'ä O‡dJâqÈ5ðšJ%ËNÁWà=“¯9QJÀçÒïfÅE6„·krœÀ97tà5åR6'JÃÿ€õT+cv2ÐAgÒÇIW;%< ééu{Ó£åC%OéŽZ ç©JÚÇŽRzL“ãv¬V€‡šæÃŽÕ ‘MPžvÈZÄÑ€ÖàðcGj ï}0žHýØQJ÷Àxz;N«øBh*�m¸·ê|O?“ý±£ô=O»±£´N`nØ%s-Þ‰§Œ¿§›-Â'ѵü==ÇþX0xšù{:…# ÷ BL3+>>îSèeìYÛÂÛÓ“b¯©7ËYÞžbGÈ†à ¾š’�$è¸�¯§BIçíºú_O3m‘Æ)¥ÛùzzÜU¦A_OïbÇÇŠßã´š±ãc…—ë¦<‡=ª'cÈà.žžFØ`P%Ž!OOS;°ãcÆjžžæË?æ›`OOUv) (=ÃÓÓzìèØÑÁÓÓ›ØÑ±#ÌÒËÕËjv½ZYÐõ÷'ØÑ±#ôf–üÕ½a~éÕî%‰�F_aGÇ�ÙÐïÈc/ÇGi ?©î<�² ;:vh“i|bYâc¿½/Æ?ئ̤4PÂÈÓŽ¤�¢ÏÆÏ̵OY@#ÓØhš}4ù„©é_^|òä^ –ÊL49êËSþ®�m\2‚Cb,KvnmÑoMùâcrä–_J¼º'a‡®, QúyòKB”~öìÐØÒj}_õKÝ×Y¯3¾hÂŽŒ-¬¾]Ø@£›“¿(j¢úËU¶¥3ˆ�oϧ6ÿ;F6LØÍÑ”×])ØÔ“J>Uùt}>w¥Tõ÷%™ô†Ÿýj µ¡{�{®Û¨3}=‘Úr)ëÊKRð«S*«Fåó­¾;ŽLÞ¢y­çt-ðÑì¾Ø¡p¦ï]ÛtKª4ÿá‡`7�c‘Ou»/§#5¢jàÇÅ[3À‘ñ¿?ðfå*â ž]]qŸ`äMY¶Çãï0±Û1âQƒuÏÞQ`âµ+CJ—þë+ôzÒêŠø:H¸eÏ“³FK0ÑÀf.YY³÷hc›�ø) éÄÝzü£mk›?cë³Eþ3<Ä< endstream endobj 123 0 obj <> stream xœí�ÛnÜF†ïù}`©>�Mè4Â^d;’Û@ëÖÎZq€}üÅÌØÖ´=§ªÙáÛ€1V‹]ÕvýõWUOíðùc¬±æõλÁ›‡wÕ‡jÝâÛÖšà‡X÷]kßT?ÿ`ÞWªP;ßnž}úôð®rfý÷õ�Ù~x|[�ÝóöÏêì_¼ÿéãã_ÍùùÙ�×ÿ¼1Ö\\\Ý\oÄô.gÛ¸–ð[õªzµ+ÞÛ¡^ëÖ–_G7D³ûïë;óíŸôºº¯Î~úï¯ïÏÏÏ.>þõëîßüï£9_Ý®VÞú› sqaÖJž­ã¼¹ÿ­rÛs&v®Ž~èŒÌý»êÜZÛ\˜û߫۷ƒºÿ·9·6lØÕ­mûvh¾44­µÍ•µÍ°ù…5®¿¨‘ ¹½Ÿ¢g]Ý5Άp­µîêD:º¾ö¶íMr¬m.O¤cðµzÍc´Öutüêµ�¿•vóáõ�Ù~ÈÙý®1.ÔÁo‰ô5¨Ýú‡�BÖâçYp{fÁ^~z†!ö�{z¼ƒK ÁSWVÛ•»¥®PÝ�°«†„¯´ãX/�r€×ÚqReðȃZ««bKË»„´ÒO»^+�k¾«•�~¿Œ6vûeì6$›:é*Ð×Ð�ìݤ«�nµêrW4ò€]Yêê­’'VÔpIZ‘º²õØiÉ”ˆ&1ÙíGÚ>¼KDêâ.©+GÒîÝ~§¡ï µJ¦w O&1Ž]á¦î «@Â3v;Kúqd,ÔJŽš¾Ud†¨€žò¸5d°Ã¶‡Œk²–¢6ùå¬Úi¶o+и–¹Çi§)É"„fÁ˜„x¸áP†þ švÙ.× ô@]%g¶ =�µâ#í’nÔÙžä _j€@$Ù‰ˆEë1ÑZ‰°YÆÒ¢pZÚä�B«G",�4ì>‘D¯Z"ž1&5 ºÉ¢‘óìBW�!Î7àÉ  QÞqÀN°c`GæÒ‰§aÇVWï³—£®2ÔŠp2;Œ›Ô%ƒŽA­Ôû*cÓèw‰7¡%ùºHc° E(HDD Ú74ùžØŠ‚&ŸÙ ½ƒzB.hd3ˆ˜6zP;Ú{äémO$ÛÓ¶mmmüAÛ“ûb+†ºçí/hfÛ>ÖÃÐÄ!ÛÌê)~>ïÑIW{¤% šÞ#­R 'R—My› {³õv^Ó�n½Eò*Œ(h#é9( ѽ¶ç´� »"áú�iÁȨl3è=æ¿ DZŒA>î&‘ÑIæàn$à}*w³KÑ0žÆÝ${W‘ô­†Ç´º�m6‰3Í3Ì›ÁÃSÍak­+ÌÀDqWj>¦dö /Ø¢'†Ù7¢…�Ž!Äý] ÑÑÌ—8ˆ¸ Q5rÁ„=nBZI Až´ºê»9ª€xCTu¤Ð ku$áÏ=´£·­}g+J`�—ÁV½ûRð™�1§]l£?#D¶í4ŸÀèÒê½J}q#ðŸAÂÁ>LI—+ˆ„õ'E¹ .¾/xxêe¤_|æ]ÆÅ\êIÔ'RȬ\rR�s�q-³Ð­¨FR`�;�.#•�(ë9rØ3ÊD—i£ƒ.[(}ë )L‘á¿Rµâ$5™‘ín/\ôvÜÃzéfl‘.dŽ/ƒê¤¬ ~; ºEzжÇV–˜&º3Óš&žC�LÏGªW4WÓ8®’‰ðTGs¬_ZôÃõ_¦R.R0K©â´ë0e•|úXÀ�»¸1#¡¿àÍY" ¬/ìýø}š3\äC\]Q–ò¤VуúfÈ &´\Y_õ·¼q"}ê%ÃóPÃwüúùœB/5�qZËþâ ÕV— WS> Ž•i¥¿�@ÿfê×à“ð%r(aüåeR êx×qœéŒ‚ë!lTOÑ"3 ÕÑ«9ÃÈK^ÿTðKWOxå|FHÁo]™ÅÒë‚Kœ,€igÚë‹3¼þ畉L¯y“Á%V›–(Ãj"`’áè«i€½, ˜†kEñ.,g¦ ¼zÓŸ f ‹Mgìûñ{#fH©à$2ýwN �Ö* ŒrÙ~ånÍ�`ê‹6vuJVl9Ws Ó¼t,P”.ûŽ1¿jÈ©FŠè2NqA±€ºÌQfÙ1‡Grsy�F MO—ñ\å^¾±@L3Øñ %^Ê—¾é}öS~«ž{8é×´r4Q] ñœÃs&VÏ=¯ÀKF„Lä‡&¦'ñ4Î#~!j»Ú6Þö‡ZÜzxÜðfÍMwXL0¡umm}páÀ¬�‚¼ª^U*k‚¬ñmk�·±î»Ö<¾©~þÁ¼¯>T¡v¾ÝhùôéáÝF!k^ß™í‡Ç·ÕÙ]0oÿÔLFG“l_[ï;gœõ®BíhhåiÃô®oöⲯ® !`W7Ô€OxjÔ°‚†�sä+u{jˆê'hJP¸¥®xÚ±窣«V—V�Ý»¶W‘ä]ó.Ö¾†Þø~ó:E_·ë_Ý~Úy›õ‹·/ÅÓŸºl};ú6žýâ­¹ùã“ô¾ñµ[¿Þ­�uŒ1¦�í¦“º�€fG…Ïm[¾ü—^œ‹MíbŒá€Î ;J¸õ@]ècmƒ>‰ßý°+¶5Ûg¼õ¡n‰óõäÿk]ñü endstream endobj 125 0 obj <> stream xœí}‰[I÷õüéù^’^Tģθ鮪î€,îeÓ1(˜tWuVG·q7ßïVDDI§;Ðç¹��¯/C:�Êíª{ï9ç·ß ªžDkíxE%T³\Ý.JØQ1MÙ,•ešÅ4BeäÊÈUˆ«aš´½d–é“‘›0BÕcdIÊ–âÙR¬w1èw!B„f‚d82r�¢E„ª2vu‹êÓ,zêê]»öàÕðÜ›qçô÷)_©Î.TgJŸ'ÙDZ'ïnå_÷Ž?¿˜[=Ú]V-šÌz ¦±ÞEÙb:¡¢A¿³"„ )h–£W2•ÀnçD_¹çïGçߊ„³û˜¤¯L½ï?ÿlËEçn®è•1•Ï/%þX�ŪA¿õ"¹ÓëY­V«qUÂÈèÚL¹Îùgkäòÿ¥øF+«*>mEå o@„‚„B ŠéÊ�žnÑ}•±Â;ÿòÏ—zûxòò‚nÓVTNáR”ˆ"D8´P�£`G!�0sèŸ|ÅÇ-жxXù §3›µ¢²òçÓýÍÔž9Õ*(–#cš@®D y¢öÌÕõVEˆ¡þPpQÅŽ‚ vuêeÃòÏfä+Õ ·V’�Ū‰뻿òXG¡%S” G#T·¨f;jÏ4àˆ— nmîˆN^^Ð0•Ï-*Èùñ5Çr¹–þIéR^Fn¬£ !7I`xR%T%¶UÙR[O)•õTLLSY–²˜†]Åtc¹œÜó8•uSÝNÛ@¡Aw9B„ßA,K%Bjу³�¥ SìcÊf r¤K¿·]�üÓ7d‚Ý$ŸÙN_Yì�x>øè¿ûìãŽùmôÉ»«S/ñȳ¶^˜ŸLY0?Ù6Pг®b1™x ¾í"D¨V«Ö½ÕXf¡¯?xl qcæ5œËr¹ÿË3ß^°‚‹"AÉ&\ó ×g^íµ‹ó“Ó/Ó—5B5În �D� ã"4C³kД·™qçiàùg3Ò|¾:ÑE·–©«ÕêÈìzæö"œmvêÊâÈü~[xãÎ{<úL·˜nÓ8*Kƒ=�PFˆÐ ¨=s]·ì¶÷VÙûi ϽIZ0AÔ²Q¦N§'n—«ÕªNXÊ®ó¶mÚû„Fžñ}‹�¥RÆU‘ô‡!¡€j �DèðüÛÀ3϶hï/ˈJ®þß…ÆbUý�r:=¡ÖÞW¹Ow¨üì?îÓ�ÝXÖ,ª"73¸42»^­F³Ü"øˆVTÖ¸þÆÅÁÕÀsηÑ;þ\· áŒþß�Ü¡öçµ%_¹gª×g^Á ÓjµjÿýOÄ´�Á?èFUÂÆ��çœocÜy¯YLÅ4a¸Êù¥$¡éË ~§ SìãÉ� •ô.&,/Ñ�Î"Dð:a qÏ\[ <á|/4(P»’éHÈmíö¦½O {釕Ïs0Ë�èrUÃIvÍýqEˆpÐËRÙ-Ä\>à¡DúÊ¢„ 4B‡æ¨\YcëºÅ’]óšáÈ�Ñ@Q„õD‹åƲT³hcÎ8¿æð?² Ì‹§Èèh�tzíæ*BQ±:B„º!N\ ;é+‹�§šgÙt5‹Mî4ݰ0‡žêˆf§ÉØm"Dø1âÊØ%ck�§šD÷½u¹häY°—‘¯TA¥Öfmd)š#Š¡^Ð@ˆž] ‚;¿ûèùû_¹÷ŠuИÝgL±�­YOE®j#‘�ƒ¹Ó“ *œA™qµÎŸ°§#ì­¨,â§?™´YÒfw¿ ü ¾cÌ”?“‘õ£Ý¥c=•À/FÄÐã70¿Ô3§e#~èCùÿáù8z"!G6‹ÈÙÐ[ˆgèÿ:¼MnN’PÅ„rŸ„]1­ÓQMG'ÑFwoˆ[n‚¸2q5B©\Á®Š@®Pô¦´C¨LÜvãÖöÛ˳�7Ê,”¯TOô•k¾fصF>‘mFÇà*ÜUËQ ÐÇ~ØËy*¶wŽX$àv‡ 1”�[®b¸2*B˜ s'þ®�B•cgi"Sûyt`èÖß “ˆ¶³[û3•ÀPq܂ڈê€@=d!ñµU°«�ÓÑm*™ðc q“Y'™-njé€_aX³ÐXá�JÜÍåÑÞW ü’DLyŸt›©Ó"Ç�FA¿°¬v•ÃÛÈðœ…ô‚¿$�]Ä?¬˜_ÿ£ ¶¡•“x=j†~ŠI5LU fIt-.ÜZé›x>8ûßý¸ÙsXù|Ÿ~ž{Ó;þüÜ­˜x±™l‚œ—Úû¨¥du‹¥²Þ͇¯ÿj“ô#4Ç7–Ç �_Òfdï®ë6U`‡_ zEXÄbÕø‰µÄ™PÞ3˜~aYƵ‡ì×yƒÓ�P5S‚µm}//ÕŽfb¿Ô‚˜„àé¬ðiØí™Š@3ô¨¹¨˜Žj5#:}× "W#°½QLš²Àp�<Û½)áÃÊç›_Ÿ¹¶NÍd¥KLUÂzÇŸþ½þÞ—‘{¤»t·! ü»ŒéÒ'�Ðx6üA¯‹ƒ˜…@kÇÍ•ÄÙÅX¬ªò�ÏÖ|"™TÎP±i�?MWBT6™n¹)Ûý©ff åÿzÒ‚ “&ìG Q…¨TÛQ™ˆ$¶aqnºšQ�y¦’0T?tÂ9†¤"7iÓc=¥+S/yÎpxþ-X]€k|Q|¦�·ÃÈcÑuçixÎb[Ã~¦aؽ:dÂ$L�pÿquãp´E±Ï‘LW2\èjeêpr�©¬‹P6?hñëŸËkJE'âJ|ë¥LÍ”êð†› “ñÛâ$-šÊz“/öêȼcôM<øSÐ#=^à_êãaå³n±“ai�m�‘ùw:´XEÕ¡}¡VóÉxâ($mœ¹$. â¥ÙÅdwÁ'mp‘‚DˆáÕo¦"Ö™[¬V«PÙ6e#©™’lºñ3Ë-'Öƒƒ§Ž] “›L³h×í§õõE+¼kÍz:�_>ᆑPíÁ+¹§ÃÊ´mí.%øÖ=èeÒ¬HX°ù‘ O¿°¬lì: ò“¡’Y«äüÔþÀWT«Õ¡ü³ìè²Ì‹Ø�z¸8¾I؉ŪòÙ%Íôªw^:=qì⣣fAÇnÊöýa›N¸Žö”dìfï®þ¥þ6N,ÈØ=}5¤sè;Bû(ž&˜‡ÅxyAŠÉíŸÎ.ÂY¬®úB"öi¼N.möæL~vCÅ4Cù ¯±žh(´™�ATÐfí½•í$ꘈR6kíöêrЫcðù@ª`–¾¢îØÖ¸6ý6“Vè¾/!„Ú3§X™k§->½Æ Ë0g"OF4qz%Þ¾ò3lÛºJJÆ“�³yx”±Cy5Äƾ(–Ë©Á›Æfg®-Õ÷¶cŒÌ¿S0Ì7êëÈ­†$ýqyAF »züR9ð‹Ù1þvރߙQH§'‚^5a‡b�ª°"ºQÜNù§Óƒž¦MçÁ$aWÍTÄ›tüí´¢rWni(¿ÖÔ*Á /: ö7ºMÏÝ\nLB¸9ózóT.c·güßÀ¿à¹üºM¡WbA6üz¾2¢éôDÛŵ÷ )*_õ¼xåÙteƒ6µd“ºùvH¡6Q`:ÕjJI¨YgɆ¹ÖzÒb§¯.5ÌÃ~¶uãìÍ•`¿Ú3åÏGºK f­Y˜kR°û0LÎ [ƒ›[»½p‹mDé«ý/1HaR®ÕÒ¥Ú¸Qú]eýÂrÐW·7$LÖ5¸¤z¢¿ÒHÙ±áù·À5Û`Ö\ Ú�¬�¦ñþ)¥çqÒbcOB4²¸5Žöx`hK¢ÙÅÀ-œÖâg[ã“i_šÝ�žœ9 YH@ANüÌr,V­Õ®1…"RÆ“qÓ¼M.­ Mù”Í&üñ¸ùA\ŸyÝv©¤Úšõ”'ìümŒÎ¿Õ,š–Møìt.HxbüAâýM³Ì9 ñ•Ü`oµ øü”S’Ýž‚XSŸÅvD-ñž[’ìŠlÂÂ��­O5³9ªÖŠ _=Í¢ƒ�“€}òNFîŸ×—‚*PO—>µö”T>9/h)h’]‘°'z+|Uk±�@&SÔ°`¿Vô/(ÈíºŒÂóÙë˚ŒÙ/ê ‰ tuÛûÂØ&ËWª*qA)¢#jÖ×À‰¢ó ³PóÃ|èôò!$„ª¢bY*Á­ ‚"™!]*U�£Õ„ÉZm¯}ùÇå© SdSc¨Ñ‰È¢:k(´ö|)³´tÂ×\Åtª�@»Œ{Å÷0ÑdFŽö5¨™RÂ,ÆP^t®‹Ÿ]j9ö ÿËÒâ&øÞ^p6f¡͇p¾ñ¤¹†P5iÑ3Á+lL{ŸT " ºEÏçVÖœ/TBÓ»¿¢EÇ΂gÊf—'_~s¶Åµé—)ÛÓ¢Ùi•8ŠÉ9VüËÒ8xYFBp¿A 2Éœ8²´1*o;-ȭɦóGX&„O^^”L§•9“taÒÿRù�Ço€Zk¸À®µ¶¯[ÍvLO] ›¬spU�*G¨û���ÂP ïV›nµZ%wWbÙ(?× Nâðˆ50àp1e³�0=¦KP‚;öp]t�^Ò†Q¢«Ó/ëØÄÏåÿã» X·Ê{°7Cn[˜e¿÷W@£ïÏÕÆ-—ðAÐá…ø³ØªÑçÏ ×8°bN¸(™N°�³8¯–‡°”´<9C³#˰I5Aé]ÁEèaõ”÷xÌW #¦*!Æ5̲�PÁLF|R8Ùk ršŒ¨�-'л ëÍEÏ4¦'Âb dÐLG3Š¡*EÖ �‚L!ûìÆQ9�û¶p÷³‚’/ñÛ Œ’„ ¦§ÃWwåú¯D•\T UJ¾q¿÷/\{ðê×:h#óoO T ¨‚Ê|Sº«£ñ‘Î9ÅtÃ`f 4·ž’„©ÓƒÝ¬ Ç.ñá�UÙFjíö„še²k^CŽf”š‘Uô=ÔTèy JvÍË$¢ /ª™ R�Z£MÕÄ®¹îÆúî‡N|þÜ­¾Ì¶çg ¹Çñ BUÂçÏzsøŸ±]ëÒ�>ywîæ pÖ0´Q²cOw¿t�žŸM§'tB÷-2‡ÿ�ƒ¤áÀæÓö¾2]»þàÕXáݸóaÚû4I?ŽÞÝÊ¿Îþ½~ê*Sc¦ ËüÛú$„ã"{‚„iM¹’]Qx" ú¢š5>>a"�'HËÕÉ®y»á¤jšCÏ„äæ·—�Põ$ZkÇ+*˜-zŒMÙìÜÍ•�Éw ï¶m�fÊŸ‡æÞfï®·÷•5‹jüËØukehvom”tz¢µcN6�£=å)öW§_ʼ\ßÚí]>µ º‡•Ï7f^Ÿ¹¾$,œb(ß1Xâ u]P Bm�'" ?"&Ù• /ªY!t¶¥-Åj;*¤…�m5£{uBC¢*¶5ÈÈèëþÐæœIÍ™HÓ&ì  m„ù—4ËRÙšWlÊë4¹ Óû׊ö«Ùt`÷h³ëÓ^{ðêØ¥Ò±Þ’}wM…ÑökUúqçÃù[+¢p´×­`H (~"©Ð4‡nàjiN¢¦Üȧ‰,Wô1ìWÕŠñ‰þ0LXck¼ð¸«ŠÈðq8j�_ŠÅª ÄK<™x*¨n©†©tf%¾oÏ•À!Z'ì^ñ}cnEnv‹P}—§÷×J+¼kï«è6”Å QÒ<ŽfB—µVÊ0àƒP­CÇóÒ†ÔÀ¦ø˜€˜�8�)\é\Ð’b;†}wf«öþ�ÝΉçò™§*ö$Lyž¯çB…•Ï­ÙŽ]*7F�äbnu«üNáu„ªºEO_]ôU…àæÃ×­YOÅT·¡›iÜù§¾¿ÿ^ñ=è)ÕQxGŽAî‰Ï—ʦ«‚·{HF“BÆžh5ÂÑŒñÂéÌhÄnSTK™…Îß�ú�.6„ª§:Ëи·Øñ¾ò¸SKÇ¡¹·éË0i¯b:êgó>ûx¤»$¦ŒÂCoÜ y2Ï<2rV¯8TaFâñ¶#ˆTƒ‰Ê›jú^£ó^è÷þŠp¦öõìÜù‚»F¨ë¿ÿ¼.fùJõÆÌë“—uÌ„ãaXÆãÎû” =Dx†lGÔ6PÐlr%ÃiÀ÷â�R�°i5jŸ'ˆ>÷…GÃXjíö4â¨á üþ:Ì ¸ )$-v´§tyêů¹ä+À«5†ž¦€yáɦ~p„⑵ÆÜðÑ'ïtÂ$BF¸4ÓRÙbÛ@AÜH\$'è+:ø�øÑL(Åqw!׃è‘ýuc9ðœóÍWò³ÊýÝ’8ìYH˜°hÄÑ|M’\sì­•kÓ/'ÜŸÓÆÝ¹üÝÿû×õåÚx3oCk0 à¨Èmï«4ÌŒiv¡:0ùB·èÇv†% )†«�v™Sc4ÏPA³c+­#Ž þ Û+¨¨àb•Gæß;ƒ4‡k€€hy«T"Uìˆ�I�½â̵¥ ·V:WÏÝ\>smñä•…ã}e˜~$´Õ‚·)c½S”éäj¦Ó¤–¿å ãÜ�e¸“Ê!h™År¹D÷CÅ€r�n#²|#¾f¦+ª"1”�›s¾½P‘O¿Ð°YþõM<ôpŸÞ¸€dB2ш«cH&`†©$(7&6ÙpbYªX4É3Ã�Ú p ‚ú ðãî ÿ?]ú”²˜LX÷ÝÕÀù-ýS`Iɵƒìèv³:�6)ÀÖ-ìEÁMÀŸ³°HAºåNÏÜÐBLµšûÙ¢šfQ1kçë/Þ ¦GN 7Gøö¿’ kA°A Jk¥ÿ>œË¸Öz·­†D—·ÕX«<x1‡‚óˆÌ‡³#Ë>=˜Ä©ÁkP t71í}ÒeÏœbºg?w€V€=Xã2_©ïý´`é®bsÈy»Žrè%mƒ¤ ³KB L³k~¼ŠJ@0¼µÛ ¡µwü¹nÃFHíñë(ZhÎ XtîVþu’o‡îø³ê~ !³+Àh.jQE(8%‰ Z^¼½ë]¬ûK¨ÄÑ,7iÓÁÙPHæ+Õ#Ý%8*J_ �ÀŒb]˜bûŒcÝåvºï®røì\ꢅ–̡ۇ ±X5~fYÁüãè]l±K~¼J;Y‘‰sòJ(l€®N¿LÚ\Ž#” 2_!!O0)†ç‚/Ó]™|‘´=¹�×Í�L±Å£ëˆXóC¤ …×6–ëÇ!å$–ˆìæÃ€�€ Acƒþjø™•~€‹Ýy©¬x Òp¡ !ÖpÞº Y¨(Ä-f¤  ˆÅ ä(ØÖÿ¹€Põ^Q‘ÛÚíë·u1·¢ÛTC^H<’ Æ�\s8,£ìçn®€A[cµˆAî�+±KØiÉ>lveÚ yRÍôÍMØ®/Õ!䦲®NØ_×›£î¿ÿ"iQý²n4ͤb‘°ÀYL·ÙðÜÛÀó�ˆ3¯Á~Úô)˜ÏŸ¹LB4–˵ôO6ìu#ü’!<¦yu(ëùñ­=œ¸d32@×þúÌ+0×a¥†®ùð Á�©5BO>›1S�~aYíjÐs¡…çnOéHÖ\,—kÌëFØ m4.[É2BõŸâh(¤ºy›ØbvcE•û'žC ‚€nÕ¡å*ÊX̧B`3´5Nô—eLU×¶È·H˜.è‡#‘úô¢vi£d'(üx Ý.*z"šÅ:W@ë˜ö>A-È¢\#‘ï«)À­ÖÜ@6¢?cø׃õ½4”NO$ÏÎ(�ó@\5©l°Ã¹%96Û—rÛP}¦8ª¦Íµãæ²0‚ç-r0°ˆ¡¼n±ö¾ÊÝ Ÿ¯éÒ§º�5^ð ŒüÔ‚T³$_NšÍÝ¢É,»t›rçÏÈò·Y ™n²c.�žˆuÍ £g9²X +T“m�"�}ŽÓÅ’Ðcx ¡ªb I –Êzð§í¥l¯5ëqõ!zöær õ¨f±¾‰÷¿°…Š×‰¾ üZÓÕMOÏÃÐ_p6{ëý©Hƒcdþ˜+ù™…xµ¡F²S¸[A²—Êv”…B Íô³l?B+vUBU’zB󼽯l =¸ÿbpö¿Ñù·#óoï<~s}æU÷ßë][V¶(ó'mök^"Æ ïì±µVžë$ìÀXø™•ˆ¥øÛo¿ýïÒd,—S1m¤šÐnbŠ}„AJì£ÄЂмóòÅêDn£½PXÑŠÊ*‚‡Åî�º¶Bí™Ó²ÕﳤÅZ³^Ïø¿?}øíö6—‡Š)]»ýèÍ.sQ¾òyÜyeêå¹[+:¤ê„rÝ**ý¹Ò²ok°ƒ–.Pó<í|*¹9Õðk;”êx¬YÅ­îœAH›M„ˆ!‘ØË8™ŒŠŠUP{æt›¦²Þ•©—»|ìfîü#ŒŠä¶]*'m&vÎGº½?¯/CO³w×ûî?¸ÿbàþ‹¾‰çÙ{ëæÐ?§¯.µv{ qu $a¿�¡Bl_E‘�ÔvÄM(†„djz[èKt¹Šo‚óÇ.æÓé åË^ÈQ3Eň¸cá…HA0¾ˆ@8k—ÿ•‚)?XY»óöê^�=¯?xý×�åþÉù tµÐÈ3‘L$ìÀâ!0î¨ ê‚“¹ŠŒ¬m �Ì‚À¾bRÉ€DäóíiVıӂ`wxÎÙ9 YLòm/ݱ®B+*+B\ôbQê*ªƒ5Üà–¾Òî**�/ðß¼1SŸÌØ“wÇ/•“S{æTüwÝ¢ºE5K¤;ð­Óáá“�þß’¦G z"¡B8Od ²’))ØWýs}1>…r,³¿¥ °²aB²OF?ù¼âr3è|�Ìדð°ò¹óö*dŽÉáô±j´ Ç1”WPèªÓb/¤ÛEéŒ�§Ï˦{-ú1‘¡î¨¥ ˆâ� ”eÃ�n;qS6ûÛyïÇí¿ÿBXé)ˆ&"¯º_¤ RÔ-êÓÇ´ŸgÍÿí‚b±jâ�gþ½wÐ4æÅF¹,W"ˆZ±òCw à“¢l8a#~$oå_k˜q­þÃ( T/h„¶fÙõ™W�gž­1î~Ð-¦œ_ò¯›ÙbÎÅP.ÜÔ§W‰PwÈw‘F4‘}ô=Æ4å{æ4«nµ Ä�Go ô„øÖ+JD¿•@“(„ïÆ�?Ù”íïìtÜ|¼ PÉ®ø÷Bê )CåNã‰årñ�Ôäh¶£Û�ÓœýOå‰HˆöqWšv%Þg �øìBõÒø¿àí'�LâÄ1î{=¿š �‚øÄ»JœDÏÃmÿ/BÕv¼¢ çHOi¦Ô¸jçÕé—÷1ü?�jŒ{…ÄÚu›5À•~÷ñ×�eQó3?ˆ• r �•S‹°•.…·½9u�‚«n°žÍágºÅªžÆAZY5)ÚñŠl: „B\DÊfšQPL¿ZçñL�£GåÄ¡Øljˆ™Ñ,Ûúï@“Gk2vYÌùJõÔÕÅ$aÇ xw{š'Mx|ðR^(jÔÃso¸O·«~ }IF1ž)r¥�ò͆xw^ˆQ+_+±Ô6B„%:í}:Ô3ªZÅCh(¶ÀQ½7•õ‚õ#‘¹ó†Í°�“`’ åß>L#4Zú¦c¹œP¥Ó¶rÇ+rOôU\½ƒ�þÓ ˜«ªÙhvoPL·5ó$iÓÓW—‚-SÏ”?ëÇ4_‹B¢°€£,Ô”ˆår‰ì#(P#WÉÔ¦,ÄæV·Ù•©—Á>F;W5ËS-0Ö øN5Ú.εÊb™¡ »ö½Ï“YOÅ>ÇDa�s¥i”…š²�^Ä_Zœ ÉgŠÙ— P]œÅ²ždU?÷óéôÄ‘Î99ºE�;OÙÍ”?§l–@TñÙŽŸÅ@¬&Iy4'¸=�-N\û¹î½pk%Ø$B¸¬ª$bvì`� P'iƒÖeÀ·]ƒ‘iD÷¤³WÄÎÒDÎbñLñ˜y¨Å6›\'“Ê[ÎÔ²A“–wíA(:,ùJõhO)a2%"í�‚¸"�n±ôå…Iú±aÜÈü[áʪìZ:æ×ÐÒÉbg© ÒÿaøÅS‹à+&•6´¡Ä¿Ä΂]B°þª[ãÚôKÐ… L>”ŽÏûDÛ@A=¿‹UU ¦obfÊŸOô/h65î,iþ�{IÄÏ…¾¢ß¯Á'ü?ôD�‘DuKBîù›¡( m]S-¦øl%s°ä³ÞÙYÐî¾4þÜ�JÑ´÷éÔÕE�°jµ:ü¨£ïÀ`^ŸQjZ€0 a–VTÖ¹žFè¥ñ:˜õÔ1Æž¼Ól¦ZÌ×:ç�¤ £¢š^Â(ê6kí.]¯kõoÜýÐv©¬Y^,—³'iµÚˆóWv…^_^.‚OÏÕ*¨< ¥lo0ÿ_à™g[éñ@%;Ù7˜ç‚‹¢:aGºK—ÆÿÝ«Šø¶ÈWÀ¡ U/Í%¦æ¶z¦0”‰ÖFCd! rTíŸÁ‘ùw�§�mÑq{UÌÇ}·$DÁ\€0 1î(G/ ® ϽÙq²hÚûtýÁ«á�Ä~¹=å«vnO)!OÅþ*x| Ùt$®Ie¡æ…„¡u&®ÚQ‘ p9 ›¹çìBµïþó¤Å4+:‘Õ‚…0É®¨ +“6ëÈ­^�z9îÔÖÀ­ükÝ¢\“þy}q3ù ϽA£k­Ý¥/ö”®J¨Ñ:‡ÂbXŠöÉM‹XG!nùà4¾º²é¨È |júÛ¸•�ÊÂw$è{v*©À”a*v[ /�Æ8÷; í}å¤ímuT§g^í(6ūӯÛ{+:Œ•TPvmègÄ+°‹‹²Pó‚oe]Þ1qÕž’Ì­s!ìÔgKQ§¾.¨uê1„u›½äõN<ßg§6«“/4‹©È=bÚ.>J§'óvD§^ŠÄ…š¢G¦�‚b9jO)„S‹£OÞi0‹M-î [§“6L Õ×¹lÂýÐÖWælzbàv¹1S‹`ÅSPô„jjŽj4.î!›Nè#k`Uæ§Ëù�‡„˜j|apôNøÂàxPútúêbÒÇHCŠér¹×hŸÜÄÐ/,+ÛÊà!›µ5 ƒÓr”…~ UOáõ6¼$!Ö6ëï IÎfmÀƒC1•û{FY¨y¡vÁóq+›5v<­ö_(¨W|:‹Žc{Gì,=–Yå^Ðÿj€Ç®¨fí)�e¼ÿÊš 3K2rgˆ°¨¶Í¿:¶6 �ÊYkwI®A”‚ö *θ±³ð�žº¼ØH•³ÑF©œiüé)óQ�øñ}}­>A�Y5çk}!WÁô|h_G2:Ží±,•ˆ+¤§Ï¡øJ¢øÚŠÊ —éS3¥Ä©ÿ^(‚a†…6�Õ �Jµn…CýÞö � ïS“!†òq«ËÒC£~ïJfQ6¢uÒ”é{>n!m ‚Äqu›^�Þ ˆÓGN@{Cƒx/' Q ŽHM‰šNþªÅÐŽÁÜóDo ®ˆ³5WD-rEÜ#@H;:a^ �+¢í»+¢$ÈG8¢’5%ªA‹ü!ÂâÆ—O0]ó:§C‘Ct³!–ËI—ò¢­Y/ �N£Ñ.OD‘èkS"Íýè¡¿ÐQhÉ|ùª¦ñšLœß¿nó•ê©«‹IÂŽ“%9êÎï-}“±\.i±u�‹þåž{“´™N|<”Ù#+r†¡Ìtü ˆPwG+*ßÍ& 'ÖñÕ"9‰!Aé»ù°&[ ÿ£[ ¡êi܈áÛéR^6�?‚x||/RYC ¿NÖC׫Ux˜&º\Ɉ[Ma­ �úo”ê¶ãUÑÖîÒƒz“Akž°VTþ?�ì¥ö 0Ú 0t+ßègÇâ¯›Ë èVùu\ªV«�¹E~"cR¤ûÚlØhqî¬Ù 2°ÄÑlÖ1¸Ú˜å:8ûŸÊ"t\䎰'ÈÜœ+e³`‹ÒÛâÒø¿œŒìã.¥&Â1ë› jÏœŒ‹ rUƒ&Ì�Ïì  _Ýj„§çíGo4 bì2v/–u0 PîÍܲ;ÿmÜyô&Å)´>¾qX65oD%ªQ7«‰¹0áfÎïø31”—pA%ŽFØŽ õŠ[_ëàA99:—þEèmͲúêuì?ÆÝ0D}~É?ž—†<ÁãP¢NYSA&E®Šà&P!†òßû1•€~‹d:ºÅîßû±Jû&^€�•x¡¨)ö«ˆ¡¼BÀîpÜñåcúåxXù¬`‹U<óé½�h­.·rˆ²PÓF¦a¼Íýi7\2µ à0R× ¢™òç‹9�–QQÁŽJ¢õóëH�9HDˆæNûièÓí¢tÆGž—d:’ÉYüg"r}S@B?þ¸â/?ýyáÈ "W#uS‡™w´§¬Û^ åe\ÔÀ\T¯AÐ QE3Aî>Ùí¶ De¢Ÿ#ŽŸèvQ·Xà9g‡,d35SòUnH­I|€3ZüôRÜ|âßkE¨ $“‚«è‘íÎÉNåF02*êí\Ý«RÖµ¯þ¼¾Ü7ñ"_š*þG¦<Þ‡½ð.S8Ž% ƒ–+ ¡ÁE¶ ’YWÐꈶDU£ï@ÆN b­Y/ðœ³C²XÂb’á×g—NO¤:Ÿp~=(áÇÍ'ˆED§ûPƒwçî(·‡Î&Xàñš¶nÁj¿2ùb—›ÿ®ÛOEUAn[o…Á@€ýhOéÏËæð³ì½õþûÏÿ¢ïþóî{ëÆÐ?§¯-µv{ qu~”xö‰6Ø…ø¶¤› j³©Ðf!Ðòë#;v1ŸNOÝ×�)8ªD³C!F‚ûòr»G÷vTôRÍž{Òb©¬×ý÷¿ã?ó/㤰šß™Š)]»óøÍ.•Cò•ÏãÎû+S/Ïß\ÏPÌøw± ÎŒ/„ˆg&ºÜpžÈT’ªoŽ#]�5«(m±ÕS¸d�O/aÿ�°› ðIU«ÕáüÚ/ü5âjÄU‰“âr¬Ç{K]·ŸÜ18ûßðÜÛ‘ù··½¹öàU÷½õ3×–”­®‹ö¾”‹îÞeï®·f=݆É"0ã;³"£ˆwÿÛÿ.ƒLÁ¡«NO±�*ab$Þ§÷®‘¢Fù«,D#YªÐ"†ò T€´`ÒÎÜâ~ìZTâè–ÛFªJfQø›§²^*Ëÿä‡C¦çn®$m0@× í›¨�ÍÐ͇¯ï¯ð"RQ!E¡¨SÏ;ÕlˆårrÏc�аYëŽÌ¿ƒ©EÛÇ´FDy�ò j0ŒNöRGgö�"nÎCOŠ×™¿¥�ýªž4Ÿµ¡eî]œ$´e]Q>jï«Ü-ÔÆW¦KŸêÎ,¸1óêH·§YŒ¿©'¾ªi…ºE“Yv«áäǵ¯RYÏ×Ùi.²MSséôŒÚrØH«<´H˜1¬ÈÙõ?Èè6?¬!ªYàxÞ¹ã¥O\•‘qÛt”C,û wÞrÉèZà™gkÃÏDUÿ•ÃÓé‰äùi%3'8eR���Qè @\…†GÝÛ@!Õí𩚽»ÞÈ¥Þ°Jî ¶J`šÂtO]Y <ól�ýe° Ï”s@¾˜ÀÑ,v–¶tÒ•fȦ ‰¹éôÄÑ ³uÿý­=NÛ@A·™5ÀãøÆÌ+1Z)ý�“r€¡š|Jhà™g3fÊŸá¨~aYéj�H‚D(oƒ^M˙Ȥ,\à:B5Ö†ÊOÐuþý&Mfá ö×�å ÖüÀä �P¨À“Ã8: )æ?Ùp@R½;=^'-O3=ýÂrÃœÊ€¼oÿ•.pŸ D6ô]ë\U4´ª˜´µ§ä«ñOˆi6SHñp:w(vƒÆð³Àó�ˆs7WTLœFÞ„(ჵbºÿw(‹år�|õß󚜯�]Ép·é»îBÂ:…Øm1íÕ\Ì´C9.Â燽�LPÏ”?k ýXÔ¬Fó”¡øÀYö±\®¥o²Á¯aG@ …paÕ| b�À a}2uÑ«Ó/S\ÜOòÓú!œ��§ ã =~øqeòEÒö4°·kô¾T¤ N“t¥ìãHº3p$8Ex£°]¯¿˜ªl8:üàì�¯|áâq¤»$�fãalÔªØÑ±Û0�ÞıžpÚ”J|ç/ž¼zD‚H™Ñ %ºú/ »²á´f½ðÈ÷Ž?×m&áâ!l–)¨(¡‚FèûàGp+ÿZ礿 ø5Wç³C*wyä2"pÁá“íGÑ¢Ÿ…FhÒ¦ÖXC„~ÓÞ'•7ËZС3U”8CG³˜Üøb¾Rmï-ËØí¾ë£²ÙO‘0œx¦)Á P–&E.¨è‚×!ª¿Ã—‚ž…¼0"¶ÆÉ+‹v$ÜÜœŽD—›0¨d«‡‡+›_ž,ÚN*:À¨ÊзC÷_$mV­V‡fƒl”Ç3E•¯‰?‹%ó0žÐ‡b×$îeLÛЊ_ **dÊ@ÖØSôM2ÿN#L2œD—ª-¨ÒYÒ/, 1XQ¬úŠ>Ì„ mù„á¯ô%˜aÚ}/D ²Í8Ù_‘¹æ•oŸH§'Ž]œ=bTÞÕê¿ÿ¼.û–|TàN]^G6Í¢ p®ÿÛy˜ˆÁü¶®{tÚ ã&\�»ãqÝy”¶"nAG@ÁÌ'ÊØ6h˜†6 �»µ"zI¾Þ�_F,—K’ÉtzB³èñ¾Ê¸S�Ä‘¹·§®À–X%tdÞÇÑ}úñH¬ PÕ㈠ŒŠ�¹^ âšçÝ ™ß�슌= Sh�`7n‰6n1aëNÛ†0ï…ðÈšðþðõü2¤ËS±\N·Øé«K3%K7·ò¯[³Pº¸ã[æv�h÷ ïAñ’ÿ~%Äô½¡üZµZåú~ŽÞ9�Ëê ‰x’]QL·¦¬Â3˜¡øÏ+W¡Mïà‘0Ö…²÷Ö! …’M½°Þ¹d–�º²Ø€!‡þñç_”á±{eòE½~óíGo6zy4äsÕj•Ü]‰ek¥!^2 õ7$~þúØ㕆Ìh…¶GYèé/d¡X.÷¿K“ñ˜„={ìéíüó:޾Ä-8¹¨„¶õ–4Dåbnuë © Ë,_ùl�®A_�“ÅšBç9–…6™ 2©…!óÈ—¼Nà™g‹ b—nîÊtu¿/ ›.§½¯xÎù6ÈèNdšQPÌ¢*Úå=�c¹\¢Ë•‰'/ŽÊÕj5s{Iô­¦Íõ}ÎÊ�[®NØßÎûÆÜŠÁÙ×*¡›+äÏk‹û”�{ò®½¯Ó‰ãk¯iÔœD Í2ð"T²+A_ÔA©å�e{!Í7+̯^š0É®h„†‡Êºhdí§"Ð̇C¥«aW3 |\ #â&¹m«øŸc<ŠIªA•šÿ5ª¬Œ]͆‰ÄÓ®?xÕÖ[jë-Ùw×ToçòÔnÝu·ÆßÎûs7W4B5–vÙ»« Ÿý5êyÃ3fª¡¦q]÷ ¡i/ι¼òF“–«ãú+xìÉ®¨Ó-6ÖðÝŸ†9üŒ?¦wX```„ÖÚñŠÊ“�J˜f±”ÍÎß\¹<õâ^ñý¶ZÍLùóÐÜÛî»ë'úÊšÅ4TÙŽÁÊÐìúžNjéôDk県ݶKåí ¯N¿‡Jî®Ûó÷¿÷wA7{Xù|cæÕ™«K*aIBõ Ë™[+ók�s4~ µT3.wè°ûÙíÜΚö ìdrì&¨±)Fvû'žžv¶Å¹›+BùsÛ+˜¶c`ÕI¶ºÅÌ¡gw »Í¢cOÞ�¿›SØ Œ=�ï:á½0›NOpiè€É¿æÐ3áµ <B�÷•ÉèÚµ¯Æž¼w>L±�“ôãè“w·ò¯³w×O]YŸ²br¹³¤gÊ�”’öv;s‹âÌCùÿ¡ÇQ"úð™[‡{ãÂH¨\6þ24³¤`zúêRàig[üÞ_I˜,±% qâ-¸7* Oï_¸öàÕ¯µ¨FŸ¼û}`A·X•¡ˆ½‹!™jµŠo”ì¦C J9Sþ|¤§$!÷ˆá¥Ó ì(LyZ†Ê9¤ØzI›JüäFϘé¦�^Ï ÆßËq_W‡kÌ[k R€ïÔ¦¬% Œ £vÁcQÅËj})›Å-×['GÅ.©S�£[¬­·œËïW2_©fﮃ´,þéýæó*á¥|ôŸn1p.èò’�s ˜*Rݦï¹óù&t ÂÄ4H£ÖTƒP­V—^ñ!¢š*£p’ úºš¼Éè(„K€ã€óí¹£aÐ/,k†—´èÀýºM¡ì?¦K tV­Vo?ZS0Sø—H·Yk·wmúekéƒùÿ4„פòCoôž1Pçn»"ý�ßøùtµ�ë%\ØLDŠ Å $³6J!ñú�jÐ�]�#á€oZÏØŠbÂôKà_«Í¸ýèMÊöŒ›ÿ\{Õ†— ê£æÐ?3åúׄ‡æÞ‚ýf2f‰ï´&Õž9ÍrDg*𛳠Ëj1É4Á´�O5¶üZgn�ýº’áHܹ/èë /^ÿ‘LÑjdòNÕׯc(¿.Î `Mî2²w×UÛMY Uy‰Ã»ã§äðü[Í‚$£�uu„âœFh°~mÛ"_ù¬[LE±pBq M| •B:u,Ú Én°v‚DI»(QÐ×õ›xšd×eDÿXü›%âäåŠd:±ÞEݦéË ¨YÝyôF' 1¨ šæáVh¶Î~çíU¡ÐÚ D‹§¦i #ÖTC§¿¨VAÏÖ´+7Ô¼‹¡X=‰`¢8i±3Áo‡¦¼O*¦qj„s+ S£½>ó 8™’ÔŶ ìÄÎRÙ ©�ÇD\{ðŠ»†EYè7îÜçlô�7ëÕ�Ùˆ„ ÜФ¨Z[S�¶iOhµàU ÑÖ¬ç+C|7qyò4w,f7Hàk3ºï­k¤ ©óË÷:Þª_ÐFôBtq¯øFšJ×Wh¤6Ä(×ZÏÅ0”^,uã]5g%Éä3ó£ËaKA‚&oÒb(hŸôßûdìfî ý.„—“œë±YX�º@ô2„êÜbÞ@%�$Qª!†òdtgXøª; vTâ4Þd6ppµRžª¦�v;o-Þɇzf^·ÀX#4À‘˜Ñ'ïdäþu=0šÿ´÷éHOIæC쩇kÁ¹fÐÉù{ö…ˆ&q›ì[£ŽÜB �°°Ot/žêY9Õ³"sç_…0ÝÞ^<0ˆõ.Ƴ¥×L§°š"Aèº "2†ÈO•Ûë7aS'´5Ë‚=ŽÌ¿Õ¸S�έOt‹¦²Þµ¯O8;ÆÑOáý( mGÂ(j¯Çbq¡¹\Uår1vu»¤˜Lîl„xEƒ!a'n±Xo�á"c'�ÝÒ4VJ2¦™ÛKºåžè¯ø1œó½ž{»)^¡b÷êôË`¿Úxt-i�SX¼oRéyœ %á÷«,b™Ä!zÓªå›õ­‡”NOΨû&!O *H¸Ö+„INT”›­26òŽ�ºÕ !AÆð³­+äÜÍ€…×€¨Õ]R�Óšuc¹œ‚ݰGn†n1Ý.¶v=zá„ Dã=ùX.'6E›:pZ �çÑ>¡Zî`èðDän¤ G‚ú|ó±ZªÕª=I¹¨2={c¹1ÒC7ó¯•-:o—þžã?˜¯µ`ÐÂf�_Ï÷BF4�žh»1ʾëÉK[÷BöB‰.·¥£¹;Œ ¹Aóñ<Í*|I¤:æšzt3–Ë©¹=sm©º¦#óo9S”::rOC¢ºöÇÀ‚Š©ŠÜã¡l�m:ø´…Èç§�-n¹nÖŽfš!ÎeÜÒ r~y=�¿—Ú,´«˜0.» GÏÏ€%Ñ6Ph3 9�öÞò}?‹ÕãîÝb­Ý¥À¿ÔÛbèñn—줯„eª|[\›~™ÊzZ³é%µgN± 2)rÆOÉ®HB`Çûþ¡j­G+�EA)‹OFaªÛEnÁš.�þ|Ÿÿè¨YJ†ûÓØ99Žö”D³¡4$:9°(›îé«Ák íÆÐ?Ü®¥‰AAÈœ¯yJ�ZNÅ?ÆÃÚQjA,aº­æ"BUeÃ5CA|äÁÅàÀÎDi8ÅH„Å:Wë{:{ò.e{ ¢*aný�÷×¼’‘{úZèd"Žd½ôDB÷}iHÈêR¼ºò¥�&¦kdRPì'jÏ\°Ï€;aÂtÈmA¬Æ•ãõg˜Hìr4?}äC Ñ„éÄ: :ßõßÿÝõo£oâ9hûÀgÍŽv{�£wŒ‡œ·~r Œ6%#óou®c¶£@„ÝCCTET:»‹Aµ³Q"cJI¸(™NÂp†_; „ª›!þ%�ž8r~6Ù1›4Ó‰gŠú’|,Þå¶tºM]Zßb…„á(àVì$mïXOéÊÔË_(š{{òòBÒ¦ààÃéÏ�·ƒákì&2wž¶÷…®f%Æ4p {£Y‹U[N¬'άȸȓ�³Ù´•L7a9‹�3%¥«Rín0¼¾0ÛÞå‰t-ÂëbGïšO§'øðÏFVäŠU�¢ÅrQ•8 +jAeŠ¢§#óowÙÒâN¯O]YÔ1“ ÜÏhL|,Ö;|k~Çè¾»®rLJ#Ý¥P .N{Ÿ4B㙢lÒÕè Žm?�ã˜Áô Ë0hº_ØèP †W ÆËJ8ûß„ûas�4Sþ<á~zü¦wâù_7–5òìÐEù#¨rÃýÔmp´¹õ0xE‘oc’~„”»±?Õ¹,{w=I ¬ÏÌ‚d©¦«¤d<áÞ“�˜r-ÇͤÄÿ'ì^@ñ¦’²�¶ iï‰ /é@‡‹mH´Õ‘R³I¥âØ%!· ­í� ïGèÐÖÐ�Q±Ë­`WÚšõÀ‚oT PÐ`·¡• ÆâVA%®„ -æSÂ$øDxC~J)þrŒÞ±nc…�(îû¨¦"W‹ºc�Nvøp²{„w© ‡˜Ð"ßÜ)ý Dé[Ifëð¤8jmýGÓÝ2Ámtw^À‡-«pŸáYÈ• —‹ƒ¹Â B#T�ÐYÚöŸ'mÚ,”¯TÛûÊ›Å{t-ðKÑ‘[M¦°q èc?Ô_N¼ÞÆ'vj9¤–Ij2k ,oÂÙíK˜N-·’á:‘‚¸uÈjI+r´è”]ÄÎR?ýɤ }7_e¥÷3åÏddýXwéXOX6Bw`–’�öi^pËdk´j,@7ÃfW¦&Ñÿ8zþþWFî½âûÀ¯d’}lÍzœ4T |Ž%B] wz X€<‹ ³ˆ‘Vv£!ô^ÈXX;;F÷½u¹h$`¡³|¥ vÏ6k#KQÅ B„z�ïQÙÉØ.ÿ Èèš‚¡Æ¬ƒmæÎSAó?EÖƒþÜ"D88�Í¢�UÛk˜COeÓÑ J {v¡ŠFžéÜ#»¯DMÛê(q7i‡È“ñÛH_Y”°“ìš× ¤�GF×t ¸Ò ï°ý¡EˆpУÔ8¼ŒÑÙð‡Mt¹²Y”°ÓÚí5Ò¡õaåó…[+º ‚Šªu D"D„‡¦JظFZýßÎ{ðGÃÆ¢.,¹õòBcÎ�“ôãï š ÷'IèAÕmˆ!p´¢²F` øBn%ðœómôŽ?OÙLøŸ&~_�Å@êùÌÕ%¿Ñõ¯Àå³jµziìidv!‚¯PmPãÔ ž{xÚÙm½`þ¹ò§]'ÿ( Êã}•ûÔ—ÍÛ}úñìõe °N×àÒðìz˜mì"D8P{æºî,(Ämï­„ÊíD_ ãškâR¿HP‰]¯«OÙ”÷É~nh67ªîre#ªEGˆÐ Í‚Qʲþm¤¯,ÊÈ�wÒXì«Ý$ LU¨sé+‹£óûÝÂýí¼‡üà ÔLI6X¢«¹½!"Dh:T«Õž±>;ÄwEq}æUÒb±\®¥oòÛ V z­"TåIô�þ…ë3¯öZ,ºÏ>^žz‘X„´F@BELCžš9°æÅ"„ r¸ô" 1ú$¶¿ûq!›IˆI—f¿']cÌhíJ’�›äêé+‹—Æÿ©¥�ŒKfÊŸGæß]™zi=kë-)„êY�=‰¡¼„ŠŠ ‰¨á7>B„_ ‘D¨NØàl`‰èaåóï :¦]ƒKú‰Ïè< µv¼¢Z S,aG%,e{\Ï”$[³ìH¶¤ÛLåò¶\FÀãÞE„ªÇð’„ ñ-šK"DÂb Ĉ»×>_©ž»¹¬[Ð"™Ýc ÄŠí'ŠUTáxÅÛ‹õ.&»æeâ�æL¦ë]”-¦»ÇÑr=‹è"„ .‚Ò¾¥ZãÎÓºX~ì~)Ȇʰ=´ºŸy¬wQ"TQDGAL"^ܪÄzëy§"DˆàTƒI„ƲРoï«4Fy^Ì*ë¼KÞìöå"DØ?bYj߃݈L�P<²V_OÆmq+ÿèZ˜V«U{x5JA"Díû¡ÙµÎÜb¢ËfÝ÷þ­{.šp?€E¦v»—F¢Yå"|�D—«˜àž •"Û¥¯‘gw u8£M¸2wžòD`ŒjˆI8Ò“�!ÂÎP  vj˜B¿É†6ÓñÞr÷ßÿŽÌíÖ–q3Ĭ੫‹*X„€j‡j²$ò"Æh„~ HA–+Ÿ_KqÓ©9 Yôôµ%<²vuúåÐã7ãÎûiï“cžö>M²�c…w·ò¯{Çÿ½pkåØ%ÌŬ ´±à/‰®h !B„=è¥ík‰3+|,ÐÕmÐS1°ºR6wfäCGÜœ‘ a`urj ¤0ùÜ’d{q»µÎ#D¨#þ?Ø„Í. endstream endobj 126 0 obj <> stream xœí]y\TUû¿0 n¤¥©™KP¦ae†¹o½ánZ&¦å«id½ù+Óê-—̬,ôµ,KS´Ì´ sÍ5-wEÅ\Á�Pfæ.³ÁÜßg�e–sžsï93ß?páÞsŸsž{Ïò,߇ãTG£a³¶§æKE²UÈLZ6áq�ú�¨†Whú~—a1ÊeL⎑µý-×?οi,’Ýa4ñ·lÿ´ý]´z~,âœêï€2îÙ(z'D]o‹x[#hoó5þ.Ì ö·˜·/îÜÇ£Æß¹(ï¬åoAoW´Í²`(@–͇«U@Ýy–dYÚáy" oùhópæ‚ß.èŠ3•NDñ•ï¾cøò¿MV‘7ÖÂŒ­3z†ø§Uí �e±{ù{Cb“,Æò�Í(îæ¿ÎTEÔÏÆ�‚Š¡-{ÉC&ç™<\a2-ˆôk—ª‚vã-·À¿Vzk×+Þ¾«´â^ÿv« a hr"»x1š.úøx¬Ò¼šþîZÕ@øM¨dcç�¡ß—‰ýݹ*�x¬ÇZŽã‚7 otˆs‚üݽÀG-ð$Ër>Çq‹_€ ¶jk ¯�hÀܘ‚£Y6_hìï:Î(@6 ¾Û€y©íjCw1°Q¸-†eòwØ÷Y/ÞéïN4†I4P” Ô•Tífö�Ùž\’£êÕ•æÂ|÷2�±�H@ˆCüÝÍÆi¢!-ž!ò×l™ø[+Æ�¬èa9K¤(¤EŒ;éu[¶‹ŽŽéÝö^—ͤ�I–ùG=¼eÜò6Ùn¿yqÅØ–%ÿÉF²ø£NzÃ]½_Ÿ›x캅מJNÞµ799åºEHß¿ò„SºYHù¿L©ÜÊ$�ï²á`£û¯,:éuzÏØrÍppÉ{ÏwjZÁoQ7¢×Ø?œÒ�ý¿ö´·kýJn›>/.„㖲р,5§ÜEÏî8óˆppî3÷y» d¯Õzrü’sÆ-ï§'FÇcž-üÙ¸7ÍÃiÆ=—ÁêæÛ¤MŸýÙ¹ÿBøë4®×ÿ®ØåÙ>¡³ Ô[ãÕŠ_(Œ|Ì“‹ ©~O6•Îù@ûotISZnŠŽ¿z~zSÕyRïë-§�hÀ ÿdþ1Õ»æu^MNŸáuêñŽN‹ol¬nTÚˆ�» ú TôÓ ‚oÀ:UÕ~ùÄ=sòÖõ#Ç:ãŽ]|M½˜¨ÐUHÛ³„ge.Ý È;Uë-n|¥(N ÇFÝÔºêÈvãì 6 ñ/u$˜…䢳ÒgÐÍCk±w³Bí×Ä+òzÀ ™l¸^_1ÁÕx‚Í��jÝ(Ý©¤÷Ôÿå¡©râÀ<ØRŠ�,5 ¬I:u‡¦j,ºð8­¶GëǒܦтFÇÜô4ŽëÝ¡¿§¤ýíp P<‘5=ü{}z­?˜²¤ü®Q0s�a`­í;'¾]iû#Á!Ò•¦ ²¦Q ޼cýApÌSPlx ¿à‚?Aª@(Kf OCRKŸ+@ÿœ¡´š.AЬ+Ð�ܨÅ3Źîßô½ˆýÊ=a7,飸 T01«­¦Ë—ÓvÃïÐñ±8?ã;|Ü'TØ÷êØô¼ÊcRŠ©—¨}\åÑ_÷/ÈåuÁs„PlKïzÒ›-Õf¬ôç¹LJ©àï¥2JÕé¡põH°Û¥ TÃC´ïåVîèhÐ3„Á\�˜�wfæ‰&í¡…CU æ�ó7³¸à޹ƒð/^ U€lSz¯fø©òz ÞŒsÛl„êÍ[6<±AºÅ˜Sd°œ£ÈâRŠg¨Ñ ÚçâÛüà†3Û;ån�œ§Ëf£"£~†§ázßðçp\*¹!LÂlåN�·Ø&'ôÐá.Ç áé…•|ˆã7\·›M&³ýò×}¼Lábۨ풇^4þGá.~„¶™² $ê’°Öýîp'¢ã÷f‚¼ÛÇcZ`^8[„ŠVÑŽ¹í0®R+eYαԽ@�0‹@  J6S ÁcK™­ÀrL†óÎÙâ Œ §"y‚Üñ)‰Dß+ö‰ãIžëDíSIo%Æç¦Ç‰Âé$i6#-°¨`�èÁÇ­XEx£48Êçf¼Œq!�ø1íº#tµï¯€G»ßÄ×0žãމû‰çè!=ÆêC �‚' š"z�v1åMÅðäˆÃ •÷ ¡ÀŠñï´î§ÁCLÄy$m“<“CYÄ3£Âöá8ê¸ ?ìñú¡«"/y jSðMÇì3Wž‹Læ´�ZsÜËXÙâEWÀþËøßÈÅUŒzéȳqW¸W«H¦¦¯ï6˜ ^à Ö›I _t�Ub¾ âRàóÚå0ˆ=òŽ'µ¨ã|=p$ƒc¥b±v:vÂóCcž(ó.Ãöÿ·=*äÄhÅâ*Â_¢®¸Õ€ñY rF`g};NƒìÿÝNAZîÊFË@#ÒÍ4²MÆßðÿMã<Öé§nxéâ•é<«:ÖS�²€ø@N|?|NAZ‚�¾ˆ¸8 ñÝí‘àCˆ£Ž »Ýèì;(H D×LoÒxi�#™†� öa·»�ì­2Ö¾ãû÷�WÆ`! :oÆõµtÓ„O©�(béìX ¤4Dü¶%þƒÙî_ãhH Ç*”Iq)¶ ZU\¶•q ¤Y>†×l—+©ü ±„¥`: Tl\÷@flxïÁº×iHK‚õ(I¥c© Ð@'�|Ô2bÀªï¡§òÁ’ [Š‹¢qÆk(i)ñC =âå9‡Ž¸$8‚ä­ª»‹»‚Ö+u¨YÞ…n4´a“E<ŒÝâõWšž“I¾˜vfW^¡Ï™Èt¹'5ñàáiÈ6¿6Z¨§â£V¾ÖŠN¿ð†£d‘Ñ{$®]HF¯¬Oœ+�Gµù sVÝOMd8¾ñâÃq=’*G§É÷ѤìETƒmCŒB%¯ÊIÔÍÙ±“4¥¢Ã÷ÿ _á‰ÉÆ,šJ? «Ád×o…€v„–ð8 u*M•eû›”á²_L´Þó«g•æ›ôɲ?'|>yèC,*”DÀÙ¬Å{P�Öº¾¿+Ùñ1§òÎl¨÷ ~ [¾É»á³�ˆäVj© 0òÞö—*þ{¼/[˜YËÔ­Q¾£y'^c‰Aæåÿõ´ocd‘‘iA HvA1 ‘;³M#ÙÈŽ�eo”ûÇèãiT ö€5pÕd Ãt < ßZö÷ðt®0/xœÃpÕd·ãlDàNc™¥öW[$¯ ùÚ@¹�È ¡÷�1"ìqöV&í ¬ý·#ç.f²]jÀ„ò}s›cÙHÁâI%Á¥‘°b¶Ÿ<ˆHn}–˜�Xò—8Üî ß°’M“Ë*OG5Ø<‡�à D•œ4ø{?A%64z‚VóLT{ƒ˜Ñe"›÷‡‚¥õÌÇ *��“ÐÔylĆáïâSÖAÈËö+áB�àûŠ‹v ›ûé%&R±ÒºÑä»±’®ÞEìC�ˆf¥>Ôƒ‰Ð@ÌšíüùÈL'BÎ#êÅ4ÐY·¢»îŸ ŒýÉùsD²Ì³³N„¡]Õ.Ñs5-f-F¯ƒ.Ù`pœ`'`ð_%ŒK!`¯G"·«~AD†ÓYM¡ça)+ÊÐé:r&¾Ài3¨Ž1êŠǽ õÚþÇRÆ:Ë$ßôîâ:œä��ÛÈJs-Ž[¥4“sÙ ùðÏ ¯% ø+tŒòT7*ÈjÆqG¡ �ML+’8׫ÞËwP$NÆkbâ·´…$CJ˜ñÍùÚ±í²ÖìéˆÌcuO Ðò¢©Ó›q7À�ýñE7xW+U\”müYü ±÷?£+!¾s8,“ ¸lùG܈7¶ß4\N|Á`KÿRaaæG#ÆÎ}hfÕÑÀýoí*(Ó€6BÕÈ ˜…üöÑð½ ±ò,tn8ö,450g¡E‡yR•X‰»­ó¼Ÿn‹Ù@ ®Ä)ÓšìFÙÖÇsra¤š¼îFßÅkb"3ï çÚVù™°«LV ŸÈƃ­L½Mh«Ä«Ä ¶? Õ"°Ì ,'¡.–¹ít>Ê@X8êH$Öiv.N3ÇY,`„>€ÎròZ\sþÜ Ó€€•7ª jnSÍCSËL/çJºqþ|æ¥d~Y^Ê\õk7«€Ñ?;6¥KˆÌòPê_RÓS„Y„“ïìGÍß³®ÆQü #Zåç3‘ˆâ\<�[ ![è°Ñéþ§Öò€ãÅÌ@µØ µhAF- D7¥F(!üÂæÔb¹’Qãé}Yl¡uéYsóMc½$þPÓPÐM¦%Oððü†Ò¿õÇËàÈà $‹ë6¤¨ ±°Œnîgœ)�k VxSªÉé<}²ó­¿ÖÍFïHŒ~^ð_p&²lbïÃlD œ/G;ˆdyuð½ÊF!›µ–±ÙññôîòÿˆÈè60( Y†<°ÐÝÛ‡±‘‹Þ®ðÏ—|²\}Àk;@…ÕàMäRÁi•¢�†xgö6*¯€ˆtºhf�²Ì<åvˆ‰Öyî¸EúU„Ã?öÐú©:wy<–ãÛ[„f­ôÒ¨Š¢žFˆË�g‚½¯úþ=¼2(�íÐ*@eP‘eóü긧@ÕqgÿJAZµˆ¿TˆnÜå¹ñF=Ó©É­ÿJÀ® Kê K}F±¸ŠðÕrÄUÒ•Ñ'5{s¯I*0ð"_PP ÙÎ/ã2 5ÄL¯¿>¯gV}Œ«¨¡cnCÄ/�6æ–¾ÜR…Mfí'Q7kS\t üðïP/!MÔNE §á/�·†Œ8’âᣞ‡Ù*ž¶gàeë\„õV‹Ñ6„x°äÒܲwÝœ¢åÔš?£,™H­óÛ~h@ºB5�LdÍÐ5¾O¼¹)_!zò´ýXyàê£e.† ‡@öi$Ò„lEÆçŠˆ£‰€å˜qGÐzœ$d•Ñ௻ôÆ…S øn>&‘h%4@Ú âX’çr®4ÁHo%ÆNçú†“@°r Mãúõ›QA¨À#ºÎW©ŠóÎðÖ'0.ì/ËYäÁÖÒ82ò^‡Uüº{^~/2LÎúç0-ðå4ˆ:d9 Ç.Ø»/VšŽï�Û”c—x^´_ù¦ŸÈìM¯]ò·$&€lîxõãâLÝ%ýa¼ò¼Y` XË;=/–½ßEÆü™ž w±ø>‡ã²PiE6 3•—Fþ4™iFA»Ü~¸—®k l7ª~Dª3;g™ë¼§€TÎÆïüÌxJ5%ƒ¾§ù ¹½ËŠw„ƒ7¼µ²à/åRO�”¡váyØG`X{'ÆùªŒ%¾ÖKïø–XbtqÔÚv"lɸ%VãÕ0ß{Ç©ëÈ+ ßUVt:)Z�]I1‚¥Ù‘�$ÇŽ^ ›Í�sx³Š-µØ�U¼Ù’e�êCS†º‰Ç©%ëÌy‡ìì¾à®7Ù±}êÅîÁžpO´l§wô†´YÄFͯµ¤ù›� yDøVfÁÙ3�!Ëb´Ð ðð鵸¡§DŸ]CÐ{XÑŽ¬r09ò¸d#å°°Ïsdž|yýôÃê5Y{^²j²/| Ô|ïÖÍD¦?úà¸Ç’3²œ§Zí NûIÙi/h­b–'ƒ¸x0o„b„¸ÒFTbÒ‹Ú‘ÚW±@;¨¨àš¦I»E \ëkœ‘j´Ôl±~’ ‡íÃ*ßÄèÀ�ëH°’óÔÂÿ4æ']Sñ®«É‚üxuì·¡+‘n3|µÐ „»AeÍéªÚmÌž¡høÚ,½ñ…zSæ4ÄW Tv^aÀô#�ðò…ÕAÔ²‹H“t56çÎDÅ…‚ÐKçëü*N‚ÓÐȲ•`b[y¥ÉÌŒcvò³2“âÔ>:Þ±Úk�ÚB!¶=<²E–%‚o [ån¡Ü­aó‹ ŠçæS’t_=BC˜^‚kù3÷s“,<²þ XãiôÌ7Â_ÜdÜýꄦqyïB{}v2/!†!nßýf7ËŸ7^Ãq  �äŸçu›¦Ûðv¯q¡û­ÖãOÏþËtlvº|ÄñZ©ìKp˜ÌÉc]T™Ø(À¾†jï|¢Ùȯ�‹—×}<®÷}•R‘k¶°Á)ÝÕÙý™„½4yéñ«l·ßHIݬä?ϲрD…¼š6#>üq_†Ýp9i×ÎÄÄÄu»vŸÌÍv¤ÊìKV\éÙh@ ”rnõZuŽéû\LLûΩ©µI–y*«/.N�hÐ,‘Ϭì‘k™2±ºa=‘€ùµ���Ù`³� ˆKA@ÒôÀÁ³Ð‚~.-P0,;QQéîÔÉ‹°OrÖóG™X8M¢Ãà†¸ÇbÛÆAþUq$¦9scn0žU[J¡ï«â¨E¢§·å[¿P #NíHtC âÇ •þ¿Ö€ÉåÂý ñˆZœ¼Ãjp£ÁóPv ãäû^=.b‰yÃÎàÚ ôðJoí|Ù›ö¬Ò÷Dè¨w–Ž‘^fäÕ¼¡÷äd3¿ –.p[â�«R¬�Q¦žd©PæÀf·Ž¨áýaÕð„N€¥@p«{>li²Ñf6ñ¢­0}ãû]«�èÊãZ褭ž7˜µF¶jZ›¹à·ÊÂ3Iû«78”PÎL$l«V5�7¡ ±æTŸqi¢ño’ÏF1—?u5Êã¡�n¬·`?®¶²1@«¹7Œž¶EFñË,R~{"8f±Öb(? Faëˆê�&S4öá–szÉ.[øŒCKã �Ú/�Šÿ~'X» endstream endobj 127 0 obj <> stream xœíÝùsÕ¹7ðùgB*?¦xIE’R¥ˆ�–ÙdæÙ`Â%` ±soÂ5qÞ!–¦÷™‘,›�r“°H½Œdcc›ÕÌblp°%YÒô9=¶æ½,&a7 7§Ï¨§5Z<š¥×ç[O©@cI3Ýg>sÎéåD£H�¹%•þõo‰D4�¬>fÜ~'�G£Q^3úýÎßîÚxû·ŸÄÙ²aî;îD}}º(½øH¡£££«««nĺS=œŠ�¡/Çgç  j¯ÉbÚ&_<ó™ ̈ÎʈÑëh��ð„Ø•a¨`SÏ{öMjQ¿Šþ`,cFôìh ƒª½&ß,!Ž+Î#6>;ŽAj‰Î²:ËZ‚�ÏÎ5±»¶ïU,�¯Á1¨Ë×™“g©`CwÞi!Vå+ƒc�êÁ8Ž|¥©çŽÓfÓÄnúéV±€¥Q,�¯‚cP+ÖÄ›gǦÈ0¿Ü¸ÑŽØøìÜKSŸñšÁÊ:« ŒŽA*YR°f!‹Å¤Q,0§!ƒZ¾&ß<7/k�%íˆYŽe�Ç óYN°&"‰D8 ñæU ŽA-Y“'Ïé¼ ÷÷ëf7,‰,‰WN}.¨Ä1VAìjÁ{⧬ Xs‹D"D0 ‹C,¯¿pý]å�"‚ ",Ãèýý´Á,‡ØøìÜÑéÏÍ`G'ƒc¡NE0A<óìë‹›Js‹D"bÁ4Rà”UD0Q¢}0K°•³;ÆÊ(#ƒcaÌekb‘HÄDŒŒ+Å‚ñÊ 8öZN°Ë"f9–‘™ÇB–Zkbåq¥Š {Mþã<%ÂËV V b¦c_PÇXs*nà=ñS,ÁðŠ‚µ1ÒSÀ±°LÈš‚qº9“_•Z³ãTL«®÷ÄO± 6µ¢`-E  y™‚I+V;bã³s/Ï|!ÊŽ1²QGs…ø%ž>�ak¬ÕˆYŽñ5p,DE“VêƒÑÔŽ˜å#œb€cAM±¯¯˜ÉûúPm‚9€™3'ùYA,$eöÁD�çI-/Øj£ŽIóŽq 8´,ì™c5¶ ‹D"¬Š8Ç4ã8ï"е@0ž_¹a¬1Ë1N1x TêÌ1Ĩc¼Šx šqtús×ßkP­¨U VbvÇÈü˜ ×%!d¬.ÁœDŒŒ+DKÐŒ—Á±ÀÕj«±Ê¸RÕIîwáóX}0¼zÁF¬ì˜ŠÈuâàX°ª|>Øjk±ñÙ¹Wf¾ ä~œ‚8¸NÜ·Y8“¿jÁœG¬|�¸Šsžÿè8„¢‚!–]•` "f9Æ)à˜_3ÃqE–- vèåúš�óˆ‘ó.LÄÀ±`ÔÄ©w�”E‡8±ìªZBƒˆÇŠæy°ŠÎ›GŽVÙ„!n†Æñ3׈`n!Fã52®Ç|]T°AÐqÜj›Aãˆ�ÏνVüR*ôÈ×Wú$ÍÌEÄæï?Žù¸&N½£‹D°¢ ÎBm )ˆÇtâ'#^Áà˜÷cìLc‚¹‹uL(àìX ó]Ñ>XQ묉ˆQÇÄÑ8æý4W0׋D"Ù±’4jPÇ^Ç|R´F3«î½ßDÄ8׉{5Ø<ôÓDÁ¼€uL,|óGMZ}°Æk:bóãÊg^®ËÀ1oó<â☠�9x´Y;Ý ˆ‘óÇ %^#’šñÒpÌ»Eâ¨7,X++;6Zâ ˜/€cJ‹óbæ} Z¤?Žy²,Á�(â†kb Ó F…ë+ÝOëóbÔ1A5Dúc^¬IsÌÜ$ÁZ‡u,;ZbTƒÇÜêïG,×"Á¼†YgD1ÈýÇ XÐŒ&?sý� E‹ V$烉F½Ç"§uˆÙ£3ÍzÎ�U‘µXòµ5‚y1s~ sfÉܬqó@Mž¾@+ b±y‚µ1Ë1:M÷íq>6Á²-Ì›ˆ™÷í!‡ÈÉÕâÐs»¨`˜ãt^h®` 6>;w })JíáÃuIÆÁ<‹½ß¹¡º¹„%8æVY}0�ðê¯*ºl@Œ:föÇ�¹’ 8æDÈ<ÃPÁ¦µP0/#fžÏop fG� G&À1§‹&åt^jú(ÒŠ3ˆU9ÆjàXkc †DiêàK­Þ¹^FŒŒ+çW±çU|s°&O_@Ù’òº˜Õy©Eû×1ÄÆgç^G—rc%VC|kaÌûˆQÇÈ*ö 8æ\Ñ>’òÈüÚº�ë$b Ó຤–ÄyÁ|�X$É(æ*ö¦cG&>uý=좂•òyÚkéžu1â¾”›¿. kj\Ì/ˆQÇX™÷"ÇZXt&_çy$I¥|ks1»c‚†9kNÈÑŽs^0!FÆ•²N‹SðsŸ¸þ~^™‚Ià nuw™®;® FË�•8÷þ'³~ã-©TÊ�¼tÍghóf�œF(`Aœ>à¨`þBÌî Ž5»&ÞšE�3IJƊ+Þ61n!6>;w_ºõžßm¸õîT*O$œlÆ�‰…ØwÝå–`¾CŒ:ÆÈzf¤È*èÙSı{·÷¿�`€Y=} m¹gköŽ;ˆ` ƒ3Çö¦‹ˆ‘ÆÿÜéX,‹—‹F£ô-éØË÷uâñ8Ýw±Xìî¾›öä‹îìG¿!FæÇFŠ´XýI}uÃÆMÙÝs�?Ö¾#§ÿë¾ßÇcñîXìȶmOÝ{¯“‚¹ŽØøìÜÝ[ÿ;j V{¢Ñh<ïêêŠF£¿ÜxãÚA·v¢‹D"wlºó¾¡Í÷ ­ßtG4ÝxÓ-o�»äº >ªGGÿò?·ÅãIúæ½-•úå† G¶msx?ºŽØÈ¾£‰D’v'èû«%ííí|kÞ¸é'Ò®¿º²}ŠXOO�}F£Ñ]Q]—Á/uêÜWù½½÷Nºé’ñxggçúDÂá�èÄHglËob±XïÖ~NF[3�ܵ}—óÛÁwID£ííít<™L$¶ü×}�}ÂÝ–ìSÄz{{7lØÐÖÖF‘$Ö¥bñø®¿»6*÷]‘«Š8þðöíÑh´££ÃÁ<‚Ø©ó_?<|€¯Ì�•À±ebÞ‘‰×û³ÃÓ\oÉþEÌÊW\ñ®ºª{ýÆ›ïùÝ]Ûxî4œwqùš¿€x³ìÃ÷ÜC{bõ5€ÆãÄìuÂ Ž ´?çó/Š%$·ŽE..¿#Fsó=¿û%ó(#? Ž­X“ãï’»�³,bÙÝw–§ÅÜÚq^Cl|vî ã«üÞ³¢Š%Íà|~[f2™"Ç—Ûÿ‚ë{ʪ` ‰D¹ÈȨØàÁ±åkâ4LgIJ˜eÝÞi^DŒ:6¸÷¬ `Ѽ”ÛÉ!‚±ìL&ƒEo $Ä"‘Hÿ°‘ÁàØrEû`:Ãè,«;uNþÊñ&b–cœéúq¥%òž`CŒ:ÆÈ˜¬ Ž-,"˜ zJ0/#f9Æ«˜¬ìbÇ<.Xð#ãJÕ`Õ²cÏœÇæ¨`º÷ó8bÔ±ê˜fð¡\gd�`{Ÿu}�,YÁC «ªÉÉ÷Šb–ðÅržÌûˆ•ÛsŽW ±P árŒÆx]° "FcÜ/ã�;69ùž.ÁН{`&¿*ÞGl|vîÍqL(Òhˆ³Â8åaÁŒ™“qFµc¤&åHÌ“‚ù1êØàeÇø8æ#Á‚�X•cOŸúØõ­íd‘>X6çÙ>�_³ã †tÇf2™Ö7‚1ê##v *~êÿr}ƒ;Sæ(2‡XVç½+˜¿[è˜Á‚y¼²DÎ!äf2]”|!X#÷QFÜHÙ±C'ƒï˜ÙË#s‰<,˜ï#óüeÇp +1ŒÁrÄ11;½ç×·v�Ĩc¬ŒúU²^R°ûcÁx¯ æGÄìŽI£† Ç1Ÿ ÄȸRE¬Œ¹aƒôÇêØää{d�5ŽÓyÁû‚ù1êØÎ'Î ÎűŠ`‚Ï b‘H„6¸‘À:VîƒqâÄqnoìšâSÄÆgçNžýzè‰ó‚Fúc~WúZ°°!FceœQ1¯Aš3û`ùrÌ'‚ù1˱ò¸Ò·Žù]°"FÖ!'óʱ‰3ï£\ñ<ü$˜ß«ôÇ æ¸Ò‡Žátg2æ<˜äSÁ‰X•c}îØÄ™÷õl¾(Šº("GV¼mbüŽqì\Ù1r¬æ§óÇp:�úúÈW? ZĨc¬‚9ùÚ1Ò3+ŠRQÝÞ¨«N+;¶ï<¯™×%ùÄ1b׎²`S~,̈‘ù1Ñò©ceÁxÞDÌ‚±²cûÏ š‘õƒcÁizìi×·^ƒfÄ8¦Þô“cÁ±è·Q¤•À æ#Ç*£È@ˆQÇXe†u^3úÄ1*æyÝÏ‚ ±*Ǽ¹ÎHE0) Á1šÌ°ÎŒÇÍ8àùq¥%DìgÁ‚‡Xùxåþ󢊕/ÿpnnÎím\I Ĭd†uNA¼ªóª±ïÄ?]ß/Ë=©“g|/X £Ží2›››;sþc�8f ¦‹ÒÌžàˆÙc f:¦yÔ1ó|°]tQÔÁí Ö„1Ë1¡@›<ç¾c «ŠÝ±ýÇ?r}ïØ‹Ž"MÁ¤``ÄÊŽ=yž£ý1W ¶`€ØâðªÎɈyóÞwÂ+Ž•çÁ†¬¹Á‚�˜å¯¹éØÁÆžr}›´¢±ÅaÇìöŽcÁ8{l¥�lĨc»ç+ú8�vÔ1rgò lÁ±åÂ<Žõiäþcî:FfòsÁ, ˆ�Ïνuî›?x[ÔŒtz®/çœcæÚ ùhÁ±Ò§¡Œj:¦à}.Í�ML}€²¹  ĪÛ‘u±ðˆ­»cO¼î´cSèRg2ˆã)Xx³T'³ 6tÁ±Ë¦OCŒ‚XYçTcïëÛ/¤&e1ËÁ2·7C«Īkݸ2l‚bµ„•uV.;öÄq'³ Æc?Üeºî„ 1êØƒÞ–F[åXÄjŒå«{ZÜ �`!DŒ8vž8&šïXE0!D‚bµÇÖísŒÌƒ‰Ys&Ÿ ¼`áDlÞ±YêØŽ&9ZÁ±U…•ufDï{¼È)xìXó#}0QÂæê¥A�ɯJ8³Êý±Otl�`…C®¿:‡ [Uú/öÇX�¾úAwD 3b•þ˜VJ§çþü±,×éXÈÄêHÅ1k¯¼ß”½01}es:=ÁBŽ˜å¯²<7°§Ÿ~µp�`Ê~×_‘+ˆÕ‘¾Ç‹Œ\ä´VÆÊË�:f ¦ó¼‚y0{BŽXÙ±ƒ³‚JÛqðµU96“N3LùŒÖ° ˆÕN›á�—1« ùè{uoÿÉé‹E1NÁ1ZvÇúÕêØL:=³£o&�ÖùP ˆ5^6K’ÉU–#/ÖãØÄôE]"‚¹0 ˆYEµZÁìˆ5’Šc2zì…ÿ]Õ–/ Æ0tNÃí—âN1«N½ýÍŸžz‡:¶cEÇ.‚Á° ˜U€Xƒ!‚ £þÇ#ë�ù5nö‚…i&¿*€˜½N½ýÍC‡ÞVtì‚ œÄ ‚  YŒ ÖxúCý�ëÔ±G_Þ±‰©‹ä [\ı§ÊŽõŒ »`€Ø’EU£Ê1l¹ÄšÓ1:®Ä?uaé ~æC$Š ˜@lɲ;&ªo<øàñŠ`V]€XCG”B¡ÈÈèO‡Þ©ÚÔ“SyÁŒÁh±åêÔÛßüù©wÄ‚ñàƒÇÅG§Æ:DA°% kn„B‘S‹Ô±?š­lê©uŽG, ‚Ùˆ­Päxå¡YVÁŒ¬³#úñÁÿÁ–,@¬é!‚í'_Éݯá�‚1.ä©`(¬gS,@låzàÀÛŒŒhå•éÓç¿qý)y°±V¤Ï[éçŸgTi���ïýÃ^¬*€ØÊ•+YMˆWñq|Éõ§äÁÄZ‘ûÿ†Ìë+‘½²�M¸ý¼<@låúã¡Y«ý ÊgNŸûÚõ§äÁÄZ‘ß?t!�žËŒèV ÜõÈ›ûþ0ª;TÔ@l…"÷äò<« F! éäàgþ.�ŸǪ kzú4Ô÷×Ù> ±#ävÖäÓ¾³gèýZÃt¯°Zˆ-WöÕÃ}~V}pÿétIRño 8VU€XsÃ<Ž32Yå�•Ñߟ¯œõ:‰>.ßó0dw [9€Ø’EãT"Ø™sÏÍÍ�N§'ûúÀ±% kbȺáÈy³2’_®¾¯Åú„¬ŽÙˆ-.»`“¦`t[Ù›y« Ö¬ðªÎŽ”+,wÇWô Y—®è G*±EEÛ^(T FŽ-Y€XS«:¹G¢ª32}íÃ6øúDÏæÉŠl¼Žbö¢‚‰ty¾Z0Ë1rö>8f Öx*‚�à=5¬‚DÆ•ùAp ³×ɳ_í?/h†üâ…£ã.)�Í1è�Íb�'3¬³²)˜‚÷ÿ¨ÆÍNúcù�Ä1AÄçö‹p-€­“çÊ‚eGK‚f\v»�cöÄIfXÏŒèıÕF‹860„9‰áu «C0û¸²ø¨fDZºÃ™g±Î öÏ:6>WRǤp:ˆQÁxÕ�V#Í‚ù±;ˆÕNF´Xï;Q�`´HlpWÙ1žwûe9��#FÛwž×ˆ`¼º:Áh*ŽIáu «#–`œ‚¼Y¿`´&Ð'ÅÁݘçÉYd‚àö‹s4aFŒÌä?AΦ ‚­²f8ˆ­6•¬mD{òd£‚Ñ"ý±�»± „ͱÐ"F 8;jÜàf\àØ#¡s [U2*Î(8£bVÆO6ܳ—å˜.åt^tû…:”p"FãMÁĆ£ ³c€Xí!}0*˜‚4©f¯ ýãâÎÝ:/†Ç±"öFé«�Oœ4,�|“£9�NOñüÌà`ØÄj 7l°2ŒSðÁ¦öÁì5¡¬ÇŠáp,lˆ½QújpoY0Ak¦`43ƒƒ3ùüÌà ÓñJ@¬–pÃ7‚ÉW8ù¯–î³?öé�esºpÇB…ì‰s|¡U‚ÑÌ Cæ vٰÈ�ì`‹£eöÇÐÅà;ÄÞ¤‚©Xlö(rqÂæ ¶rLÁ;LŽEú‡‚ÑZà˜ ¹½Z•� V¬`ÁÔÖ F³À±Ç´`;ˆ­�Š`*>è `´ˆc;w낤góºLÇ€˜M°_¨ÿ|°Õ&<ŽbË¥_&烱Ãd•™CŽŒ"W¹?&Iz.˜Ž1*˜P0ÏÉwP0"X6w.›Å¢`DZ%Ó/㌌ûeÌ«ø™SŸ¸¸ƒ*ŽeóÁW±7Œ¯öœ£W Ž Fs.›-IRÙ±Gƒé ¶8 {ËMÁhUÆ•�;ï"Àˆ•S Qk誢ÆSíØÛA[�« £Œâ!ÁhÇw‘ó.Ä@9TĈ`{Ï’c‘šÁ+n FlÇ1{Õ`Ų§â§]E.®ŠcRåúÊ@"ö†ñÕàÞ³œb æÈ±ÈZbs,0Ç1+ýÃ#Áx?ë1ÁhQǹ¾2 Ž1»`œâÁhÎe³gYn6�˜c€Mÿ°‘Áýæ`§½(-Ë1$e‘ÿσ bo_å÷ž<)Íl:}®¯�:6=¼'Žb Ó<-­‰â?ÑÀɸ²èóù± !FU,i†àIÁh‚ç ÆÈEFF~Œu¬Hæùý=® b'ŒKù±³‚†¤=3¶\lŽIEy¯ß 9bŒ\d�‘‹‚f<çÁh™Ží$ócbq~u,ˆÇD0ÑLÐ�Ûµ¦ɱ0#–‘ FA~ŒÖDñŸúÀâ$H>u,ˆÇ—r{Ê‚‰>Œ&0Ž…1S0##¼?£Eúcù�eÇ|¸Îˆß#‚��5Ïh5ü%�ݱ™¿:NÄX¥È*Èï‚Ñš˜ùåÏ뢤ûm~Ì׈Ñ>+‚ê‰3ZëK !b¬Rä�UŠŒÖÄÌGúÀN]|·ž¸£}0V6xÕ`e¿ Fc9FÖ¯ô¡caC,3BfòY…̃žøÔõí߬¢ý1²~¥¯ó)båQ¤Šÿ FãkÇB…Xf¤ÈÈzf$h‚Ñ"Žå}昣‚q ¼tUQãñ¯cáAŒ•u6¸‚Ñ"ãJ_9æ;Ä^Ç—²c%VżWÏÉo$–cÈWŽ…1VÖ9±²ÎkÆáÉ` F‹8VW ÞwÌ_ˆQÁ8"fÔ³Ç�Ž…1Ò3‚.-Ó±_8æ#ÄÊ}0 ñæ*�m\™›‘÷yß±À#–Q;ß;ÐQäâª8Æ ˆeÝÞ ËÆ/ˆ½Ž.å¨`Ìúð|°ÕÆt¬Ÿ8&d½ïX°Ë(ˆQPFAB˜£EËæË"ŽG ãö®X:¾@,l‚ÑÇö‚ xß±#F*¢‚©Æ‘‰Ï\ßÔÎ9^)åÃè^uÌûˆC_fGK¼Š-D‚Ñ\„ó‚è}Ç‚ŠL& ®ñ§`´Ìq¥wó8bT0N1ój¸£©8&y×±@"–‘qY0¿p&¼‚Ñš˜ù¨˜õ¨c^FìúR,ÁxÕà|{UQãñ¾cÁCŒ“I,#c^ÁʵÀ1/Íó{±×t:Š »`4ÇD/:0Är q2Y³ûÈ$V)kžßSŽy1*Ym�œ“vÁh8¦ì÷”cABŒ1�EÇl‰"ŽI9O9æAÄ,Á8Í`@0[ªs{OYåwÄÒóaGÈ<£�>Ø Ø2E²ˆe‹ 3Õ×çÖ^³â5Ä^�ù\-qrU¶8 æÇæ;åöªâ¾F,‹mÚ´)�NoÝžceÌŽ�S©_šúÜõ÷‚—kbê"â…©¾¾ûo»í¶nH¥R®ì;ï öêäÛûr7ýt+¯a¾€¹B�ÏÉo$ λ0»w{ÿÑñÿuqßù±h4Jÿú–ûÿXl»|�ž|ïg7ܰeãÆT*•L$b±X<wkºŽØá7ÏßϦÖ÷D£Ñ[ï¹kzˆ×@°•bwì蟽éæ[wðC.îAÿ"ÖÑÑÑe&�þö¡×8½p«µî»ï÷ÑhôúD"�ÆãqêX2™tx'º‹Ø¾#§·¥Ùz6Òç�\·>�NoùMÚá�àÇüñ®»¤Ÿÿüg==½=ÿ›o¹ý„îÚýEý‹Xgg'ýëÑhtãí[ö{Ûu|T'ô�×­»Þ2$‹%“Içûcî"¦:¶-Í®»>EŸCWW×�7‘Ù ‡7‚cm1kŠ;ÿâVcö)b���Q[n¼é'»ÿ¢¹Žƒ�ê~&O7]w<ÞÕÕåÊ Òõáäkú—¿¸ÿ¡˜¹R©T"‘px ø4T0û{ðÆõëO–¾pe'ú±x2ÕÑÑ5»a±xbëo¶�>}ÂuüU/�z7õë±ØØ¯­3Ìß·lÙµy³ÃûÑ]Ä^+~) VEÖÓp÷0‡¿ÒÙÙÙ5Ÿd,–ˆÅvÿn‡+ûÑ�ˆeFôÛ¶dR=?‰'º·Þûû/O¹‚OkÛýÜÿÍä&¦/¢lNgY�çugÏs±WŠ_äî¬ú–Ì#Ñh´½½½³³ÓÉ׌�>|4ú‰ÄæžžÁÍ›]9Ìwˆñ ¹GkfD¿sÛÀ¡×ßqÝ_×3ÇðÓ¯é伋é‹(—7tï£èb¯Ì|!ˆ`œ‚6ÿvW§™öövÇ^xÀ²¹§çá{î!íG�¦wÌ_ˆñŠÎ«ˆWt¡`…óÁšZÓõÜ€nÞŸßpÊ1W£‚Ñ;–sŠîÌ+ |ˆ`Wv¬pÈÉê#Ä•´:¬uEËæ}­�YOÜyÄ^žùB*¤-©ä~¿¼Æðd�ccO9¶Oý‚¹¦[AŒª ªñò4Öªš˜ú€\'ÎóX”J¢ØêÝê0bT0N183*Öü¸â˜/£‚q2Á¨‰©Pv $ŠXÊb)×Ò=ë$b–`pw�–ÆyǼ�¹¦› ¦GA0GŠ8–ÀRåô�¡Öí\Ç+�"e³‚µ8ÇD'ó8b¬Š8•Ü›BÐŒWŠîœJ΢ŽéCz~'ÜÕ¢ýë b/Ï|!Ì ÆÈ ˜qÒ1/#Fî' bVE¢f¼2‚9]d~,7ˆw¡Á!4´»»ØĨ`œJî‚9Çó,bD0³@0‹ôÇòƒhh7Ú¹ =Ðô½ÜjÄŽN›g´š‚{Å[oÆîØLËó&b‚‚s±x±‚¹\¤?6°=€v¡|“Ç•-EŒ –‘É�~A0·â€cDŒ &( ˜WŠ8–߉ò»ôüPskbG§?§‚‘Õ“å0®¶æ�Á2 N§[ä˜×4ó`Mœy¿޵1*]{óBp:�úúÊŽíyº¹»ÛSˆ j‰ ¦ ˜k�cÍ™çob–`œ¹öhSž'¤ñ´Î1ï FS A-‰ãU8›Â“Uvl`·žßÕÇšŽØ‹SŸ ª‘QtVÁ<—9æÄ@0¿Tsk.b/M}ÆkD02Wv{2–cHÊN�5Ç1/ &�¨áyÁ¾tý} µrUÒ:Ÿ¿‰ˆQÁX™ôÁ@0/§éŽ¹Ž˜P@bI¤@0ߔ騠>8DξØY÷Þob/žùLÐ fDge¸7…Ò\ÇÜELT1éƒÇ@0Ÿu ìD¹”¨¯41»`Ìæ�T#׉7䘋ˆ‰"˜¨biÔx óaÇLÁô\åóu´�ÆÁü"ØŽ&8æbü(G±XÁü]eÇòy”Ë¡lvµÍ AĨ`ýæL>æÇT¥©=ÏÔ× \AŒÅÂ(æGqv¬t �`þ®‰3ï›#ʬ.åtauŽ5‚Ø‹gÈL>#E|ߦ2®¥éºs1Ñ<— RÑþ˜.duquŽÕ�Ø ó‚±ŠÎÈÅ:Z/Ä;Áé4ÎdJ SŸc#F5#;Vz]Á‚S¤?–%Ž!1‹%©ÆöPbD0 TJ c°qLÈ®Ö1'ãUÂÔ¢ŽaIÒ%©XÛýùë@ì…I"XÿˆÁÈ RêvÌ1Äx•\É« X�krò=”ÍE±(ÖäØj³ËÈäk�âåÔç˜3ˆ vÁÐ%×ßkP­+Ë1]ÑåÖ_bT0FÁŒŒA° ¦â˜X«c &j%‘Ü` KQÇYOœ_Ù±Ú;<ñ)§ÁX3 Üá0ȱ;6µ÷Ù˶�V#F+”D­‚…ª&'ßÓMÇЊŽÕˆ,#¾@°0„Ær3™ ÄË:ÖRÄÈ5ÝZY°c XÈÊì�åHŒãu†Y²…Ô‚˜]°Œ ‚…%3™L‘akq¬uˆ±ZIÐJ‚ ‚…·ÌþXNgâØRý±Ë"vxâSó.ÓÂÔèX‹ãLî‹}°ÐWÙ1–-.åØÊˆ'‚qØ•qV[ e,ÇÈuIË8Ö Äˆ`*æ ó`PÔ±¢”Óé¸r¡c+ öü¼`Ü憡ÞÇØ²cÓK9ÖtÄX²Ôš‚AÙ‹ôǤlyõ.ÛüØrˆQÁ2*9 ‚A8¶ÿ…ªÖÒ\Ärs0ƒUqnìì ƒªTÙ1†!”Í;¶$b–`ŒŠ3°^$ÄÌ Ž51Á\ëVÐp~ÏÙãÆW®¿k ¼V“ãïê‚hwl1bÏ�Êk˜3W¼Á ö,çX³ã@0¨jrüâ˱*Ä,Á8…,¸Ö‚÷Äß©8&Tk b7ýt+™ƒÕðu¹š8]î�!ŽÛ²q£…Øs㟀`�ˆ8ÆñEA Ž=ùb³»{û¼bä÷œ=‚AÕP“ãï"QÂ,»kófŠØó¦`̰~Ƕ¡ ·þ¢Y>¿Ø¸qçæÍ–cMALPA0¨Õ�Ã,KëlüÞ�‡Ü~s@|–¿nÝZÄ—~¬AĺS=ý��~iââñâ¿  VQ/�ŸÚ±#�&¯_‹Å£Èê³qݺ?oýUƒˆ%’×Çb±D¢{ݺë×­»¾»{]¢»;‘èN&»»»×AA-Wñx"‹¥‰xr],žtûÝñ_’ñø]7nÞ°áW›6Õ�X4�Fcñx2‘HÒ–™ì^—Hv'’1p j¹J&»ñD2ïŽÇëh{�@ �@ ·ÒÑÑÑÙÙÙÕÕ�FëXÝŠ5QÙÈ/�¸›T*•L&ãñÊaVÚ0`·B\Ïâc"]óéìì4�n�V�Fü þˆ»‰Çã©TjqS¡×åÅáøĽXŸ§U�ÓþQ�F‰DÝÂþ››úÜ!Î%�¶··Ûw%ýTŠF£ñxÜÞ£¬%‰d2™J¥Vû‡è§'ý­zÈ󪫮úÎw¾cÈê%vvv¶··×ÿ:!> ítU‘e5QúM:”°~„¶1ÚP«Zi*•ê&çÑ•CµÿÎx<~óÍ7÷öö¦Ói7^.¤Î´›±·{ߌ"f`Æb1Úl(e–xÖ™ý;]‹b è§'5*6ŸîîîH$rå•WÚ›V2™ŒÅbíííô O ,<±kkk[»vmWW—ÕVéCTžd2iorÔ±T*•H$¬OáoûÛßÿþ÷é7é£ö)«¥ý»§ÓéM›6AÇÌG±#FõÄú¼³>õì:YŸ€Ö?¶#f}g¹OÒD"A©¤Výf«XõMÚ†;;;]Þd§bG¬­­íÚk¯moo�ÅbÖ÷«RÕfb±XggçÚµk¯¸âŠª�×Å?XõhGGÇš5kÜÞ�šbGŒ~„-n!öýkýcÚ%»þúëkAŒþ7½fÙj3´Koÿ+‰D¬»»ÛúÁd2i‡‚qexbGlÍš5ííímmmV«X’#úAlýƒµk×F£Ñk®¹ÆÞ»»»(W}gÍš5×]w�ÛRS'—ìwÙ[ˆÕ~z{{»»»kAÌþéiïÚYý´üà±…±BUYJÇ•în4ˆ3±÷ä­É.Ë¢%K§Ó===V¶æÍªè³�2–|hÉÉ[ˆ7³¸'fß¹‹9¢s¡V ±é/\®'Võ³Öߢߧ~+ÖŒG¡Öº´µ Žf¹ac[[Û’ˆuuuõôô¤ÓiÚ¥·Ú°}8Põ'ì •¬··^—^7duY<'Vuðºj/W!fQsõÕWW=Z5'FÜú�Ý¢ÿìG?úÑ•W^iVöVW:ë–‚8«µÐS[ÛÚÚÚÛÛ¯»î::´\1Ú̺»»«f*ªÚ°ûÏF"zðÝþ± ñ~ª†“ÿþ–Õ!·ŠÙ»[W_}µÕ´R©”ÕCûÖ·¾E�U5ªË"ÖÛÛûïPû³ZN0ú}8{-$±Ï‰]{íµ?þñ�ÛÚÚèC‹³7³”úMû Ôú¨µbÿqz¸ó]ωÑ9ýï5kÖØ‡uV3 ÿ›N§o¸ákxHçµì=ù•ûáhýfkêÞbjÉY‹%?L!AMÕÑIûCµ#ÖÑÑAЇ¬�àÅG31Ÿæºë®[²gn5ûÔº½;‹Å6mÚtË-·TõÛí Ü.‰Ø5×\C[£ý4 Ë.ûd¬uJ ªØ[»v­ý¡Å|ٛdž ¬öCG öIÇ‹g\é8ÔB Zš_²víÚ5kÖ,櫪 d�QõoèÙƒ2UÝ'ûì½…˜õÐw¿ûÝï}ï{‹�Ñ¿E§5ÏëBÓ O¬½ŸJ¥ªŽV5Tûôl$¹é¦›z{{ì.nçV£¢íjݺu´A†äãòÿÍyz¶ endstream endobj 128 0 obj <> stream xœíÝ{”Uõuð ÊÁ03Í⡆è‚�º*(y¡  **ˆ!Š †VëøŠÖÖR‹FcSc+ÍÃ,°6�.Ål騨?çRVñc�u…(;l”Q•c,h­ ¹¯´Ìì· \Ÿ�®ÁFɕ߭¿%Q.ÇTüY`m²\ÆT*Xк:ľÒr\%€Ö$Éåø+âª[“â2óÐ1• –$¹ØÇß§TÝn­ ©¯´Tª²$Ç¥Bj~“—*•`øD2\*U öw ¡¯´Ì¨RQ`��'Á¥Põ¥ö·±w©QQaI‚KµJ Ú×÷•–Z%¸.îï+kTêYâíR§¢Æw—Z´¯ì+-3:kUY`uœ]êTÜX0½X_i™Ñ9T7XEX_—Býç+®÷˯ê+-õ{0 –øº\ÞÅ»ß3–.gº©¨³ÀÕñü^¬ðQ—±zÜ×^/ÐWZά?® K<]\U¼Xо�½¯´x¨è°ÀÊø¹Ü?Wñ¼¿//-–ø¹x¨x³ÄËÅSE�®Š—‹—Š ÚûJËô}^*š,°õ÷bþÏ´ï õ•–iûê?3®Ž \”ãj°Q‚¾;QØF„.Óö©²ÀEÙ"O‡M2p]ÐðT¶bÝiÜWZTLY`If„£Ã& TQb‰ÊEEŘ–¤é6IðsE‘­»ŒúJ‹’Š9 ,î‹äB‹¼ÊwòŠÛŠÀEM…À‹{ûi6H1§tÆ—êæì»µûJËÔ=jû ,>ÒCi±AÒ}jç­*opä7¿¯ÙXóÌÿš² ‰.ìù_ó$¥z–·Æ6¶œ§Õ\ó|çwg«ªÐXàÂÃßï…rf¸øIÅqim7ý“eÍ5ÎŒC˜W~•Dc� ÃØsÔ¤ÇÚÉŸS–Ö–�þ,”WÊßÒ�eKi¾Ý%‹Ø–j ´¶<¼Q½·æ™Ü«3&Ë„{¶|æÆk¿«Ü½MÛŸVÞ°y¾QÔÙÝwb0nõ+Æá¥Ð×ÖùAåQin<—©ýJïWÆBe€;ä]ûÖ€Ægñº›·Ðùƒ ¢üʸX˜‘vJ¯Ñ‘vëA­íëFW……Îv9Ú¿Vo@ú%r­WA+S:t??davÑV1`ÁÜg4k¨G_…‰Ît)ftULX0÷�nŨp±º³Ú*F,hɸ˜¨°±È¹d ®â2«d?¬_)0F*|,° _ÄÅDÅ�í¿1¨åŸ)»�¾-äc‘qÉ]ñhZÍâv1Tád‘p1S1fAësFõ¼bªÂÊó¹�/–áUu„Šœ.Æ*¼,Ü.Æ×:jZ_0¬YŸæ7�ÏBáe�s9÷cæW Rª²¹T¸Y`^› áz:ZÝ¿7®[Š ; Ÿ åª`Zå‡ I…Ÿæò¸�®Õ&ÖÎ}‘P{44[õl ×P«ç¾D©î¨ì¢�s*ÀÂá’§]L-Oui"ªˆ°@+Õ…¨BgÁÜ— åÉ*2,ÐÚK:K)ÿGÄúĦ8±¾j\�®"Ä­G.ds)˜sÄøúº Z_3ªÝôÃ&R,0Çt?Æ ÂÂÖ× J³¨È±Àl3—<Ç �Á’Ë8ÝÊM;Y.Öc�Ù&Çž™?8:ãÄz\Ó…IE’fë_˜æcai�럴\¸TDY`V·æÊÃq8YÐzBÃ…ME–fuk�yË¥ÂÈ¢ãÒô:Ûô²,ÐÒ¥á’ãRádÁÜ“ãÕŠ6ò©H³@K§ò„JY6VUNqhéTm–q¶B¾þ8É=¥àª"Ï3(]¿Ÿ½…±&cƒPÍ…W%˜y@á2>Vn´ÿ%À¥qïd^!°ÀÌ�*eXUØYÐþޝ ·J(,0sÀ|™[y òöƒ\ØUÂa�û|]ú™UXÐþWO~•�X`ƾ´çŠin ´ŸöpP ‹f¼Óí1‚â‘ÛØ«±·É‰ýƒ“Üj5î˜ê6,8sÏ×H¨È° ýÓëK5þNbBÕÐX`ú›»]êíPbqs™,¢" Lßµ³®üHJBEŠíÿ¨qR “¦¿ñJMõ‘”Ì|Ä"­rbU»H©„ÊÓv¾PU\JEŽ­U¸LzYj¢îPY`ÚÎ_VÔ>,5w·P³°ÚEN%d˜öú³ÇN¸ê›Q]ª[N¬—]UÂf�i¯ÿ¨|â…uHnž{±váq—Ií‚K „ÍSwl)}a™:(¸ú€\¿œØ?� ¬> LÝñÏyÄŽý’sÜ 6ÌI!�ÙÍv6…kÂg�©o÷Ø'ºò€dÇÊ‘�*–“!b‡d…0XdË gõ—NÉ a°ÈÎgËøýˆ¸W²‚4‹u õâ/E'´�€¥eßÁ�η$g»f)�Ñ×ð¬äÊá³´ìy*�Øß!é"ذcç%‹º„Î2kÏ— çßt‘ëWÅÙâ ÏÊíÇÂf™õN{¹òÐ~9±vU][!è2Ëìƒo+=rPl–[©nÕ\‰Ô°UÊ%\–Ù�µ‹]R.Bͪ»ž²ágB.¡²Ì>Xó½ña!™^¹\å*å&ËœZÄ^™ã‹H«\¯ oø¹ÈÒ¨!²Ìét9÷%-â"Ñ)Dë1—R2.á±´:â6€ŒÄlÝ�òœo¤á.¡±´vy¬+#1[7Ÿ|fç‘p ‹¥µ«Ïóïå¾°·ÉwŽ1—�Xæv{Ÿƒ,àÂÝ¥€™ßø]Âa™Û�õý›¹÷cÌM œ¿òn—PXæ¸îˆÛ…·GˆvÐì•§<Çë˼Tà˜m^Ö)ÍÁËì˼”ÂÙ¼.œRœ™×Eže~¯Ò9"¬.Œ Ržß�ÕEœe~ŸâüZãë1¾þh̺Ïé"Í2?­<»ˆÍçÂÖ­µCNý›‹0Ë‚^�9_ø\¸º£¹Ÿ‹,Ë‚>­ÅØ\˜š£½.›‹(Ë‚´æÒˆÕí?'Uº‹ËäH�¡ÕfP˜¸�âÂÏrÏéŸÖÝ„1�*ÛF¨|<$v– ¹NÊÍ\(umÊÿ‡ÊP\¸YØTH.„ªÖŸW­ Á…™e1ç…kæ.æ5­»LkºÄÜ…—e1ïeYÓW´î4¬èž‰/ÎuÁÊÂú\q’1t1­Ç¬0ñ%3N–%ü—àô›õɰ» À$3F–%´O\ÜÓ÷)“¡˜Õ²%æ¡1sác¹Èü3c¿¤M\Œ*Ù23i¹°±\dö­— \Lê䥿73qáb¹8#67��‹AûFí*ª1˜މ岬àŒAií}¾~ A–e­ótÓ«ë¢]ATÅÀ……eY¿¨ Sš.º˜V!õŽ® ™e<Àå½"צWd¸Sïø¢¹ù¾5ü¼¢9;/•eÅf¸¼Wrf­Ñ¤qšF4·þ¸Æ¦M3ée�õD¨,ÿùʪŸ«UÙrûŸœ¡<*½mïW\ï“–E:Ÿ�YÞ×�ƒ/ë¶Ø(YÄ®-󇥵åâFõÞšçñ”Θˆ,ÿ¦Û]ã f¿ý>ÅailwhpGƒzs Yñc[}–^KKsò–ÑX=ê+%¨oÕ^ÿÌ#ê­¥eñ³EÕÑi,?/»LÛ¬›k¤Wu å�æ×ÁªÉ�%fQ—âë1ËrÙ·+õI+º¨n/¿N««ô¨®ïFa¹*¬ý×ñdÔöcŠ[Ë_¯ÙUzWC$°D ‚˜SrQÛ–}­vWéQs1g¹Vú­½{ò*ŸÃ(mɾƠ«ô(¹³¬ŽF± ðÍ®Êv"RQs1e‰Lq ø<%…­Ø3ì*= .†,×Eq\Ë`à9ÂÁÛˆP ñõ 3–�G÷\q2tOÀø·`¯"t•ž@#–OD«‚8ð1VÐã­hU‚]LX"WAò?¯/àÑÖÕÄ®ÒàbÀ²&zÄ!ßïÅü€&_}–X¨¸ø>ÒZÉÐUzšüÖâÓf¹^ta?�ø¹ø=.&*þ.º,ë㢂8äý~ßçQù«˜ºJ��‹&KŒTü\¼#€¦7¼f&Ôc‰•Š�‹ç#ò+»J�§‹Ë'㥂8äñý‹×ý­KY»J�—‹ËÍqSAºÕu¤÷Ž� @Ó.W –[uNt +ƒmnCu¿o U¼\ÔYb©‚8x³ËX]ïi]"ÐUz\]”Yn‹ßl47ÕÖí~öR‘®Òãæ¢Ê[Ä�úóº]î[€æzE–Ûã«‚X¨s©¿�_€æ7k]ÔXb­‚X¨=ã¾îÖG»JO�‹ËñVAÌo¨píïc®Rï¢Â{•:—šßZî*=5. ,ŸŠ¿Šs.qå�k~•Z—`–;“ RãRý›‹Cè*=SvW¸²$DѪp©¼=!*Õ.A,w%E1wü<ïÊ[…ÔUz*\Xþ29*ˆ¹cgzWÜö¡ÐºJÏ”Ž1–{“¤Rárü–$©T¸ø²$L1Svûwv•ž1?–¿ŠÇ9.:ɬ-�¼ü¯Ä©sñaÙ”<•1—Ò�ÅìBï*=£.Þ,‰TÁ�ôÚ2K2U¦ìôaÙå9ù„Í®-±$U`êžAO–ûù\)ÅZŽÊû#è(O¦îô`¹?¹*ˆ™5ˆ¹¥ÍÉÍœ½W–®ƒQ·–’m)ìÉô%9ýV‹ KK®ß*ò–e瓘læ°À®åDNäDNäDNäDN$Áii{·ëí7�úPTrZGGGÇo¿{QÔãÊ}Î_÷ý•Å÷ºÞ¡@[5O*“ñ§mmì‰ãùä ÙŒw´Ýÿn€Ù÷6ºÞ!¶,Ÿs.ÔÎ?Uú×­§Ößeæôòïn=}\釩­!NGÊf|ÀäÃ/»¡ù¬“F8éì³FYÞóÞP&WÕÊ( ¤¶8+4¿Š˜ä$€²Îm_ßða\ýbû,ÇbË0âÞsÎÙ†8ü­S¢¹RJ,ð_ý£;±Ôß}cÓÎäDã6õŽ.dSøÌG±çʨÇY›Éø…ææÙ�]0­gLJμïèÃÕ,�7·\–úw€†×RkÏ8û–?€ÓSÿó�©«Ó�E=r¥”XNîØYfI{ÞÜ­™ßx¨øèœÓ—¯(¤¿ÒzÎó©IQ´&“KŸ¯•¦—¹·xŽ3‹mvB‹³DøÃÀ:,_Rþh3Ü3˜ˆ§Ëf\´ðò-øÙ2ËkãÎÅåИ²|‡Â6gaD\ñ8k3_¸péÃ#÷<µÛ¹a=ήbqÎ?Û€ÍðM{ô¸ÛßjkkkÛŒª³5GšÍÎwRû:¹Ìòg!3lƒKpìRìÂßþÿ_: ×F<ÎÚ”�-ÿ8ÐÏlw~ºW±œÎ3e <½·üˆ·»¶–ò‡Q[5›qz³st)³8 x;\ƒcß–^‰½oˆv˜u)³|Ï…8àüô'ØœgÆ÷ªX¾48aôÛ¶G;b­ŒòëX.ÄÕå;ÄšeüóÓà6g‡5î¹®ñ°ÆÙC5õT±\�·Œ>bÓˆê¬æ1ˆË»z¶–wɱeyáóŸÿò|`â®ÔÍËŸÆûÚ¯]ÿêž*–q?zdÙªÇÞ§ýöÈÆKW=ø«¨G®¸¡ø“Õ—m¼'¶,“ÚÛÛÛŸùfé×éO¤_+ü.x1ÿÖ ›¾°°}.\ÙÞ ÐðàÛC]?lhÜÜ1Üý<ÿ╹»½¼´ÀÅígluæ5šÐîìÀVl³³¿Yð‚séccûr΢ÿ—¥# endstream endobj 129 0 obj <> stream xœí�ooÔFÆßß§Ø×•êì{mKQ$BÔT"µo¤ª@¡ õãW¾KÈ™Þïn{¹; ¡#ïÌŽwwžyfv¯Š©_þqÞy÷sµöß¶�îÅ›ÅûÅЛƻû\umã>¼\üö“{»x¿HUˆÍòÙ»O/Þ,‚þ>}äV>¼^œú¾tëv˯rè³[ÿ÷é#÷ÿÞéu~½8yö÷ó·§§'^|üôü¯ë—ÿ~t§W—WWÑÇ‹3wvæ%O®j¢»~µ+‹—ÛP娷.öîúÍâÔ{_Ÿ¹ë?—�WƒºþÃ�zŸV?l«Æ7]ÓןêÆûúÜûº_þÂ5~Vc,äòzŽþ­U[Ÿv 4Þ‡‡Ò1tUôM·ËÈMò¾~p S¬Bßù¼ËŽÙûÐÎÐñ‹ea_•~ùáé#·ú0eö‡Ú…T¥¸Ú$ÆË  Ã[×§* ò­Â+øt³ú>wu¸[ÉCC¼ÚÜ�bOÜÞÐUM —rW •�4ÀHD�´Š¨�L’phö ÕVúÙˆ$œg 4$”�Zqš]îêfCÝñDÌñNF¤†u[5¹Ý,c½!žSW X+z‚…_BÊ-ƒõ†TÓÈIFližLꎄ_QWH+o±•í}ÔÔp¥Žc4¯ÐV8¯ô®Lfgá½eä&#Žæ®Íìô¢lë£kãf#šl…Z%Ü2jŽsWÞȈÝÊèÌ‚SÂà¡°;§†–oÈN‰»"—ÏÎUwù(="tUÒ‡fŒü4›�¦Ïh5ÎzE‘¯Þî*¦­7sÄ46XÑnnHè&øP °S,�b§Â#Þ�;ËGêHÀí4Ž‘ïÁÉ`"&Ç—Ðì2H`á: BèB¶bèŽÑ�ã„£UË#7áØuáºÂyåe&4·ÞÆ7ê#tI~+t‘I öo²Ÿàb’îuÙUªxÃǬúiv|2ë23ü·qA>Q]™À êdØòÎ ´±ÙPé8Ö´GؘpJð‡iäb˜{ -�qa3}£eXA2�*)šc<�t @É1ßdãæP†lv[0?Í4»�´³¹c$íè}`W3ÙÕ™ŽÎ®špÓȈô¢ŽÓÔÝ6Lƒ¾‡ýút|àÀS*HàÈLÏÙÄ?X0A¸Î‚Ɉ‘!1†PzvDß  R%¸ý£#ª„w`ò$˜IbuM[³‰”Ð}(Êr&a~e ›gJÍØÌŽ =1ó Ž<»œ�™@| ³ƒ@DÑ6H<nZ8:$Þ0K„²�ú:%o-iAO’tÖ¥£Ýë– ="9>º¤(ToᘾÊÛ¯›¸¬kª·¢T=U°I§€°¡ ]VnY0ù…èŽL‚ˆ~‚uñ ¢ VH•ËqF„–´îyÿÂmJ‡–Ø€à‡ ¡fºç ®4ˆ»'”’-�f" O8E‘g¦ìnÉD1 gO£&voF³¨îôçÒeu ƒQ9³„‰æêéø ,#®e�(£9Ù¶Åë"Ì“áƒ9+:Jbƒ™èÛæ„—‚@D¯2�®&$&Q%‹{L•E#WUûÈŠLâN˜ �йL91b”—g¯1rN­©W¦šJ޼^Ö2ãØË£"]¿ˆ Õ/±ÉØÇ!,"2(8@6"²{„&Q§Hõ Ž7�†ÕáZW�”Laš­¶\á�þ牢ÇT‹dó �ºo°ÂWÙ�›è—ÌôÖ€�Ê2',$^Å+<)AÀ‘ º�‚§=0Š“…3ÉM{ýÊZÖô]UvìÆI«‚þ„ßò³ë4“ ¸ï�²fueΑ+.ôR <á£; ìÈÑD m§K1FžçÌlE¯¶ÝŸþÎåÓ¥H­ï‰ëñÆ2:Å2> ï0^š—¿À®6�ÜG“5i{Lv?ÊçÑO9¹‡Ør¦ÙÃá”’)r„.2Ñ#×Ïγî¼D1S‹zÜGO ŠÛÿX¡·fÜ�õ;6öqÎåû ·I]f[åc§3ý´íH¨^ç¨Ï]¤ Ó”?%{„%“MÓ~@DPõ %XFAâCîj‚ËW¯îšr7…^™ «[›Ñ­XÃðŸ�«\Mv”@dBøo‹\m~Z¿i‚°€-m“¡ã¦8S(½\Ît+Êá و̈LTÇHc´ÍÖ”Æ1f& Ñ/°;Æüc¹;DK]æS¨á+Ü#b+'0�XÐe‹Cm9Sáõ¼]þ@—fÚÒêÐW>_ïÜÒô#V2jÞ•¾=š³WuÛT>u}Øeµ’›Ÿë€J?Oyo®œÓ3 ò9û {�ždÙGÒ Õ5Ý¢iËZÐûø¶¸ñfp[ÒK?눳D¯ÝÐ/ßÇEæ¦qؾµE/êEáX2]%¬¾™0r‚G“�ãaÒ«ë¶ßíN~š‰`9ÉRîð?ÞQž*ÔoMâ'䣲�ê…U oGÓ«–i€œ©2ŽŸväÓÿ‰¿»N¯–¿ƒÏöÅ)ó°@Éâd=׈Q>qŒÿtžF¯ö=šêkB1‘v8ÀzЯ¢7ݧf+N6Õ9ÏÄfúûˆ*BÙÓo½©}/Œÿý(žp¨œSg·ß �|ÿùÓ÷øÍÐ-Mœä»ÊÇØ| UŸRÚšÉöwæíBWo\Ù_4œCC®.¨ŸˆÔ�¨á ÖfõêvÔ�å'È$(ÜSWlvl@[µÔàeué rC­­µ�ŠŒÖZ ¹Šußw.vËå”cÕ ¿ºú´¶îr¬êaaäÕ¢¸ûï]½¯rl¶®Æ“ߣwïn¤ç6,WwÓŪ9÷. ~P#…e§õš·m+ùŸá¶“C]…œsÚ¡Á0Ì;bªê4<ÞåPùzYÇâW[Kªw¼q]‰ÛÆ•í`§›b“òÐÃ. „ØÞÊÞÅ#²ON endstream endobj 131 0 obj <> stream xœí�çwÛfšöùÇì™ý¾ûe÷œý�O“È–H+‰=I6É&Þd6ónÊL2™™Ìb&±DZ{{§I,¢H‰j´eGnrgGaI5;c§;6Þ��0Y–)6°à:×ñ‘¬FÜÏ�@àÂópú�qúú{1:¼Žq8ÎÉ“'_~ùeV¥Üݛ¨µÕÇf÷ôôüUwù­?IŽ2btM|:rù³SgppðĉÕ£Œa‹·¾ ácÆå;ÚÂNŸ¦€æ»z�ïJñ¡Ì¯ÿ ñÕwéÞE5µÞ}å5éûÂæiT Š^Œ÷£XT=ÊÓÉ1Gê|ôÚ÷Æ­â0rK1™‚BY'&?ßÏd}bH½DÅmɨ½‹Å¨\�ͨX]¹‰�Ú¡ì}@9qn›ïL]B¾§}aÜN~‡(µˆR+{ïý"ÊB8a9³)�Í1ª¹WÓögÔ&""ï_„ÅbD©�{TÛÔeoüú·Ú…¼ayCìÉ\Oþ@ÿžÂ¸™�}[¦¥6(–½ûŸ¯•¢ìvö‘ÆŸçsh[·T¨éNÀ¨´sýAˆÆÛœ¡ì#ªmjˆ²žžÃòÆÌ¥mЗSÎá·2�èß_7«ã?"Wàê(¿xñ¿øÕé‡2oV·TPùs††fŒ~VÜ8‘�õ#z+¢5‡ÒŠ=S[”±X¬õø=‚ äsd³ôï2Œ›Ð1ÿT"O·Gù§Ùã( áÄÕÄ¡;mX)¨ü¸)ÀÐŒ)ÄÁjcÜ8�I!ô«Ò†©9Ê‚XøÁu™/k_ݦ}¯aÜlŽ®E0�Uê)š±X¬}Q‰Ïcß�9R¦@A½�3ŸÝ¨é>Á¨õ5NÃjb‚P�8½³§[jŽ2‹‚ëò DêÈŠ=™™+£}ßaÜ<Ž\Kc|!fs  UꩆyÊB8~=æL™Ïnhs¦³Ì¹Yç 6ŒÇU¦¨qˆ"7²�·J=PÆb±¤Ž¬Ü›Ó®l \©¥›LØŒ1épì.*”ÄínDgÅlŽb·€²Nø®Ý¸Ó¦³ÕB\¼Sõ>Á¨õ”ÐëQµ6Œ£qô|hß>©ÊX,–veK9—Óù |'6cL„°¯©±9a½-nw—¶ÊÁ( áÄôÚél\¼£ó|ALج³´‚Q•†¤™T[¼ô¤&©ÊX,–Î_çrúåM6ëp§ SÜe}KˆÍ¹§OžŠ2*l¦ðâD˜ÜLج³t[­[AT©‰OÏÐ!uE‹ÅÒ/o‚s9ÝB^<“fÂfêì#Øæ@4&‚ ¶oo’rPÌ>Ò,äU~\çÝÖ/3Í:EˆÑÑâ: b‚B™‡tH}QFž›-äg.n©çs ~+Í„Í:Îq×"j3´yöAìóö°”‘a³6Ó/3a³Nl�F´fÄh‡UúPò»ƒÛ£(û{¯^…ɰ™r×-2a³Îrlñ2*UlBPÆbÍ@оíQ&ÊvÃf?ˆvÃfê…œ•‰g´µ`»ÖY`ë4&–…á{Oí�>N~Ê~›y³öÕ-Ú÷/Æ�qôŒ ŰÝ�4Ú6ŸÀ±C¡,„áïøÎ”u7ža<·Yqß2jf¡�Ñ[`»ˆ"Á�r£1(£ÂfÒ‰¸À™Ϥ=W¾ }/c\oGnå1¾†<°Áÿã-Ë=:ÊB8±ù†ïLÏm‚þœÚϼÓl7ݶ»bF 90¾0²ž(³+†2‹%p&$3зÁ„ÍÚÞáè]T$�í.Doƒ!ÏÁ�qX”…pbáÆ}¡+¥ö¤þŒ �¨¸{5›6!3ÙoÛ]¨X[½U~K4eä¹™oC1‹kçó|gê\„ ›µ§Ã‰o³NÃz+lw=µ+*@Y'œïJfIŽ�.…�@ âfÔ<"`[¡Ü„ T¡ŽûΪŒ22:;ŸWú˜°Yû:ó‚5Žgäê˜uºœ–¨ e!œ°¯nË}8Œ-Þª¸�5�v„`µw¶�2*l¦šÏ– â™ôµ6k+Ã3¨ÆH^…Ò2û¡b”³„~© šÏIüˆn1_q3j!æÉ¬\�ìˆÞÊ ´ ŒÅb– žK[N΄ÍÚÈqOUj &Ó¶TN@™ÍP1ÊB8q3ýPîÍêóà<õ©´‹Ñ,Øî@tÄ<‰ÈÕáD%—žèB6CȰÕ�Lج =sIƒFÕ™ &Sù�P ÊȰYòÑLZ·XPúÈ˰‡oaF4 †ÜyYÕ�‰¤áX…ñQFÄ™+ Ê}YÛY&lÖÚŽ^FQ�(<>ÑYƒÆ'FÈöU•( áÄ%ø{¾3µ{×­04k%ÁÆ)2 ¹ÉèÅM¼â e, ‚‚&oÂÈIf23Lجeýc„Ìêˆë¬áñ™Ã¶Aõ(#ÃfáoÆ)ÝJ^6›;Ó‡} Œh¬ƒ`µ6N!» ÀUÓô¢ŒÅbÙ9ÝBμ;³™ÿÆ}Ú÷JƇu¾‡Še°…|\¶:Êó½ª ÊȰÙÍ/®”Ø™:S'6kv!(f°Á:•(cËëUŽ>í(c±Xæ•-íBÎz† ›µ ß"J-lž„µØRVôâqÕ e!œp_úBèN œ‰ @ûÌÂÁ¨ID¾z.AˆRŸY©~è›e,Ëz&¯ñçŒ+Lج¥œ}HÞ:ך³+lž¬xôkˆ²NŒŸÛÏd(8âB*~IŒê-j8Tû ÀUã&A‹Å2®0a³sšE”:‚v̶j†¾¶( f ÃrA1‡‹gSêù\5/ŒQ�7CYïîp*C8U›S—æA6çqµ?/÷2a³fwÌ»ŠJ”›2Ù¶VO=({²òÕ”Qa3å>2•?“çN`5ß FE? år±‘Šfáøßê:¾Í�2r}WZ<‰Œ9Rš…<6k°£klŒóxÈÈ(ÊåÖc|ƒ22l–zÈw¦¸Ø»ŸYógm=¶…‹Å:yò$Ÿ¼ý¶ÿ�$i6:VæpÕ¸%PÆb±$æ0®�L'­g6iß»;Èë ld;u åñ`¯NƒÛ0”…pbö<òòÿî7Ö¾ðÒ›½ýÇz{{ë´Q+Nž<ÙÓÓÃápàÓ§Ñѱè¬#Û*(Áu�=ÌsGOO%œ—î†pâ/ÃÂó7 ôïìmê á��ÿð×So¾‰ñx—‹�:U¿Ám$ÊB8ñÚ›¿fszû�÷öö²ÙìÞÞÞ¾¾¾jvF¥¢NÉzzzŽq8èé‘xàZc†µUPÆb±xî(×�žšNžžLØ–“¯¾~ò/\1í»|ûùúõ˜Ìøüó/rØìé>pýîwXÝÎÇ(5eú ›MýEöƒuÝÆÎÑ+¯¼ÒÝÝÝÓÓÓÏápßý a}ÛB(c±Xo"ÿŸOï~ª;ñÚÿëééyéåW×a&@[3ßH|+­¯½ñßÔh¾vìØ¯_|qúƒê=¬ FY0ûè­ÿy¯ˆ26›Ý××Ç ¬&:zôhOw7û§#‡Óûæ[¿YºÄ¼ÁÜ+ê=x©N‹µ´ mls¯¾ýÎûÅÚ²Ùì—^|±ÞcÚx”…pB¦�ìééxþøÇü@Ÿx÷“©·ÞoÀ–¶½žïí=zô(ge}ýýï}ø'÷ò�ÆŒiË¡ ’üäŽÆéééyáø¯n$¿£mãÛ™‡¿}ý¿(Ž�'óf•~¼1›ÜfÊ|öYr˜›ûlWWWcÆ‘^”‘‹'\i¥—y³*fÖÙC lx8óÙgä,dbt bK£ ‚éTžçŽŽL'\ÌÌfU8½‹D0_„ŽŒ ÿ뿞ÙUÃÆ‘v”íÎlöݘ#¥ò¤³¸Ò˼Ó,Wë Iš‰$±¥+4Ž`K£¬4l6âHÎ33›Uä0ö5*U’S)Ф0_ÔøAl”…p"üzÔ™RzsòÙ¬Ú—m|ZNA¤–ÖA•*âî%z‡o ÅQÆb±NM'¹ÓIîTjÔ‘<ÃÌlvX§ &WáB ¬¨ÁìÖ¨IP ߵ{wZíË*=9­{‹–j´�v®Ý$QjËdM€«Æm€2‹Erl:)t¤F© 0“Í8„áñD¦$àÎÈ]Ã×<( áÄôÚ±'£uoé]w!ˆ™Ù쉊[§³^?¬³ *}­€«Æí�2‹%t¤D®´Â‡ \髉´¶%ŸYÁ¤ò†¹Dfï)SM…²NXÎl*|8&76Û_°uÖšãÖir8äKÚ‡¬�PÆb±>\:›UÌã _öfº^“U¶�c�ë¨P  ¡\^‚>Ž5!Ê‚ÙGš…¼z×Ín˜…çb˜@Ô&Ø:MÎBl–ð@;¡Œ¤Ù<®öl)¼¸–™Ùì@G/£è˜+á1!<4Dï¨5ÊȰYê¡Ì›5,Ôó9ã2C³Ÿ•T›PP�&0¾0²ž }¤Šn3”‘Kœ;ïA!›ÍÚÎ2ËhîïÈ­<Æb Ëa±’îkF”í†Í~ºÓÆå‚ÆŸ³6é.RS¨02’’(Hš %ÑÕÛ´�Q©Ûe$Ç\;€''žI»vg6c\ê0|Ia�•«0°)fRmN”…pâ"üß™²6u‹yû¹N¿¡I@ЖJ]Ad`lþsÚGg�Û eàÉ�z²b_–ïJ1a³pâ[D©Eµ&D©­Õ‚¼Õ«iQ‰ÕÈ7gÊ~nK»�7.u4ÍvÌ6‚È¥'½´�ËãnK”±X,±/+™É€3ø˜“ ›ýäìCÄhGT\gBµ&º‡èg53ÊB8±pã¾Ð•2.miü9ãR‡Fgãz{VoF4fXo ešqí³vE9‡ö .›É¨ærcLØl×qhS¨ Ú1YéœP“£,„΋w¥ž¬q)« àú:Ýk´`Ó$¬6ÅõvT¡'¾¡}8öu£ŒÅb©ærroV½�º;=ló®¢REaddTD÷Èüƒše!œ°¯n+æpp}]µ£»` UÜê†5Ø4‰Š¤õ^®·7ÊX,–z!¯ðeU�6‹ž½‰Š$Yµ:#‘FF蓽j ”‘‹/Ôþœj9a\ê”xF|Ê ÆãV7&En7õª@m�2òÜl×Ì’ëi;1l½–B¢˜~5Y5=OY¬–@9÷lú¡Ü›5.‘a3ÃrûÇ32FÓÛâS^T(Ž^ŒÓ^ÿƒÝ (c±XF76Sø:.lma|!j°Á*}LߤÓ×· ÊȰY’ ›–7Õþ|{‡Íz}BkÊ!T,‹®\¥½òOu‡  ‚�÷®,°)ñd\;%lFî£9jž@ÕzÔ`£{ž¨BÙnØì{¾‹ ›iòæsíI3‚ +gz= êâží5/Ç?%dÛe,KØTøs:?.t§çot@Ø,ùêã¢5¡æ ºË�Z edØ,ü͘#e>·©^ÌVòtׯöÚ¹$gïÑZ`›“öÙ{Êtç ŒÅbéü8èŵscÎÔ™P[‡Í²�`ó$ª5…d*ÄØÔkE”‘a³›_ \)ÃJ^=Ÿ3µ×Ú°u:ë[„Ƀ 9”n™ûþ…2‹¥�ÛPÌåÔ�B{‡Í`‡u¸FǬ°‡U+¢,„îK_ˆ<“¿ ñgõ�ÝU¬�» ÑYÉY/$ŠúíE.ß�†22ž((æpýB¡]Ãf±ù5D¡ i ë"e€ÖÙ{ÊT‹¢,„ãç¶e^\Hh3tW±‚§fƒ±»P¡8½C{yåD‹ÅÒ/”>\í'× »Ñ^a³èçaT$�-®˜ÖÒ4WöIj]”³„a¹ šÏk²úŸÙ †|° ‚§fQ�(r#K{mëÎDynæÏig·Tí6‹\Kc|aÜ> ëì°ÅEw�ËUë¢,„·2�À9\¿XPûó¦•V½¡1:↠ò¡bit-J{U+pÇ¢ŒÅb™vÃfʹ6 ›EÂÛ¨PŸðÂúñ¸}–îêB-�²N\Oþ ödL+›ÞÜ‚a³ EŒöˆÑ�È”±ÅK´×³2w2Ê ˆ°xïB�MÉlÆÙê3›a_#R%2î‚ öø„—îÒN­Ž²N\A¿¸RæÀ¦z!o:ÓbsE¬ãAB@}|zŽöJVìNFI³À¦®6kÝ™ÍÒµ±Leç–�ñ–y_YT lwQàoùΔéÌ–ÚŸ7.mÐ]Ôr…˜ ˜Ñíˆ eZøºq‡£ìǰÙ®]jÙ°Yöl�F4&‚ vn†è.g%j”…pbùöWrf³ íRÎv±h†N¸½1AˆJJ¶v6‰A6["Ãfš¥Ý°Y¼Å4îZD”Ú„^_X9C-¹ncÛ ,„ž+_ˆgÒ¶‹Ƴ8´ÖÔ dÂ�lè„ËÂð=ÚKW¥”QÒ,‘ñ 2læJ¯c-6‹-^B%rLmCÕ†„^Ow+T;¡,„ç·eÞ,´–9s{§i.ð¤1Ø� 7½nÐ^´êÍ ¬(2l6—S/¤³­6‹^‚É(£É«Ì˜ºyŸªÚ edØleCáà ‚¸†Ü§»ºû(<í�›'àIÚd ÀUce¥R/´³ÛjNíÏÝnî°Yäfå‹›#®µ„Mº+W•Ú e?†ÍæsÚ…‚çò¶¡Éæi,˜L˜Ñžö¢bYlõíµª•”íÑ�a3_ÖÚÄa³Hô.&#ÆqDcBl­Í±¶D6K={2†¥‚ÊŸ3¬4Ë-¶¤ò‚É„ÈUqß9Ú«TCS(;~üxÅÅi3”AaôÜ1ù dج)g6 c_£2�|VNm@ŒM:›â¡Ô–( áÄeô�À�2¬l¨æsææ Ù_D¬2ÀãnÚëS[|ýõ×_~ù劋Óf(#OÌüõlVëN ]Í6K?@´fTgÅ¥$Íè.UmÔ®( áÄZì[rf³• õzr�¯0ª³" 6Œc"I8öí©‡)”½ûî»W©]Q¶;OcN>›Uúp¾“þ°Y,pŠ1¡K`qûœ’uÊB81ùùŽl6 zrBóhhØ,!Q™ ÕY1¾0r§½uòÀ±Á�>úè½?¬¸PmŒ2‹¥ôáROVîÃ%:Ãf‘Ë:&€ÅJT(Á„Bº«RcuÊB8a>³©˜Ã€àk6C¹\T &iÆ6ÿpÕxàØà»ðþ'ŸT\«öF‹Å’ûp�}KæÍjh ›EnåÑ1AR¡@ÅRX¬¤»µW‡ ìvö‘ÆŸ×,ä%ж¾!a³ Äy§Iš‰e±åuÚ+PWS({·Š /m�2‹uZõ7 $ž´ie³Á†ï‘gbR&–& º+QuÊB8q#ýP:›Õÿ6«/Í‚À]®  E|f…öm¯·:+ûkÅë”1¢ßæC¡+åhdØ,ñ-*W¡*–aÒöäXG¡Œ\8ñ€\x¥Îç õœuöÎÚ‚ P‘±9Ze¸j«¸b�€2‹Å‡2|(1j‹�9’ ›eÂ:+&’â •´-Ç: e»3›}7æHV6µ‹hm§%Åx<|BLjRN}Oû&7ÀÊ~ÿûኋÖ!(c±X£¶ØÈrz™J4 lwcAw´­:åE™ê4”…p"üzÌ™‚Öv +…ñÏkü @òÔ)ŒÇÃx{FF¶å j�…“*V¢Œ ›]»'tgÆ?ß�ÏäFL5»ns¹èðpòÔ)tŒŽìо™ óÀ±Aàÿßÿ�U\ºŽB‹ÅâAožÄF¦“u ›EÏÞDGǰS§R¼Ó…‘º·¸îêL”…pbzíŽÀ•1†Ç“Ów «¬€è.¾(#Ã\˜ËÅx§£W“´o`#=plphHú׿VUê4”±X,²ëviÆw¥k6‹^M’ãñP.;uŠîmm„:e!œ�y3C6‘žÄ†¦’�„—‹í¢Œü—w:ÚF³÷”i欬2 M¢$Í ”7…I<™•à—Õ�EäŽÊ@ŒËE‡†0.7ÁåÒ½• RÇ¢l5ò o21 a”‡¦’C“‰ÃVoc##Ø.Ä(£|!í›Öx3×Ê*ÓÐ$zj†Pª y“عhU�è†c_�'c?ucrx814D÷V6H‹2ÛÙ­"ÇHO&†+BÙ:bCC?£lŒß~_<ÕÌÌÊ44‰—O‡!¬Êu�c K¬dg2(kw/Üü’;õsñ¦Î ‡¾›Iž•�Ž–¢ ëà³2e‡•óÂÆðy‰ƒjB.„ùoTõ3r 'o SGÕáadh(þYåa¿ÖRÇ¢,„ro– aCèÐ$BÄùÐÝ ˆñx‰ÑQ´xäñÚø±ñ'™‰ÈV&ç… ‚ Èëÿy+sü\ îzÇæÎ“ï1¹\ŒË%ŸžûôSº·²AêX”-ÜürÌ‘úÌŽ M ޵Âj¨Âš££äqp÷*ë�·ÆøáèÚ7°‘f\ª@è-�ãB �3}³Öw0#×ÒØÈ(vêT|hæU~ ³…Ô™([ 3:�ΤG¦ŸÙ‘Z“ fœÅFø¨DÞ–S,>ÉÌ̇Õðd‚ aÃèÈtòZ¢.W£kldæñ�Óä´toqÝÕ�(»Ïw¦d¾¬Ð�Τk[Ol„ŸÃ"XcêœëÿÔ|e¿ýÃ*®[G¡Œ;sw/øŸžJ\Bêøh[l~  \îm.7ÐFÆî«NCÙÕäBwZ5—“Îfd¾l=Jzg˜K&–Åí.Ú··1¦PöÁT\´ÎAÏžæA îÌ›Jœ ×ÿÌéyT(À5^›þ; e7ÓåÞ¬jßý·^“c°yz$Ãç#"iÌ»JûV7ÀÌ„ØeŠçŽžžÆxöôÈtÒß ™1!æIT¢ ¥˜BKwê¨ÎAY0Kè— Š9\4«æðºV5Ãç£|™Óˆb�ë´o{½Í,SRŽ@p]8á¹£|gÒ}¹�«<$¿C@-¦Ð¢r5è.C½Ô9(³¯n˼Y Y¼Õ€ÂÆFG�•JÑ1ad=Aûæ×ÕÌâqåHa�€àºÀ�¶­6zÉò0rËЀÈÔ0h¢»uQ‡ Ìyñ®d&.¢‚…4¦¶¨TŠˆ$°D�Ž "Á Ú‹P?3Kú>Ur/.w`2oF·XÒ2·h ã aЄ(4¨ÞBw=j¯N@ÙÂ�ûBwJí/(æÒà"ÚÈò’Ë &”„á{´—¢N8F‚èøñ㪽QÎã²Ù,I3/~+MÛ¬ÂÑk)„/DõD¡Ad:º«Rcµ=ÊV#ßð�)ó™MÕ|NíÊÔd½½½l6»§§§{Wû~õ ”8ÎS+LrL¢J-¢Ô†’M±¨kÍM¡lpp°Ò6lg”� y™7 Îã"wºN²ò="çi—éRRpS&£»6µT{£ì"üß™²65 yó™'Næ?88Ø××Gq¬··—B›Í~RÅØlvww7‡Ãééé9ú“(2ªÔâªÔÀ¦‰P†¶eëgeO’f—û²àB^àL*BvîFn˜ÊtS|�Pa惫×÷ \Ì»ŠJ”›2Ù¶F×NS˶1Ê®&~¹ÓÆå‚ÚŸ³öçµíl6{pp�½+êÓ¾¾¾ž'«»»»4ŠcÅÿyR�ïÍ¡ <壽257ƒ²}ú6ä^\³€�9Sç"e=ýqùJ¦›zïwŸ<ÿâñO¼ôyð +WRÇ_xþ…ãïýî™vòjÙ°Ç¡YT¡! hÇl¥»H5S»¢ìFê¡Ì›¥8f\~âûÊ=t*_¥o3‹ÿsÊÊ)Á(�‡Šå±…‹´×§¶fPö¸4ó¥7 ú6®”ÿÆÓ#dÂ;|ôçcƒÏ;jàØà{¿ûÓÁî8VüþÁÁ>øèÏ—c{ú�e";¢1fõØ8Aw©j£¶DY0ûH³�Wûs:ïö+Ýüâõ1êã¾¾>ΓÕ××W¼¤¶ç<퀿åñ`‘AT(Žž Ò^¥šAÙAPP7ƒiæ3OzæJ¹2ïjø÷Ÿ ýçkoR×.^zåU×Òu÷ò�'Ù±°þâñ—¨Æ{ù•×>üã§‹�rG-ñ-¢ÔÂÆ Xk‰Ût¬jK”YÎl*}8&÷½2+@½ÇÜs–µ/Ǩ÷•Å3ê�é· J…‚ ¢ã:ÊF®gh/T­Ì ¬TAœ¹R€  |6[ÁTŠ·3?˜§Wþø—Ó/¿òš~ÂÀw*�Î/ýçÇ÷œ¯ àA.Y.–ÅmXg��»é.[µj?”M¯Ý‘ÎfÀÅ;:ÏTî¼=Ô•‡ÓÝÝÝÕÕuÀ>EQ««««»»»···¯¯ïP»p\g‚A-b°¢QÛ¬ÊÄ ¬T×ÐûA€þÜn„¬òª®Ã÷ç×â|ÃüZü:VÕ,‘[yŒ/Œ�»c{òÐ]¹ªÔf(ó]»'p§¡À¦va\¼SAAººº¨+ù ìÈ®ººº*«9b°Â .®³ E{¬•É ¬(óÊÆìåmíb^î£3BV¾£—QT Š@ž¨Á¶NÓ]¿ÊÕN( ¿æ;SÖåM½?=á–e“(®³d=s¨ÖŒ¨ m°‚9ƒ2JæÀ–ÆŸ7¯lˆgè��•ï虨H¶NczsÁÔª�5µ Ê>�}7æL™Ïnhü9ërSsŒÒ�k7 ‚@ÕFØæ Ññ$K Í ŒÅbYÎn�ñÅÀÖa#dÍà¸'€*5“iK*'Zsf³ö@ÙÕÄ¡;m>»¡^Ì™ÏzµZDîñUjãží5¬Æ Ê •-ýBÞrvcÌQn„¬Ù OÌ j#;B)Ýå¬Dm€²é‡ÒÙ¬ayC½Ð2£D®"!’cj*–Å–×i¯dÅîp”�žœÆ—ƒVÈó±Å[5X–—g~€õ6Ä8ž•«aó$ÝE=´Ze·³�4þ¼n1/�Ü6,·Ç(aj¢2ÁÆ)T Š^<èvU3»“QAA­+zr♌§ìYs:œø‘�°yÖYâ6'Ý¥=œZe»²í}ºkY¡`ãT\g�NÎ`|aäVŽö’VàŽEAg©™7koø,dõp8zIâ6'¢µ -E³–FÙäç;roÖä/H¬w ’¥ßšDÑÉØ`ƒ'f0‘4k½#{Ç¢ŒŠ�©æñ*#dMe2l6&@mNXk‰§è®q¹j]”ù®Þͤ-��¿`zÚì=Í/ò¢«Þ[¦…ºåžëL”– žÝ™b®5"då;z Æ„â¨q Q[úÖ˜=£EQ¶üŠïHéV ê…¼%°Cwk#Ø2•5ÚÈÇâtÖÖZx®QfX"gÀ3,Z+BV¾c�k¨D‘ÐC˜Æ”Ðëé®÷ÓÕŠ([‹};æH›ä³!+->VªëA°Æ�»i¯sùè,”™– $Ç–6[1BV¾ã®ED©Mèõ…åA4ûœ–CÙeô�À�2­l¨ü9csGú+Ayó$lñ! u|î<íÕ.Ó…2}`[åÏ›– |gê|´Å.ÎÙG°Í�¨ AìÜÒ]ø§¨µPv=õPìÉ–ÈYÈL+­½(G°Å›¦âS³˜X=w›öš—ãÎA™Ô‘UÌæô�m�+µt³e#då;ýјÓî[@LM=³Y ¡ìVæ8ŸÓ.æ=—· Kmõ¾r�âS³ä3»´ÆÂs‚2 ª�˜Ô‘»33Wʘá°=Œ}�Ê”ˆiÖ˜ã–æ�Ù¬UP̆• …'âÚª²òÛ=ˆÞ†L¸É¹€B›´×ÿ`wÊŠ³�É|Yûê6í5o¤Ã±»¨P·8`­¶ºèŠýÕ*(ƒÎ“ òꉥ›[Ͳ&B&ܰÞ·:Q©"Œ4õ{™N@Ù:¼; Ù<®[jŸYùŽ\Ï�ËhZ]qµ1ª5Ó=û¨%Pæ¹ò…h&­÷nªçIšÑ]³Æ)n%cаaQé›y. ¶G™f)ï¾´­šß��eÚ*BV¾£kT ŽjÍ(¨Éh4t�É^5?Ê–o%p¥4þèÍé½ívËò©‚ ã1ƒÖYÔ´sµ7ÊÔóä<Šš¥¼È“¹žlÃYùŽû/ REF£ ‰Ä�&› ¨ÉQöyìÛ1gJØTÎç4­é¯L‹=AˆBŸš£}Döu£L=Ÿ“ÏfÕóù±¶Ž�•ï¸Ã�*5¸6&¤{pþAÍŒ²+è÷|Wʸ´Îçôm!+_AŠhL©•)cK—i—Ç=ðSÜ¿âmlN”If R®žÏ�9Ú=BV¾³�`˪6¥JXÛDSÎ6-Ê®'�x2Úå8�—Ú3BV¾"R#¬2&lS¨H]‹Ò>:{Ü–(ãB(ß™–ÌÎÔRëÎBV‡Sß#j¬5! ÑYè¨Õœ(Û��ájœÇµË9º‹Ô"9¦5¡;9Ð�,ícTêöC®‹ì1.„ŠÜiOçDÈÊv¹�ŠeˆÎ+µq]SÜÐlB”‘²å‚|ϦÔþ<Ýj"¡; êQ½å‹ÂÑ;´�TÑm†2‚ üç³ ¸.�Í@çÛd�¿š;ÚBù¸Ό(4ˆŠ~š5!ÊÆÏm‹g2q!t—§é„êíä¢Òj#*‘‡šfá¹6CÙ¥øß‚�Îf:3BV¾#WS_€¨Ì …:«VÓ;j͆2÷¥/„î´À™q ÔìO°Ò"Xm̺g¥Õš›d. vB™Ø›™^Û”z³ _çFÈÊwô|I²juF"-ŒŒÐ8pM…²…›_ò])±3-t¦ÎŠÂV;W®’ ÏÉÀ&Yx®mP&šI Ý)±7#šéôYùŽûΡREadd[ mó46ÊVÃߌ:S²¹œh&#v¦é*HKˆ ˆ ÷LP±4>{†ö±ëo ” C©‘é”h&=æH^F™Ù!‡fQ™’€ ½�®ák”]‚¿ç;S*NâÍÊæ˜[–OW’\nvhˆ¢+Wé¾6@oæMa»4Kž‹~K;ZÌÙ‡ˆÁŽH8¨A%2ZF°Pv5ùƒÐ�–ÏáRoVåg8V®²CC)ÞéÔð06Æ�^‚iÁVG`�‡ „7 �:’L„¬B'¾EäjT"C"ŒŽ‹f´£ìfú¡Ì›‘Ϧ¥³ùÞø ´´RÃÉ‘‘ÄØ6Æ�Ü.Ð5ˆ-�2\1E |z:ÉDȪq¾‡Š$ØÈÌãE‡†<Žô¢,˜%´ y�+Å÷Åä³Ìõ±J”CGFîÆ…ã?î‰·Ó ½dÝŠ(èíí=}ú´Ú² ‚ë<(1q®³f!«‡ÃÁMxd4:4Äë­wNœhÌPR¢e à7Þùý‡|7 ÏÝhäV·™î:ÂOŒò1©"”üöJüÞGü´‘CÙŠ(ëíí`³ÙA C˜j.ÇDÈjâe×Ùÿ~ñÅwNœx¾¯�Ãá°ÙìÆ (-(›=üß¹l6gàù—ËÅ?Y—�@ 1ÛÛ®JŒòs296:Š(µ\¡êø‰—.„So9”uuuõôô°wõ‰öò˜3ÅDÈjèW_z…Ãf÷õö²Ùì"aê=¦�DY0ûhÜsþÃ?~Ú×ßOýÑþçOüêä{€åb½7³íõì³ÏjÞŸ€ å;ï<ßÛÛÓÓèֺ-‡²£G�R4ëéé9þêÿ¬\ËѾû·“eº)ª¶?ƒ¬½P¶ÚþÀ}éåWÜ̾~²�8}õÞÆNг»*iœž×ßxëf£&žm-”õôôtww—ÖêÄK¯pjÚ Ð6¾‘üî•×Þ(–—:7kÀ°6ø ¦3~á¥ÿ¢Ú‰ÍætuuÕ{;AÏ>ûlwwwïî)}ñ¬^¦Ÿj̘¶Êzû�‘û‡çµW_o̰¶ʸúÆ{§^x‰Íé}û?r.М.nW/^D_xñ„Ó·† %‰Ó§Ñ‘Qtt´®#ÛH”ÝH=”y³RoæäÉ“ÝÝݧšæg´¯úûû_xçW¿ò|üñŸ^{íÜùHF¶UP@Á¡I˜ ¡o}Ä×ÏÞ¢}ooô'ò6z8z¢££ØÈH‚Ç«ßà6 eÁì#ÍB^æÉL×ßùhøøñãÝÝÝõÛ®—çã�~ˆr¹ˆPÜ€…çZeA8.äÈÉ£¦“L„¬þ4ÑAäVKðx—‡}öY�Æ·a(³œÙ”x2Dè«Ó¶0*ÊåâãèèªÔÔ{á¹–@ÙZä.AcÓIÃ23 Y£¹Œ cì³Ï0./5<\�ñm ʦ×îˆfÒ#¦‚ºA± o3èÎçkA bbž¬ë\@Í�2¾+ �+ð�Ie/dI¯c�ë¨@”FùX,®ù7e¾k÷î´d!-pfGLº-""=ï_AT¦Œ»–ê7ÄMŽ2¡#Åw¤ø®´Ð�¾ÆÌBFŸãî%D"‡Åâü¼Ÿ j|JSo”‚_�9SJoNâÍH˜§,­u „0`bYléJ�F¹™Q&p§øŽ¤Ð‘bf!£ßÙG°Õ�*ÔAì\»UÛ�®+Ê>�}7æHs oVéefï¡G0Àq\mB¢è…X=ºiQ&šÊð)�;5:�<ÏÌBÖ N?@5&XkÍÎúÓD Ǻ~(»šx t§õËp7,2£Sqµ)N.òe%ž»‰×|¬›ešùŒt&-šÊŒ:“K·šeIÆ!ìkTªDLˆÖÛ]µî:¡ì9 YV·T _f®�ѯ¸Î «ôqÓ&¨ýÂsMˆ2 g0Í|F4“ž]gf!k.‡cwQ¡¶»`ƒ=>é­Éˆ×e·³�4þ¼f!/�¶uK ÇšEqÓ¢6 F;"W…ßÔpÄ› eAÌ\)PP:›�\c²lFG®g0¾0>é…�q¨4«Ê,g6•s8|íýê_!£ 1Ú³R%¢2ÀZK žk6”­Ã÷‚PÎãÆ• &BÖ´Ž®EP¡8yÓd¢jšÕe“ŸïÈf³ ''4ß&BÖtÚ€*µ°ÝU«Ao*”é— 3—·Áùœj>ÇDÈšÜ1ÿTªL@Þ„e"SÝÂsµE™ïê=ÑLÚ¸¼­òåAs©¿EÀæ(?Ãç#R0æ]­É¸7ÊŒKÕ<®_.Hg37RÌd-à¸sQé2”°VuC³†([ ~5æHY–òÞ¸¼]Í«bTW‘“(àIc�kÕ}“ Ìt†ä˜q©Àw¥˜YË8û¶L!ÆqÔ<ŽØœ�~­P¶ûvÌ‘2¯ljæs–¥|ů‡QcÍ1P3�#|Qd=Qåè7ÊtË[ ?g:Ss¤˜Yk9œúQ›1Ž#S^4« Ê.£î”1°©öçÍ+›•½F VÌ<×`ó6 nTÓ´£Œ¼¦á/è–·Æ\©åÛL„¬õFî£92åEL𴯂¨e×SÅžŒn© ò猆c­$Ø<�hM°Í�‰¤aø^Å=@/Ê µŒa9g\Þº™Y ;ÚÂ"xÚ[ Øå?lT‰²[™Gà|N»Xð\f"d-)Øæ@´fÄ0Ž€ºPò»ÊÚ€F”q6¸­e¾ìÔZ�£¿ŒìÈÕ*Á.ÜîŒxϪªAY0KV6”s8A×P&BÖªB ã¸ÁŠêm°i"TÑ÷4¢ìzŸ õ|ÎÄDÈÚÂÑÏÈXñž�OξÕò;¡”Aç·eÞ,´–9Ü©ù”Œ©;–q‚•žòUÐ t¡Ì´²1{y[·˜Wùs·ë9!ãF:>w“«aßjlÂ,;lV1Ê=�¨�AŠXÇËì‡ÊP¶rû+�;m?»©ñçµ [70£æQHÅu6 r£BIô\ðPýÐx”W ªÜ(]é+èÚw=Æ5vö!l‡�ö˜É·—6«eŸÇ¾å;Sæ³[Úżý,s˲}DrÌhG&ܘ@¹ž)¿%Œ22B¶�3®îFÈbL„¬M�üQjãv'l°Ãž§vÅaQvý^àNÙ[Ú…¼ù,s>ÖnB&܈ÞÛ]¨PŽ”;§D#QÎo)æ˜YG˜ ›‰eð„6NĦænŒC¡ìzò±'c 4 9[€áX{ ¶»�1O!E-‹ CÊHfràü–Ð�ö2²p8¸‰ ı©¹˜Š@EgËG!›#ÔU/äŒ&BÖÎBÌSYïb°#*C9 Ï5eAÌ]Þ!i6›�ºÀDÈ:ÅÑË(*E _Ü8‰@óOj�2QFFÈ– *^³˜ef…íí\¿M¬³Â6çSžk ÊÖ‘ÝYÈæÈ»–´ï_Œé虨HŠ@óˆÑ[,û¶G™(?GFÈô�„f‰É]t„‚(¬œMèõ(¨‹Ï¬Ü @™~™|¢DåÏ1²Ît|ö *WÁK^¦ àñ)eîK_ˆ<“¿ ñgô�DÅíʨµ”Ðëƒ5yP‰<¶¼~@‡ÔeÚ¥<¸; ™Œ™…¬ƒ CTk&`G(}¼IžŠ²Å›_ œ)Ã|^íË™üÌ[ËÎR ò F{r|ˆ¢ãOj’º¢L=—WøpíR^àJ_Á˜Y;ób°ÃƉ¬BƒØ{úä`”­†¿u¤ôK*n˜gf!ëD%ǧ½5f÷�sÝÊíÛ'ýýõB™~± ôâê¹<ß™Z‹Wø´;ãöqò[t—cˆÞ ÿ#Í@Ù%ø{¾+e l’ À-mT±70jmÅ잸ÞŸ!çŠ}ñx« Ôç¬LæÝ”{súÅß‘d"dŒ)‡c_ " LÑlb¦Ø-OBÙÕäBwÚ´BΦhbf!ëxÅÆgâz[Ì2…(Ô�/<×ß?Ps”úÄØtVæÝ$g!»ÊDÈÿìð­<ÆÂ3°Þ³þøXÓ¾(»™~(÷fM+Ô㺠Ç‘ŠY¦2 5l´Ã:ëž…çjŽ2 †5[€>!ñd¦™YÈ?æÈeˆbV'¢6cjÛ¾( f ýRA³�ןI™V˜ëüŒ~ÖŽPB¢6ÀãîÒ¾ªùeÿQõ= d>œ‰�1~’c�ë¨DŽ©mˆ\ ‹Å�£l|u[9—ƒ‚Aó´¦û£–["IŸ;_ì™Ú¢Lå/ˆ&¶”s¸jž‰�1>Èq×6‹óþÅ�?þ¸e΋wɧ,—²ÆÕ Öt?`ÔÊ� ¦PÇFL$�ž»MµÍO$«Ê^û·äj¼~f!KÆe8ûˆ¼þ¯21ö—O‹([¸q_àL‰}YÅI³šîŒÚG1…•©“ P ÏÕðæ»ÿ§0¯lÝL„ŒqyN?@4&Ø4a>5D¡Ì»~ot*9êJ Üi±�ᣃ”u˜ DU:Œ/ ‡6ûjwÙŸacÎ$!c\¾ÃØ×ˆT�r¹ʆ!Œ ¡ÿó'ùKo¾ßÈÑÓôÞ«¯ÉÞ{UjP�ˆÍf²Ùì*QÆf³?3ßö]Þ\‡ï3f\¾¯\NÜþë_{zzØœ^6§—î�ƒQKªŸÃa÷ô<óÌ3GŽ©e½}lNo_y¡L;6xlðùZø…j<øü ƒÏ¿X�Ÿ¡ª¯³«*NÙ~ú0íýþ�cýý½½}$ÃØìÁÞÞÁÁÁ£ŒU*ªžyæ™jPÖ×?ÐÛ×Ïéíëíëï8Ö�4kV71ÇŽõõõs8½lòlŒM~ÔÛËf³éÞ!µ¤ØlvïîѰbŽ1bĈ#FŒ1bĈ#FŒ1bĈQQGŽ9zô(õoWWWÅ¿‡ý“8NM_ £Æ‰Íf� ûÕ1bÄÚÓ“ÝÝÝÔl6»»»ûÈ‘#===]]]G�­æOP«&æÇˆ^Qƒ¸/ǺwE÷ dÔéÚ·3©¦-~@e jò'júÚ5N¯J�F}Úý“ŠßIø*>™ÿÅ/~ñ/ÿò/ûþloo/u@¤Tú¥þþþÞÞ^êàûË_þ²Š eÔªzÒYYé§GŽ)íÕÁÁÁþþþãÇ�ÿêW¿:yòdéoàäÉ“¯¼òJwww±K•iQíAYww7‡Ãéëë+ŽlñMhwwwWW›Íîêêú·û·_üâ{ÞŸR¿°ƒÅ¯þû¿ÿ;õ%ЇKÿ:Ò+a9»¢>èïïg³Ù¿üå/{zzúúú˜ë4ŒÃáôôôPüÙsÀ-6R±ñ{{{OžšKƨ±*m ‡óOÿôOÿñÿAýul¥ºwÏÛŠ¢Š×ó‹mùxCpÏ/9zôè³Ï>Kw•¥ÒÁ¥ŽG¥ghܨ+«E¼;ä_ÿõ_ËGõ³Å¿U<½/m9êG¨?QúG‹g‰Ô™?½cÔ`í9ÆÏð÷\++í4ª»z{{‹?H]Ä(ÅT±ßJQ¶§áŸ}öÙj’eÔHpœ*Ž,õ1uzöø7”�²ÒÃâ¿ïªÈÌÒ_Kõõ1õî øÿÌ�²UÚoÔ»†ÒOGÕ6Ôq“:VR_-θûx¿ÿ€_|±x<­òn£Fªô"uVVl•âyZñ¨#Tqô©Kå ŒâaéŸc±XÏ=÷\é7—¾ª'¡•:P>÷Üsô‹Ú·Øl65¯È¾(£.’”^R+=>>~_¾øƒÇ�§hVäs¹¬U´çZÙžV±öÀªPå Œºª_úç(¾m|¼[J›v�ººº”u”öX©3®çž{Žz÷·/ÊžÔ�Ô/9eÔ¾úê«'OždòH­¥R”Q´)=ØQ* %pâÄ êSêÝ_éW©»�û¢ŒºÆUŠ2ª[Š?[úªž„2ê:F5¹nF-§Òs­=1‰Ò»Þ£¬ôÝ%uêµïŸ ~ðä®”µ–JQF å‘#Gžyæ™"¬J¯óÏÀ‹‘ ŠuůR4+eo¼ñFéÏ–²«x‹¼x®øøÉ!£Q)ÊöÊžþyªo©Þ£Ç�·ƒ²ÖÕWA©# ¥Òo(^ E±«ôôl_”QMXв·ß~»ÈÌâwQV¼¹ùøÛ^ºkƨ¡ÚsV¶çKûâèq”?~ü•W^Ùs?ýI?xüøqe-'6›]zÍj”(šQ'`ûÞ¾ìïï/ÆY÷�°eÅu‹ßÀ¯ýëâ•ÿ=È¢ÎÊJ_Xé©#Ý5cÔP•òêq”`ûïJ“EÅ_²ç˜û8ʨƒl‡ôÛÿzË endstream endobj 132 0 obj <> stream xœí�yœÕµÇoÏ8Ã"«l€ˆˆ¨h �¸“BLõãB‚+DŸã†[ÔŒ&Ñø> †@Ì.$�ˆÑ€ "‰QwFŲËD†uvfº»ê¾TwÏLW÷­[÷žsnuÍûðýzº«î9u~ÝUw=·â˲¶LŶ&¢oãÔóª1'µ]nnhê$¦®ÜÎul1æœ:Nxim�1nyS;ÂÊupĦ:ÿîlxDiè[Ͻ…a?ËutáX³Xâÿµy�Ç”‚v\& {ºÍÞÌÞdIaøŠÀƒJ@d— Ã^j£Êl=¦Y{^àaų<áºL˜È{¹ 0�ªn¬Yn?x\±ÌLþd°‚Ý9�0Œ¦!¬UnM 8®XŠS·)©0¬GM# ×ð¼åïø7�+–Ññæë� Æ6å,Â0ì[“Ž·¾Ó8(À¸bÜoaؘ¸GBÊïS~§½UÕ5°¸béVÝⵟ0lJ›jh.ov;ýÍ]ùÅKÁ®V§}…aÓÛP¥yC¤Ùk×ÛW4¦ùlû Ã_(û:´8íþàù ŠfaºË ÂDÖ_(õÇ·:íþÄ~,€¸byÔukR†”a±ái>g|fß`:¬h®w?2T„aݪ�0 ëªt—3?�Ÿo8®XÎϨþ* Ã7av‰Ëã¬ÏCÞœp$óz”„im�†–¹n‡³Ht¡…•N3ÝU&ôÍ™72üR~Œ±¸bÉ+ËòVUö‹P7g6g‰‰úÈT\Ѽ›í¬²0ìïÄÊÁc3½¶ÈLXÑüYૺ0‘µÆã ¥ñ„,o…ÇÙ¿0W,÷ŠnFê°°ŽÎÄÏÍvV|¤ÆæÌ¥ÂÇ·†0¬g­áð& |õ86þmò¸bzª#L8GgÄ£Ç^G7&Ž+–^u—¥#L(›3ó…žz²æLa…‡Ÿz°CWi~Wì¨÷ ; ãŠ%ò¹—›šÂ„®9³ÍcLrÊûtqE󊧗ºÂ°¿‰/”ƒb÷¥ÂØ/P…Í ï¯¹¶0,L£3 ý½¼”�eÿ’&¬h®‘ôsé S°Ó@„aD‡{z)=Ϻ‘$®XÎW”“è ú&�0ŒøUÞNúœ†æLÿ™‹aØ@i‰�aɦ¿úœ‚æLçJ©‡aØÈ(i„aØse.ú�}¨;2®Xò}žÕ aØø(ó¶ÔCßÓ7·CÅÍ‹>mu˜0¬8ç�3›äÃ^¾ç[+#Ò 3Íï« †ÍÌñ,€JŸy¯þ%™ +šk|¿ØPaØ_2gJµg&…BUw@Ê#�±óýƒ¦`uîêfvÝWüÜS)&z0´8¦]4¸Úß9°0¬óÆ\)oçë�J91þþ÷@¡E‘·æe•¥úpaXß/ßÏÉ(@Üþ‰¿sJ%ÙüȪ;ƒ^ pCÌÚªâ\6¦‰_°9ß©à›RYç–�¦Z¯'ìú_'\˜Y9™`sûf…ËW,­v{ÐIFÆ•tÁ“7ù­(—õÃa7_/NãF¹¼5'iXk«51·2ÆÆozܬnÓºÙ*ž)h¿¢X$—Ƨ´â„alqÀëš œ¯Ôÿ¨^¢õ;�À"Q«úMÆ “ÿZ sšŽ gj3�5Ê´îÔˆ,Ž"…L ¬0¬ó–§›Ç¾¯ê–N©ñ ª¥"éâ5%FZÖ÷ Â0â�*{¥UnìkÊåb(ؤá^6,¨^3k�ºSz%{Ï $²Z§¦D P�ù�š­fÑ;k\/�…Z5X aØÔ@3ZmAÝÂwï™Ñœ‘G" ›@s¦º—ŽGÚÅ›žx½fˆh„aÿЄ.M§k9¤oÀì4ÀQºý½DÂäoÔ�„ñïè9¤oÁþ•ž-i÷ö Ã:îÕ…ÖíšþlØS4m¨sì}wˆ„aýë±PÅÖî6�X‰_ kE‘|•˜L¨„a#ÌMi²—i{²Ótж%Þ‚8C& »ÜØxæúuY˜¡šú—íÏŸ@uV:aØ}†š3û³‹û4µ[e¬G“‡`m Ba€_ ?@ý%PcŸ@®[ÊÀ¯+¥0ìMh<$ľñlîï  ÷æè žT˜ümà€xa] òn�vܬ<Ç‹TA!$¶zO¿ „Å©0‹BÚïûA+LvÞ-$ÐŽ„Ië»@›ÙDtF`2 †�GZi'LÂ�ƒZÍóÌ¥†ý€°ÒüpŠ1”ÙºÞà«w1ã¹0ì'd•æøfV8Õ$ÓïB‚^ö,‘2Q½ž~HÓŸ#.¿™‹p·°ÕȰ$±.F¸€5¾\Á†œÓ‘}‡&„!iÎØwa\@›ÿƺ³Ã v¾� aHš3³P ÍÛw£ìîÁ:`D‚æÌk8°æ9·.ÁØÿmߌ0èæÌäšbt\8�ú®'ô† ³«!aØ$T�]_ņóú>Pë�X7% ª9SI3‘á¼²ƒ‚%“)Ú Æ„aû=mœ 2ÎÐ)è†zI߇9aDù·• èE¤ ç|%Àô@š…©…ÉÏÎX¯Éz’ØpÎçh[>–hõƒAa@Ó©¸�mÚ%  çö�5 çQ�Ч¹ÓÃú&›½Jb™(:œ[Wê~ƒÊ°QaØWµ;Œ>£YELÎcgëØ¥ÛÒ½‹°|*a´'›}I”FŒ*éôêê¡Äæ¨ÃÄ9?\¿ý:‘©®K+þYAŸ¸5 _ c¯I›Ðç #�S"gÓx�©��ÅUôæ‚yÆ0ö=i«8®»\Üú@%,>(8ÌÕÒ�j”0/ÈÝ€ Ê ”ó‹±n˜Úìô%Ñ› JŸD@Ô‰öéÅkâÕψ机µ¶Ü@šÃ „‰l’mÈõõˆô�âµ¼Í]Lÿ�  K&Á#ÿ‘^4br�ò8ñ¨t‘îTreæjùð¿}ˆ8Çu˜¤¢9Ì¥N b|<&Á~ 0k—φ0šGI¾!šCžVbEfX�¯×ÖÇàe}"hƒÄmÿ~ÿ°ÉZž˜Zvèw@áÛ_Ji’6Hü“=i·¡ @˜Î»”~åq’ e)HcÄË”~ͧ�.¥7;}É¡`­b»8®;¹Neˆx•âóï"Êtºæ…Y¡üTŒO$3J!Þ8HÕê-„ƒ˜&§È&˜«Ñ�Kè#‚.@<þMu³OÐuš™æÇZ®6HZ×Z�ŇۓÝ%ŸøÛÖô6=•9ßjY¥Ù°05ÜÅþhCžŒä²�~ôú�ªÖͳNØ_õæÃ®N­ü T†Í 3Jûq¸•fèŸ*<üù´B{.¯r–»½ÑJmâï~iÇt†ç[rcT˜Á€™#ï’X&ŠNF–¡¯/Úã•ßÛ̸ÝÜÞùª{Öù D•f“§¾�Mó)LÓ‡ïÊüýæ_½h×½-ýÏîÅWgýÂÏ¡©4¦¶íŸýSÛ$±7`ºœÛòr„°y~CÈ×`FÖ]²&á�S„†7� 3®¹ñ…sÂ,û?mœ 2<þ-¨õ— ¬fâkÓ8k� 2ö `ë‘ÏðæM s êç|;/3ǽPc›8 óäp3r)&:.ü9”ý>è=(Ì3=Ъ¶VȬyþÎ>Ž­4¦'Átž¹(°ÖËЋ§/CÞ3LƒÏ¢I}àiýŒcŒ•à*Í„‰|Ž KÝÔ.p¦iöÅ\€òÁ€0ðŒL&7”áø9ˆ«Oã#ŒôÂü–lH¢þx°³–Ï2eòË^� sáü*x¢?„QÜÃÍE—*¸ÔÂŒ!]»»šaS?–7'ÁWÌ Cš‚s®¿m\¸Å×�Å\þžÒ ƒN� 4{Ø 6}m&àü˜¤ÂG`dØ¢µBþ@ÍÑl·�t €R˜ÈZh<$XA\«ƒ×=y æ ¥0K€á�…¬hšÂ§¯P ò…P˜é†6�‡l#2D¸ V:°<�0?4´?)çÛõWh@ÌX·è_´=äÙ'„PíNÎØ7�íè ™Ò0bpßx@#‚Lýëu¼TÉæ`c¡® .ÔþÖR C›Ý. KwJ“¾‰Õšô¸Q÷>O$Lñ:·,t7�Õ6°�zA{�j*C#Ld•v t‰}CË#Ýâ«Ä«· Y¨§ �0 U”ÓѼÒ,¼QšŒŒ„È*­ ‘ó€Á Y+ûu†{õŠŽ�¯s¹@Úkeý§æ2êܬÓX¡¡UpüZ�«…ÓCg aFš¬(»|]¢î”N¹ñÔËEq’_Êô‹E ÓŸvy»Œ˜úäH�R£äYì<9W}í Z˜.e<ø›iôM²ÛŒz™õ&–™LRV+LÁÛˆam}jG)ú¥\bã'¤©RüxD5KJ˜!ÏFì‚»_-ŠåÙv“85ˆ1æ”W+ÝbPÂ<»ù[q�Ö&ÊW+õÍ«•ã|šf`±äªö›ÁÓ«œ ôF–¤f¥BšÕ¶m$¤Êq×%¾¾`„™… 0Œ盞ð÷M­0‹ÿZ?¶8Nœ³WÉ5„0˜ÈjëOõÓ ×¯TRlA9mú:%úþÍVh‘#„™mXQN£ö°ÂŽî*Åg<ê_’®R7ƒ Óõ iz.Ž\áë�B)6rgz×øO¿ Sø¾Fÿ5GÎõsO¡�®7j~íÛ�&òŠ�töêÔú-kö/b/í¾(zD|“¸A…y2g÷±$ûĉ¼[ð- ¾Ÿ¼Ãlññ(̽’ÙëQ&o€ø�û&¬tñéû… 31 IgûœŒZFHÃiò‚„]¸ý’ÌEŸsDF•ù6³a†52&Çž%ñQ~&n©:·ÊÚça`YÈ `ßáí¤ôDdr2fJªfúÂJ·µk‚§—²ÓT·N6Ï2o'µ…1²Jì«^nJNRßlÜ8yÞ)Ý´…‘ˆœ¼IN)¢ +<»šu…™•›ŽKOöwûéyBœ,ç6 }½²4i swÈtáü ±£^‡ûï™0gyŒšé sIN`ä,zêq°]BU ¾/Ž©–0#(w{ C8næql80nÞ…t„)Êi‡²'ö=_ŇRï¶IÃ_…W¥.LªäèÔØ—d;+]”²0‘MÆ# %vf–·¢ÃöyÔàrN¾`ržº0oa(u½2½Ô�ÛÇe/kVfN †R‘¹P/û�ØpSa% ;¹«ª0÷„®ãfm†¿YX—‹*£3Ç…Á¦D5Ïb·Ã™ «na⎌o¾š0álÀ¸ù�ËãÌOg�*¿w;¬$Œg‡N˜pï%–ñ¡¸{ \¬p_Ž‚0öa(Ö·Ó|vôoãQ% ²1Ýea"dû¡&}»×{ɳá}ú@A˜•�GJUë"¤ô·ëzVŠÒ&ëù ¶Û[�ÓÞŒ &¬¤U²|…¹#ôåtV5»Ýú–5. ¨RpyK´ý„HÒ :žMùÝò†l*My°ùþdÉ…93 SûthžÊ×òå^ôAð\Êï¸T˜ãs¸ÔHjì¸ùOhBíÜñ^Òq©0íñ;mO<±‘kê�uG•€¼äBpÙ­,o}N# ¥¾O‹0{ g‡3BÇDsFöð_á�°²§]J˜Ã=�*E‰0oaèö� š ‘„0µ$û&å€QÙ/æ�6« ç+ç¬;=ðˆR1!îýð?»­U”Ó‰ÝÆyEYûLq{u½‡0õm£GÙƒõ¼©îP[¦!&îx-ÜWWßä&*$b ±³—†¸øtÒ½I8ÚØP{¸f§îmñæ(G9ÊQŽr”£å(ÿ�9¾8kŽq‚ëˆö6&¦OYYYÙÚ…¾™žÚ,·”••­_2‰±Q\œÁ¥bzà>©PÄ_..þù¦èy¹vÄ%¼¤øÁR~?+*/2­01ÆzÇŸLüÕhvZ¡È æ[@·¡}’/úÍeº-=JøÆÚmÛÙòF×ÁÉyƒNn—¦ûI9LëæAR˜üúyNúœ/8¯}$ÂØã»œ�½ÇØ|ÂzÎW;ßµ^‹s¾ecç|ÆyãÌð]Š˜„0ì9»]âV¶ñ™™M¼.1Ÿõ®JÎ~ÊXÅožŽñªÜ'DÊ ˆÿo÷î§>»�±�5�ðK~Ÿ[˜×¸¤z®“F¿ü²>CîÀN©]zVï) çÚsEÂDÖT&Ÿ1«^u@…óxíÀMí %ùŒa‹kÛ±þἚÄÏp s¢s;æyì�5©3—ÿ3A:-ágtO¬KM 3ÇyYû36š7oo�¨•ð°MÍK 3ƒŸÈ^Ü༺Ÿwe�U:¯þåæùÊÔ[^Í¥¿Ú$þY ã7§µ0Ç|ZŸÏJìáŒå}º™±Ûì~Œõ­u sO%‚þ]ÃÉ~…† aòv®IÍ­0oOŸþÄ&Gžn;¿œ2a‰}c}Þ¹|ʆ�.aŽYÕðð¸+ç a½¶ï¾ëÂ+§µ…eRÌ[viü­Œ½çáÐ Ó»´´´ôõ§]2þz°±ô2çÕØÏ6\ñ«ùŒ�.uÖ§O*Íc¬ãôÑ=‹z2ÖûÉ]±=ÿšì[t8˜\šjŸUzc/%vç}ç&g©î›uu¥×2¶òNç–Q:‘Òèÿªa Ó endstream endobj 133 0 obj <> stream xœí} |×}&m9’“ØñÚ›8UÓ4IÓ\uš®wS×N²Iݤm’¦›d›¶Î¶±³±[7Ù]ljšº»E#˜¼À[$EQâÌÞñ¾ï$3ï R$E‚÷M`÷adšæ%€ðý¾Ÿ~"Á3~oÞûŸQQ¡ ‚áqšÇi�`ÉœT”§5Ôz á`ŒAŒ1À’ À@0£�}úœ Hj8ôeb´ ¢%Í:«¢®+2¡/£e>�+(²�ÜW|A‘ .ç Ñùæ31VdRÔÕ:«’æÕ´€QÈÄNÔp"ÉBœ�È Ì]ûb4ú?Î’1è/Æ"«h€éœ4ù’|6£xÅ«)›ÜW|¿c¬jÚ†3¼¤\‚á1Z@–2ˆH§,H,v\­¾MµN—öÌU .6Œ,·Y×zàF¿}«ß¾5äò �y‡Ç¼ýôaŸ¸ÙÁ¯7™Wn—*úæÙ÷õÚ‰”rg¬AD†fÑ_ˆZÏc¯È˜ýI¨ @t.ˆ(:@ˆ¥$%’4D²Õ¡û¬BK+ï,Äi!Ö ¦–;¯×M°ù[Æ¥&óJ¿Þ+n";¶$û¹<’Å{àF›u­Þ´\5¸XÚ3§o™¾Z};±Ø�ph "²)¾�@ë¼à[ç�Šå¾ám¹5Æ`ÓpP牸¨³Ç /FC�o}¾^;Qk\ÚvY{àFq÷\R™ÃççDÆ)PÔ6Ùdt{½‘åúЖ[5›®ÑåõJÆ…$ õÍw:lò?y�ÂÇVyï¼¶ÄI°Èõ­05 ðȺ½h…È@�'’Œ@²0©ÌQÑ7?à�ÿÉ{¶ÛÖõMSƒBj x½^}“KSdÓ–[å¾µò#=½;áúpeÑ–[Õzž` ¶Ø^Ù¿œ+ó=Ù2ºv]z43Òº-à(&ÂË}›åD4+¨Y bÀe o=|[­k²ëtznö/hKª^[n�Ó[âs†ÓÓ»å¾Íò@¡ð^Nv™öôôn×cá•ʱú‘eÙ-uzöÀ ªešD‘/ä!Á(A:Ê}ËÏJªY¨f@4+¾“/Ý:Ý”‡£ã²~d9ýæÉB5%¤§w™öèä™ûÍ%‚éUÖ„BáUS(È›^1ÖbY•Ý4þe¿}‹n™!|ñ e¾@°BLŸlÀÙ :OP递…8‹ô˴΃ÛÊ¿l6¯¦ß#|ùB …W™9¡Òß¡ Œâ Z |)4¤T¸Í+²›#pì7õÍw_f‘¶ÜJxæe5•(ªîK«ƒúæé^1ž¿±Á´’Rî$Y¨ÒÛPÒ-†qZ¬’gÔׯ0Š×0(=²zpQvœ ;…õÌêqdh eš‘4 ¨0t|)Yˆq€@þ_¸Z=Þ‘Á³aÕÀ‚/Ð ¢)G^ýíæá0tbã” ÊD[h·>³íî³ è ëG–ã‹ì1,$(@ D_(·Yü_”p&¯a\ÉB�ÄÛÂÂÅq,:=Lë ÚwÑÐëõ¶N¨taâØôz½ÍÃ3õc8z Á”rW0dnÈhhºu†D ~0†4”M“o‘ÛD§…в¶Ýöz½jZ XÀ¶Í„hˆátn�˜§Í£–ªv›¡’§ŠùV¸^€XÀñt‰ÍPi©î0uÚF,îá×Ûn[»»ÁÖ!Ç&΄ü¦kÛ¾#,,íž3ºä¶N°Íº–Xâˆá€&ß‚ëm*}¯ØRµˆŠ²’L,u¶…fi›¦¡qKUCbbÅ”T§N§¦f®§gahhÑl^`€E³yapp®»{ª²ÊU ƒÉ)Blœ�G[j:G†'‡Ç¼F—·¤kŽd|©þlh¯ÕmÃhŸ}Y˜X⼟Á{ityX´û*=¯ÎW¦†^ê&Ey¯Ðn-=®Öó$tMS¡û±¸Go6ƒ”41-}ª²jÉbÙZYñ›KK‹&ÓdÅM˜’ Ò2F«ÚFlóüzŠ,ûÖjŠW…àCGÕ�FÛR­ÓÆûï|Ö›–c8‘àPê&–5:¾MçLb¦(ÊK°ÈQÙh Õ@ƒiÀ)äR0>aª²julìèÊ=+ÇDyˆ�ãu†á¡q}Ó‚EykbÈxB”QI�â,ï+ø…5CK²[*˜Ù'n^¹9¦aQEIŒ �€2Jea ŠsjX˜Váê ÍDÓ€“Ïɇ)©ó}}žÍÍÓëw'<ëë³��01IÈ¥š[ET!ÅÀxÝhÂ�‘àOôR@4kUPF’…ÚbÇýh8 �.�¾ù‰ mÅè`o:�£T4”Vªa�¾e:$`ÙÆ”ÁĤ…ÁAÏÖ–õû-onÎõôÀíW•là ¦§wÇæ™ƒ9)7šr(Y¨0 ²ªÇý[Óö¬ê_ ¨¦l�:NÈmÌý!•Ï£üpVö/È~ÓN@sëHÐÞ©®ÙZ] œ~wbsyy¢¬\Ð&1]¤¯NóÁ)d\ÕÊZ!9¨kš É%Zn6[V�•é»-Âä6én� ª�'Hr°!ÂŽ +W!¦¦­��Ÿ�~wbÅn‡IÉm¹åuú"ôÖ`‹&«(£ ®C&.îš“ß^!ËÛzœAÄhTB“W“`}£ Œ3ˆ¡n±Î éYã†Â­µµ³—°„Íåå1=eJ¿O™U:žÐ�*™`IÇÅQ ; u+ªè É]VP±n&£²tÔ½“ !“¨I$X_l?ËFIþ¢id $&»Û;äÒïNL××[“R“ ŒJFÐèÍÁàQ2Æ8ƒ"†U÷M^t Ù 7µ%’1TF!¯‰ Ÿ„IhK}!X×`p�í¼Ñ(·|߯lW7¯MJ/èWS6RgQêä2j$ËJµ ®5F"JþdŸ}+±Ä�³¨°‘`e‹34@ga$–:B±´pdx$h—l6¹…» F£-!1¹`H©³áz«\9!>W›@øZCW DžÂþg¯¸™Pl'X¤bµV–º74ˆ/²‡bPxÄ6’R††ä–ìþ˜ëíµiS´:êeDƒ³¯gDö 6r »áfœATûÆ`ô™>‘qi‚â íÁÙ½ðׄÔ+³]Ýr‹õ0L74˜Ó®ÆÐ<êŠÌ x‘ùÌ컹&XÜñH–]üz ?¡”ò¬ª’•:ˆQ(.c€]Bè¹³†Ç¼6ºd¢¼Bn™Þc Û]PNr/2«Juugcbí Ô.ŒdanÃ¤ìÆºØbY%Y¨¤Pù Ú DS•:Wj6‡d'%sC¿=#Ó³¾.·Fï�­•˜’ZÉu‘PÔÕ)Ëûm_ŸGKˆ×�’Ȭ�¤vœ«‡ _{�¸mùìLs‹ÜÒ<¦ª«GÙòø";NŒDŽ¥8…öu ÛC¤ß{˜1«z\À¸k€öÕ#`,rwdU�Ë~±'£¹‹SÓ<rëòxØZ[ƒ‰I½�PÊ¥W1B€Æ‹ÄÐb¬o£U3‰+ÉÃ~ûV\¡�ðù�üžN™‚jT)ÄÛC14Œèò©W–y^nQž CCÂÕÕƒ‹$ƒÆ‹(9ÿ‡$pÄ0¢†�MSòë>fËè*Πº˜$zÂ�SüP‡Ò¬I4¾��¡ÛuÇÜjrd_“[Ž'…Ç#¦¥›zÅüÆ)’q4>ÒŸ µ´Jã4H(¶ß‡½+ƒ�E�n’…¨aåö—‰•)¨e�†ƒE�³²_à‰ 2²—¬V¹ÕxrÌ × �ž„ª^ôßx ¯×kh ùU:œhtyÓ+\ èqÜ=êU”¨Î'Y�~s,tã¦^Ñ~%Cn!ž ž­-˜”<2<Ùj]“v\¸ŸŠžš†g¼^¯†……¡¼J‡»ÁÁBœŠÚ&NÙ½\ÚK«(4z;ë•¶É3e³AQµt Š§’Úá1oa§›äÉ‚Óï«5ù–‚:WâˆtÀ *wÏ‘ôµû>Õ¾ZÚK“,ëž—ý¢NNdž¿¹¸(· O‹õéi!!qØå1º<‰ÅÒ¾5’=•Šõ¨•.Á€–ÑÈ^:¸hty“K]8òn«8çÉìKr6uÎÁ€ärgèî¥%¿–K§—[‚þ�ãj¶©ÜÍÙc€Š²bÌÉÇj’´ 5I“ÝLîe›ïô¤âœ8k?©Š’³á •�ïÑÆ–ÏõôÈ­?ÿ`º±ÉZZ']—®iŠäÀiz*â Tû†§‡jôð>`~㔆…’'ä¸öÅtÁÔ7ß‘ýBNI!9u}jJnýù+¢(d^“®«ß±å›’l;Ùé5ügQ·´òÞP>.…;ûí[R[EâøÉ·(Ù 9äWé‘ÑY˜ •[|~ƒgshbFàÝþ„e½s5T<îÌ\…«ʜPëùÄGH—î–tÏiXY™>†•‘ð€œZ½!_[jn3�QŒÜâó'×o˜zEéêŒ.¯¶Ø¡¢UÖıÆE'Ï Ö ßwó+CŽF§'¶PTÑÇÏG0(£ ¶È¡Keë�ÚZ¹•çOL”–Yêû¶/ð–qIÃB…Â{9yæˆö¥(oܵŒâ“K�²(£°¢oÞw:ª£UI¨õèA¬á`å@8ôi±1¥óýýr+ÏŸ˜mk³ßÚy�I¥N%D'u*_5CQ^’…õ÷ß é%zÙUéu4Pëù¸"{x—@ö�»]nåùK‹�Ïì¼ÆºáeRz')= ‰žPÓBJ™KvëDxtÞì›G]_|«Ãí«D�‡A +Þ Í-{ Ò2Ö&'åVž?�ÜÔÙ¹».3¹Ô©ÒUÖä=%¬ÒÛpFÐp‘Y‡!Æ!—‡4@äs¾×¦c€’A µBwÜð.‚Ää�ÙY¹•çO¬�� Ww]fõÀ"jkLC\w/Ó‚Jo‹-Ãc¯u_±Ð× Ó ÊüÇ„¯[ ɆvíÒ. ±qÇüXŸ™)i».ÓèòÆÚq �**óÑPK’…¥=!}¸Ùoß" ÌTúƒUL£‡5΀þ0j¸bbÏlâÙ`cv$¥ì½Òâî94j‡Fw™Xå[Æ „zÀ}ËÜúI5 òêÆ÷-tòz½õã+ä…WóR!!qsaAnåùk““ =sï•¢…š(i–Ý?•ËëõæÕ�c ¸QV&¾¯Øl^%XTèÔ´_¡S£¯È”daËhHö§=ˆ 5}}zZnåù+N§põú¾{£ncAAÃØ¾ u£Ý’ƒ-–°2ñýFm‰]MƒÂö‰½&.l›PÒ¼¶È!û›ô/AFöêØ˜ÜÊó'–y^¸¡Û÷b›Ì+¤o¡nÚg¡.l»­ÒÛâÃÎÄ÷‹»fQu9'hËßQ”ª-·’¯a`iØ�óàóÙE“Inåùó½½6¶ü ë�óù¸ŠZw‡œ ¯úÚÉCG¨v!ŽPbÜÄ -·j ßáÑxm¹g@H]:”£¥uîÖV¹•çOÜ©©±Tµt½lÛŒ†�صñ]y\ÑI(qšd@(މ�pSÊ\*š×Þá!9A¥©c²¿=¿ÓÜ8p»¸DnåùczÊÜ1zÐõvðë$#åqMï4±*sÓ Å‘ít8°´gNÃÁzl»Õ­¢®NUh"P�i¸m§Qß¼Á1{f–ÜÊó'`bÒˆå°]q|‘C¥·)³nïT1A‚†lÈõˆp'»á&AŠò¦ëï:@.—õ*êêp6 ·ÓˆÎ-»¹¼,·øüƒ»­·½d¶mç„�2qÖŠz>p â�&#H’þ®§ZYlTÑBb‰]ö7 ¹Ô¢Ù,·þüäÚ¢K¿ÞfËŠÆÑ€é‚»ÍšÔ´Í'dɺ R-ÓRšÖ[ 5 XÀ´ÍÈþÆDKuÇdÅM¹õçŒsKãàá×kty% cº»ƒ`påìåÜš�Ýú‹ #+ªi›‚2*r­˜ožx“yEö7 ¢¦=qñžÍM¹%xZl­®‚˜Øapï¢à«·n«ÑÄ®»*&Éý‘þZáÃ!—g€‚2þ’2GçóŠ\+Nƒ0hëq…ìÜ¥ÑQ¹UxZÌ ðùìQ®·¼w•8ù*Êñ;AC’…‘Ó¾ÌábÓ)‰ÙtmmOȸñSÊ�JšWÒ£*�éAZE˜wn±Ô÷�³œÜ*<-œ¹yæ6óQ®·ÍºF2HŨNM‡v×d·BpòÙ/¼pÞ÷Øãï{ìñ ~ðÁ¿ñíí!0 …n�FG'•·¬Ƈ⻄« .~Ãí–[ˆ'ÇÚø8Ð& ;�G¸+a `zÔ¼%³2T§NšÏ~á…gžý’ô£Ë£ŒËF�›Ø,Ùߨ=‰Z®q�ðùµb b­1üÛ>XË&Ê+äÖâÉ1Îr£·ºŽ~½Uãj b |k5ö õI¹SÅßóÞG^úÇŸmXÖlù«ÿþêçŸûÊW¾ö-2µ`ûóW©[ÿêOw~ãKÿø³ ]•ôÿzãß2Ù,ªæO¾þ�/þñŸÿüßbo¯À}põMeâ—^øÆ>ÿÇßþë—s¸†í—´W _ûæ{ö‹ò×?x�­î;ä�£¨1 pŸgao0EŠGFgÍÝ‚¥¶Ûf¨nè@F6HI´IBlœ@j@|‚�œ*d\Ù7xºÄRÙjn5™†'†�÷*˜ËBlÜæü¼Ür< Ö¦¦@‚vÄ~Œƒ-Ó:£¦µ}1X3´(»eƒ“»TœM×¢lÆ”|éC®¦ÿ½�<ú;Oþ’"ö¯þû«>øà�~ò/ÒKÿüËø'þãvþ¨|ðâÏþ¯Fúÿ'?óÛŸùìï}âÓŸý_¿Pýý«?=þÂö7ö‚•ßÿOÏ=òèû^þÇŸÿ«2éÅ—ò×?xMzé•ÿùæ… ÿíK?~S™øÂŸûÂ…‡óJZyóRÓtbb¡ìwrÄâ67ðT±��´‰Î¼‚©Š›s]]K6ÛêøøúôôÆüüÖÊŠg}}siiÃí^_Åù��éº:ÍŠéW€&F¸^`©l5 ¸R´µ¬~¢¨XnEž®�åVç±niõÀbŒÁ·Ýâx’ƒ�Bĵµ?Ÿý ï}äѧ>÷ôSŸ{úcÿÔùóþ÷¿¨�ou¬zþËú±�ªÞÍ–ùÉ¥èsçÎÝê¶EÅü•uYïö¯ûÑOþåýOþŠôÿKŠØsçÎí}ÎÕxà�¸+ôögþäëßùüs_9äͧ–;Õz^M�4ùÒ§Gl –[]BF6ŒOç ó}}k'Ųµ¶¶ À�º:{V¶gå*Lý»��#öu!9uB‹,°X4™@Zƽ7ïd¿Np� D¼ÈŒÓB$ßã >û…>úŸTé "ýõÅÿèK_}âýO”Þ­7yì?<ñãŸ_Þþâú¾±¨¨¨„Lö(*þÎßüpû¥„Lö�è(žûùç¾²¯6ÿ�:åÂ…‡ueÔÍn‰ÿøÓ{ßc�òæ §Ôz^¥tMSgëÌ�Vþ†ÄÆM”–­ˆ¢ÿì7fggššÅÔ4!õÊhuû0|;íÐÜn¯d„Pìxkm &%›úŽ�YgtyqZ ¯ßVR ¡8lóNϽçâgþð‹Ÿ~êwQ  °ŒÊÁâÞîUhtyÎ�;÷Ï¿Œ?ŠŠ_~íÒöK)×K£¢¢Úͨ£Ý§ŸúÝ¿ü«ì}'?ø‡7z×»~í#¿±‹’ö÷eI÷ÁB’egYSìò˜[G„+YâÕì…áaÏÆF@%°êtNƒø„ÑòÆ‘·’%ønªª: ¿×�˜(,²q'»ÛñÅ¢RgSéAFUÄA} ÷ªøÅ—r†|›ŸGß÷ØëÿŠo¿Ô4„ ·cÓ)éÑùèûÛ~Éèò<üî÷EÅ_þê_<÷_¾¶÷�üøg¿|Ï{Ùé»'o—b b¬ž™ƒÚÜn)éÎë7–yþ,…°îvO”•£mvYÈ}}®É©!‘Y=ßׇZl9N»L¿9¦¢y eØn… w©x@\ÿÔoýÎG>ö éÃÿüÜ—ŸúÜÓCogÞT&>ðÀ7[m¨xNqTT”tF–\ÖQQQGQñÿþõùó*Ûø]ïDWÖ±Ó±v¶ÙÖ4œH²°Ýð!ò&‹[È¥Ä+ËÈ¥ˆ�¹¹‰Â"�”bî5 Ž�ø„ ïǵ:†ÞäˆùäóÁó¦0Z Y¡¸+|Zû�Ï~á…‹úõ—_»ôòk—¾ý×/ô7>yˆä<éÕ…MçÏ_øÒ ßФéþé�?þÂw_ü‘ôR¿ôþ'åwžþ¼Z{ýõ7±ßüÔS�<ú¾£¨¸Ëºð‰OöÉþê¥�KÈâ^{õý«ôeßû»¸páá¿õ§qWhUüµ¿}éÇþ—sÈ›plaŒ€ÑÂ@@ûÖº<£•- .ÞÝÚæÙÚ’[ÞeÅô+B=ZÝ “S‚6ð´>3µ‰æëin~Qç,ÁB «ÂbäV€øãŸ_þê7¾+ñ¿~ï¥ÿüò®§dAiûÿé_~ì7?ý{ÏüÑ?ÿ2~玷¨Îø•¯}ë7?õÔ þíò–Ñï¾ø£”œ»gÿêOñ¤·GxЕ=_ýÆw{ø»ûÞv³ûüøOýÎ|ü“¿õž¾ý]F—G­½þG_úêÇ>þ©ß}úÿë÷^ʦkÿ„o–bàîÏ¿À_Ësè6ææä–ÅÛðlnÎ45m¢•.³gdaÏùÍ…˜’ji8åý¿Ù¿ÉN¬�Œ7 _¢sq¡ nê‚6iº±ÉëñÈ-‹}°b·ÃÄ$>3Çž™T «7Ün15m´ªíô&¨5.Åp0Æn݉#ÜÉ„"{bI@*8F«ÛabR�+Ü\Zrè@zLN ’3òÚä$LJ­ëõ‹Z,«1TÍÔ%„@n„'cb‰#í¦ÿÇ_Ž–Ö‰éW‚j} <žÉŠ› )$h—AÞ÷‚²;âŽXµtv $ P†­D¶ú—ÉeάêÛþü™.��-wd_ ­>WîÖ6A›§ª«eqÁy67§ªª…¤”>ê?sôÂM’ñ ÞŠLe _¦”9³ýØÅÅåáõE.�Þ³¾~öB8%f{z€6‰ÏÎu\ËY›˜8Ë_½âpØ32y�agŽ™_(MnÂha0¬[@„1{ø¥ô¼ ã¡cˆSÊ�9µ~S±µ¨Æq-'%,a¶»$§™k:A‚vªºæ &-n.-M”–m’¹Õˆ¿�A§§P01’D¢4º<ŸùìïýÖoÿþßüàŸJöÿ#I«påÖûGÅ–ÊÖàŒÚ wêê„Ìk&ëœ�-‡ñ 3Mͺ¢ÍÅÅ;uu 6ÎV\3,*ëÆèòª)AMET|¦ì×Ro”ù‹_ùÚ·¤æi?üîßüÔS/þð6ß‘‰ç/›[M0%5¨â5GÿÎtЉ’R´¹EÅ’36¦ ÄÅß¹ukmrÒ_¿nullêf%ˆ�³V�X›Á.©8²£>c¶™fžÿòŸú‹þèÇ·ûŠŸ;wîŸùíKŠØ�¿.µÂuúõˆÅ âVÇÇýõw~f¨¯¯ÿâ¿øÌ3Ïìü¤gsÓq5ÛR×s÷ê¬s£e 1Ùž™åno?á‘ÙãYw·´ :è”4ëÍæþ,jö¥5NG¼[!Ì?ý‹ï�;wùíoÿíõû4{ñƒw˹%dåÌvuûMZg‚’’’¯ýë.\ˆŠŠŠ‹‹Ûõ꺭K¦¡u@.�¹Z¹ �’&•B»ÛÚÍæõ©©}‹=k‹&“»¥eŒf@lœ�–a-ª6 œi—BÉ»…3‘HS¨²Û¶øå¯þ…&UwH¡SJ™ã”‘&kqMhõ–ÌÍÍ}æ™gÞõ®wI[”Ï}îs[û…–Pè69mß9#Ö9sÓ�µ¤VÈ£Aj:Àq@ .¦¤Â”Tp\ !õ _ÀŽ–Ö™[†ÏæÉ»—R¤É×è#’õ¶ò‘�‚ð£ýè�7Þ8ü‹g»»…ìܓݟ` ª†0@�A¬ì�T&†-1Z èU&ÂUŸàÇøËÙ`[Â^¯×jµÎÎÎÞã<{ÖU?&6Ÿ1oö-Äp0Ò% ŒÙoßÂèv ­j»j-awJøèX²Z…ô°/¥.‘Ž=aL©c�æ{BBbh=ˆO&a ö«Ù¦N›ìö:ó§|Y #2Þ%Ly˸Ë�¤{ž¥¶{Œa µ@á4–¢NBVŽìö:¥îy˜Nˆt² WJ�l V,í9^ HN]ó·Ô…SJØë;‹©iþ­<ÆŠcUPÆHWùpe~㔊jZ(hºsôï2õÙíW2ü)³@">>þ´öa¦¹Åf¨”ÝdÇ¢ÑåÁiAQ2†16’‘áÅaÉ”r§š²©iáXËm\…»½ÝO" ,ÒÒÒ>úÑ�ž^ÂÒ° <éGa»m�d Ɖb8X=™¶†$PnžMÉÂçvlqñÁÚýu'ü(a hxǨìV;:«c "É .j}dòi²l ^.¬€³([¾çh“OÍ£®üé"p𻄥1 aty}ÕL6¤âü»³È;lWX1¹Ì©ÔÃhʪÔñjZH-¿·ƒkDX±qÁÙ"^ÂüüüóÏ?6žx¢¬ÜRÛ-»íŽÂ6Û‰r/‘�£¢¢p_}byß¼ìo,BqHŠAPÆ_êG/عVœC‡öÙC‡â6óEH !�£Qjæü,ë™ÓDœ�R&Πµúšû�F(7F–Iªi›‚2*r­jJÐpb£ùÀIÇG+šgêëåV’œX›˜Ò2d7ßQxµæ¶JÔo©cl8k%X9‡ ©–iŒ†î.Ô4ÀipÏ£1¯/ Åjb?³±!�ä°3Ø{X](Œ¨d¡’~ËÄH‚†ƒÍ–H»€0aB±CÅ-=)™XY4„Q|bÉ=RmAFöªËh¥”––šL¦Óü†a@À¦$Ã䔋[v Î&󊆃¸OÈÛí F ˜HÔ8LØ7P”7�vKö�.íUÔÕa 8Í?þüÕ«Wýò>÷ÂY  þú&_¤âôÛŽŠŠ*l›À(>þÄ­]" &–tÏ‘,L Æ(Ê+ÙWQW§*4۰¬÷À²ˆûº@’þÒÂ믿þÈ#�P>�$ù«¿ú«øÀ¦¦¦üò,¨Š'JȨ̈+hƉ* Z'wª¸É8ãõz Tˆ‰7…<“Ë\*=¯¤¬;M¬1ð*JH-?°lg„_„ñ þÒÂ믿þÄOlX[[•““ãõzEQt»ÝÒç].×ÔÔÔÖÖVSSSiiéøžPõââbMM Çq]]]Û­,%///WTTTWWÏû5_tªªÚrkŸžÀÁÃ6ëÉ¢X[£Ñ½ÓÄ^¯· aŒd¶=ØOθ�1@A/ëÍïPq¡M[ŽâMmªG,3bJª¿´°KÅÛí(wþùï}ï{Ÿÿüç?øÁ>ñÄïyÏ{JKK·¿‹¢¨Çü‘GùÌg>óÈ#�|ë[ß’>þüù7ÞxãÃ>¼÷½ïýð‡?l±XüõÎg,7[d·ã!dZgH4 /ê�À£mñÅ�š;áÙ°¨{VÊRŒi§}µåV’ãI–tï¿©6oÛ3ý¶MÝ¥â7nDEE1 ³WÅ>øà�¨Gßúúú7¿ùÍO~ò“ÒKïz×»^y啵µ5Z[ëêê’^:þüã�?ÞÝ�Ýß¹sçŸøÄ÷¿ÿ}½óÙ¶¶£¶·•‰q…vœŠÚ&¢ö£m¾<ØñT‡2㋘^(j›Ükâ¶ 5eK8ÀûapÚ¯]÷—^ýõ‡~øÒ¥K?ÿùÏ¿ó�ï<ôÐCO?ý´ÔTv—Š¿ð…/lWQQQTTÔ‚oÔk¯½vñâÅÕýÆž?þg?ûÙö‡¿øÅ/>ûÙÏúë�Ïuw[ «d·ãAl4­HÛéfãÌ^#O5Åã4¸ÞÂíyïs6[VH™¸i?7§½^/É–ýjÓð„=3Ë_Zxýõ×ÏŸ?ÿ]^{íµìììõ·æ¥îRñË/¿¼ý]ÍÍÍQQQR‚å—¿üå?û³?Û÷‡Ÿ?>#ãí>�æâÅ‹þzçîà~çÔN`´�_?¶w;}WÅ:›&ßB°‘ÉM¡Êõ“ ö71ò~Ô�´�»ßB=bqÀ�‹wb—Š_yå•í—vªø›ßüæ×¾öµ}Â.µUê�8¢Š/]ºôä“O.--íý UñTeUÐú¨}1DÔ@õÎÄ.à´ Öñq…b$3ähhw£‚b–—Š\P1ªRÔp°°cO0±áßxñ)Ul±XÞýîw¿øâ‹R iqq±þ­øvIipÆ‹�.oœAT1`;±ö ¨u *v昻٠º—U e]ªî¥â¨¨¨$jB­ç“ËÎt k„§dEß<Éœ0氽ʩÖÙpZ 9xsÏd�ymÅéô‹–——·S;vavvv{ÚüüüÎ=óÆÆÆÌÌÌÎA¥ëëë���µµµ6›mû“333RøIÂÊÊʽ'¹01id4§¥$•:U” ÊÚ'À´iúŠò’¨�La �ž¸BQE #ÅÄ8#¨)[l¡ÝøÎÇ1O—Ì øK¡Ï:JC¾W!öÙ³Ö¸D²P¡ð^NÞ?À´ å�»æÆh�Xy‡Ë{çI_£K}$«)ÎT¼³5„åfËt]�ÜJ’k·oƒôLÙ º—èALó¹e3 Åþ¦½ˆNv+^ {ìÉ ž=щ¸PÄu€ î}\ÚNó*½-Î î<›;F�:½ÜJ’ ƒƒ¼¾Pv›îbÍÐÉ¢JÌÆá#=ˆ%(^UÖ¤š‚ÚGÄYä,îœÕ0�`\w «ô6©SÓ΄Ì¸bb=;Ž¥÷n—Xêûd·éN]m±]Eó…mez5 jXÖéǼD1bÖçšfîášÞ Œ�*J$YØ·#v,d\õ—ƒë lmm±¸¸Ðßr2 ×–%¸ªìKzæ4œH²@EÛľ�PRh¹î?þôÛφyõ“àÔ½]Ó{¡¢Dœ4½Ý»ÕZ|k¦¥%p2ÙÚÚú»¿û»çŸ^J–*¬OO Ú$Ùmº“ýö-’ƒÅGˆ.í %0,Ô7cVW„gFTgÊužˆëàì¹H åÜ’ÌÛŽM�6ç�ÜÉ$˜%,ÕAؘRÙͺ“ùMS’4òÉLŒǬ]Å9I´ŒF �‚‹F—7¥ÔIÐB~ݸ:O<™}5ù,ÛE0Br™ó®Ĺ â6õžA.a¯×븖cîâe·ì6[,« b)G }BûJPqNŒ�- 7—3è‚h÷3‹»ç4¾ò¥æãø-÷B™‚‚$ KßrsÙ •3Í~ÞT¿„×gfÐx— é~ityK ÆRŽÓ˜XJØ#8@²ûeÞF(»„ 4^œá‹Ú�í·Ü…«̚T1€`a7Øð»ÄÔ4? $ø%ŒòÁm%·d·ì6 nÒ7f £Ox"Þ5 ¢Yg`«uMö«‹Ðèò¦–»Ô¨vì®é½P1@•ƒ*Óoº¤}µ�zeÅn÷‹:BBž­-˜œb2ޖݸ[FWqFØÔÔ‘ÒxŽ‚hVPÓN ÅöÁȾZnJ«4Ey¯Ðî#XïHP&£}µ†…�(…ØRßçòGúGHHXJöròe·¬ÄA§'¾ÈŽQ¼ZÏGXžvà”€s@ÃÂüÆÐ˜(®”<8kMbno7ª==|y>¨›1ÎÀ–ѵaçHJ9åðD�ÇóÊ+¯¿„½�ýJ†©Ên\‰¹ “¨v‰Nã—>*( €d@¤hQ.öÙ·â ¢šá1†ÇÙcˆFñ-`4ˆ+´÷Û·,·ºÆYîÊ@~î¹ç‚]Â^ï¢É$dåÈn\‰• ¨ê!תÒù_Âÿ P²‚M‘x;¼á™ÑèòfTŽ‘ ÀŠLj‡÷£A¬ÎJ2 ³j|X\WÇÆN ‹’°gsSL¿$¦6ëÁ¢j*½ Èõó*½ %#¨i ¦@|‘} ’Ðu¶¤[gH(êê”e}²/jx{}8=½›d!×î67 9®fwœqIõÊkmãoèe7.JÓrl¡µ¬€1oOB ÔHdn“,̨3_f¸²²ÍÈË”…FE]]à웞Þ“oQ²(g¯zh‘ÏÉŸíí=Фñg¡%á�¹9Ÿ` ‚ÙjF§çÊÍ1‚X± gýæ—>Wh7Ey Þ¨�ô¼= 6™W*AE Êü€›XÉB•¯«ÉÂö.'ˆOؼWåBggç³Ï>Zöz½c k½Ù,»}Q>|Ã$ÉA´Ñ*àFk'(ʛĎãEf” ÒŒ½M‰ü:ÉBTï@#§ÄÙ˜X©³aè7B’…ÃÅõ®Ýáûêï~÷»�=öØ /¼BžïïÒ3‡�‡ ‘<ÚÝ$Èë·ÕS@7Z»€™qΊ3 Rº8vƒ�ØBG)7(^föõyºP£6ŒñhËΛii=H‚ <ùä“QQQçÏŸóÍ7ý;û,@X›šB{i“üe>e½ó$ð;Qà ¯ß>KK³Ë1Ú¦¦l+÷ôa‹ðôì7ã‹í¨Å4 Ÿ©„%`¾_M20�—ßjM¹ /½ôÒö·\¼xñ‡?üᙋòx𬯋W2ÌMC²›¸jp‘ð–âz$ä³7±Ô¾IMñJ��`@ÍP¤·�?Ù'njK8¥dZYì‹JËò8 ôùí@›¸·ÖiffæÑG�ŠŠúøÇ?þýïßápÈ$Í#ÃãcXS&»‰k†�„1ÆŠÓüo´vA©CBö=‘AÕ@$Ä?ì�› E’�ƒˆs� :Ü8 iÎ Å9·Ä”Ô]ž®W_}õÃþð¥K—Bå8W ,� Pê úDü5…9Û¬k±Ñ7n rœ…ÁÂô‚Œ éŒóú��BÌ4·€ä´Aæ£_a‡›dzöÑ| 2¥O•ŽÇ|'t’7ê'# !'`½i™` Æ d< Œy½ neŠé¡à‹ÞÆ�š[BzæˆMν¢ÑåÍo˜"X©ä�?dÀ ì*Êÿ$X˜Y5IÑ<Ëû}»,=Š qÄÃÙƒ`Az^ŸR‹³n‚ä”õéi¹Õyox67o …kyÃPήSŽ-”ϼȬflþ-9ô/¹Vò† %âr ¡ØÞÁ¯Ë®Žà§Ñé)hš"ˆÆáѦR KPêaRÞ�ŠÙ«5|\ÂÒè¨Ü2= ³³Žk9¼Î0ìØ�ÑĶõø";*Vª«S•âEf¹Íx¤§wko Çé­h[ÈšHã¡ì7ÓnºúJÆŽ4Ov¨(1!wP‘kÍÉí°Ä'OUU{67åÖë>X²Za|ÂhE“¼s—n—|áB/6)ËûÎ2;ë”@•ì¾p¶Ôwï�͇ǼuÃˤ…ƒ½^/Û1©0„€„% MWš¨Px“tÆÎ”ö«×Ö§¦äVíÛØZ[›ªª’RL.í;èô蚦$_ŽJzƒz—µ/PFН_A '&9Ú"%É;8äòÐ-wHªi�ß0Þ<ì>e¼³‡Bá%’&Ò¯qš/̪âcãïÔÕy‚ ê´h2‰IÉ6¦t®ÈhâÛzb©ƒäPKÕóïAøpH=í5Èã*� ,éš‹L}’z£i‹HÂy"¦GB–ÛP'NóÉC*Ι¢7¶¥S01yÑd:nI²¿°69é*Ð�ôLSŸ]Fû]Þ¢ÎY‚�8+Äp¢†OߊVv¾½Áð$ “K�m÷q#ÍA§Gß2�Ž”@Ò×Ã7„¨8g,m»’߯¦@öõsj–x%cÁht¡¢ 2kR¡ðªi´h§W¸šÌá¦å>q“j™ö� €Š²jò-ñ¾Ætrßû³€‚2FS5m%9T솳€j¹Óo[2·[¬…U -hbÄ«Ùã†Â馦£q€U—kmjjcvvsaa}ffu||€¥ÑÑÙŽŽ‰ò Ç�<� ñ ¼¾ÐRß â•:)¥U¸4,hèõz Û'C"ÜïG(ÞËÉ3Ñy‚¢®¹z�^1V?¼,»iNÏn°¡o¾ƒôËÂhÊ¡¦A¸n¡’0ªMF­³Ie†ë›§¥QPÃpÕ48fn6Ž–5ðúBázȼ†Ô�”´‰ % dd 9ùBm-ª6×õšzÀˆuNvËn³nx9­Â…º7Ш+in‹Ðd ç-ôáPÔÕE—ö* FeÄh�da|‘ãfÿBˆÎ‘i]½vkÂ\ƒ¨ Ô´úQ†ÓÀ×Ö‰Ç}õ;$ƒºåÔN„è ÝA§§¢^[âÐP'4”iÌ F—…R:Và mÀrë�^¯WM£ºZ‚�S¡“ê·o•öÌi‹¨%8 ¹V5ÅûC÷Ýó÷  Ù1ôÝ, 5‹%•8Êzæúí¡Q2Óf[+hšBë3'â” aA\¾9!ç~9"¨ä|x¦°}c„hV X4„"±ÔQÔ={wdtzj†¯ÝºMÐ †ƒj=¯Px£³Ç.ð�kìÒ@¦UΘÏ%‚¶^ ²kn× -çî« luÍ&–:_ƒîèÔCê”%÷½ v �¬ÏŒQ”W­G�p&—¹ŠºfƒáéÜgߪX�vÎ1œ¨Ò ±”ƒ¤�*kârš<(÷ý vH.UÖAñš| ΀$Xp½v¢jp1žÎmÖµÂÎÙ¤2Î@’J=DÓè®�©)!˜+ ƒåMÓÏ$Rš‚Ñôôn5…œE$ b bnýdeÿB—pvèÇVýÈ2Û6“TêÀ}Ç^µMjÀ(@Ò�ÐûaÚû}M¾…ÐÛH§@ѵ�:8'—9ÙvwýÈòY–¨w 7ûrë'c8HpèÁ�é‘çJUhRfMþ2ÉYŸOƒôôîøœáØ<´h ê ¤Ò#-£¶6xµæva§»Ö¸ä_Q÷Û·šÌ+e=óy�SI¥vœFÊEi9”MAÕ´ u(*8‹I ÷  F14 9A[nUëyœ†NÄ!©Ôž×8UÞ;ßlYñïcºKب5.v¸¯ÖÜ&}›�õ²#^ªÈS£K#ž+ÿIX‡ž€HÑ,T3¢šæ‘Ä8ô˜&�XlϪ×·L—tÏU ,Ô�,·Z×:…�~ûV¿}kûð%}Ø7Ûmë�敚¡¥òÞy¶}æzíJ‚5 ¿ cP(`´ÍçB·´ ¢F/Sfe”ûN„'´åV�ÁFrü¶¢UzF!·ƒ†C½Œ41¥Ìy½v‚kŸ)Zj4¯´ÛÖ{à¦dSɾƒN�ôa§°Ñj]«Y®X(éžÓ·LgU�'Û¥8>ò£Ò@Mó—)ˆKµ´¾Ì:"0#)#Ø Ÿ„‘OØW¹‰rfÔy¢š²©(A¥GuÍ$ c "Ê‹óíÓp_' 5%¨%…¯eºýyˆ¾Ñp"5…~`4+(^,g5í§%5Qî™Ã§h+ÁÚp¥`×Ç‘ó�ES;U4¯¢‘¢·Í'”`€d_Œ$‹“Ô°0Æ ’>÷”J/¨õ<ê›'â2.M¿¢„ËT°ô¢<þDã[ endstream endobj 134 0 obj <> stream xœí�‰“ÕÀßÎ^$Ê}ìrB8D@@HP¹äX9"! &P „K² ‡‡’Jµ@„DH‹‹pÊQàF¢Èµ¸È²,AE–…Â…½w§§_3³3/5×ÎÕÝÓ=ÓÝï£Êß°û«ï½÷½ïý¡Äi=pÊÊ�'Šn×r|=!Ëñ„Ôó\íí¢Ov®øýÀV´ÍBÝfn)°‰VÆA"qá:ÖqsÿÒ!�hú5ºì@±ƒµbW” ƒ±ŠÌÅ-3ºÒ³ëõòç6lsG©…!Zí×ÞC%Š?·åºÃ**û¹msrYOóíÒ³«ÊÆ)Ë»#k?¿°½¹‚創õ*®úÃgÓL´K»Ÿcbô½H8áÊ‚6f f,úJPÛ¼~Ü Þ;&Ù½Îo×i Ÿ,œc1ÞÏ2îSÇãçfjßü¹ázIãòù™EÉÑV¹º™±‚Í_­Š¯}½ˆÂù±IFê¥Ï)I@Ï‹Ào7°�;oçâê~!à;sÒ�ÒKÍ®fÔó`çww4F°ÓÁ®ƒ [5?Õ=ˬr›zÂŽ ýÛæ$�_ÂÁå3õOØÃnèÑÿˆxµÎC¥Ñ_°ý/ûí`}ý:Ç æ¿HpÙ='•'šÿ"á�éXÁZáèU[ÂàÜL½ÛžÐ;~ž\ƒÿ¬×´üÈ=pˆ";G¿¤y6=p\Ô]¿\ôª\/Åÿê°;Òús: �zœ­ƒßgÆt@¢õ׉ fÕè5K�?M´�Õ3@à6$T7$oÔ¸þÕŠXýDBÌæ�õó´r^‹øýZæ6‚à—Åï—¶×x?BÄû½â|¬Üàâ…Ûï¥ÙEƒGˆ7Ÿà3¬ÎEª b~Ó¸üÚ™¢Ãàþ�àsØ3'ߎg%ÿh�Ú^àVh|Õ´â®Ñ^ö¬1¬ ”¿£Up�9:ÓG£ß/ÝÔ Þ¬Mp³‘eªìM~}Ì !x½Á·Ìí�ØÞüºÕš@Bð+êW˜˜`z¨öëXej À©^„¾D#€„TªÝïjZâ¤"H¸qê'Ð q7Vå—š'Ð$„í§F°¿ù9Ð�㜪›@»(µ°§‘«Ulº¶§‘¤ýð9*8ßì2!gQÌ%hÚUöËUÃÍŽÀ~ôz ×p{,Áº‚8VYØ¢’ÞñÂMQ|�Zôá.‹qéâ8µY$«¸ˆïL9€„ˆG8›º q^V¸Ae)4q»C<t { ×È þ•æ4@a”$}A©”‡{DN°'ÝYÄ�óœlç@è‚„¸.Ëœt[®ÐÃX¹qÜŠ¡­æ‡•Y /†Ñ„0­¥÷™ql£ ¶¥”_($â.É>"ÉxwH ~hÚ¹MLxɺºˆr- ÷X´__ê¥jW�D'C(¸ÎF æSÙ´”��¾»g)¡-)8Lôr+ê²Ê4H]�÷—‘‚…€’Œ§>á—\J[)üt¸`¬.HÈ�ˆNø;½n™ë…û|¸àEÚB‘Ø&† ^£-×7Ô¯œR+ÀWa mŒR Tð#ë¹PØ'Cs!U ~ø�oN2Õ‚\ÇC˜P�𫃂kŒ¿ ª!ä[ÕUð² !¤¬a‹&©Œ¶‹|ðÂYÒ=Ú2’0£`«Jšx0´RƇk@ð¬j:@p.ù'¼‰Î çÿö.bô” ÿðÐRK[Ef¼Op"”­ßHjüë’a01!îC>Á#01!6ÿ [�bB°÷à3d¥àÁ¹ÉÁ»´Eda¼©z(ÔALH‰7€ –Ó>k=‚oѼj¤ŒÐÎ#ø"¼5qßzoÒ¶�‡�åX ½‰9°‡$~Ø«NBx gÅ ð�7߈÷�mÚ1p@=Š B¯f\ wˆB/ù𣺠ü™äÇj&AØ[Ô@E]øB€ð«ºï@Ÿ%>; _£m'ôbáð�;¬ ²u ðræ.´O&#àþøIÓ9ð'M}¡Ÿvþ‹¶�2¶^ÃÎ3â’—a/Œ?E•´±Ž ;Í”!tжƒ"B›¶°§ºÏZö[ ôÛo¯#ôè©ü ̉e@¾öáøB¯CžëDÏ7Æ´-°Ž@ôTrÏs—ÿ0m п†Øç‰à<À»ßx¿§m!û‡â«°7á&B¡­÷ú;´=d±yélÜj¡Ø÷mç»`+Bð_ÇnôEpØ/´úC½`{ÊÿÔÔû[Œÿ')'@ÆÕ�Ç>Þzy†KƒýR…sKà­�A0‡±k_@ð ÌaÌlx²çÚ.’؆üFÂlâ‚ïf¯9ÛÝ ¾uŸ¶‹Üò†¢V ¿*(ø Ä&Bßõþà%8>äiµL€Mì:@ô+xkcçžPÁðª~6ü§¡¯Òö‰‚ ûUãÞð†qQXÑdh³�;â',ò¡4¶ˆ7½“¡=|ù¤÷Hhy¦$òIï©°tÜù~¨V'dŸ‹´Ü¢í~2Rp0¬Lø}ô¯ÐL‚Ô ëOGù¡ó�*.v|´ *d>ûè ¨&t]” í_K E”üåÄ�pŽ#¤~?!´ÌÉ1Ó\ʯ˜<#ì” j å`–�'-¸JES×BZÍ„aè*”ûµµË0ÖvìT™"”b³šë&ç×Dªvž‘ ê!Óp«ä×@d&/ˆfÐÇÎB¥_>½H”ài DèõŠÁÖAɯ#õN(T jVFû '+ N¥œ Ý÷š( ¢>tÇ1ÞÃm£+È=KÍ¢iè(H‰å—z™æE$nFÌ"”C/„îÊŒØ~m«é%,¹ÜŒ$ù$µÙ÷Q#Ø›Úl"œ‰9D¼4¾I©dàŸQ凯QšMœß=¤Nu¨¤²ÑÅÍUé‡þD%„®²vjQ× ©+¬E"YF!„îZÙß—— 7czñüÐzÓsµ›‘ØõU`€Ù!ä6iòC›LÞÌt3ýµ ¢G«MÍ…x£F?´ÆÔ²ÐU'½+­D÷*gdn©f?´ÂD?gEWí‚¨Ý Ór ÿB~hŠi½P¼¥´¡%O“óæ¬N\Á«–ÚaR.äÎ5ŽO¥î2#„Bi�8ýPOSNvðûêV"’Ìâ Ÿ’ÙSÍâ÷kò¥á~nn~ü~¡�U�î5™c%uX6|ø$V H(€5=jdù/V Wá È(C3 þDî`Só±aÍŒs%�ÖµÑò”aeM=V½TW¤Û%c¶“ì65Û•*0*[s]ôDIÙ¬¥>ÒZÅÿVEÆqJW;;/¡N»CXçfÆ¥cõÓCèÙR�Óµ›ÿ(SOA„žúFÏ¡,²ËSõõK[‰õ¬ØkO¨ø§Ú°L/Õ붺]ئÛÒf§W ñýi:à )suyÅ_Þoo„B>àõxÕ‚­˜�À"D™´™Å¶ó¡ÀoU¼”�ÿžð«£\É �L8I£ó„øÇŠÛV¾2Ö‘‚4]]‘@# ÂY•§]‰Ði] ×î++ÏŠüÃ,£s…¸:¢‹©^ß.–f’³v³ZƒˆÅ‚uX ©£Uv¡Ö ºv×Ú·�Ô±9XíåúzF8•­â6‚ždfŸ¬j—£xñžv\ÇF';ÃØkóߙޙ¦ŸŸæž_¾#÷RIÇ;‰›çêJ¿>½wí¬á�ÌÌ+ X: Ÿ½vßé¯K­Oˆ“çªJ.åîX>¹¿;Cý~0Ði endstream endobj 135 0 obj <> stream xœí]ï[Ççšý½ Wi¯´Z®>�dgg6,‚µF¡Z ¨‰ŠÉîLÀz±­­Úªì½g'�)‘’Ý ó>çá |ØÙ}™=;ï9ïI Â�SQmj¦Ú,™.+¶§`&ö™@œqv¦4”sµML7äÁSFÔt¨‚+Ú@<\ÙvGg6vÖßdæÒ1ÕÞÊN%™«%¦a_ @Çð}¾°cÝ®Ÿ�)i6Õ ½øíæw…ßlìæî½0²l0¨k:ìêê¯Å†Ïc¥òÎZxvXbº1~{k¾¸ãû~Ø—)pX(¨œ[Úö}_µ<Ó‹×6—J´žï�ì��©Fè¼UMÂî<ý°4ËôíØõ-H!°çûþäÒ¶†¼°¯TàÐ50Õ±§ ²á°‘éÚíǯ÷<ÙbÃ7x«Jñ fËôíÿ/°ØðÖ_�\Ù0¦!öaÛS‘öõ ìƒÑÑå3— ¥žê�Ͳ!‡Í¬üZ¨ïóL‹ ÿŸSU)S–­ØSW#t­ú~ß5òøöáoÃÙ ìÀÈ5ˆ;œ+Ÿ�)…}Õ ZÞðÄ“ÑÑe3 ³ôüóƒèÈ•š–¡²û]HµéÃúî+-6üûµ÷hqGÇL·½³3%3ëªvìÿg‚lÖÀTµ<�° ×6ïyü(‹ t¦.Ù®ÿ]WAÞÇÞ,ÿŸ_¾±­ÃšgªbO±_~L¡LT4‹iˆjpêÅNOVo~?ÌCêÎÖ5ä)ñÏuUû°ÔåqëÑësS5“P {*ö4Û•‘Èú‡DÂO~ñBÛT&*¦§ñ¹»?ò½ù7êÎÕU 6ê°—rT(È;üªyêþìÚKƒ0“0•äÜ£ä7«‰|>ì¥ >$‹Iž%¾Çïôr~{µò®ÓÇ÷å\]At0†N×Îc­ú>Ý”0h"Ÿ—& �ùGÉtYµ<Õ¦’;Æèl}©¼÷Hó�ñÕµ†l¹𰺦.�»îŸ_]ÛÔ “-WÇT·™–‰ýYw¤�˜nHÙªŒi2]61ÊUf×^å‘ ê¶ÇÍG¯ÎLUá8ÃË“,71.à£ôÜâÎøí­ÄtC·áhÝYÚy°ÑAZ+¨{˜(lìNÿð‹N˜îÐÄxé´ÕøÒ~��P�»„†ÝÉï=Ã ØØõ­�)G‚ºÇ«•w™ùŸ4ÌtLòGìm!Àu ‰0•0�P »¦ÃÎMoÌ?ÙGÏÔ=^êò¸óô�/®ÖM‡ªÈÕ±§W#"ø4cTJy²µ1†ÃLR9@ÏÔíuyÌÝ9䀂¬‘’a{¦Í†Q-ìåFªåÉ)/1F Ò˜½¸s¿v�ž+¨Û;êþƒ�]²´£ƒXé £ZææÖBñ…(¡ÜS•@U-/S¼0·ùƒwÄjPBùAAFÛq¯…N¢šbWT›)×tèÈ•�ùõ7¡ßgAÝÅbé�]­Áἆ©b³S(~%”pZ‹*ª$QÍ ÐŸ;wÿHeŠ‚ºû"RÔåq£ðûé(ȧ“HEÊVcdŠÉ[·™�ZüO�ô\AÝR·© ÿB#Ѓ˜ðlG_AV0"A× ç~}}ë‡c*SÔÝѤ.�eödüAA–#™?ÈΆF**f †Š¯sSûÛÎD$uûwÖß|1&<2b`þfS=2·�1ÓeÙÙ0 Õ1×sÿiq§n"Ÿ?ue%™{([žbAë½Dû£�>uyÌÝi¯cð&І �b¹ÙÎD$¢O]Ùv““ ”Ë–«XTA{mà­œöNMÐÄ�u!®5K([&ÆEN{Éq�ˈ-ìÑs3 ñÐs»ŽÈR׸¼•ú®™Ä&¦I ª“á”e x+e%s/æƒãä%þÀS·Ý„GCÀ[9Ù„ó\ ?×ruB¿œmÜ-zŒHÜ#²ÔmÛT!m€6Tþ §=8ü„W§'–¼¸}¨Ëƒ�q μàÄ;xéXåNLjÄ=¢L]ß÷ñìËDÂWöÊ–×¢n‹Æ ?Y®DØÉ¡.�›�_éÁªy¨6ÅK/úc;‘ˆ2u?ã‚ûç;ò¿ë†SVöP3ÕrµL‰‹þ'�ºÅ†~¶ÞvC¼¹û¿…~IýŒˆS—#à­ ÂYP¦+Ã&SVlWÁJ­Nuo>~¶­]ÑܽŸÅ®A€Õp>CT䎎.�?ÞsÂyr¨ÛÊuUÛ“ì&uõLÇ#óâq¡.‡ŠÜ3— g.FG—÷üê$P·U£Þv¼ƒ,Of•*–kTŒ‹†Ø`à©Ûé¹n\útºAÝèG§jZ¼º#»AÝ(Gw5 ¼']ƒ½WÔ0ÄFÝ•c˜j“OR·êG©Ó ½p­·“ú‚ºŒöz]�¸šSÒ&Ÿtw[D½nô1ÔíG—„#º$¢…¸S·½izÓ>¿²± ¯QAÝøR·¯ÁøCG°!:‚£�˜R7,Iø0D±£nÜo`¸$nºß|û fÕ;‚ºý�èxŽéØ5pSAžca!.Ô�¾Ócfþ§µ8  êö-ù<ð×Õ2�¹nôüu‡S%>/5 ² nb�«ùäÒ3-Ò¶ƒO©ÖllvnZ¸š÷ѤngIð±Ý:³$ú„R·5ÁGIS31ÁGPw_DŠºísÓt›jˆ*é(fƒÏM3PEKWM17­gˆuoZ¥–®ê¨¢#*¦Uö¡S÷äÌÖ‰˜|œ“Ù{ 1™½G‹º+S$T'®ŠC–z àmº¦YLAe3èAþ.¤dAÝ®c­öÝy•3ˆ5õÜÈH ½†‚Ê\ÎPÙ ìülc©ïöþ‚º]D¡îÏ®½4f&¥à åÜÐõÜþÆ|LÁH;-hD¿ùl¥Ò¿XP·Ó¸õøõÙiHkáèQÕ‚ya¯>4$òùä7«rö±2Q1hp�‚Ü�XP÷ðñ#{{)°�iM©–NL†p0”‰Šf1QSƒÐ3“Õ|ñ• î!ÑSê¶Œm ì £ZææVôõÜþCÆT 2® _˜ëm² î'cîþË!ô\hK´=Óy4ìåFЃœgƒx:aöâN�dAÝâ·�CE8ª ÚOÜ·Xàóìd‹J„ð1[™YùõØK(u÷�Ù»ñ[Ï ÓHAϵ·Obè5$ÂTÂTLù ðÈôÆü“ã,¡ÔÝ-=—,;m5FHÏí?Tæ ² ¯-:v}kù˜J(uÛ#(S¬šÓ3%0£>˜H�|ߟ/îŒßÞûØdA]\ÏÕÁM‘˜¶«gi�`“­Â(±tÙÄ0ªxvíH%”‚ºÜv\éš¶3EÕî_SùIC2]V-Ú"Y,èA®/uÛƒ|’©Ëõ\ƒÀ=”QIÎ=JöÌvF ’Ť M C åjç ò—su}búy, Ú^GÇ/·½>7U3 •°§‚ß²+#‘!ôÜ„'ÉMxžÜÝŸv¢ �ÎÖ•`”FØK9*tXêò1"AZëAö$ûåÇ`“¥0»0ãŽq9?[×`LìÕ¦ŸüŸ½_{�wÀ%é/Û5$Û�vÈ>(–»X³ ×6ïyŸãr~¦L~Œ=u5BžúÑ#’L—õhØÎ´Cµ¼ŽÆ¸ŒL×dL•CL(ˆ8 Â>vÖ½°þzäJ`;ƒ`†LNÇ~½ nÂ3”z ®Vô Ϭ~TA>3YUqIµc¿ëeÙ�§{;U—éÛ±ÀMQÅ^`;³­Å?«xè¼y †Iع©Ú­ýLx¸o›êšY¨ñh­k¥òΚÎÝÛ™­NLj„ è! ¾£ÁÄ5ã²ØÖC´ÌÞñ1Ññmëªí�^­?ØØ]X“iJ L"L&1³�h‡b{Fš§xÑÅë›×þþ`c7{÷…é0ÍŽ=oyšÄƒ!X|‹Á¡_ÀÞ°/MàH8;Sš÷’aTSlÏÌÂS6°ÃÒâ¿åþÿs^f¤ endstream endobj 136 0 obj <> stream xœåœ]lUÇgkkÛ­€Z¾âgÅh ¤(~ÅD’¾ˆ4!1Ý� !‰š�Ô˜õÉ€/é !$jÚj4“V±1-i ø…–*m•lÝ:âÜ™ÝÅí³»Ý2;;»3sÏ™™»Îÿ¥�—sÿ¿´wî¹gνW’ß½DWámƒÉ³·àãlaq­³‘“ ª~QfÓÇð‘º!­¸º'Lá‹X¡ÖI–ñw k²R£Ï†(¼Qªù´’s‡ÿ�›‚œ”î#±G¥†÷ÕTÎÛ¥»ÑáÔYPH©G—’X¤PÕË,qÅš|?:`tJ°öj›hµ\`zcòèˆÓ�'m#1ŠÓÇY¾-y-:f Rï!1˯¹ï²¤Á”ü$:ª‘ 뺑Ä0Ÿ*"Ç <ÉëÑq Abÿ쬤ðÌ£ÇÏ)&Žä èÀf ì<>2�–|ÄLý¸ Àúï$±îDáí_s7.‚BR;p‰}» µNªÅ̸  )/]E‚`K+¿5›œž€(g&�°VãV°Ðy )õãÅ$ ¥Uó†>ßóಶ§–¦„Z.�œÞ�¨SW7pËúÌ—ÏA”¡å$HfšwP›¶và(¤´®$XFUn7É÷|ˆ+»\ØÀ­-±¤ø À~Ç'Öùºí ëÉéh:+¼‹0«º¢ùžï é¬ðzHI EdÍÁȃĈ²Â{¿·99ýPFA�¹¨G-•ï‰  öÞŒ±¶])�ï‰ —ÕDY¿ÄfL4PLV¸â¤³Éé3(€òÓƒÝ`+ß RZwƒÃ¡ò‹ïž€Vnxûàþ­ Ðôn·£¬p͘íDˆ ôéñ¾]‘‡£{k0 ÊÅM¶Çlú’“ôÍ‘‡2?ç}0p €}c¯V8g¿f,¾»ºy8Wˆuv!AaZ=\o9¢iñÝuÐê ͳ¿×Œ<†Íd…eýGáZR° ?×=< jµ�[ÜS²¾çèÞWuM£6F±–Ú[¬m$Üν¤èÅzh‹î¡Ž#3S2f^Öo™p²+.Ð}¯èN�øÈd…mYáÊïГsF< ›�êZ�9I¯ª??˜7P}'g¾g"к?—Íþ:ñ •c³"ß3×:ºc ,Ió#é•þõþ :3Ù²~Mv�5¿a¡q�†õ-jƒ?ž«ìmÄ& F±©mýªüޱÙ+¾°âµèœû´—ëš*]ÚK¡ò=ñî^æ÷Àà µ{ñRÜûÑC3ïHrO‰”@QI’–VIn€²©¶Î ¬cŽæ‰Ô�î­;îÿ[×5PÑÖQ·@�™w%ÌD�Š—ëºšŒ¸Ö,zËÍöHP!÷£ô V§_”µ®­úÑ—š-¨Í* ìC�Tèº.¨“Jýí>Tê‰@ËàÛ (ß×´xÙ�*gxŽÜØë‡”ÿ‹÷òrú┵÷&ÔˆeÒ•BÑg´°[ø>£€tŽ¥0 Ý�é× HvPzêÝ<%1÷=aNI¸~îåk!νä$SPΦ)Ã�8m¨ÊÛ=œñfçŸ"±îTŸÚÈ= ÿÓ›5¼+eξ»RÖ¡£ yûMÓWô·ß”É}F«Ñóo¨çÞ<à U«Ð£W&§ÈwŽá‹8¿Î„ò¹S¹¥Fsú�§PfÅQÅw÷´i2‹Jp/`›à7=îüKH~†�TÕ“{KœwP¡j·žH ã>‚dô EQþ endstream endobj 137 0 obj <> stream xœí]Ûn7}×Wð¹@i^–ä0 Ø–mô!’h_7 P4I“:@?¿ÐÅÖnª£�Ã¥Vr�h�—3œ%g†g†#í|^ýQFõ³îü3e§î?Ì>Ï–‚QÞå¨ÛÔ—·³ß~RgŸg^[VÏn?ݘYµüïÕ�Zøò~vvçÕûfg¿~úøúáË×ûu~~öâú—¹2êââj~½bÓÚ¨¬ qÉáÝìåìe—½3Y/ek‡ùëhsTÝÿ¿ºSÿÿáV®«Åììõßo>žŸŸ]Þ?|}ó×âí¿êüöæöÖ7¿Pj)äÙm£¬S‹w3»Ö˜U1Y]NÊeµø0;7Æ4jñçìæÅzR‹?Ô¹1~ýäƒ mÈÍ¡ Æ4WÆ4yõ {ĸ~£Ïäf1Fþd¬N�5~`6cçG’ѶڙÐ)9xcšË#Éè�¶¹5qH�Ñ›FÈøÍ¶�ïJ³úðêN­?”¬~Û(ëµwk#ÑßÚ.˜TöÚ/ÿÄG-ØZ0—›í�sl»Ý.Âf˜OÜ"‚GCó¸a‡²ð zæM‹‹¤òH%ö Õ"Â"$R*_ðÎá«EÚõŽÖ­]7¯7Á.Ýîbڽຄž®ºCõ˜w ®A„L3¿DCµ潡sçè BíÞJxôh¨ŠÚí %b>Å*é Õ›‡GÌ‘T2•È´;—¼ó6u‰~QHí©‹ ÷=óžvw %Š6 ?:@’„ vCá sh�a,Í?tÇ " cyð~º|<>¦�àÆöè  õƒ6bï„_Å­b¬¶.ùP¼Š+®Ž8˜UTÜâ.gmMÛ éGÉ| Jïׂʼn^% odø*¡T¼AâmÂg)~¼¡ ƒÌá.…A}{Z{.4Ikí>z£7_%¨Â«'±¯‡çLöú¸KOÆ·Ä`t޹qƒ¾¥¢ €8Nf�ÇÜê†×ùQ}ËF›§£´mÌíÍ^­A  ŠŸ€F˜´h¼‡÷>ÐtyŽaÅ~à£ê¥ëG0(AG(|þ­f� �ª²Æ™G|@qét!v®è�¨ýðJ XÏǘ?¼îs÷ºÐÅ@8†×î�œ«h]�t®£j”ý‘Š3aéAÈ�ÎÙ7èøRg§“ú¶­Î­3qhFÖ›OK×s6üéB¼ë(®Ž=�e±�ðÂþ:~Yðê¬Vätrei[=ÇW‰Dû=%á–‚<àâ T„0U-G¥ŸÀƤâ¡d‚蘯”ãA7þ b|Fc�ÑPt.^�‰œþ-¨ŠºÂ Ÿ ÞÇQ¯ÄU\ p(\ZD«¤—€ëakðP‚†ò ‹é‹3sÄÑÕ¢,æÈ<´,!Ê']ér*Œ0¶aïQ z+:á3I©&}Ÿ^+/pùG¼ç >é:Ñ‚H fæh•à|!L¡Ò9É‚²oѹTäß Sš¢†s¤'‘ÛŽó$�¡|`*é:�Ú±Ã@C!]$®žA+�ŠuV"—ÏG=[Ò‹`—>ƤQ^,UEµyÁÎŽWp�`'¿7Ø�Ñ{ºf¡Œ…EÌ<ÂÉçÀÐ<°EÕÍA‰Š7rpMäA—ÐñíxjVÿÜó+•ªgnD�KD0< âH ""|¯ê€¡¼‡é4‘JÆùiCoâ/[¡™€(é µ;ÒO‹xŸò™°‚]°gCÀ1Näò{ÌéºnìÂF†®Ið + . vÜÞlUý.5ü[½Ä—‡ ÙÁ•Çõê¬p�=Ÿh9æ…å‚ÞƒPª“éc­¼¬b—.â*è§e1�ŒÇL�¡|'i,Yd$”Èß”aA2\@¤ÄžŸ>P{L�IZ%¢'žaµyòyo¼1Aþšߢ‰·àZ÷áÛüœp±UJf¸ØêD[�Ñ�"Faà"§[ÅÔ,kâïvBqy( V“ñ1ç7N jªx0š)¾£B½&Õüá{aQ/ Ø>@„©à�S´î�0ªŠÃy»Š¡L@º�~Ff,E–(K�yÀåC‡¯|Þ®@*É�ë !Y%Î|Šž'Œ¼µ{#áŠñÆuâÏ­ðÅëG=ñ{é!8y9<Ã�CŦH„Õ¼®Ž¤‚Ù+\'«ðé+.�ªØQk ñˆÁ§‡ À Jð*A±_U1}-ëÚ5® VÁ�ƒF=]Ã=UYSkÒ^ä�÷ˆ¼Ÿ†ØC½>FÁ1Ðþ­&zDÃ~5+‹êá©e><â›h"%Ê d}ø#-ïßDRÉü*¼æÁáê0¶Î·‚›¸|É$¿_øPŸGB+ž3øÀýY]¯i�°?A徸քǙ§¾8,:HMrkÞ(e­e5tûö‚Ð’ïx »ÎÐùaÜÑYhÜ_ÖiHtõà¤Xµ©üã×{“Ÿ¾�{Â/NÈ«yÓjã\²ÊguöÞlٹ×Ú¶Ù¨|C¸‡š#|Â!‚G„[@è¬êoÄm!ÒO •@æ …Õ PW  -.zƒ˜Ðp{m§ ½½ælÔ®Y~á½kWÛ):–¿ºþÔÙwÑéf¹1âzSlÿ¹"]Ø»Ï~wFÍ?m¸GuX>Ò$£cVöñ«Æ—ßyߦ&76Ħm7B<ýÎÓHÖ6N»l£�Ãz»$­ Ê6)êcôʵ *¬ÿê±!¬$ØPŸžÏ­ÓÙÆ8ÈÜo™gktö)(Û¨Mc—%Áë·á6*Ýr¤¬¸?’·#äµüi�xä¿\ÿ‰Ã› endstream endobj 139 0 obj <> stream xœí�ûWÚÚ…ÿü{OǹµVk{Z­µ¶V[@@EDPDÄ#Ê#/Þï7! w„xž–X‚!ÙIö߯M…=,²fÖºNö®!�@ �@ ÈópG:_ÕuÛ–ý/�LˆJïë;�Z¥ÇøçŽpsƈZ¼¹E+>kD·¼å ÎÈþ¢ bqr×Yqd¦¾'¾¹Ò®ÌÂ6"_dÅž !µ^_™RgÃ�™6 æ‹Jˆ€VQ6Þ(ùÉ‘�6 žH¥Ó¥¹#~·ƒ ÿʘ5¢¥z·÷HéRç³#õÚŒ9®›²¿RÈPzã¸ðR�‡Kd—y|¸Öó¼é¢"èj!‚ùc#Þ¦ûdcÞ‚}ØO{¢¤ì¯2"!¢gñWuÄt–«·¨_�Õ©¬»ó‚®@驉¡&éõz4Íx"�ùv\`ã<)qþÝZ°à+ödºÔá;ÓËxuí('è²çñîìÊwAN­½ëË¿Ô#¦óÊ5D.ÝχÙÙ-ô*Q{ú4oÐúŠ##èâg1òµ{ú²œòUrí05gÆ`¡Aœ1ž•_êçU±K1¿=ÇÑX¶§ýž(9oÉ$œîˆÆœ[ÚK{c]Ù߈-XŸÙB7Ý™r£;Âé=œà¤MÂ*g·•—zdÝ�ïÎ äù¸#í·;É¿v ,×t|wÉÆò¾`“,4 §Z‹2zØßàVMöwLS\$¨ÕÃìŒñ÷åÇPÝ'KBMrO.l�cNÉB{i/ùÆJŒq"” Î<¥)=â¸*þt÷d“pb ºr�ñÆa¡2)ì¡ÆìúÕ™þéΧRLÒëõHŠ9³5öÆIáÞQÏ=ù~/µ°�ÅRÍ矔Œ&áTmR†SöëÒ€…ŠPzÝÍÞ¡òF*̘_/?Kv“pJÚöˆE+áú*c‹¯:m@v}ù6I‹x:€˜¤×ë1L/c_ãš3çG(Ùßsea5^™°/Ît¡JŠ~4à˜„S›¤÷/Ù^¤Ñ[¾‚ÁƒQŽ#J~è—Q1Ê�¡Í$œŠ5rÓ�yeÂlÁºì§,ŒÞ<)è Èq¸LÑ"ÕæI8%2Í·Vü/[êä®#û‰EˆèY5öóö4Ûhiî‹+�MÂ*ÁD�-TŽr>X¨ô9 ·æ-ø§ƒd¦ÌÛÜW€›„S«CÛ/ÙÏUÙ¦ •óø¨Í}q¥“pÊUÈ~Bw„5<¸Äè�“b?[8Ùòc¨dNwDãµ[ÞOŸÅ4‘�dË?û…»åž-”@Š3ÉC𠢉à�û¶ýv‡xo#ð|[Æ7\‰&áÔü'!¹¥Æ„äùóšûâJ¹&á”.u>Ú“ ÜyÓ’ýdE�mî÷³…ö`að䋼RºI8qÁƒ¥½ô™Â’\sÝ™.?¯¹/®Ôa’^¯×¥˜£›®ù~ZTâ3§îHçÝXÙB ¤“pª6»†ö«|÷R1Á_‚Zsæ¦�Èe¬*Vs_\©Ì$œ I×-Ð…JgLç•)=²ë¹¹/®TiN7XýÕ›�<2!é7_›16[X¿¹/®Tl.!é¼*NýHü©PñDÉ¥ýô‚e‚Í}q¥n“pª4º€$$¹l¡N�œE*4˜õÇ0iÁ$œ™ÖÛ�~ðà^†àAˆ`L]?[Øê€[~ •vLÂüQ6!ùÅ%iB’+?>¦òÐË�¡Ò”I8µHé‚g1rå óÚŒÝ`u¹_÷øÒ I8q É9f5&a� Æü8ekfçUQú澸ҬI8ÅÓÍE+þÞ–:¯Pá²…º~¶P®æ¾¸Ò¸IØàÃøú…ÊÚ‘…Šû¶½¸C|°DAÎæ¾¸‚&áÔlSÛç9�±øªã¼ñîŠ#óÊ„*ºü*h’ÇÊ”;Ÿ’óÛ‚Aœù~ZœÒ#®ëÒ(ƒƒ'h’_5Œ2šÉ¬Ï ¤8A“ 5Âh¦±)NÐ$O¨Ö¢ÌÞÜ´µøª”þxÀ¾^wåÏãÝ/G¹#ê�ÚÜWÐ$¿UªØ^ÞO¾ØŒÿg=Ö'þÇFðæ¾¸‚&EÍ6õb3ö�IbÓFDî¿HRA“Œ¢L©óbcðI›5 ªüÃ'h’§5mýõ(?¥G^lÄutÙž’þYKM§§ïĪòÎ*Ÿ I†j”žŽúz4|‚&ùIB»Ãjêöò šd IÛü…‡çFbÏbä’==oÁî’ ¹_‡ø‚&1±¦ôŸ I�,›}}·›eèVˆx˜“iñæ$T%�´l’ɥ蚊ç“6M"Íó8Š{¾†O4 ûdŸIº'ûô¤Ÿ4e"ß~o#Þîni·¨\ŒÁ ÖÈAÒˆIkvä›6àKPŸ¹éq… To’A|�…)ÿÌ!ÁQåD•Ôm`' �9шOj5 ø³Ôœ�Æ'õ™¤©¨©Œ@MY䓚LBÑÌÉM_ÛqAYó]]·­7Vby?™*‚3‰/Aé OM»e¶¹?c€Í}ÐqÜ4ç-øêA*ûdB2”¨­f]9ˆ1n&ø.ˆd[ïÄ™4Ü–ó—ú§ÖŒú£Õ/®œÐ+¿ØŒÿú»»T#¿¹Ò³&lï – Ã�Ò_]ýàÁ]…þ¥P9—6OŠB¯¹hý×�ÛZ‹Ú¹Èk9[¨NûÁƒy Fë�[?›îÌ®ðßߎ 6ž Shï\°ó´7Ž ðî‡:pÜ4­ÉE+î�V›mªÑfKÐ1¦BùjÑJü÷[lÞ‚ÿð”`uª>áæêaößn&ŒÞ²ì�@ �@ øüeFÃÏ endstream endobj 140 0 obj <> stream xœì½Wbi¾ö]ßofzÎ3'½ÏsæÌ9Ó¡BW§ê4ÓÝ53V·’AÌ9GP’˜ÈHRQ”¼3IŒU–VU÷ìwÝl mS©lÝ€\ëZ³ÖØ ìÿ¾kÿ¸îøÞ{ïý®�ôû÷Þû�?üë¿ýû–}¦ÿãx¯ÀnÙï~÷»ßþö·÷òÓŸ?xøÑƒO>}òí—ßþý/«ú?òÿQ)úGUÖ,ñ�œšœŸ±k^%ú{¥ðé�üœÿV)Ìý§Ã_¨:ú…¿ý$Èýüûè5ÿQU}øóJÑÓùßýƒóí?}ùõyø˜éÒ®¾ºÿèÛo~øæ‡ÿòCåw«ú®‚ýC÷D‘¯ê þöï•Â~ä~WÁ~ú#ïo•‚l“¨ý‰Wÿ·®‚%þëßY�?ýê�ï¿ÿ—¿WæÙ?zøÉý�?ûä‹o¾üËßþò·ÊïÁ;òÿ~Ô«�7Ålã9»)þýtS̶®w4EVuîçOä_ÁùË•_}WùmU'Ó7¼põÁG¿þë?¾ýþÙ_~¨ük¶)~_ÁÉ™#M±JøÃ3hŠÏxà×@“È6E^ý3¶ø»°þõûï?xï½÷~ûÛßþ¦`Tñ¿ÿ»Ìâxœˆ~^ö /ifÙ<¦oѯD�•¶>øÓÿ~XÝÔ×%™.Oõÿõûªo¿gúÉQˆúðÏ|ýMW�ŒùÛôÖ�>ý²¶u°‚#Ο­Þÿ˜SÝÊøåÜ!Ñr¤Ð߸LßöBÔwï¿ßÕÐÅø=:îÏ¿þž_×QPlýãþ0úäKœÃ�ú$þ$Yö¯œø'RS‡r8âG3}£ú~ÿ{ZØú?þèß¿¯™…˜¯ó1‡Í‹pG?I’—éGH¡èóGŸ6ýíLjT IՌߠã~úŒW×.­k—äÏÖû?Uè¿¢ã–Ïmõ×L$ù=¿–é&P(úâ¿ÿÔþÕ7H]cÈdü7KØ,hè¦Øšÿ³‘.a••XEÊýkŒ—¨ ²xQa5Ê ÓwéP¿ÏŠ®Üúç[ýñ_�ºÆÈô,ì�˜H’¦²·Bã3ƒ×BÌß c~úŒWß9Rß9’ç>øøó�?/4¶.E*³oÝ�ÅÊM×ÃÕupc‹?ñOÆoÐq³„Í¢¦Þ‚ckEZUs¹PŸ”ñ�ÿDjë1 åò˜¾EG¢‘­ïôèýû� Ž­I2dò@݃&’tcIšÊVÄB¬¾ˆ\‡$cŒßš~úŒ×Ø-kè–åy��>yòèÓ'…ÆÖltÝì�Y�ÅH/ò†¦ûYÄBÅuHMZÛr¿5'Ì6‹[ú �­àßo6º"a9ºæ¶,#BÊçc,Ó÷çH4²õƒûxÿq²Õÿ©k ›V<0Ýõ¼M٫׃æoͯýô¯©WÑÔ+Ïó?þì«ÇŸ}]€l]Šþ"Ræàþ\xÚ¸ëM©m@ÅupCs¡…VŠ­5-ÈV¬¢çp.êa¼Ja0ÒZ�±Ù(¯€B+½lýèÁ'=ü¤Ùš$ÃÆ¸g‚È�'ESåŠRˆÕ+uá‘ hXÅøM9í§Ïx-ýÊæ>ež—ùÉß~òäÛd«?IÊæ6ûÍëÐé‰Þé芈둚¤¾)d÷3~SN›%l®m,@¶Þ»w/Êã¥ø|„/ø×/ãYWP¡á 06›é;ó+ÑÈÖû�>½ÿè³Âd+ˆ®5õ‹78�zSw7/ÀoCkaþ«|úŒ×Ú?ÖÚ?–çe~öå_?ÿꯅÉÖ¥ˆ®3¡tNÞݦÀ*®Gêš 0´¾eëpa²5ÅçGy<„Ë� Œ2^(†�i…Ùl¤ÀB+½l¥&�([AtuC½RoŠôÖi*^‘)4‚ÆôÐè4¤düvœé§Ïxmãmê<¯ôó¯¿ûâëï “­ ºÎn̤ÃIÒƒÝÑè©m„kÀô`›�ñÛq¦YÂæúvia²5]Ñ;]C6*¡.°ÐJ3[þðñËVì RS´,”¾‹y!¬› ͇ 6´RlížhœÈóJ¿øúû/¾ù¡`Ù & Ëq[øÀ9¸›½(P]S¤¶©oòÇaüvœi–°¹¡s¤`Ù ¢+ŸóùЀŒñZ1æÄ?‘ú&„ÍF izpN4²õáã/ š­I2lpAý#¡4 ݹèð á 3$›„†Œßˆóüô¯sh²c(o¶~óC!³ÕŸ$G›ƒ3ioŠtݽè ×5Âu�H}sÁ†ÖÂg+ˆ®|>5êZ€“oÇ!»ÉŽ´"…Zï[©è²ûƒ‹˜oýnå…�Ñð  ¹ðÔ}�[‡&:òÏ­ßüð¤°ÙºýE ÇíÁëÝ‹®p}\׈ph- ¶°r8(Ÿ î·åtâŸp]Z�#­”î[“dXï„úG}ë¤?”¦©„E Ð<ž°DäÓ…ZÙ:H[Ÿ¶>-d¶ú“äˆccКÑ•¸CÑjjlmhYW¿Œ·v4[Á(OU•¯¢L.°M`nÁ!G€ ­hA†VúÙúÉ“gëá¨ël0°„ß�èÖ/„æq¤¶ Cë1¶Žçy½O¾yZøl=Œ®˜0 ­Þ•¦7¶@M­H]c!‡Ö·¹µpç2QòUTDªª..ÐÙ‰7g¸® c³×T*¦o¹¢“­Ÿ<)¶&ɰn”ùÖÉÀ݈®�ÅXxÒ)´Ð œñâ_ìlŸðx;-lý¶ÐÙJE×!kZ%½w#º†[{ ÆV¤±%lYf¼ø;›[ �­à»Je”ÝaøNE×�#ˆ D$InY­Lß�sE/[[Ñ׈¸6äú<¸û,0 ™‹1¤¶>°²Êxñ/öÓg¼ö�ñöØúe1°u‘øY¨ fáƒù»]¡æÎpkOá‡Ö"b+TQ�°Ù8ŸI q7˜2\ߌ°X›6YÀ[ÄÓÈÖGEÂV]µsPÿ¨;I.J<º®D2!ÝlD¥/йút­o-Š>aʹ躄ÿLÓ=/PÁ­=pS;ÒØ²x/û;]àë[� årÁ¤&ÿŽD×Ðl‚кi±0]û‹tsëQt� Ý8†î7ŸüpøW"´¶>Xð¡õ-[Õmý4°µ(rëat•ãöÈkGøÕ2QÊMnî„[{ÐÚügÆËþNgs«¤(ØŠp8‡ sù°´àN߸ Eh½‹s™Þ:¬�…dFB+%»ÖÕïßê�aµê/޽Ñ[ûÕmyïyXó„s–ÚAt]&H7R²Ñ5Ò3 7w‚Ð:³ÄxÁ/ãln-¶‚ï-œ·Ñ5¼ÉxénÔ¡¹0"(‚ÐJ÷¾LE°'ç·Ñ5\ÆÝ…ýýçÚ Ú~ÿ˜½œd¼à—1`kßXk-l-èõ­ÇíÁÈqGä•-rPªsסöÞHÏ0R$¡•bk]¡î'|Z º²Ø`°TÍxénÔHc+Z ¡•v¶>(¶F×A™›$Wb%]—ûAÃØ‹©x΢:Ü«¿/ßyõ…¿wÄ Km™!kÆ·Nº‰Œ®H×ÜÚ7·‡Í‹Œ—ú’.ä½úÏZYNNá-Æ«wCÍGŠb¤•ÒÚOø”©è Íð^øß‚®ªÀlx9¼ ×6Kh=º¢m]pc+ÒÒ6ß�` ›EM½EÇV0êš�®`ÔµT¢kÈ… |Qq…Ö2[� "qÄì�Æ 4Õ•1AsAل뛂‹Qæ {E?}Æ«ï�Ö·Kó,B‘ö û“¤{“uÝ�¬}tEZ:Ѷ®b ­‡lmè)F¶°ry`°l’ñ2Òb¸¥åp6+«Š(´–Ç[sOYáþQht"dtÑTZ„¢/`3i…»‡/é5üô¯®]Z×.ɳÅËV’²f†l ºbé×4µ Õ7à -HsGØèf¼¤×0KØ,hè.F¶‚âóa�lÓï2^É<r£?;ÒZYÉt]¯&zÙú°hÙz8êjt…U:šJË€à¹0о@Š3´æÖv =lýºXÙJEWsè¥Ý£©]0 ¨±ªo.ÒÐJ±UX_¬l Ÿ� �lšñJæi¸¥ãñ6«ÅÅZË}ÂÇž´@ý#©ÒÚiªî­ ö�ODm„»/æõL[¿.¾58Ç=hIY3²Ù K (ñ©®†jÀFLãżž‹š­à»� ¢kpCùR*Ýjmeº¢WV™­9ð}¤ºÒÚ!ùMÕ½UÁ³>€×úæ ‡`¼˜×s¶O˜–Üú}Q³•Š®–ÀžÚµMSë¸UAµõ‘êjD\ˆ¾f¼˜×3è.f¶†$]# ãż¶áÖn„ËE««Ii¾s0n_e¶wdbî“BCŠˆªÈ&5A›¥ê`¼Œ×ö![Û†ó¬Æç_}ÿÅWEÌV*º̤峛¶Ð>Mmä–q8�HŒ4´„õNÆËxmgÙÚU¼l³/ø|ŒÇ†‘çŒ×ó¦B«©¢ÂSl#­”Ês™ŽDW‘8¢2D$ù!zË‚,³!õM¡¢ ­‡lm®Í›­_|U|{ž°{#T¶ÐþÄÂMmä– «!©®)ÞÐzÈÖºâf+Æã¡¼ì„a¥–ñz^Ãpk7ÊåzªªLÅ6ÒJ©œ[O82nŽôJ"}#‘Q M5¾q‘Ri\©†¤ãpGãÌÇOŸñjé`k äV]gÒƒ–´Ì±iò¾¤©¥Ü¸ æ ‘ºÆ°nžñæã`+ˆ®¼b�®¡‹7´–ÙzÚì%"¬ŽŒj Á|Oc¹5m HH©ì¼€3^À|ü–­Cy¤÷>mW6ºš¼/ÇæŠfÔæ @hˆüÄ+Æ ˜�Kƒ­ ºr¹ŸQê/é• ·õ`ÅZËl=Óaµ é†z†!Y¾‡t߂ȊŠ�¦V¨G·÷2^º<�eë�¸y ÏšõúÖã0§ÌëëÆäRL&X,”ËC…âˆnŽñÒåi–°™_ßYìlxåpðª*„/ {ŒWõ’.Ũ‘ÖÅ¢ ­e¶ži]EÕ�l ÌwÓø[ЗOVT µ ÁŒñÒåé§Ïx¢úQCOž5)Òý„OÛ…¼ÊñÉ¥=Ù|DWŒÍxå ‹=´Rle [J€­xUÊá |aD¥g¼ª—4ÔÞ[졵ÌÖóQ¡îáHW°'ß±¿­\Û·÷0^´üýô�WÓίíȳ,%ÃV’ìŸY°¤û­™ÑÅ‚žÔ„s¹‡ƒr¹��ñ¢åo–°¹’ßPlÍFWn.º=…>lôÆP¯ØCk™­çDWq°g×ÁUU4›N¡Ìá$X,Zŵ!7Ê|Ñòö![kÚó,N±¯o=nòZ ÇGwºÌk4µ:嫨ýôSè§ŸP6çr¿Bk)±«¨@«ªP6ã“H]cAï&A¼Â„"”ͰXEZifëã/<þ¢DØš$#cT „«ª�ª*”Å¢©Þ´ e³Qâp0néd¼\´øé3ž°®SPוgq¾øæ‡'ßüPlõ'ÉÖédíX´^�Š{|--nšZ= VUù** <½Ùìðø ãå¢Å,as•°©ØŠWUa�‡dŸ(›²/ï™D¶à†ðdãrQ‡éÊå+ºØJ’¤P\ÿð“'%ÃÖòårÁC#ûÜ@¹\úªNƒÀ£ìí ¹ÆËE‹Ÿ>ãU7õU7õæYœ'ßüðäÛ§%ÃVýÊ ¶eK‘–·p8Ì'hjD4(\UáñP ts8¥Z)¶rÅ­¥ÁV‚ÇÃØlô­#j#ãå=í E[©È€g¼LW._ÑÈV’$•[³óÀ»Á½³¹ËSYY8݇ÄÏê“BRµ?`¼by:»/ÓPmë`žÅyòíÓRbëJâŸÜQŒ%EÙ#({œ`+Žã5tŽ4tä»/÷“Òoõ'ÉÃÅVVöÙÒX¡°•Å‚¿r#r�?ñOÆkE‹ÁÙè�½¥ÁÖ{÷îÅD"?›mª¨@³34ü…·Ö5°²Še¶Ô¦ Fƒheëç%ÆV’DšÚ06f³©évHaŒ°cÆíÌú o1^%ºüô¯±SZמ÷~Â_ÿEi±UbÛàŽ`\)Ê‚8RŒ-Å �­)>c³©ÎFHã`¼J4äÖÆÉ­”¨n·XîÊ… o­+Ô9€q85«¹ÌÖ_ëÁ£ÏŠølôs w @}RT @²=4U=/‘$™Sþxü"=xúXë*ŸFÄ5°@óù4•ÿúJitpsÜÜÁxYh÷Ï8O¾ýþÓ'ßæY¢ƒ¡™¶æw�p�i­~<ÎSÀRM êš"²3/2nf¼,´»JØðäÛjÚ†?û^X­Œ[ÓKá—ãó[ÓžçŽà+f+Ÿ§0.Ü»‚‰®Á•U”Ç�‰Dx<]ó”Õk0Å64•*±ÖºÉ§ÿúŸÿòoÿñ¯y¾ìÿý¯?ý×ÿ|ôc‡mbag¥T¦4PÑ5 VX\CÓM¸¦ ~ÜÒ Îi-‰•9/&6µ„ú³¿ßÿ—ù—ÿ÷ÇÿγJÿý?üù£ÇOë§Æ\ÛËñ’jŠs0ئ©BꪚÚÔ5…ñõˆ¦ËK‰=1ý ÿãÿÏoéQT g¡W=ƵUTjßp_�9·µËÏÝøkfëm�»Æã¡adÊÊxµÁHkÏÆåâ|ALTƒ×I’Øá]_˜ÆäFT?Ž÷*ÐF[lQeXü¯?þéÿý÷ó|ý?üë¿¿÷Þ{õú.CJ¬ŠªÝ;¥ôXƒäÓHC3,BÌ�³“$¹j´¼6µ—Ì„ÌÅÄ¶Ž˜’¡Õz|ò�úÓ{YåY¨û�ÿï÷¿ÿ=·q¸Ç¸&Rò¹Í¥è/Œ_)]î1®µj’ÕãDƒi�¦–ue�®E.Õ„'Jd#&ŠªB'CÅZbüƒGÞ{ï=Š­Ô¥+RÛ†­vok–^ÌÁo˜ºùæó!¯¾})4KU¢8C«o�t%’+ë0I’fÜ6A (0@U}&6-¼¤Û]B„�Ȧ�Ö.D\‹54Ðt® "có�И ij+öÐz‚ªfÂf‹z?ù’v¶þÀb/K�°Ý†µn}ªM¿&u0p8V]�EHCsA͇¹ž½‰Ý·T�p&c$I2ðã/ŸœÇVÊ9ÂŽØ7�Ø›ñ…ýòžÿùöïŵ…py`a2�ÉèZ¤¡Õ›"ÝÉõù$H“³qÿ.9MUÊ*ãÒû>¤‘­Ttu,¿šY| A¥CØlta Hk'Mwé Š8£DÂ-�!G�ñR\ÛK¹`bj6‘0e©êŠ&îÝ»G-£—­Ttµ­P„Õx_”ag¡W"!uì Y7ij_WRßð*ù±—Œ—âÚ^Nì èÆ'æ’„1j d�øîI’¹¦ØÜ«<“­¹»�#¬ÿYíÞÑx÷æÐâ ,Ìf#\ʆ™;0Ò+Á9‚Ã)–ÐJQu6�yS€ª“„ô<ªR¦Øúþ‡ó|ßãl¥~Aä¼ÿ•iå¥;IêV^”a#²)¨{në†d“tÜ«ËÊ›"CöpD》6´§ª+š2¶™˜g6‘È]ã ±•ú‰›$-©WÆèNÑ/ïõ?a» ©þ™ôàLưt« Cðº:´¶níŒíHëU‰I*«ú3ð\òè„K²•òqÂΡ?«v–£ñí_H’¼Íûr !<>5©‰‘�4Â$+*b…±ÙÝÅò¦H×U¨J9ËÖG7ÁVJî$i…_郀°†åâ&lÚA…Õ�l’¨ò,וä_Ž{S$ÜÖSŒ¡u)±Mu»é‰ig2i"ìVbÑM�¸Æe+%Ÿ�œ[y=ãÙ÷ùH�w¯Ç¸&T+aЫjaXz9æ¼Õna¤©àU(*À}óÞéUuщ…8˜½€ï$¨¬züsM±ål¥< ½ê7¯‹”„lvÓIüL’d$y@d~.d°òø`­«–�=µà¾pÐXUU²°·>NUGøèÑû=Êó3œÇVJî$iƒ_ƒ/½©C EIXht�ÁƒrxÚ‘gÅ.©EŒôÏF"z'ÜØZ\¡5GUCT³°ºN’d0ƒ9“É3/óØJÉç#g—_Ï,šƒûý3뇄�a»ô©a[F>»åßÒŠK¸¡©o‚Ú{ŠnMkŽªzbÒ�ͪÄN<¹³u&û®ÁVÊ9ÂJl[øI’‹èKÛmÝ�kåñq.÷ö£+­<¾¯¢"\À¡ue�t'Ó³ üU.IUÊ ·Þ¿q¶R�yeò¿\ÄHÃÊ^¯i½è2l ²�ŠÄð´#¢ÔåY±KÊ·˜\ÄH¸­7ä(ÐC�O;7ñÒÕzV3$IFwRÉç/.økl=¬ª�túßXüûÞi  !aAtUŽð«éÅçyVì’‚[º^ÅZ�²*1µ�H˜HÒ»“HœÊªÇ•kŠ­Wd+å9ø�°Ò,a•έ©¥];rp;÷èJ`åña�0r»ÛAÃý£—®¬òdh+k’ks te�tÄCø•©J9›[?¾¶RZÄHGøµÙ¿ï�‘Æ"$,42VAÒ Hïɳhï´Jç °ÙS,¡5GU=®[Hnd©º–|¾÷Îα[f+%oŠœÇßX#¾uÒ8œYÈñÇF±¶SŸ’Ú7TÎmtã[À}R¸¹îè «MŒ_øeLQu­ÖEÕžø*‘s©¤cw×té¦ØÒ§º[)ç+±eìÈ�ܹ9¾°cíßômºªn?º 8´ú|¤^›Ç³+k¢+¹¬º’¼ÎÎ퀭÷?þà£�óüT—g+%Œœ‡^[ûá$iôïõe [ƒ_�ðR-†ôH=“gÑÞ©°oZ%Ꮎ�ÝÏø…_ìTÍ„µäîËK91ÂVJ¾uÒ‰¿±A¡4 ìÀLºXk�¼) ôZã½ñè ÷ Ã}RTT(øÐêÍQ•wÅSF.áIö‚®Ö[ó`+å9ø5EØakÚÚ—ÏmNºwlþ",Îåb\^vÔuövîÔ/øÜ›]P¡ ì®®$QŸ�´Å}ÓÄh>T¥¬2.}xÿñ÷o›­”ÂIÒ…¼¶…÷ir&°GµÃÂ'lddË5>û n뎑a'œYBê›ýñÂ-ȱ¥÷SÎøª›$í;kŽÝ—ï ÇÅ [)…Ò¤cã¤5|0`yKØÂnŠ�úÔè܆ڽíBo0º¢RÒÙ�t FÔFÆ/ù稪!ÆÝ‰ÕXŒ\&’~â9†]§)æÏVÊÇ kóïËcó[Æå½›»_WÆå,ÖíD×`0ƒðø!.âr™¾î#™csÞôI’¶Äâ>’?U)¶>xüáýÇy~¼ë±•R Mºð×ö0ȰæÀa/q!DW‘Øg÷5ö<ëv�Â+káX6´Ú|Œ_ò™>–U§<ñ‘®ÕU×Îs÷Õ§G2ÎVJÁ8¹€¾±G@†µfÇa œ°öÈ�Xu¡¯õ+/ò¬ÛBG^Eâ‚ ­'²* j,Œ?�Å®ßéb+åù·„œY7.ïI¹{s*Äüéu¬\&…us7}›à9ÌD¸¼Pa°Õµk‰) 1fŽÍåÙ|Ú‡l}À$[)…“¤}m îã¤Ñ÷²Ï\Ћ!©’M…Ç aW8ÏÒ�©•r"aÛJa†Ö#ª“îXÒD’ó««—ïv;­a+¥Pš\ ÞØ!0kñï8a;t«ò¹­‰…z#›ïa£¤g¿ØÓöWu%“Dzñd0vªR:oí§“­”]è›AKZ('ÌëS¡Ý~Ûú =-u3°Èq!<>Äá€ÿèë›»S�ð&š ­.�Ùë½wïž�˜œÆeS¸ÌµOz©J9ËÖO �­”‚qÒ ¿¶…öCé,a u™ ¼‰ˆÄaW8l˜Ï³tgÊï__I�P×@ÈºÂøÅ÷Q0>åL¬šHrf;ißy÷‘‹UPl¥¦ bo¬‘ì\bÿþx$"a©èêAߘ|7Òͪ^…Õä9ã{ÜÞÄKŠªZBíN$²ãª‰|÷Ú_ð(åÖ`+eа"Ñg\“º7;M«=3©Á9Æ6ˆ†8°Ã°°:¬sÞÜý‚‡˜@³9Ì†Ö t`ë�Àú Ää8>pT¥¬2.}ØúIž˜.¶R ¥IöÚÙG6I³ÿe¯©—ùC’±°Bš´ø—¸¦+(#ƒ.4è õM…Z�eÕ)w–ªæíUÛîó<©J©ÙJ Ì%FßXÂÞ9Ú²"aÛu«JçöÔâîR’æèŠÈ'à^I¤GRP¡Õ›xiŠZå˜8GU/‘ðGw¯4®zžŽõ �Ý[);³„ÈñÝêàÜZËt¢u2Ù¢>{øM ì0\U¾AÝLt¥B+TQ�ÜâQb£h%eêÿ*à%Ò¨DZ&Ð5Þ­Àjgb³7AUÊ€­?ù¨ÀØJ Ù$=Äk[68€eþæõ‚",ˆ®Õ5¾ÅDмD×%S ùÒ`¤µk lYfü2½¥ù8µMœwgÕNU),[)®Öñø|¤1ør°À2¬-¢ëRò�?q@ï^@ð°‘ONh=FU•;I¸IÒ½FU)Ë­7ËVÊ9¶iXÅ ¢I¶Þ$Ù�JouO'V.VGô®›¸LhH‰ðHUt[ÓƒGP¶e�¢•R´JŽr˜XŽŠp� k—£7KUʇl}Xˆl¥äM‘sØ›lŸ$Ééìf°…³ÌVEÆô!�#ä?¹‰ßµµ²F†ÜhÐ,„ÐzlKs•“@MÄL ŸÞ&.8[)ù|ä¼ÿõš¢fLkÊq‰-ãÁ¯¶¨ü&Ü®]smƒC~·¡ëzC½R¨kŒ´ªôŒ_`ŽªB9‡!$IúvâîÝíkLœ»X·ÌVÊaù2¼i*^5 K¥dµ4É–¢l)Æ’ UR¬r¦÷2O ÌhÊFWŒfèÂ[(��UT U·ZGöÂAÙ”=‚pdˆ@Žr”x³«¹ªRl}ôéG?ÍóZnŽ­”H’„R¯ç"/†­íÒ‹CêÄ"D7ö¦ß¼~ËÿÞÁ”òêš�?¶.Óu¥þÀúʉt†,Þ[¾œã>¤*&žÆå¶¤×@è-ø¬“@éºÌ* ¶R"I^{=½¶e¦–ž÷˜ÖNÖû¥Û�ºåûe Ô¨¢‹ÑŸñôkº¾ùDz%¡^)­ð.ƒM‘¢ª Oá£öøŠ×û×ñ­ÍÚ­7×Ûn‘­”©qXîÊÁØ£ w6È¢•Cp¥ýIŠßÄõæ„UU¡ ºŠÂz7½× «Pžc±±[ ­£HåÂxE9 ºFXr¬NŽŠo�ª”UÆ¥û?+|¶æ¤]z!slö™×[íÚdްfÿosmßæ¿ª¯#2fëfC¡Õü¯.œ¡5dó#u�þ83i(—U'q©=nÒEÕÆ˜É–ôÒq÷ÎU±5§©¥ç£³›}æ5©5Ý¡[Ív~Å—a£³›·|ãÚµ«jw6ºîÒ]W†”áÎ~Z•:FÚ!hŠÉì:�P‹7FMöø wï\1’[�Û…¼)ˆlh}ëì')~ÓlÍnÓÄÃÙlz£+Z 6ãÜÆ¦AT,A¸£H¥$W?„kŽ9n“ª”[}vÿágy^Ñ­±•Ò c«Ç¼Þª[m5®6M%ø2L˜m�B%aôÝê¼ÃèZ Ùiˆ®áÀz8IÂ]ƒ¡™¥ÛùüËÉý¹lŽZ4Ęo‘¡âQT4�÷kðÞi|зÇMtܱw¨ÙJIjM÷™ÖZ§ ªXót‚7ŠU«p¶ȉé¥[£´…÷kÆ¢‹ z¢k°teH ÖeÜVh]NÌÇPsÔªÅÕJ¼U†UË0ÑÞ­‹õOâCl€Zhºi‰q¶‚yƒÑ_êÇãoÁŠVË@‹ª’ Uƒ7ÕqD g³£«a�®k�$c0O€q¸›}£$ÖH½®DÅR„sôÅåMàƒWÝ 8«ŒK}vÿQ‘±•R«qµn"&T¬”óökŠXIÌ#7¸JëŒÆ3¤�úÙ@ ¯Q×eL;HmÃí„V ¡”c5G_�ö(*K¶¨‰¶)¼Oƒ÷Òw¯Þ¡âe+¥U¬FId8çèë2*TÖÐþm6Å6íªÚFÃSùE×p�4ÜÑ÷ GÚÛùäú¨FŽÕÏj2´Z�µ¨ñÖI¢Wë§ï^½CGl`Œ­ÔnNµêw«�rFPÎ+GŠrG°%,ÊåâUUhu -� p¸I6´¢7Z•X§ ëT Í£‘ú”7‚q”Xý41fŠšæâ!oâÅíßAÀÖ�?{Pœl½wïWŠr³#þlðM¡þYre¸»½°ûtuM � Úòê­ò/¯-$Ô=6/ÞÚ‡×áÙQ ¶åH`Ö(&TDëÆ’-ôÝ¢K©ØÙzïÞ=ö0,EYR”äaSœ…nï/kh¿Fóæ]#=’pÏm�´ê£z)Õ1ÎÂ2Äû•h½c¬)¶ ¨d«?  «QŨÉ$C–4o)ñªAT(ÃkUDµìFºˆXÁZWQØìÉÿ é8ÂbY¼Þħ½wïÞ8ܧF{”h»ëÃ;åX�1f¼ýàÓ>dëÇEÌÖ·áaI!Î0Ä‘âœì¥öÌ­-‘ÑUm éçƒÁôõ.Ù$C hØæ»µÐêMì™ãƧ¾’HPö@˜/�ooõÙq•[%K‚p¤˜HãŒà¬ìTE޶¦nk.q«&9îÎ+º¦ûú°ön¸gRhnç3gÇU-£˜àðŸ2Æ!IÒ¿y=À§U8lß7Ž�p¹±7ö k˜ˆUËðzu¬M³Ú¦¡m…BN�³ÙùG×´ƒñø1‘iÿ�÷îÝ›ŽMàýj´kîûdØmÏVºØÅÎÖœXRˆ-�ؘ#¨¨”¡B9Ηa·³œö[S ¦Ãvÿõ>?I#›$Ôs¡•Ú&nÊ0ñP”;‚‚>õwK�_L÷m¹¬J€­9‰¤1¾”àJqÖ„/‡ù Œ7ŠIl™[ ¬%ø6ºf®]c=é¾>D Dn|fàrrߵޢ"&†xR˜%EYêdÅ|FvCӀߩ‚bëi»±7[F(ÇÛ4É6MªS·*±¦'œ[4Vf³ÁZTAužÏ"hdå P/&ÑøñîÝ»§AU“ØÈ8Ö7Rc½·³^õª.ö>á3U)C92Œ#„­QEù²ÛXæ Ê¡qsØàò‡¯¼;( êvo:´¾Ý|U¤D›†¢\ Η¢ÜQ˜5˜ôEª[Ü·Ýÿ–S)±õ¸XåO+V‚QlÐrã¶M“_¸ftM÷õÅÚ» î!H>}£’¢ª +ñæ,UR„+Å«Xµœ`«“Œ@Vàl¥œ#l§~u¹50³.ulŒ/Ò¶ó?X2Ãåæ]ÐÊåA,LëH«!:9MÈ&±! ªÇäÙ½•|É[�`sISs™JŒ­”*e(O�så[�5O'²›]æð¯#â:x3è^õ£F²¡î™hã8Ó‡TÅDj¬K�àÕ#8­£0KBp%w0)¸™ûp)•*[)ñå°P� ä(_SMñF ;xY;vÍèë͆VaõÍ…Ö•Ä«™Ø¬ «±.*SÓ‘€W¼jä{ž«¾±[ñn[)V�wSã‹»CÖ´bvS·DÉH¬<>"…®]Ah`¢i“CfÒbê)lÄ¥ö.\ªR.a¶Rb+°juT<mœJ´k“7º‘4 ‹Œ›CWŒ® ´z±�#ÐL÷Ž(¹-ÍeXõ$>8VÍr¢Q£¹—&O•6[)ñåp�¯'š ±6m’"¬ûfš"uõ€èº¶s¶b]R¼½L–MÝħ:¤*V3ŽLâC*¬e mR¡Œ�Dœ©cl/p¶Röà?�86„r¼Ï´¦[z!±eó[ú•|n@¹<œÅº^t¡•— ­tlËo",Z|b“›0Ó>Dõ2U)—<[)5N%Z¦ÍÓñÞ™äÍ6èK!5Ùè:ºüg£B+Ô+ i[SF9·MÜ>jŒY'ˆá‰èÐD|ø&+}MݶRj2ÄZtñÆéX»!Ií8q„5g£ëJœ$2o.]‘n Ö•�Þ¢÷óPT•c5S„Ô€&°Á |pºáb_G¹¦Ø^$l¥¼HV¿²'µm(ç·M¾ýk×€•ÇÇ@t½òZ{ht`.7ÏÐj%æ „Fƒ«L„e.äàÓ.êõ­WUïL²Ë�l×&†fÖ;õ«Bý„…úG#“–�Ñ}Éè m��Í†è ­9ªNr[lYCŒk‰)cÌzó5¾¦î[)µ’íúd›69lMwS7AØÖéäD6º®_.ºÂM½H ý¡5GÕibÔõhp•WpÃÍ×øš:Ê­ƒÅÄVÊa2¼×´fòí�Ø7œÐ¶v…ïWÇ…ðø0‡ƒŠk¯]ðs”LJùÀ×¾ ¶˜Ë@ètø¸•˜›"¤ÅEUʇû2Ý ¶RšYï5¦:õ«Ã¶ ê±F#aAt_!º†#ihƒ„û¤a#={xmiŽ+ç°°×£f[Œ¶íŽoHw�­”†­é~óZ·aU>›é3® •Dv–ž¯XæÀ˺ñ˜?F†¯/óaàŽ¸©­ÓZ�¨ŠËgc!=1m$ ö¨çæëš—Š4·÷ Â’$ŠïãëW&,Ìá <>*…f®°·9$›¡õZl%I’Ø]]ɬ袓¶˜k •cµ¦¨u9qÀxU¯ê;ÈVJö�~Ùµq×v¯ùp»uZ¦—@ý#‘IkÈäñÁJ“a/š �žä¼CëÑñ[øØ|+×CsXø¶*š—î&[)Ég3ÖõAÓšÞ¹38R¤‹°- ºîê—_øcïx¨B�R¸¥î“@£“ù¿ïá¸*Ø’zÔ‡Á™5éàlì % ªØJÙsŒ°3@Ø`bK_�°à\W+]/µÎâÚ¡ÕM’ó;ëËÛ8I’ÖÄâ4!+^ªR¾³l¥4îÚ±g†,iÝâó^=„ ®¬"µ >x70]üîÁH&”,+wòxÇÜ–æZB=�’$‰oÇâ;[L­¼†î2[)é�;*û†ÔšÖ,o˜×tÖìYŸ�®öÐÁÅïuI N) FZó:b GÕ)|t>¹Iry›ˆïlcSì(Â>áÓ>"¬yÍ�ò…^/Yp"—°õùUÜM’ޏ_CÈ‹�ª”ï8[)éŸËg7%¶´Þ¿K aAï”-h^¼ ºÆb$äÁƒóa¤¦.½æ8BŽªÓ¸Ê• 0Œ ¥âñ�í"z”Q*³•’fy[1¿!±­¼‡„í7¯»Ðë¶e:9 ¢ëž/yn“ˆµ·#­]P�™¸öQ•�;D(MΧ çîíç«Þ´ŽrëàD °•ò¯Ú#Ir>ò°|©Õ:(�‡±Ù—‰®äÊçG¹\œw)°Æb¤?¾±HD!PuW”U)—Ùš“Þ¿«pn ÙÒê¥�>ÓZ>‹—ˆ®p ‹‘pÿHXï¼Æ[䨪!T®dÔ·N.Äâþè6†Ù£ŒR™­Çeðn«æ6$–õI×VŸiMHöZ'P˜@t�û’¤=rntÅ;zbíí ´†6®ñ9ªNrgœX&Hg<æMm‡ÒÅÝK‰­”‰Ÿås›BÑc\3,¿�Ú2йÍwÛ4QÑuåâ×�(4(_€óxÑw-½ñùH7”Y@‰XŒœM@ÙCCJ‡ª”Ël=!õÒÎÈìÆ�e]ëÙ·°`MÍ”-d^ @;§ß‚HØ…æC×­GTÅUîDl#çãñÅÔ¶o½(e”Êl=­I×Ö¨=38“V{^äCئ©Ääâ®~åìèŠUWc�ÍH×Pddüª¯üv¶Ȫ®XZ%]±˜'º½L”BSl*5¶Rζ7KØa[ftvSs!aaj‡ášº ¢ky�ð¨ÐÊ»à¥(ªÎC„ÏGÚca ^‚T¥\fë™Òz¶åŽÌ�edXóuô&�Ú†´œ�œ~ý°7 ð:0ÖÍ_þ5ßRµFCŒ¹âqŒtñ…èÎbqfÕã*³õ<©=/F›ý–ŒÒý¢ß´.ÊÖ‰^�°FßÞat…Έ®HsV]�ˆ®Z�SÕ�Ò¤;[IlC«¥ÓK•­”s„í6¤4Ë/†­i™=£õœwæƒè²ùÎ{AH©EàœÖóB«ÏG."›.(NQušPʰš’¤*å2[/ȰsƒÖõiïQ†½ü"D¨g8< F]W~=ê Add.»¦µºÆO\ê2jóUŠªÎxre�tÅK±�wÎÿ,•Ùz±”îRûVÿLFµ2ìU Û4•˜ZÚ5øö‚¿Ž®Pm-\ß÷ ARõ%_j%ñÊsɱ:Šª¡(éŠÇ—VwÅÙ|Zw„­”�VëÙ4¯K¬éñ³vþGx<„Š®‰ž~0ÒÊãÇ*+qçôß§ª+‰j‰ñÒ¦*å2[ß©iï¶l.3l]×,_�°Ao©mX�wÎ_�ºF–3v™kçÞù"'¨ê['�É„'¹»²V"�2Je¶^Fª…RÇæ %3uEÂ}{ ñ`’œ…^A¨¹ª­EDâË„ÖT ÇHw4î�í„¢¥Ù;Jn¼õ—²®O.‚¹Äo{‰ß1�î OÛÁ„áðag I’±e"⌼3´æ–Þk£c®XÌ›"�‰ÄâênQ�«ž§2[/¯©…2ǦĒ1.=´d„—#l6º>7úö|o»m}aq-Ô5IÆ.þÛ•äëU]‰èJ‚tÅUÃ¥Òmr\w�­”)в„U΃ItÃÖô˜ëˆ°àÌt6®m8]±—_q¹Ð±éÁàA·›ñ'£>é\½[T¥|ÈÖ‡e¶^J“‹»£`¦SZ»¸;0óîEˆ ºÖ5úÂ;�¹ÃQ×t,C’d¤4¢�=ï¯rTÕc ‰èv‹Å=‰oªe”Êl½ªŒKÏÇæ·d³t)Â|{�qß*i]ƒ¢_ER-3ç6Å·T�&ä®x|e�t&b‹‰í•Dé7ÅŽ;Ð'|ÚKÇ;æÚê3¯ YÓª,aQ] º:Çÿ$¢Ò£B!ÂåBoGZí1�/í#Ir.Öàê»FUÊ€­Ël½š´‹»Š¹M©=möïΤ/ÞHî MÙ‚¦Å•Èó{÷î%<�àlø¼Ðz‚ªá¹M,ÇvK¬Ûí´Êl½žlÐó Ï–lnÃä{1lzö×æÏ™KÜ8 ¢«!]S|>,¬ŽtôAê3ùUÁĹx|1¹Sbƒ§uŒ­“w�­”—¢¿¨œÛBÑ©_U¹¶: ©NCªÇ¼F­u…ësÑ5€½Dy|´²ÍŽ´Z“CL«‹ŽÛcÍÛÙJ+É}Ưèö]fëµeöïª]›#öL.Þ¹Ì?¸CêšV"ÏóPH7–M��˜4Ž¿vœªîDÂ'ݱÄJ|·$»ÝN«ÌÖ|dò½P»À˜Åa†=‡°ú•Ãèꀢ"q Ìü¬ø×O6Å,UhÝ>2Ç@V�ÇKiâÜÅ*³5goì�°íÚÕóZ«&¡–Îz»PQuȤ~'dI g¶a">½´ëp`xg?RÓ +�ÿ×#ª#Î8Œ“Îxt!¹UòYõ¸Êl=áCÂÊñ¦ÉDßÌšbØ�°XH6º°—��±Ùóã­ãø >>5‰Kdhµ‘0ÝeªRV—>zôi™­yJCÖ–Ñy_ž&lÈC õMÁ`Ü'QÃ}ái;õóãÚ¸I ¬¬YLî.—î¸êy*³•.Y çãž-ù\Æx>dÉ•ÄqÂêW^4MƃÙ>aD Ì…ÖT]N’ÎXt)¾¼K_ð(åšbçp™­G~›añ–©DóD2PÝ08u�ú- ÃÓªA5*ŸÄåX™ªG>dë£2[i�ÎûR9¿-±oLöÌ¿Zæw ¸zÇf[ú@/¾ÿ«ÍWcx( –3,ÅwïH·Ûi•ÙJ¯ì�ç“î-™#£_ÚÈN ȶa"ÞkX[ÖA}ÒãT�$¤óq(�YÕ“ØZ>ÿáÒV9·^à\†åH¶eKQŽéuiËYõ´Ël¥]Ó�=¹kkÈ–Q»w{Áù°D—aU0Šp¤(G‚ôÊVrTuÅ£`eM,æ�n•ül¥‹UfëMH¿´«œÛ²¬+�æ45ùS Ç9#gnGsYu>�xãä| _Llî*U)•ÙúN�»w(°RnÔîÚàËømŸð'y6È2[OHíÞ•Ú7:õk-ÓiÞ(vÔGéŠÒ™@ 8æIn—ðʚ˫ÌÖ›“Ò¹!µg:MÉF+Á“ÿª)ö-L8¢Áà*éŒ ñÍ;5ÄžÊl}§§½»œclm6xyMX’l}øI™­7!®*$Tâ|vü;[ŠÔLÍ«CZ3aµóLÆBQ™­7*~oJ¨ˆòeG]y”«Ç=ª ÎLXìQÓŸ±PTo½ÀNôÍàLš;ŠqFQŽãJQÑ¢ŒÈÀ1—„“¸Î9J¥ê2[oBµ“Pã$.C¹ª[‚qFŽô�°Beh­Qa£X�oQ=ãÑ^¦?/ó*³õ†ÄïMÕÉV«¥ ~o*×�%(_ IázÞ¦F›UhûÚ7† 3ýy™W™­gÚ…¾´¤ù2\¤À+˜†…ã¾ijIhؘ ë¢SeÂw™­ôjДìÕ¯6OEk'¡Ö©$ëÔ§Æ•)¥åJ°žVÌíyIm,ÃÄcx÷x´W�÷LâmTÅôggRe¶Ò®Ýf».]?¶ÊïMµi’9Þ¡]U9·YRŒ%�Z¿a�Ú"X†ÖŽa�cȰí›Ä%:bŒéÏΤÊ}Â'|HU9^§ŠV(°¾‰8I’z¾àܧ®»^êøXE96³àˆù5Ä„¬LجÙú ÌÖ|5µ6 ë3¥MÉN-Øp873ÓܖаQEaHÍt¯R•?$,.Vc½Ú¨jžF•zTÏôu0£2[iÔ´{OîØî6¤[t›Ýú5¡ïÔ§XRmöï±¥hK‹3 µ þøÏG›ð£ucX�ޛć§q…ž¸ëMñnîyxÜóðë~óº@N´L&8R„+Ç”Îu§9­c!¦ÆXî×L- -hZ“΄ ¸Ñ‰a†¨.»´ðN°õÁ'–Ùš‡ŒË{cÎm©-3µ¸Õg^ʵ³ë¢÷À Â¥>CgÌãyn¨‹z�fªç:Çô¨~š�ëb“3I;Ó×tÛ*³•�Å­‹[£Ž�i÷^¿9-R9ªRnœŒ³%H¿2 Žî™<¹ÿt¸‡ .Çûô„~ —iñ 3î`úšn[e¶ú“ä\–ª"Ñ¡[mŸŽÕª±’àHزB«ð0´R^pîéùxEÙñÓ¦ìø‚·.Äãú·„½›3�TÆ¥Ël½®fj×ΨcÓ¸¼7dÉœyæ—¥wÕ6°fh‹ê‡bóšŒCµ1Ó³zâ.P„•aâIbh&i×FÕBo�y˜¾¾ÛS™­yÊÞŸZÜU87Á¦LÖLµâ$UýIÒ>àË𠩯[›ÙÑ ÝŸ‹®9ç=Ç̸Cƒ�é£Zkü.6Å»våCª*‰CJ5·Ö©M´kíÓ1ª8^庆…b'þÊÔ×±‘ŽÊÍŠ 0Õ|!·Åg¢ö¥øª!ª¿›„}ËÖÇy6È;ÅV’$£?/b/ó[3�j»þ3O!Y\90ÔFݺÍ9e49ë–ß¿c¨‹..�±È:—a'q©=æÑ“FÂèˆz™¾ÜÛP™­×–z¥ñ¾P¹¶má}©}£ZAœ·]»vU¤"X£‘ ©Ïï^÷ùÀnœaóâéßÌím2�Yã-1i ¶ØÝjŠwálô㞃_õ›×«•DŸiml~»ß”’X^s•ѲP#­ó{'þva~O/ ¢ëÑ™tKñUGÌk!"eˆÁq™„úî6ËÖÇe¶^RU¡ÕW$ Îê’ÚÎΪ9[úRvEzv,ãÖmÞ»wÏïßqÊãÖ¡õ™Þ“Ñ5ça§ˆGÔk ´fÂ>‹0}é7«2[¯*’$[?/ûc®m;ôJ6·U­<—ªþ$i åD…ÔÇ–E¨C«ƒÓ ¡ ëéèšsް“¸Äóêˆi_ÚÛY'ÉR^{Ùš£ê€y]ãÞšIKm™±ùí•Ñr1- =Z)›âZ6nèß:Ñ<êuBÖÈ� jë93ºæ|œ°³ñI’Ø6ÛI—|S¼ l�…^Qãª3ëS+/$֌±©qïž.‹†…èø˜Nˆ»çN†VÊ ó{:!N’$bÝ:ýçîèš- 뉦M1ó] ,ÅÖÊl=_Ù¬ú†¢ª-²ªð¬ÃnNÛÒ—r(2s㛋‹û¹WóI}neÜ!ËXúRï¼;ÞÄ!a5¸rCH’Äwâ‰ÝíÒ{¬•ÙzªnüŒd»MæÑW£ŽKQÕŸ$í‘ÃÐÊSÀÇ_0¢ó„ ® ¢kÎÇ+�‹…H’\ÚŽÚv6L¥ÛÛKz¼õ�ªJBbÛ˜ ¾’:6åέ©•ç•EËE5,ÄXó%Î}Mcc\ÇÁÛÉèš“'švDýbÞM£3¥MX•qéƒ2[Ï‘ÏG.ßxa*«î�Ø7.IUp¸°ï•ALxl{NÍÉ®•EëV8¼k¨�.._jÎ#Âcî$‘}¬%ì»;¥ôX+³õbQ=ÀÈ ªºU)·kWkTq�É…VJw‚H¨s 4³t™×É�‡8M(œqØD’s©¨ßİlŠ¥ÊÖ\V•Ø6¬á×òù퉅ç3ÁWÔDËBt< Œ´Î¾¸à•Ýs{:F’$lݼàÕ<Ñt8#IÒß2Å,¥JØÃÜz¿ÌÖ_Éç#=¡7³Ë>9 QõÔÑççÙÒŸ²�¦ê �mïÄ‹‡Ã»N͆Cž¶ô¿;ºæœ#¬W»1I.•P†-³õ<‘$™Üþ]£z€_Ëf·Î;úüÕ<•Ë£"éÙl¬¬º“$ÜÕ¶,_ï]–¹^âÙ(œ�K\¬„=o(n¶R=ÀÕÊ,U¯”s Ø¹UÁH+¥B«ë¡•²ÛñB/À³£®gL>O>¹„¼tâëî$éIn•a³lýøƒ�î.[MÁ½1÷öèì†%ørè-UÝøeÇžNÛ2¸fWfæ&·<ž‹šq ¢«]ž±\'ºæ|š°¾td6~rd­ÀUf+Ø<3x ^ؑ͂ I†ßµtú2v@¯JZë”ñ Þ×�$}.8d^D®]s¦¶È3�pùÜ!a‰èN¦¸{”[‹–­UŪè°mþr œÝštïÚÍV:O:¦e£ÆºË†Vʆú˜†ƒÃçO>Oî$¹�ÜwáiŸ�\\]Ëö‹‹”°€­ÝQ¶ÎöÔYªš‚{ƒ¨J…V}5±äÚsÎi=®9ÃŽÛý¬�½ntÍ9GØi\9ÇôQ£)nw¬ž1¾V˜ºãlÕû÷U®�‘ÙMcð`ؚΟª”»ô©–é¤X» ´RòùV½)êè YWò|Óã„uÄÂÙ/{AG,|[µÌWÇØª.:¶:ŽQÕØ—ÏnMºví+×+…ž Ö´‚‘Vûó+}Œ\t=s­ë;åó‘^ä…+¹æ&a³;NÂ.%Љ°[ß¿clÕz_(æ·Fì™™mT¥lZ›Uef'6–\'§Ÿ–ÛýrvrÓ!ÏX×h¹›Ç2¬Ò± é¢ZcÔd�ÁVuw–­:ïKÕü¶Ô¾©÷ïÎÐFUê1+ÌŽ´Ö©. ­”¼)2ä†"Ƥ¾9ŸèšóÑæ' ¬Ž˜6zkláVŠš—Š”­¶ÐA§>U­ŒZÒú•£³›c »†Àþ%®ø\éy¨ž�j®ZýIÒ— F]±eÕúµß=;û¿³æ'RÆb#¬Ê¸ô>`ë£|nA±uÚ»-›Ë [ÓZï‹ËúÛqU¨ Ðx­¯&À<%ã»C+%§qgqqßPK,ù_Ñò²ƒ_o3,!·Ç½ZbBOhÍÑ‚>[ç²U5·9bË YÒ:ïË¡·[R_féô%ÝmH5O&Êw‡VJÚ ¡Žþ�ÍG[S<Ú^lÄ[ÐDUÚ˜Ú´jºùê^_Glí/¶ZÃYªª¢ý¦u©cgÐ’Q9·ôçïqIiذŽ�‚‘VÛÕB+e—ã…^ˆë¸†‹æó1À\âÝçÑ,aÝɤžÐ a[ï?º l•Ïf†,ëý3kÓÞí>Ó½T¥lZs(7S›n÷»C+¥ÅÅ}Çä¦]‘¶Ñ]s¦+CÅBaŽÚ§‰QmTfLè ìwŠ­£3ëC¦µ>pÎÈæ€y]@7U©7¡¯P'ãÉK~*hƒŒ,ÀA£‡®èzÔ�¡6­š¦É4>ª�è ìEÄÖCª*U¦­>CzȲ!uì\â*ß--Õ°aCMÔÿç5>]5\TËÏ‹­”ÀÞ)»»ÄN*»vÕ�%¬Ž˜ò&v¿ çù.°µÛ°Ö©OuêVå³™ncJ¨À%¶ ½T¡5˜ ­Þ—󿫵m‡ngnîÀ &¼ôEלs„�ĥƄj*Ú=ëÖ%[n¬Ø×Ôak�.Ù­[íÔ$GgÖûŒkWÝ�äòî6¬µL'¸êx…ú²lÑ5�D6I¸£/d÷Óßߤ8� ê£chÏÒ; ußd½¯£¢è¶…÷³T%z�kjwrÀ˜’˜2 Óu7Ï”Ž�Ž´Z¯Z)»íÏuBð:Ú*„–O•]û<´�›£¶ù8®Ã§dLØìxk‰°•Õ±‡PöÊ‘ÔOê'âÍS‰¦Éx·a­C·*”ßU)[‡×g•iZ½g¯i=OssŽ©-0a˜îèšó1Âé’-*¢A‰5Éð꛹×Q‰±µR ³dÀéáS¥eoÓÄš§b¯úÔÍQ•:ÖD@…։ĕ>6²I† ðL6º&®“VÞéÜæ'ãXÿ$Ô=†4�¡ÍcˆøfîÃuTà¹5GÕ]ªvêÐG¥öUµû ß .#Ó±±k‡VÊ ºÖFµUˆŽCCt=®ù8n‰º „Ñ]Ñàc…™a³ã­¥ÀÖjÆ• ¬~ˆ#%8Rœ?†×NÄjÔÑú‰x»6y£TOŒ0­óž—s¦ËŽ´—˲ë¥&ß@tÍùp«VcÝ2¼Z†Šeh­ãÝÀݸ²J‰­]ØOÃH¥€•-EÄ*´q"Z?N´LãºU�üš’üÿí�ùWYÞÿûŸyúùýé9}¦ç9s†ÙTÔQi{q_ж»ÕîÖž^|fâŒdeSQÁ QP „}ÉRI „-ì RK6a×ߛ‹euH%Uò>ŸãA–JÕ½Ÿº¯zß­Vy†±µWV†¯É´B ô{ûÆÖµi |g « ¤b…#³KWéJ×¥°ÔÇEck¯ØÚ`{–‹øÒK‰jï•{V5vCM,¹×VˆÒŠG[Óðöu�´Ò£Í<�¤â:9¦NÁY?O³³Ï@˜tD�Ùc®ÅKTX�°Z¢²ÏÆæô­±ÈÖcÂf«RI^+Ë(ÅÄJLZ„ËŠ0E ¦¨Àoj¼©*@ÕΰQ†¹p¼©t¢±fªµsm¦ªgàE‹f¦©lÒ6ëJE�gÖ‘^ŽÞTbr%&+Ädeý)•]—ŒFQ*gUж’$YlåbâB‡¸•9RKÐÌrôŽÖ»îm¾Ö-#/�iUZSË×Ó×7F‚µ®Ý#×o†ÉºÒR1@X4½ÏVº.)1I1*hËÈ·^ÍiçlØ‚JÅ›ù圳µÿE×3Ÿgïµ/%®×xDFcZ­-«vé,YQ`÷à$3$Ó ZWu ®•±ÏV(³Ç¬wjªñ‡%#7*Ð<–¦#j»½sXn-^dõ†7‡WÀÖc‚gkNá”RIŠ Q‰•‚pd”©%‘ *Ý´6Ö?‹ÀR¿ÐÙû3’^ëúæœ=s¡+FE˜¼—>ÆeF£¨d å1*yŒJaVëç튶š¬`«7‰ &VÚ3Êq{‹¼ÞyƱ�WQ6ÂxåÍê5Ø7:8vëJKE@Ø"L^„Ê‹0I™#=§=§`(Ué�)r¥#�í*z‹¨TÌyÀ [+ÛgóëÇïhG³ª\òbL¢DeÅhŽzTd4ÊÔ= m¯ÈƉÖéˆNŽêSñ6S¨¦F[Ã<’†kå¸VÆ mJFn”9n�d=J-Eo¡ò¤¡�| ÂxÍÖ“!^‡lM)Ä2 ½ÒB@UР:dJ42T…aVÓÚT½NÓ ÕÙûs‹n¦©|¢áñxÄj¿Å5\„É•€§ ð ñ‹±u�+ùF�Xé�9Àc^‘C¦ÄÖGˆªý^²uäeª —•Û.W¯¿%-#¶úž‘·Âm]©°¸Ý*4uñ‘•�ÞtT¢t¤sÈÖìûeœ°Õ8ðôZµûõã*)rˆjìÒšÁT]_X© ¦KG�L"tÓ Ãê!õ—�Z1¦“‡}³¸bL¬Bå¥vy¡C¼Xx˜¼ÎiŽ|%¾fëIá²5­œ�c)…˜´£²1­/³ÌD¦{‡^"éD§å™ uê{[ã|ϰ®=ƒl.ÇX9]½ÅÕ¦I 1q!*+DÑ–ªhUжf¨À`„Xé�R¥©DÓJpeãdÄjó~`¤5­Ü!+·…r-ý}¾>/´®ƒ;ù—½M§¥¢D‰*”Xú#§Œ½Zz»ÞøÖ¼RNØÚ`{–Q†S)”ªòŠK1QØz€éBÄ8|O«¥žÍyAÀº¦ã:¦a{RC•^Q¥W¤Ä$JÀÖ77b ®ìöFz¦dëa²5ß<™W7~£ÖðZØzµÒX‰¿î!-z˜‹ÆK&š«¦:-!m�F]‡~nAfš*&Í…‘³®à½κâ€{-Go£ŠRôÚC4¥ »[KThœZæ/h¶*[&óMã9µž .-Æ¥EØå °=Žº{>L3�—Œ7¦µ*TƒÐç XWS¯#‚ÖµßKÖ»ZŠîµ ½^R1ë‘SVŽçjð*ÑÀRu½E4ßi¶6ØžÝT{ª×6¡•©pY1‘ªbyðrBd8Àk&aeɴ€ÖU#EµŠðZ×J¯¨Äù~©pDúp(õ±]ªÄÄE© K/ÆÒá8lÄj³ÜÐ}°õDˆI¶Z¦óüw cùæÉ\Ä—V‚5Mv;Ù\í¾Ê˜V¼«�Ó e1Ïw ¼£®¶ÈY×~/©ÆËTØå^ÏónϬŒÃfÔ5N£¯Ö¦b€•«[Aeku×´²Éÿ nLÙ²˜Š¦ñðMG_9îÇoª=é!›V¨A«oÐKŽÜºgk¶Eò*tD­ KïôL¿ÞÀ3½/0 ¢Úà2™=,\ÚÊ¢Rñƽ’ˆ±µÁöì–f4½„H/sŠŒÆ”b›´Ð! ô�ÈTášÄ�N†éä8ë¦F›iN—Žk˜Z^ë õp(õѰü±]Zè�¡2zµÂ¡¬Á”p.q·—�¡ä•#ÀÖBa«²iúA�?×0Vh™¾§÷¥rGUæ"?0­5S]m¡šV¨®�ͺ™ÆÊI³2¢ÖÕêý¥ŠÈ§þ «B3ÕÎÒb@OMÎöV÷Û·¥]·ÇÖêÖeÃDAýXu×4Ø�$Ì‹¼Þ”2­ì´]ƒ^ð^W[C¤­«Õûª Ï·zoê7/¡ Tf�MG F¢©ÙÅÎ^Kê [óT`+ ªÖ›QFÜÒŒ*•äår\RÛýï’^Q¾=åÑ›õÑXw#Ã� –MëbµzH}¦S-Fµ2^ÑUáPV¡Êü±ÙcÐàªb4„…l=Ä{¶VuÌš'îƒ 3§‹9¦*0­Ã?ƒ‘Öžg­FvL+”}ðYWÿ }ÑYëauDu«Ûmtš'0ÏÜ|8^& ¶ªš§šüŒcÕ­3áÛæk­ñ n<§Ö›V�±bZ¡¬àí‡Àº¶ q{u´×<•6»zÂ8à·»gÃòªb*¯ç†—­ Xãͪtš'¬VR©™½_>¯T‚+åÛa°~uËI#ÑÊ1]*n© W¯i[ý’ŠƒO‘Fî��.³Ç`pVëð 3Ö£Å+ÃMØrC÷¡c'å/[+Ûf &òëÆ«:fïê¸÷ªT4û›JüÍ5S�=ì˜V¨Ññ_H’l®œ4EÔº.a¢¶ÍöóôcmN‹—,¶VµÍ(ÍŒcªæ)>xU*,èKE !©"2«Wµ-ÿ*ÕG]úFrîr~�ô—Ph‰r‹ ¼ªŸñ°NØ7l½[&¶Ö <ÍV{²ª\ª–©ÖA²¦eÞÐþÄjåò-·p÷`]xLëb¸_!™„NêÐÉ#Ñ-¼œÌX�3éq�Å;‚µá#,`ëQž²µ¶k¾¨q² Þ_Ù6›‹ðˆªà6·LkçsKkZ—Ø•Úù¢ÛöIçÞºRÑí™Yô°¸ºÍé3�õ®ÎfÏÚ¶Ô[AœÔt/žu¹8¦*”V†«Sð0�´þ&Öì©Ú‹çXp1³sÄÌ($¬žÐªÐL=¡c‹°`¼õh2تí^(ižzdš¨í;}-RÕÅ#ª.šÖ4¼£c¡UÏÚ‹'è X×ç½60êÚ;¹E«Œ7–¨¶ø£³¡ÁÙÙê i™Ù ©ú¸Á¯î™ÀKªÂȯ#­©¥ì›V(›Õ¶iº™ËëJÅ•װŒÃŽ„ØKü†­· Yaë"U«Üí³8©ëZ0õ?ëÃyAÕÀ+oÀ†„HnÑÏF Ê,upÔUó¯aûgFÁ«Ø=£z\ÇaË Ý�&:Â1[I’´û^¶ /<6Oh»îó•ª0U~s±¿©r¢£#Ô/'´®å�Åü²®Tt{fÀr 4Cï¬muz�D£ÙÙµîqX^±U×»PÚ:]hžà9U¡iU¨pI‘Y¾i…%mûP}߬+tÛêŒÃÎzÜs³ë#,•ŠWo=‘­�ª×ª�Wív‘ºîóÀóÞPJ'ÇuÀV«+"³Áݯ� B-C5a^ëº&µ“dûܼÅë³ZÉNϸ�@B',è>’|àð±ÏmÝl%I{9è~F’¤º÷É}#x©eIË?©J™Ö¶æùfMXL+U,üEwßK0a˜Ö•Š.aÛœ>#nn :Ûœk‡å[I’{Ùj_(lœÐõ.ä×�ó™ª0 êü7jÜ©E„¤ ,¦j Ïgõ’#Ùwl­vÎ/y¹€/¡Ý)Îj‹×µHص{X*¯Ü\?[ßPµ}¶×Mj{êŸuó£˜.m XwFZ‘H˜Vmu³º4°Ö‘p3ax9Y­dÏÈB‡} Ö=¦w†DØrC÷¾ƒGö8âY­ƒ­í$Ù0ú²Õ¨ª·>}`ç9Ua€­úÍ¥þ¶æù me�Ž-ZW³Š§Ö• а`.±ÓSG˜]��k™éÄ-[I’ÄÆ_Ú< 5}Oòë@UÐFa?CÓš¡r†Xh+Ëê%[‡‡ê»Gnær~Õ+G�gnqÀÂY =ìÀ¤Ãâ]ƒ©§RñrΣu°µnàéõÐ\Ý1k%u} &Ûó^7ï¨ ¥“aÚ,r¦5Ö€uE$„Ó ÃË Ö‚ûÚAËæ×¿ñ° kºÌrC÷§ŸøtßÁÏgMlm'I“ïâzÚN’Úî'y†±ô²Uù4[iÉ覵Å8ÛX5b‰½U$Iº‰�`ë'>[W*è¶Óã©sšÌî¶ÎÕÍt⊭°ÛRÕ8ðô¡ÉÏá6_k�‚zÿÕ*WjqxM+Ô@ß(´®ƒ–Î/ü­ñfivÀÜõõ®–ïª\•Š™7®‰­ëHÕªU‘¾óðsë(O© Ö´¦Œhe(’†µFд°f‘4‘£|³®”Ú½d‡ç‰Å3Öã#Û=cë ,`뾃ŸEŠ­`\uôEK€ªšžQFcéDÃã±ÆâñV÷‹XNÞÀZWðfXÞ[W*(ÂjñšNQï2™]oó°‘g+I’ßËÁ@·‰ÁúDXTí÷’íØÏrž®te–†k¤•.`][†mÆ.ï­+aµxU‹×apÖ LØÝsÓ+÷¿ñ­Ù«d«ÁúäF�çz`\µoŒÔYùNU(­ Õ¤Œ é5­0€uMÖ•Ûµ®oU��ìô.´z€‡í«uÔ«'l¹¡{ÿÁ#û†½O8@ÕçýΧ$IÖv/ÜU¦õ]:Þiœi©œ±¸V)0Øÿ¬»ï%’†÷ ÀºRÑå™~ÝK\ÓáñÔ;›‡&œ£³ Ë5k‘d+�ªHâçá"¯·Æ#“ÿJ¹+­KWF‚­ÀºöŽöÃQ×6ç—¿úxCX¢ÊâÅI’$f¼žÙ¹·¦bæ�ü·²5@U7¤ê€ xUÓð³¾1¾SLƒ—ÚµrT—FXt‘6­0,z0ê ÖºÊxj])µ{Év÷\‹ÛÛî%Û<®UÎ>Îy¿¥ê\ž^xT…ÑX:a*kx<Öiœ ±¸V¯î¾—Í5ÓM%`ãbÎK`­±HX첞Ðw¹ÇI’tÎŽyçž7k‘a+xVñ½xMÕ¤ê¢i-ÆReEßKÚZlCÆŽ‘Ûyœ—ÀZƒFØšv—gÂR©˜qãÁ lePUß³`|6À¿ÙJËI+w¨¥v`Z�‘6­0¬®W`÷~™C§àµu¥ëlóª [nè>š|êHòç!~î’l ¬¬yÞ¡ööç`¶°r¼±TxÖ•ŠßzX&aÃÊÖŠ®¹Â¦É“¿¶gá�Wå÷tô"0ÒŠ‰•vEI¤[¤A׋a³uH×2rû>çå°îxCX\×á�\ìN™g¦búµ<:[)ª¾ñª½ �¶çƒ|�¼‚tà=­’Š[ .ïh]ÕRT#çÑZ×Õ(ˆ°KxXÀÖ_M>âgÑÙZhšx`»§÷•¶Lå"¾ô2¢Ü2ÓîÝ´ÂÀ´¦á&å¤éÑ8K•³6µÔNv˜g‘t¼wD�Ö•ŠîׄEðEÂNàmO˜ØZÖ<ó¨~âAÝxE×Ü=½à© ãQƒ?µÔ)S¡beäÞ“Bi¸ ³ÛŸ:nÜìÀ8/ŠÐRq‘°zBÛ9 Rq`k¡¥bZÖ=ÈVŠªÙµžrË46M­Â󪔦ץrlZa´êfti„FŽ ÈºRZ¹—Œ·9ÎâúÖ/ÿ!»­-4MÜÑ�FUa4•OÖßóÖßôš”“,UËÚÔažmTŽ5<´u¥â a ¤Íã1:�?Ib�­§�çéÇÊšgÀ[Ë…°tz5GZ%#Šnõíö§öúî¡Z“ ­+-©-²5-â4þ ½SQqåî%Åu]ïÂÕ*Wv­§¶sÎæ$ë¬ -#ϰiAR á‡i…AYW-Ÿ¶iZ“–ó°%HÓ®ÝI}òIˆÇß‘�Ùš¯ï‘,�ªR¦µ1ËÛp3¤-sCTc‘¿¥lŒºŽðzCƒÕG§gBKT–`W´DM›§6h !TÂÎDÈVeãäÝhZI”PÆ#“_¡Âä*‡¢„³7‰Ø-6‡cj$+[èÖ• ÚÙUõž~˜ŠŸî;tâœôz�GÝ=×ç% }OšmÏmNSöƒáT¬Eýi…Ѫ›AÒÁ‹x�áYWJ¿%¬³–(άùa÷ÞÄÄ]‰!yOÒÞ]»“RîÖg”•`›¯h *Œ¦ŠIãM·1ÃÕ˜Å%[[Ê&ëïxM¹£MeÑ`]©èôLhð²ôÊ©s'víÚúÐÿGº{Ï^ÑõêôR¢Ì2Ý-Tí÷’ø/²b˜V—ËŽ)w­Á^\Ö•Š@wJu –ù�èÌî�ÀÚ®�öý#åVuç\£ýyŸWØT…Ò) [ñ>˜VVç+]ޤ :©P­+¥agÌ®¡´‡òãßíÛ±ãÄ�¡vÄ}ºïÐþCÇîVtGU�iÅ~ARqý%—!#B«WPÝ�ñ–[—Š÷:¢ÄºRÑéñŸ}—v-ï'‘,ÄR:pøø‘ä/®=ª�&ªÂȯ—¡R%—¦j²ZK�Ž+×l8çÅÂnt{¦ÿ/õŸÒÌœ;v›ªïàƒ4RT#Ã42ÐõªK#ZµÓœ—3=Z´3ºT\+Å4ÒðîÞ1}´owBB»ñPðëšfþnå½¾hª˜4dâˆ à•¥R_¿Œ·Üú˄ẫ©|ìea{Áyù°.ʯÜz|ùæÃK)ùÔ™§Î”ê:8¿"v£ÿEªDS¢’ÇÜw�‘FãäÃÇ#¹Ž»ú½ä€mªß=O2â´ìÔ«¹�­¡·�|�F‚¼*p­ÜÁ+Ó £ÿU«ZŒ©/qŸÞ¡+! VòçèñÏ�%ŸŠ2¶öa¿ê¤¸VŒòáM¾P…r¿QŽéäX÷ÐKÃ5WÔŒ½B¶^¿«Ìº£ ±ˆN�þæÔ™o£�­Y5n©“¼²”M!iÞd&•JGz¦­ ɾ3`õq^Dl…8-;íz^”±U+Á4 Q`-~™VútB#AÕ—P­C¤aß;Üb‘­ÇO|yüä—ÑÄV0ñ>Û­“¢Z�–¼Ø• ‘`ª¯HDjd(¢À´´­ym¯fàs\¸(¿vOu=·8ÄRúòìw_}ý]”±õ±É/)D%J,eSHrÈdS%%àýAb1&“¡Ébá¼”Ø qZvÆ�QÃÖ¦t—^ŠiÅ­ŒiÖßñ˜ |Vž ÞÕßóNE¤x ó¢É]·Xdkòç§“??5lí#~5Ý÷¨Šj¥þ°‘€{D#Áà¹5UNq^VlÅ…‹òì¼Òy¥!–Òéo¾?ýÍQÃÖ^÷«ûÆqIÀ þåÅ|‡LB,FÅbT"A%{‰†ó²b+ÄiÙ—s ¢†­9Ö”îÒJ ã wgç3Î ™�e“¯Û[V­E¤8×%·~±È֧Μüâlt°µgðEÝMÏbE¥tb^4hˆÓI:©]÷ú61Žq^\lÅ…‹ò›Êsî—‡XJg¾ýñì¹£ƒ­íØÏ9µ^hW%JTªÄù0Ø Ù:"•Úe2T*…lÎ/æ¼¸Ø qZö•›�¢†­zZ+¶käu·Ü½C/9/áàh3̾nrZ †Hñ[¡N~q6jØÚ¢�iPŽ/V´Õ_r!b¾Ô²NjWËGªÒ‡agµá†›óâb+.\”ßʯ¼•_b�=÷Ó×状Vu̘ü2&-BAŸpÁˆ¢˜](`•«LæP(ÐÌL,ÀVôòU΋‹­§e_½]5lÕHF�o¨!ËÍÕÎüo�î�—:jÈrêäpÂ0c+T4±tPTNiå˜N žôtbŒ“„)U¥k%CF‘U'Át ÜêᾸX‰ åwVß~Xbù|}þ§¯Ï_ˆ¶‚6‡øE¦Ä¤`°Õq¥Æžªâ`ŸÃå„ff:ÒÒìW®€Îa™¬Ÿˆ’‰ëâ´ì¬;EQÃVð.9™C+Cûp~M¦G`~‹«×Ö<ÖÊPµÐvfˆe¶~ùut°ÕŠÿФâšÿàF‘‘�>a–Ê›5°^²×J0­ 눒íÂEùÝǵwÕ„X8_Ÿ¿Ml}`¢$IJ”yÉÈ•±¸×+W†®_·*•¨Lakè㼸X qZöõÜâè`«þª“aÚtgs ßçf@ô7×NkSq­ E„<�‰M¶~ùuÔ°µ¹f ¹âD¤ÃÈ%«þR'›8t°Ê1}&Ñ\Å÷[f•qá¢<·P�û¸6Ä’ùúü…o¾‹¶v¿H‹P™Ê^`ô4X§$J>¶6V¥rðFzåúHÞcÎKŒ•§egç•D[)ðªÀùlZéчÿªSàˆØÁŸ•�ë[l%I2=3ëó¨`kþ+’N Iåû+$ÓIÁJð^4V¹^¸(¿W¨Î-T‡X,Ñä[ Í’"TRì�ñ©+8Xý×n´çä8._ìvq^h¡‡8-ûƽh`«Nê«ZRñA=�7×LëR1� ÕÊùø0¹±ÈV’$£ƒ­ÍµSu·<†«NDÂw¶ê¤ýUÂxÛÓ\-¤g¹¾U©a‡­Qá[»œ¿ÊбK*4¥˜ïðí99½�í�Êì÷ 9/·Ð#zØ*G^…cZa@몕;t ¾gþrb×·FAŸ04­ wÜõ·Ýìse¸í1Üñ é„°î�%ã5[5!–É×犎>ᢦIE !)xe)_¨î]SS“ãJÖ`�‡ó¢ 1¢ƒ­€ª2T—Š qب¹z IÅurŒÿgIÅæ 3¢¥vºþ®§î¶§áŽ@ØzÇc¼7Zwo”ÿÞ�ñVvØzVøkpºœ¿ÊU˜ä&S c%BSSS­Ñ^¢y ä¼ôB 0Þ*|¶jeÓ*Ç„8flŽG$à5î\äzÛ;‚Y›„Ié¯Ï÷±TÀ‘�Iéo¬žŽëÊ[Ïžû1 Ö·7M¥—²"€W–2%ìjè±ÙüŽ«×{½œ`(lÕ\ ¬iU`ÍB}ên©š ¼,Ùàº8×,vÙzâÔA³µY=]Ÿ7Z_à3)ý,p$ÔX=Ý ¯Ïk®êMÌeb£Oøì¹Ï~+ì}™º�¿¦ªÊ‹…ÔªØlþ!CûP•Ñž_Äy† O8¯TÐlÕJPÍ¥�šVÖÀ¨«æ?¸V"¤»ŠU¶ž>ù…€Ùj%~E2‰&ýLC©�À ÕT1Ù^?‡¤ lÆ# [ï)Ceë™o8sNØû «š§®VºŸ€L+Ô`³mÀ>븜%hë |ë}³U�‚k$`ÝMSÅ$ç…J4W몑bµ�Ýì²õÄ)ïÕߢ™nxà3�7égX*ÝÈ©½~®©ÔßðÐ×RËÇ·G­2}kÈl=ý͂ޫ¿Ûõkj)!)&ÒJ…÷žèûìP]çp�É.äí……ÎV�W§à:Ö'XÓ ¼åSÀª–ÅØ*H¶Z�¯�L¢Í07d™g©h#­áÎùÎæy$· Öºæ kclUµL]«r§—9%Å‚œ!9Ô6lÃçm]ÅiÙ9‚í¦UŠixs¹°M+Œ¦Š)m*¦•¢zA½3�m¶ µO¸U;mÊ#IÒƒ>g©h#-¯ëI’¦‚±fµP­+‹¾õÌ·Bek·ó×´âr¥ëj%�¶°^“lø¼­®k¸¶A¸ÖUÐã­ ¦´®úK("’uey.“0Ç[¡iµÔÍ:mOI’d©h#-’$]ÃOÛ›�tB Ö•­½#Àx«`Ùªj™º^ë¹\á¼,X¶‚Q×Öa«}X×¾Q΋t!Üõ­F9¦“b:9ÖX6Áy1²M“ºÀÃ52^ïNFWlžðâåò}$Iº1¡šV(OÀº6Œµhi]÷f…­Â|+˜\B\)#²„ V°Ã°}n¨®Ë^Ó`/Pq^ªëáî'¬—c¯r¬× ¦Fö‹N�ÕÈì…`¶@Œ±šÖö†¹¾!›V(’$ìÏ:Úž D!<ë Øú˜…½úÏ|û£@ÙZÒ2}£Ö}¹Ây¥L�#­tyí£640êÚ?ÆyÁ®5À{pî©ÇV£ÓÀÚE¦Fcù$’†keüzÝç Š±µU;cÊ÷I²‘¶i…j÷¼l'IÓñV­ð¬kÀ·ÖÞeƒ­B\ß Lk)q¥Ò�U-Œ=ÁV– ô¢ØjìK8/Ûµ†@Ù M+]¦´®úK.D*ŒÇÎ >ÞºhZMóm=O�7­Pí$iéÖiy*DëºøþÖÇ¡¾¿õì·?ž o-m™Î®õdU¹¯TF[I’ô»'mŽ!ZW0Þš+0¶")("ÃÞXêç¼ÃMe“ºT°½° ¬ë÷­­:`Z1Œìï~ÁR‰r¯ÛËv/ÙPàkÑÎp^ÂkŠ åw×Ü ùÝèBô­ÝÎ_ÓK‰›µ£9µ^–�{Aë:Tk¶?*弄×B|7ºNŠ!)(i‰6Ó £Ïñ "ŒuÝÈlµº^é/íM ÝíO1,L+T»—lï~ÖѬ«UPÖ°õ;lÜxkiët¶Ú{£Æs³v”¥Dà^$IbîÉ!û¼#óÊ@ÿ8ç…¼ú[�©CˆÌ¡KÅUÑiZa4–ùui˜N†ke|ßVe#³µ™5åû¬ãd·-zL+T÷ðKë8i*ðµ ʺú„Ù`ë9�Íîqýš^FÜÕ�ÝÒFX¡z'_´“ä0°®eœ—óêCœ–}MPlÕ+FŒ©CÓú3祾ÖU�ieN�œïÖ•í÷à†­‹¦µq¾³ë©uû(Ù;ý¦ʃƒ½qêï�Z |·®�>a5 l=ÿÓYÞ³µ× FZ˜üw‘hî ¦«ß6iÓµ—ìÊJÎËå[‘KÀ«ßh¦´®5b»ZÊÇQWÙz’ÿl ˜ÖŽÆùöÑè7­P$I:Ÿ¶0ê Ùú<á³çâ¿o­h›ÉÑxïèF˜ü,Uµd3õ ô�¡—yn]ùÏV�Ô�HP­ 3+7¢i…ÑX4®SàZØ7ƒë ajC±ÕR7Wtp#™V(7¬«)o´•ßÖõÂEùí‡U· ªB¼^þ³µ×ý*³ŒPš'ó ѶYÄÊè³i[†Ë‘á¢*Îka…§egÝVò™­Z©àU�÷nHÓ XWfLÒóoFÓb«û•!ËÙѲÐÙùtpØV(’${ŸZêæõWœV7­ë…‹ò›ÊoæW„x½üï®hŸ½¥½§÷)Í“,U²`ä$úûÇÑôÌ�¡)Î+b¹§e_¹ùˆ·lÕIZ)ª‘¡Ù´Â0�#rL§@Õéüz9ÎÆoµÔÏ™î�ø¢|Mër2c/Œ$YŸ;j1Îq^Ë`k~Å­hg+4­ªæÉüºq–ªWH_†Ë{Q5çu±\¶ÞzÌ_¶ÊP€W9Þ3ô’ó²â6£®¸:Ý¥Qðk‡á�2OØýJŸålk¦uÀ·±L+xùûàKÝ,Ÿ­+Ø—éaõí‡Õ!^,Ïû„+�iõæ|ªæ gZ׺cƒƒ~4ãòàÐ4çÕ±d€>á;Eüdk�È®• ˆ7 ì­¸a ³r\+ÃÔr¼JÂ#¼²¼¾õKž²Õbš«Ïô‘=`MërjÞ·“d]®×RÇSëXƒ£Î-T‡x¥|^ƒÓçy•Qæ,±Læ×o¬‘Vºüþ'Àº–éìÅ5œ×È’!NËÎÎ+á'[k/9jDvD�÷Ø6ºi…Ñ;ü³6ÖZ�vÞû2Y=¤!ËÕ0­ƒÒ´Bµ“¤¥ýI[ýo­ë…‹òûź¼"mˆWzöܼÝ;¢ªcö¦Ú{Ïà+±lDÓ ¬+î°& óÒºŠÓ²sî—ó�­F‘U›b×Ȱ†Ç1Óú& †%`Q×U´(ÙšüùéäÏOó�­m¦ùúÜ�nZ¡º,Ï­V²>×k©ç£ul-ÑßW!!^æéo¾?óí÷Z× åJ ¡³õ«¯¿ûêëïxÈÖêöÙµ÷.â+nÚ¸¦Š$É Ügëw€ ü³®â´ì[üc«FáÓIQ­3?Š™Vf˜�ie8ÜOƒëŠz‡]¶;ñű_ð�­m óuw½V/ÙÝ¿ÑM+T_çs»�¬»ëµ˜xg]/\”çér•š¯ñ‹3ç¾8sžolíó¼º\î,0ùsõe#¦•åL.Õòк‚ñÖe[?䇾>"Ò(|ZÖ33­Ìèz©•ãFöíÁq]Q‹b‹­G“??š|ŠWlµzHã5—¥n.]þ૯¿ßÓ¶mgÎ|%õqký¬þª³ŸgÖõÂEù­‚Êì¼ÒSñó¯¾9õÕ7|ckuÇìõÏi�Ÿü–ë,à…¾ÿþûÛ×n ¬ëð çD�À<áÂ;vpÝ<3uî¨HþSîõÜâX‡âBîùcÿẊ~#VØzèè‰#ÇO«[zFyÚ*GYfϱc§¸nEx§ó?¦”]éÑV88¯#zœÿéß©Y¹—Y!¦bòÉ/O~qö�JÏùQaêöJò;~ÈPq]ó¼Ó‰_5ß/jÉ+伎èñ¯”tqZ6ô­\7Ï¿Ñé#?üãüÎýp1ÁñÝw—Ný‘ë*b*t¶öÙ¾ƒà°ü¸´ý�&}¼�ë:ç©v%î:”ôÑÁCG¹¯,Z}%~žðúñžÏ’õíÙ�ÿ÷ ã]|ÿïoÎþëø‘ÓïáÝ�bƒ¶ÿàÑ}_ø·Ì>IöûȈ¾QÒê&Á¾ˆ¾1²×·Úp‘ƒÞU<¬=ð)V+y៊‡�í?pôÓOîÙ½7!a'×EË;%$ìܳû£þO<8 *«ÏúÏ­£ä€ŸìÂHëøªi±²|«­¬~Wà÷ý ²l~òÿ.)Ázèè¡#ɇ�ž8~òËSñ¨ýÃ?ý[f\T ­£d¿‡´ùSd˪¯®Õ©8¸ºžÀ§`ù¯‹ xiŸí?œôÑ' ;wq]ó¼ÓŽ;ä'N:¤R45£o¤"è•%mNP†=¾@•­%úG×VYðƒSä?Sh©xôÄác'CÌØbbQöIÒ6NÂÄh±½¯}.²×EözW{ƒôþ|À³Š¶z4ÐlúÀï÷£dß0À+×Å Ž’£‹Øç üë_ôxÖÖšõ´�Õ´fžEˆ÷*®ßK†ï-º¬¾E¤.Ø¡‹´º+ÁW‡×¾ÀÀýjRq ð)°œ¤ x ÓÕE“ìrùPjªC&³iûF‡ú] Ñ éõ¸ÚT„¾ºT9ȇAxþwLÅ*+¦˜bŠ)¦(ÑPjª].·Ë噌ës‰)¦˜bŠ)¦˜¢_Û¶m£úÏwìØA}×®];:xðà‰'D"ÑÊÇÙþZKŽ&''òÉ'{öìYrjkbbâÎ�;h‚'ú`bL1Q¢V½mÛ¶-ø§"‘(99ùÀ�ðvXÓ‘WNþUjçÎ�;^+!!aÝlj‰uÅÇÇSscâããÃñÛi þéšXÿhjÅ 6[ˆÁ¦âlçÎ�IIIðû »v키‰D‡zëq–œ—“aïÞ½ÉÉÉ˵?;vìHLLLø­¨#„ëÊcˆ¨6ç½÷Þ{÷Ýw©ïS²uëÖøøøM›6­|˜�Û¶m££¦=˜Hsè�H$Z!ë‚ÍQ¤'ÿº/ž \¹K{žVëöíÛãããwíÚOoåØý ØJ%[ˆºuëV˜ÿôç7xp^md¢§JRRRbb"UÚÔ÷ãââ(æ®æ8Ô×T2ìÝ»>ûÁÆ�ñ·+Ì—ŽÕxL rQx¥çɦM›ÞÚì0’ âì�wÞ9uêT\\=iƒÿœ�WØ@1¾¹îˤۇ[ù X#�DŒz[©Úþ)½… ñS¶nÝ Ÿß( L¿/B9xL Ñ –z†g.. Í›7oÙ²…êRƒÏQ°�‚õÅ`"ýß�?þxÏž=Û¶mƒ„eœÕÐÁsHJJ¢·3°Æa—Ýþýûƒ- •uô'1ê.€Ïiÿó?ÿó^@tîS'ÀhÖèuôvxË–-›7oŽ‹‹‹LÕÄÅxl{ï½÷‚ûI’’’`ê® àüüðÃaz¬Æ·22œÊh3—lúà78<ª²iÓ¦-[¶ÄÇÇoÞ¼ùïÿ;Ä:=çaÒþ×ýK¥ÓÚD5Ô¿°u¢¾O5 [·n…i�˜˜ìAè-'ìO†�ÿ°§…jLèyE£~º¤o¥7zìĆ?‚ F} õœ|pº‹�&kçÎ�K¦.uüø€ÞÚ_´aEUè’Î~3..îÏþs\\D�­;vì€ý Á-Uƒ0‘D"ÕëÅ8[áQç¿oß>‘HÄxº{ÿý÷“’’àŸ?‰Qw<õ}ø)Ôƒu³Ð Ï^,ýÜâââ¶lÙ³‘ƒ†ðé‹Þ© Ùš���Eµ°£hÅ€�­Û·oOJJÚ³gÏîÝ»WÉVFg ã|èˆüÿi)‰<ØàcôÚ0Á¨¤b Þhï½÷^8FÙbZYô$‰‹‹£†\·mÛ¶iÓ&ØDÀäÙ¶mÛÖ­[aZŸҟ”âãããâââããáÓÔÖ­[aÀz‡¹JÏ+ØÒÝ1ý§T¿.£qûÝï~ fN||<ë�noßyç�>ø¦úï~÷»ßÿþ÷Œ�ˆ%'¢j“Bôzôê€`«g+|,‡‚æ1))i•l¥Ž–˜˜œŒg΄„jÄD$íß¿ŸžN°�\ÐÁçÌEÙo\mÿ­‚vSvúDŠÅŒæÖ2½Š©6–ê]¡'$£¡[’­ŒnjÆóáöíÛ7oÞLÒûÓŸþD¥=Õɘ�EOrêŠ(pÓ�l‚8¨$~‹*ê¿üå/T1¾‘­°žbë }tÁµ ‡YéÏWôq^Fs´2[·nÝú·¿ý-Øÿ®�¿ýíoTƒüþûïSSb‰Ä­•EïZ¡ûÖÕ³•>¶0;vì ºòèÃK>«C«BÏ¢à‡|FªSË7öîÝËøèàV78ßbÖ5òZyr½„•HÍ¿…MÒ‚ð¥š88Ÿ„(£ö!¯?øàƒ%çle$´Ì0iéß§O#¡’Γ¡§ßQíÛïÿ{ÆSý’)4Çòs9Ñ �š•õç?ÿþ4l¥×ã÷_lÚ´éø#Ï×ÁV8’»\ŸÉ§Ÿ~J²ï½÷víÚÜÖ±2[/¦5)¸ ÖšØJ5NØct‰P³J–LrF¶Óó�>Ý—úxQÍ/Ê2<ìÂ] lDÑ«cå_ †ÉèIEO8 J%0ì6ÙºuëæÍ›¹Do¦(Ì}Ð’}ÂT‚Qîáˆ-½ d$gpkùá‡þñ�¤ „;còÝ×{ÞHÖŽ Ä(szÂÐû„!ãl]²³4؇³5ø±ŠÁb:Ë�pð´—!¥>‹Ñ#͘3¿ä9ÃO¡ÜuÌuµAEO*FwÕǽƒ­ ¡°u9Q}ÈKþ&÷Òs•Î\øçÁ—¹ä-F�dLSpu,÷ ô†%xªIRRÒ®]»‚�0œ×ÄHNº¤"‰–d+õÑŒS ^µ±dr.ÉVFê/$¡Ž°\!ÄD‰^æôŽ [a¯)}*ïrÕGJ`°5¸Ç>˜­ï¾ûîÿøGøû°§‚>/ޱê�‘õlc+W¢wêB� ¿LOª¾‚gqÀÌ„yBOÆÓ;÷îܹÎ �YηR‡bdü:11q×®]Á™¿=邽@ô?§³5˜Ë±&1XôR‰>’·sçÎO?ý”š²rûÛj¸j•s™èF•1@¿ èOï^ ö«÷­ÔŠ×íÛ·CšCm ˆ¢9<}æpäkjÊÞnÀíÂà÷ïßÿÉ'ŸÀŸÂŒÑ…µd›C%càé¯ýëšæ /÷£Õ³u9èÇØÊÑoöÍ›7ÓçÜ¡ó�ê” gæêÙ {ZàÊ�%x•lMNNf+œcO%!} ˜~jÚ'½-…·LŒ­«ý®‡k¯èƒòPpùó’ûÒ0j~Mýiå58ôºf´3Ô4$úÄÎ%ç~|$êû ¶Ò™îU —E/y´XCIÑËîÃÉS zÞ} Ákœ)ÑG» s™–; z"Qbpœa ÉüÁƒ•q+÷ ÇÆ[#,ú|$Æ`¬£Ý»w3%êGôÉr[C“Kö S‡b|îÊle8hzR1ŽüñÇ'''Óó3x*e[ Kc¹>áX~‹^Kþˆš(ÂX%ºmÛ6jûSz[—2¤à®‰Œ½¶(Q{JÐE‡-'}ùöíÛ“““áw¶ ~4c†�­ô)Iï¾û.œ6@¿48¾üÙgŸ16¬ –KGª~bZi3UzUR+�¤£|½Š¡¡gãùmÉÓXî§ôÓ üuOÑ»¦?üðÃÿþïÿžŒOÞt(ÃßYrÇ•˜Â­à¶ˆjm’““÷îÝ›=1tc°•zîzç�w6oÞL=ºÏí n ©sX’­0V,ƒJNNþè£�“Þé·õ,Gÿ+¸c6µhˆ úUs\[4ý?{¾ì endstream endobj 141 0 obj <> stream xœí}w|Õúþ» $@¨ÒQ:HUAPÚs-H³`Q$W®{/¼Ê± *â ‚(ˆ^EAé½ ¡ƒÔÐ �’l²©;ç{g¶dgwÎÌ9ï9ü}~>ð »;ïyßÙgß9å-/dð!Û[l+¼×8úŒ1mÇ¡3Ó²²²róóóóó²²²®¥¥¥¥ef©ÈLKKËÈÊÊòäç绳²²Ò.ž:tr¦­8pêDÒÙ ©iW³"|íÚ¥ W2r‹ˆ7÷܆ÃÞÛ~0é‚jXŽjX~À°k> iiÚªa9šaIGŽÙkد¿O:{!%-Ý̰ÌË.gäÅ“¼µã°9Õ¸Pç±J"Ÿ:Õ¬¡|5—¹Ç^œ`#ÞPxÕYB1ìä˰©^u¶›N1�†‘nn›9àîÁ©N<�séÜcg:8ÇæÁnu–S$�á–”UÆFÃÎr«³‹›så2¸a‡²‹×d*çþø5ÞÁÙÑ�ÛÍ‘ÕQÉü†�¶Ï°EÜÚìáæ¼šÃo4+ÜwñjCå\ÿè9öùƒÍüÚ¬§ˆJá•[Þ6Ãø½.9ÀϹr6Îè¹m¦róËÏ=<#ð»9²™"ë °wì2¬¿›#Gø9£lstîžÜÊP9—‡?7–{|6 ÜÙN‘…™ÛäU¶É0„›#Çœ‹C<¶Ø°Ÿßh*ç 1 |À¯ 0nŽÐ¦¶ÙÃ>±Ç°>Å]N!8¯Ûäèܽøu¡rs7H~¿ Ø„ÑeE÷Þ„ŠÂ¶v£ËY çìrtVS9‡q-„|†PÁ�Qº¤HËGö…†=ˆúa'c8oØâè²ãªHæ\A%„V؈Rå0EŽsEµl0 åæÈEçìqt´¶)$sŽLÅ(aÄÞœŠCq8Α™ò {åæÈçàM�û^Œ&²9WP£…)0‹V“Ÿ`N\¡|G‡Y´¢Ÿ­Pµx2íYb*ç°j|ŒRøÙ}v‹äA}Ñf¸Ï‹Sä<Žs0>i9îûQŠHç\¾lG· ©mã˹š’ Cº94ç*K?é?†;a—Î92¥Í‘nŽºW‚åqÉ5줛Ã함˜ Ùѹ{ãô�Ϲ¼ 8M(Ø�ÕƒÆ9Ôf7‘ïèøJü@s®ŠäUÄqd ‘|ΑI8MŒÑ ëæÈ^ŠD´Ÿ“»&G»9rË9˜(Õѹû Õ°�sžrH]ŒðZ�=‰xÎT“hÚÍ pN®£;��—”½W¢âm¤.hƒ×b7E$rŽÈ=N¿¨óVÞ•èè²ûaµ°ƒs9e±ÚD`7^‹ß("13~äÉ[“ŸÃkqϹª—®'ÑaáTΡ§ÿûnFaµ GK%¶Qd pN^€`o�Ÿ4&–)€I¨#¸ •�WâGVZ=ЋVBÈŠL‘»ž#kªŠ;iõáwÎÝ íázÿÛÂ9ò´>:Ü,à È&ŠP¡».)壗ˆa‡8“%9:÷Ãx¨œCM—જ0þd¯Ðò!„Ön™rR>N‰è€È‡(AuIŽîŒÀ£ÌΑ!x�J€=iõa-EªØ4úï2 »Kd²Lö‰p>’âèÜ� ¨`箨Ä!VQ¤ŠíQ¥Ë˜ªR‘k‚êR8wNä6ØÄ9ò¤€N~ ² J°‚"Vp_t°¸aÝ…ÜÙ-Ä9øDé²ÑÀ.Î%‹(åÃj1 hyü‚œ»$>U=*¦¿5$ÌèÎ y{»8Gú‹h¥¢¶˜7 ¿R䊞ÿ 5¬‹ a¿‰q>Ù¡Ôà{ŠÙ³W¢îß©¿ *@ãœèÏüœ¨a‡圸£»-¤€mœ#¨PùTôäŠ`á;þ ˜aíDï¬(çà3�#gî§ÅÆ·�sÇÅ[$:>�sÂSè“b† !û°S”suoÁEÁMJû8GxË’é‹­ `E²ø²ínÃÚ&Ì9˜!4£s?+8¼�œ;"¢×táá—R$‹sNÈ0d[vs®ŽçRDÏbläé„W+ZxmE圄­‚ÎxÃÚàCFç|.0£s?':ºm{%& />úOÑbe [!¶Ñ­b›8çê 8ûTá#g;9§ÜŽÕ*JB�¾o(²e„-¶ÇÖZ‚—]+Î9˜…vt9Ï n'ç¨) –ø›èF !dE¶ Îñ×–ôã{ O¿HàÞÑeˆGÖØ9Ÿ#ÊÍ8¥¢.IœÆ9)Á<Íq†µ’Q¿Aç`rù\¼S|l;ò!J�Ú¡Ò¿ï{BpÓRÃ|ŠxñÕ r�.f,¼(aì•✫Úüì÷û¡èضä†@ÁÄYÍ=(¹ÄbŠxñ…£Š_ùóŒÚeM¿,ãé±^œs}.`W„6'} q.JÂÍQ‘õ&·J«ˆŒ¹$ù™"^xOÖ‡ ÜÉ®#ˆýU‡b»„gk›=ÈÁ/I¨¬l¯ŸSkæ,à�t‘3ðJŠx9~Ž�½·qÚ5� K#BeÌçnXNOW/~Y{çsª]É´&HÔ•D ZOsE׎6ã3l‘ñd%d¯ ÎA™µˆo8ýZ´læQ&ò¦ç=�ù€æç$q®˜{�îŠ"'çJŠŸ€ƒÜ?n÷°Ê¯HØÖý9µÆÇ§¼-•ã Èù’jvMä´+Î-�»ŠÍ’8×�û'�.§ÿ‡Ôž$FðpÖDu úqâsʲú­y8Ëu·–U·á§WöWçš‚…œË©§”aaÄFÊ™’îPÑ >…IrsäUÊRÖŽê¬�s§êkY…˧#Þå7ò nˆ&œ~%CJÛ³ÇÏfÒö•¥µ_Ìçst˜v\FðÒböñE¸ÂÀWŶ‰¬J!ÊÈ+ZË[¸n«!¾årt9ÿRLÊîîùBÒMRh�° ñ/9ƒ’³ëž Œ°j®¬â´§·!¾—ä¿S~qú–Ñ!4årtׄÝ\Ô«W5I§(ï'vˆ™ ‡u<5Qrø�ÜÑ8·ò¾²¯Ë¥�ÃÑ5”³”:\Îà£àwÑC�ï8]ο«8)0£¥s@ë±ë5YÆxÉjž£ ç$±n»a¢YlÒ†: ”s„$áªåÐŒÃÑ º¹º Jø�DùŒÊ9€X¬+®ÃªX¬o�ì«ÿhÊ9I¬+¾�Õ°Fž¬—}y.§®mýÙGXu0™]ÎH‘qj-½æœ¨0Y|ׄ–�Ï…‡ºX:XpNuââ;u´3ݬ*}¨¿€@ç9'P¯¦9³KÉ(‡¯g=÷9À9€ Î{›nq¢çïKª¢Yr fœh,�—qË¢±¨›K,Yár^ ÷â3è‚K÷þsi[OÖ¨õU¸õÖœˆ›"øÌ£Õ‚ ×b£\rë83Z�uØ C5 -AÆ?Cç 8GÈÅÇ‘¬kÅèè²±¥”#GÈÊgC9Pu†� R˜ŽÃ« �·¥ Ónaâ@Ü$!'®´d1¬™Paï´2¬2ÐóŽá.¬)ç9dø½™áWKG—;†W&$˜)yžr‘1çªOùË æ_Pb¯ §„¾sr â[¸íoZoâ p…˜Ü£)Áj.§EÈOb +�ôhc¹vçvsƒÓMåÑŠ°Ò8Pé#ë,üA}Œ7Èú75Ù‚›sqo¡v‰-êOµÄæK ¯¶äQ¶60W)üŽXéÃMsgY8Gˆwe 3!z¬6½ùž·Ø¤ôUÿé°�Á^碆^æ¸�*~7÷§°ÓVÕ⑜ˆ’«‹ÙïÞ\êó' lœ#¤xq[Ö²¿íL]NU&!6ܶ�i¿ë"E„çàÎ�Û^tQµ¹ö攣Ö[hÎÀÃ'ø 3iñÇÙË'Éz_×åd�ˆQ Ž7up}K‰kM�‡­ï“W“:­cÜJK¡È`àÀ],ž4ˆctAßpˆQ-÷]9Ða'ϳþ,Ý5ñ”ÕTYî»hœcNæÑ¾œÃ�­e¶7qt9L :ž'¤ˆÕqq Íæü4æ„Tê6y v7ç]Ïp…9ÐluÞfèÍ0ê³S×»›-Ã�ƒs*’ë²]OÕÓóËõµ¹&Z©)Œœ˜\HX¿ª£›Ç¬n"ë6€(çFç1F�Ñ­g6ìS´7ç”ÃYŸ2¬ao§®×™Ü\§…ç�'ʹ¿n<|�°Vµ‰7–Q�érE!ÞÉlJÉàܤ3FéMϸ÷e.³a.'ç.bŽg®5ë6R4Í{ßZ£N‡87„ý@Íþ³O2mlQ¶²¾`¹¶Ð“¦ÐjÊ@ÜÏÜðÀgÇ ™fìgŒÝ–k‹=—Èöð7nÎâ-øÁê Û�òýåX†ßw=Ì¿ÍEÅÁ9 gå³x×»Œ®­Âr†[øM½yk9оÉàœŠZSòXîi_£kë²\Y°¤©k;Gà·Ë‰9£+Þd1 Þbøõå}`¡M÷ˆcIœh¸ˆá9dØZa&Ã-û¹ÀPŽmNiœ¨5‹á7aèè:3¯m ðT#upœ#Äk¾ÜïlèèrÍóDÿj}æ`iœhd¾Ÿ­Á`cÍÚÍy7ð—J�Ç9€ZK¬ 3ptÖnλ‹ó<^€sêz¢«‰ÜmôÉ3­�q/ŽqR9Ðb«•‡#/²JöRöaJaËäÀ�VçàFKוV÷þ(¦æ¿Ë)Mšn|Ggææ$¡µ�Ê9€VV¬‹ptVn. ×NG.çn´0,⡎M“MÎeL Ä9BN÷¡ Þa`ÞÇT-)û"™síM¿œGgÞÙ+ù¤²9póSÃ"ÝrSÃ.Óô³‚Ë)Xµ1•Ò<©k„£Ë¥•7zV¬`›à9„:›vÅ st•Í‚ñÐ_Œœ³râa¿ŽZfg+™øG.§p±ƒÔç ·fv†Y—÷‰±CDkgÙÀ9€x“gý!ýG§Ñ?yí%tª°=œ¸ã ]Ýú�šT(É#ÐèYçIbpk»…müº¹¨¿›Ç³ÀÎôóñ#Dò Ƴ¹¢™Ü­LÂ!�s„\ïQºüËŸöfù÷e• µ‘s Y’)5Ñèý©l‘©¦°“s·²îxÉ ãž‹gs”¤Áå”TÒ^Å%=ëz…8º073NãlæÀ�F“î`ŸçX;Š>g®êf{9pË.ÖE•^ñ.f e³‚TÎrùéPá{‚Fåëj�‹—° …Íœ¸=Ò×kGº¹¢y<K&°›s·Fúº`€àâü‹#¦G8Hæ!—Cª}Ç�'ä¸1f´¤¦~ØÎ95(|Pÿ¹_„›+šÇ\’Ó ösΈuþ°Êá´ð.–Q\_ƒË)«›A JÊöíõ[T0+ø’lÆ• 纅­aý í'è_-šÃÙ¿Ä ¥Á9€6aÙ«~G÷­þUïB–DF¸œR:Õ…±à!¿ô{ýAÈž@™Ê˜7e3®”8Ðí€nÔ;Ô×¢uAÖÞE’>>”ç"X§¥|TÔ­,½?7•9 -œ#$ÅŸÓ±_û_Álßÿ/Ëꤢ‹bšdÎt푹]}edÈ ÞEÒ>>”çÚ…î×ieYæ†ö3gûC+¸œ’Úÿ…ÃWüû~Íxjc=’jËH¥Æ9½¯k%óÞ¯+³£ô8§÷uwÄ•(r}ØÉ9B’º€ú%j}dî?oÓ8¥È9€®AÖmèøÛ»¤‰ü¡J“s­ƒ§ÿ¿¼ø[Y�‰ü³€�œ#ʱ®ÐÛMH^#€.¿Û6Œ@?�ý¬Sªƒß&ïÉJ—smkØFqþiª²š5}� vrŽådÇcDùnãÊ–çD)sN=®Ô¬ùøvm*\ô™Ô•C J›s7û|݇ã´iwñü†ö ãrÚGMñBB ·“×¥Ï9€–¼Ä«x ñΗ¸;¢Gés þÒb5 7—e‰ô jvsNƒ­”»œ¨«­‡ŽŽ•¼V Åõà@µ3ªagßåIäâ„íœS´,o;�­&†]êДi9¸>œƒµªaoÚ9‚½ó9R”÷»BŠÙ:Æõà\¥QÙ !y…Ûl™dûp]87<Ý«¶ç6ûư•sJÞ‡Uu“ìÇ[š'ˆ¡ô9Wyv¡{tÊÜkZ-¢¶v�r875Ï3lûúÓªaï°k;9W0£*8N©Õô£ ÙfÛÆ)mÎÕÐ6§&À'ÚðÞí§Ô9We¾zâµçlÙg5Ôc±g›Î¾ÔÇê7UÔ‚�êVOö@õ€Å4—J˜Öx4Zå»aÙ1Á„–¢™”2çêúûf¥¼lB«$ýÕŽ‘ìâ\ñ2-nÑq\ûßY­yZg“”#”&ç:cfèÒÜO™V�Æ¡T9×:˜p�0µäæ>Äp1'ìá\°Òúߎ¶Ûߊøn;N#J�s½Kù‹«„¥ $ u[6B)r®û®Æ«á?!Ñ?—ž•=šô˜M•q;ƒU›Žù_:èJúp¼}p�p<Z�üWíµ9¡z¤UêxøL§ì0J[vNØÈ¹hãî¶¡-ìWêtMëìäœã9ÃçL^H�_—¡a9ž°’8·Ç ºðýúÎîÈFP1#dT,±�sŽg(€Ð)„¡£S—z ¢« 9×/|çGhóŠ ” [¤ ˜Á:›”=†çÜûÃ>vÌàK¨0†« �!ÎRLåÜ#—(îÖ}lM¯«‚¬³�s½iUMót­Ì©åC3ÿ-¶†眲É81èÞp6¹ ‹œÆü]ô kçúÐS†ôu›Ѓ. Å×ÙĹûNSõ�¢û`}uyÍ)òsÂ×M÷Á»‰4¿7²†±¢eëÚÁ9ª+$€†`£‰n©ñ:ØÂ9]ŽnòËë?;‡þQ’áÄë Æ9ï j=˜øÈ„ýlÚ½ŠÜã�|ÎÝczT¾Xjd¥uW[ÜÎu6=ï/¾Q³D‡KèÓ—_"©èG“šW{ ¾ ƒÖ ~D=ÅÛZ¹g(2±œ3(Ê}l1×ï2øQ:çn¥uU‘Ñ>i¾¹ag{âôÀs®èG³º~½Œê’d›„c9aÏ&är®•UHsd³‡æW(‰ü½bäs®¹Uß‹Èâ»U¬ÎEq?'D�9 _›73n±pÐôšMæ&8MSÁ¹¦V};BKl±Ëâ¢lemÚ©œk°ÆÊ°ƒ/ô[‹kˆò¢²Žsù³bÍÅö4–ê¾Çü²Ž”2·¦�Á¹ÖZöÍ–�—ébpu[k%‹—s—¨”¹úÚ®hÝeÖQ’Ó ®®m}™w3÷ÏÉåäÞ–Ur?´`\xÍôy Z¬åŽ!•À¹ª{Æ4¦·×.Á!ÃëX_HŠ¾ç¬†(ƒså¶N¨ý#C�ÁÚÛKY [Æ™äërr–ËWÜc­O?Â{Cá¦6´¢ÖWœ'À✋^I¾oðSP—‘›è¤hñ‰Ñ­8NŽ$pÎñ-YQs:“aŸ 0_“ ;=þŽŽ.'ß–lÑ–»FDîg¸º†ËÃãìÄ97K!……LõF »·†ÄC›C!Þs[–²fÈKàÜ{E¤¨�‰r…”žkY ;¿mÙ-Æ""àr2oȪÏahzˆ§ÞDE 3çÞe/oÛƒ"â¶ËBr™ûd‰sn${œÚ­˜ ËG—“9�íL19ÊV©'²§a‰r»­/¯°îϱ(ç†æ1óû(Uý@Io>¹’»€±®º0çÌe6Œææ¶±––÷_ÆU.'í$; W–^´ž�¥wknš«Ð¡Fÿ÷Ö¦3>`Å8×™§L}t»R¼…)÷_�s­yj'Ì¡ŠéÀa˜w7Ó-w9ÙÜ#ÊÀÜa,�{T¡ìd¢î)Yn–i8E¹œ…s=è�ä pÜDߎöñxkÝ„8×μmèn`—agúYëær²$Ä| ÆL1Íå:›Ÿl¸9’Þ[ì`PϹ»8ÓmÍvŸæE’¨Ý–à\G.Æ2ÏDVwNÃRž6¦Áå´.ó[ü5WDòs{•í<Â:µT˹ûNpÝˈö¦z8¸ t_xÒ< ͹n¼U:ŠLÛÆ±l>ê�–`_çrž±� ¬¬nnb:Xàæð•^¹ßÊã8×›?ÍÖ¼Éù3Üò,²°‘œ‹·þ•†ã+Súñf®êršß{eksS…"±Ñjê¯lãèxñª©< çžã¿‘´qj2.Æt¸Ð—.Źûy�·¥›C8:5Òi]žËyÒìÒßZ™«‰Û­ãTrº1È EÔ‹f×')WÑ97�’`Žûiâüà�Ñù�D�$"8÷ã–� , » eØ…‡iò\ÎãôËGærY‚áÐRÙÂ-µ¬q–^Î=™ÖɳE«”£S÷ÙËãæŽq–nYO+e�ñÖå¤>þÞi¥‹Ú³„ç $ÇŒ¢#Цö†œ‹Š I¶P|)™$Îë89^Þ‚f‹Vþ‚5ìÊP#Ö¹œ” µÃƧÙV` ñnĈŽyÅ8GŒvjÀ¹(wiÚ(!À::õAÔ?Rç¢ ròQÈÐë_8ðŠ�¯s9 Ö‰ÈxêvlÙ98ñÆM#ƒÅ}ˆà\Ù±‰��)£„b^¼¿?Z(Ø9=Ü|•eŠÙ †¡�ºs24\šËi°*ÙÞšAC¬f;¯ò®GÊ�{+’u´˜¼0Ε}]$�Û2ðO…ílTœ ;›`å\”P¶fSw¡º¼)aå ]νaŸPÖâÙµeM®ÈEå®0.<6�éÙ%X2€­N5zFçÃÝÎ çC„25•Y”Aôà=ŒCÊÓ¡OX—SŸ ¤lâÝ�ÓÝ Ö¸7ïZü á¬cX·F�lžÓJƒhe½ÔÁ%_ çC+ Ô`3ÌN�Øâ) �+ØÜ§ÂÛ§j^7¹¬ƒÂ¾¦ê,>Z€uœë/¡ViÑ4fÃn’Q_?}X´Æ¹­ÚÿŠ¿6Ë�fÃ2v7Gˆw¥èp�',í€@åÜ“º#ìàYec'#‘oÁ¹x)•À=�@’1 ¹Ü_åœVâeƒ„¾·\nNÜÑ|]þVÊ»‰$•h/æé�ÛZR�©ƒ-L8'©ëwîÊF°Lêgĉö.ç¨|÷ )«–ò¸95ËX˜Þ>•³‹òÞÑ ’¾þe\*m�3(Q.Ð*ÿo;'É07W¿cj=:N(çG [ÄuK©hÅ[à)—u1hާ×QÞ«0V‚B¾”á›ø~z&XHÁ*â‘érVF¬j\Ö3*€ÀO¼¾·ø)ãÆ¯¡¼!§Z1QVp*ôƒœq YJÀ:²› nÆ´Þ”Õšr‡Î}Ú«9ÿ¯ÀË”f*çÄ«Æj(¢�çÒP‡=wÑ´U–„•¸Š+W8 ‹¾"É…'JáÜ�‡7ó÷™Pò1ÑRá rN¼P²Š"e§BQ+ÐÁ+zЖËrÄYTÉŠ„c ®†WHáÜ.޼û\zF|h*çd5[™Ä§ÏãçeMèh¡­r¸¢µåÀ=çdµ9"ƒså±û“×Þ›Ê9YMBãTè>¶â%ÖØA@Ö\~$§aÒúïž�Á¹.Øï×}øeѱ©œ“2«ò’kœ•®š„‡ê A ,�ÒÑ#[)ä® Y›Ú—€§epî-‚#�"^€­œËÿòÓ¬VcT¼$…ï´ù–ŒG\ÁÕ,«F ö¨Ã’epîìµUiW*çdÜOã2´ŠEfh$eJG«È#ƒsÇ>u|‰0,FŠ�M•Â9ì|½è{á±måܤRá}]Q %ÔÊà\ÖM8Ã^•áèÒ$p®!~Vë Ÿ²—sEM�J5�q8I㜄y6{@‰ee,`Ò%pîkü/¯h±èà4Î9$Ü®Ò*:l•0:­È™ÎyxÂt˜%Á°«âœk Â}�hÔž�~NÁ‡¾´�ð ¢qNüÙZl�ÓJCy \çx‹NëP$b`㺕w£>\…íŒA+”,>�Ïg­il€ŸÅ ç\±C&vÎä‡�{Â,µ�iè!<:•sâ‡zß VOü·,ιyb¾¾ðk±á©œÞ¯ }çlM£�/<�/ps;F0G†(çê‹þìr �OåœðÄC ¦š!#:<µ‘™ðI»X´¬xʇ0çæŠNi ÍKîYÁ¶3þKBjgeÑ8'zÆ�Þò×–-¢œ«+¾a“'äêmãÜ "ZÀK¢÷…–¸+Ê9láŽî5ìš çf‹¯Ü ñ+wŸ­"í¿U8DãÜhó9Ágk±èîœ4LÐÏIps„ä¡w(mäs¿*F ÞÚþœ çø+N†£¯ a‚ëÖ™2} ç h`Óº5˼ö7 ¢ÅÊòPϾð�ÅUxÑE·J€¨Æ ±óÖ:rÀ=Èg°�sÿÁkÄbw…E%Æ9ö:t<&fØ!ÎÍ�ÛB 1C~ØÃ97GÓK*ÊŠ=i „¦3^ñTvL3 .‹p®Ž¬0iw0nöpnZŸP¼'tSŽQ¤ Ýô½R {^ȰK"œ›&ÇÍR0­ƒ-œË+‡Ö'„¦¿S¤ŠpNA›Ô!ZhóQ$f³¶´ÌnGg ç&£ï‰‹ÜçDæsƽÝùñwÃR8÷©œ„Š|´vpθ9=E´¢µœSºJ2¬¬HeÎÕ[@éáÁV†²cE‰n �s+zÓc^$&À¹Oä¹9B >Cjaç LÚ™r¢œÀôƒölÅsN±n¬ÂŠhæþæ‘Às®º¼Ùœ O]œ6pK#¼‹¿#ò9'ÏÍ Æ†_C|$—sùŸâÔ�?Ÿ“èæbðCЕ^ ‹ÂïÑ¡9W]ælNE.W¾ äsNÞl´|s,¤ïÏÑâ€ëãHDöç&Ëus„äóT-�ôØt³æôà#dsNâlN…Õ‘”œCÜ ÛÍñUT.�ô�s8CŒÃÞÚÙvéFkÞ‚Å@¬aXÎM’íæÉû£ˆlÎ3·L`D46Æ’vÆ�Ýó{P²aè”äUIåïtÈÅ|ݲ9÷_Ìí06¼D2çÎK7ì!¤aHν+ÿÑJHæÈI2ç¡@yC`Ý~Š<$ç—n¶²ñ9çªH*Ö†\ÆŽg¡�̹Uˆ»a…±¸»A«yˆãœhJ‘�qt¸š‡íps„äqÖQéœSÚ"î†Êàî­ñŽs/Ú`˜#¥Ê) çªØ1›S‘ÃÔÁV¹œ“P„ÑP7ƒVºµnå-’Ά'Q†¡jN°ÇÍây—[©ûsÊ-ü7ƒ¸ Z´|ç":”KÎÑaò!*Û3›S‘S�W©ç¢©Ÿ4¼�¹)a§ÙdØ Œa¹Î�·ËÍâ™È«ŒÔœj{Ü@ Æ7]¥ä“%Ød˜Ó ¥ˆŸssèL‘ÃÛÓ“Ê9ÄT[¸¿'“·âE"Wû²m†½€0¬˜Ÿscíss„xx³_¨œã×ÒÛ€÷V0#ñ ¸@‘…Ñ¥µåG"ŽÎÍ͹8Ñîöæàutû}a*‰³ÂÅ'h)Z—¸%Ñ*ŸÈÀËü†�¶cVÉjÁcŒÂ5|ê|Aã\&ïÈy­šØ‡Ûù§—´zUÜM‡ŠŸµÑ°Öü.hU³wßçÃÆ]íÄo›8õéOùjVpÍÛ¯’žd'8›z½…÷Q ûÆÃ³õ¨x½[ ãlÍìõ=‡p§ÿ¯ r§øøžíU«V[ÿÓlÞ!M›Ô¬Sê4êÕ§[ëºU+†{ж:uš5©[Í*‚¯âññw·o\­ZM½¤f:I͛Ԫ&'OדæõìÓ½M½jq�à k¦N½jUJA�?ñÿjt¼Þü‰?ñ'þÄŸø‚mã}ïºññº¢€¾ø«ìš¾þ¿jÅÇÇÇßR¡”5´ W‘Q m"Þ½}°áEUêÛ«+bëZ4Î|èžÀ_ÝÌ÷�Ÿ‘ÑÏž ˆ[«å1›Ý’hÀ’Ôú±d˜ÿ5_èòµ”º’"˜žqH+$<"##.ôõµKš�R÷«ËgàÅ32®ú¾+ÀØ,Ca-Ioû5¶F—•ùÄ{æ#³€Ø] ¹(©:uFi¿ŸTñÎâ¼X�–©î®TÈJŠäÜ£D;;ªøI=Dî�˜K•Òÿe`žÇ«¥äÉ!ºB9*ç�&z?·úRB›Ʌ]i~î�Á¹'Šö ¾³Û«çÆ›|¦„s4?בô€ëäç’gm€g³>$å Ì@õ;¨4°ŽÆ¹Æ‘aÆF lêÿ¬Ê9€¶DutQ}'Nì­:�žZe Ú´íïèÿÎ?}¥qnýÏûÿÒb:îyëÝ�2J\¢1/e•ZÆýNe>�s!X­¦ 6÷–œ™5hæŸqĵmRÆÇ¹ÆMD ° ¢AîFÍ=Äiw¾á­³Ê´V+êVm£½¹k!T¿U·-ؤ±OïØfÍ´/ÄÏ9bÚ´L­*·Ñ=lÀ‚ä®Jc€u³ß"å N‹lAÐ8×/‰LL¬úlU9ׇ<»¦x˶âå1Tß:éx;cþ¹µW¯¨9/*'—î)ˆ]V¼eUîÖë9œ—ò¤:{˜¾y,©åÈKÿ³¹)é«qÎ+V'äÙªqR6kÏÖzä嵄$wR÷lç’ñ´$/n%$éÖëh�Z1¥¤œk‡Ã„L)0„ô¹@È7eÆç�šœ³ëÛiÅÄ3ÂÿlmGžÛIÈ µÚõB!yï9 —f|Gß³õ™„\|V®•GŠÇÚkÀ‚dÇñqÐÐû—HÎùŸ­¡œûbÔ(×Õ%eÆ�~jî(çÈ—eà¦ìOž ãMÞñth™ÍC'óRÊg†rC"9Wñoä®&M¢Ã9W«h¡Ÿs×^­ßîÈ‘(€_sêÔy´´$éÎïL¢%Ó”¶eÿ¬•~°CÍWŠ'©œ;þ@�’åËÛ4\–Y`WΊ&µ?U¿%箼T¯Ë¹�ÿ»f|—j¿¢<åû“'š4‰Õ8÷$™~S³eÅ�Vf­¹íÆOHg[ X� £“cO:˜8—’”tåʨ(€}Zî¶CzΩyûËÖ¬;îsÔŽ4-Æeæn[M0Ǽ˜¹Ï©É9ÿ³5”sg;Üñè.ò�Ÿsóµ*7A'ò/ßû-‰K«I)·'Δä,¾¦¥}� C´ÔÙUÚ“{UÎUpYàœšõ9R LÙY|¶ªœÛ­.³*]]¨r®@¬ûM[ X� õ½=O�SÎÝ6sæÌüÏÖ‡ŠÇd¬^ìÊ×qN[ëÍÛ�ú�Ox]rlÍš5kNÑ‚KóR ‹ÒxÅW`ʹñññ=V«q0GƒŸsjjUÒ ^!þÞ-Écp?iy ‚¤ÃÁ?çi-Äž$­`Q‹é®Ù¦V!ƒv©> ¦\p®¨æ6¨þúâ5k’÷‡rΑ«¥ç-9°RG?·Õ€É«y„p®u$ç:~÷Ýw3ýœƒ�§À‘£eKOÍ pî´Ê9-öúËý—üQ;7‘E *†Øj‚9æ¥û¢øsÎõñeR­>Y­Z´z•�sêŠïÒ &Ì€oÝOìH`dƆœàŸËÕÿJî‚!D=n_¡fóVV+»´¯eŒ7ÊϹ^ÚL¼9ÔI=öVB¦¡œ«D^Sÿúâ²:ŸSÿ:$»Ä‹*çž"k@ã\Tþ«šj~Î �ž­çv%\¡þµ~/ÀOê²7¶@ǹ;-1(“5ÛVåY rî?äl”ƹèâáÿûf:ÑŸ­�ÒIzνLšù^þCpî ò—ÀŸ3SA+´ß8’sÚœsÆyã\Bquu¤ã\›ªþµbw)r.¶C=ç`ÿæh¨°%À¹N$>’sŽAÊB€w¼Ýâ•ñïåÖSó=uœ{ž¼¬†'|ZØ]•¹Ï_zP9W÷ý‡@ãœÿRëòàç\Òž‰sͽþj?ÎÕL? e ×ë C5/°îRt$犛”Ký!œs£sËܘ{  ÑΗTέ¹XàFµìx©qNƒÆ¹�Þßž›à\™}ž}ú½’”¤ÓydS=€Š»ò~ú¹`{€¯¦~»{Ã9çsÉŽ¹+Üqë¼kçü’6ßVÌ1/�á§qnRá}§pî†ìM£FÅYs>PfõíóÞà ÎA¯ì‹ã{fº{ ”?œþ·Þ‹TŽEpî‰ÇûlÈoι.Ê»Ÿ>qæ@Ù佯�ª£q®kÁ懞:–Ѱ”8w÷Óþ?:&¨™“§Ý§*ö½WÝ)¼HB¹è„@³FêÜì1ßæTÌàÏg *«þÕ`ܬ—bžèp‡.Úóí¶|4{bwmëxÊìw±{“Ñ ã¹_/&V¨0=5û›Û»ÌP+2vûjKbõèÄÇžöCàÛj&ª÷ uâmŽ—æ§­í�»©ûˉM ‡*54ž‘”qýKej}y¥àÀSÐ?QÝv©•“ã|õÎ § öªL{m À͉jë’î‰õŸÈ?6dÔuß~ö†ÄV°JýÁußäÉZ¦~Í.u]‹Çp*ôËÌœ� endstream endobj 142 0 obj <> stream xœí}‰WÚÊÿö÷Oçü$™™€¸ÔZíf2 ¨ÕZ—Ö­‹¨ ¨@23A–ÚMïÒÛ{»™÷�ÄZk7E €yÎçÜÓö*„Iæá™Ïú¿ÿ¹¨:¨ p€@ ÌYpú¢\¸pQ-xpª§½rF f:û}·Ô«“W†§»‚s�w·ßˆ·ö$ü])©= E €mB J)_GÂßôøL BÖ¡Â)"¼´;—zcšî¹Ã…‹SAÂö�̼8­¿"•uOF—ÿxJ>l±w™±Yê÷sZ€PEb³�ÅÎ^¼iš{ »ÃÃÄb[NØ”µ%µ�,¾ê›Úõ…R¹„eÝ4Í�ÙçÃK/6ö]–páâ‡ðô±–* qZ�¸ü¦3¤Ð¾ØîtêŸõÂÁfÉÜÎìgñ8�È !{j¢èôåÿ¶œ( ‚éñØ—J‘”½ÿhËø÷±þ^Y|Ó:’ƒ* CAÆYb¦$)rã.\ªPt1H<} (*ܱp3ö|&õÏF‘sÂfÉÜ"o5y”B‰Ÿ $‰Ú‘…_ºê¦Ç³çõî ‚•;Á¥õù2ó[;6KæSý^z6$…‰2g S¯œmÁN9}í.\8ƒÞÞxûíTkÿ6TçL�Ê.Obo�8�[þcfü!A> a>`Hb²Ÿ{ ë„Ä2î …ñÒ�Gó‰þ¾ÿáKIáä bêÁ)/&Îy݇‹‹O¿Ö2¤Ký™ÞÞ8´|t¾“^/³�_9Á²íDž¶uð­Ä’áóå§/ÿ\ÐÐÔ‘D¸óÓ§_»µ•Ù?ú¼ë…ƒHâ¯Ëãy¨2Ñr¹ˆ˜‰ Têô…»pQ]x‡t!H„!ÝÓ¯ñX¤ÂºÆó±õREó-l>éáI"IL ’D¿ŽE6B»]]x>4Ä«¿/õüúpqÜfSïüaË.…—¯:ý9\\tX‚a¿ÿáó^XÍÚFw³§;G³ìp„J’.IÍ”ætìÍÍ™¦I}þÌÒöé—q½p08÷ ñXÏ.&„ÜX† g€†vFmÁÀ Ê†Ÿîÿ Ññ·VøÄS€,rpúÕ LÓ,ô÷3IÏͳ®çBæ¿@˜Ç2„�!*¼LÃéOãâÂ`ÊÏ{TXçXþû²ˆÓz7‰ DšKÇ�ñzS¼Ð[:^yqJKðwTŠ˜ŠŠîxº¨|wvÑ`É9€ ¤²àÂëÔY< 'ÏÁQÞ1I¼@Y §AÊãÑÞ%&ýp­¼…]ÌþççÂ*ð”5!è1\T’J¤`ÎwgbêÎ-œ2Rù3+èmº(ê>¿ÓŸ¬î`w™Ó¯Ý.{y;ŸoÆžCL… ¬p†ÓŸÉEÓb‚"©¼ñÂÍ©Ýdþó¹˜Á2½÷¦ÞÝ“•|© §8Î 1³“Kç\áHòož.¥PI5ÜØ.*Ó4çSûƒKIe#Ïþ8?-ض�,ÒÖ@ÊãI»'‹c°[]‘¶öÓG3aÏȇÀ¯Ûâ°eÃíDç¢R@£éá'ÏMÓ2ó‡�Ó&=žÚ´›¼-’\ñ`ƒ7œDE(3¿Q©ENæ?_‹<‡êa':Ñ=b¸87PHãÆ;ÃóÆ,¿®©,W<lñ�9c3ùfµ:ä“Ö¶ŠÈ†ãz²Ç£Êá4 §?¨‹†ÕÃ�prPØí‡/R•~V�L¿ÙO%iCf/¼x ‚`u�Céùõj,õÌÖ?¼Ü[æô.?¸(ÈjÌÂùAeÊâ›*Ñ‘x þÖY�gµ¥ÅéÏí0øð>AಡPïí‰þÞÇs­I`(Û~{Ó�üëâL8jZˆM¼­*3ØÆ«2EqÕë½ÈâÁjL )„é¹dUW{ÅøÔ>ÊõöÆÛú³nÃÅ)aOŽ€ g†¹J»*y&ùf=žµ ,ת(Ž,™ÿÜó Ày¤ž~ÍéOï¢ÞÁ»1pr`Rˆ=ÑܶJ¦÷Þ`¢¸ÚrAųr¸·a.QƒÕ¶ûJ݈> g¯ÌÜZo¿j�”ikØX¦jÉ ‡S*�Ä=²«ƒ=œÖD6·Û3/D‹D5çrºø!DžÉ€ÌZÃÆŠQf!Õ9Mï¹A!¼€ž]ù P3�j$Ž[ÿìK óBN(ÿ`ÆéÅpQ_°Ê®©ˆIÛp®É §´íãbŠ> K©¿Ö²áÈ‚ó¯!f|ŽÀ9§×ÃE½Ê‡íAZ‡ ™Á6råÚE:„:B¢L¹5˜±Áù×|4Æ@ÎÔÜ*o\3È Z~8÷Ûîñ5°tœQ„.”xàA kïmøÞú½²Çøþß æ¶³¾à0eæ Ϩ3~†ïMï¾ÆÃý�€‰±Ó+TuèòL„¾Ÿ˜éˆõMïBÌ<}¬}ðÆÍ?TÈÅ�Tž-ò*lö¬æ±‰_ØvœRˆìi’N/RÕq(ZßÏÊtÄREóZä9Àc³GÞszy\8€l…"•G(~6ÐÖA#ÝW {�@s÷£6øÞ·!3»âøšå‡ÂA×xA”I‡ò\TÜÃÅÅBç!6Z°�:µñÓáŒÚö2!™Ï~S'LR Q$þz‘ G–ØùÜ6œùDN**n}ÖE�§Ö-~`c•kÛRq#—{{^o³Š†Ÿ Qf:îøjo+Æ'oaMøPï Ë-2oG :ðè•ãOà/l;N(BM<‹OE¨eÑ-dÿãyqA1ñ…u§ÌEue °dze¢XΘ‰Ú½ÜK!lJñ Û•fgêQ6Ylý-ÀÌÖÅ{žÙY§—ÍEµ­)·véDbÇá�úi,½¬Ї¦ó<ðÎÒÔ³l8²¡¹×¼Åýì¬÷þªÓËæ¢*༄ äE—5.·<�‘®+T÷ZZšI<ðdi»’bzÙñþ­¥Šæåû¨Pqd ÊnóÉfƒiš£K¯¸Regší¸¥Ÿi6›x8ìÛвÁ¶ÄÎg_Øà²SIu�“M…ùÔo�ÙÀ\];!h¤³›ç<´4‰çÁžÿ‰PCȆ#[ÒÞó.* ¤ÝÎrM4fyÎ[ûèÎFÕšÄVÏÒO²´‰rœü­›ùzÉW?¥�>û*Vg¹Û›N¯¢‹  sBó… PeOIåHŸÉè¥n€ýÆÌŠ`f¦ž9¾ªeØ•‰¢(Sß@V�ݶ0 ÿ°Þ9¡A…ŽÇÿtüÑ*ÛÒO³JM „÷64žl°m-÷ ©L� ¯Â<Ãnfu*º"@¦½“%ÇŸ«s½t™‰âÞÝ»¦Ù¨¥‚ò.‘™ØSÇ׳l›Úx êf^Õ�\4*<8%à,ç•­5BVï-ý$ÍsLsonÎé¥-´ÁeÑݙy±59ˋӘh‘Óœ‚JƒÅ.a´³‹ç<ÌÏ7¢x`‚@­Ö ™ØÇWòœ–Ìö…øX$3wæEÃAT™€5 “ÞEÇŸ¥JÙöÒ6±ÅÃü¼Ó |f°Æ RüЦSï fVf�Ûp²‘àñ˜Þë/D•!•9ÕGºJÆÅ„ 'tA êe_6ٵɒˆĆ€]Ïdàåò¾ÇcLï-7p„⇖^Ú¢ (ˆtK6lí4j4ù{[5>!… ˜…—^4W_Xxpª¥¯0kÍ;þüTÃH[i(ñ ñFpˆB)yìøêUÖÆâÌLÓœOí;½Ì.~�ÌÛ5@L25sYcK/n2(l¡C¤AØd²Á¶TÑlÙ˜Ý}´ë+9½Ò.~ æE1»9õÜñ'§zÆÅCƒ„-rÖ(+¥LdÉñu«†Íeþ… 󌕼á§Ûů¨9Èý��QîWž¥R¶xد{ÏçŸ3×0eògµ«‘ÄLPs^7¬Y¯àí¼¬ÙÊâǘj ´3ž 8½ð?o+-ŠL)ÀÌä¢ã+V=[¦¡B½8ï\Ô-€Ì�úBÆz¡ñJ/Ïj™GIÞºÊs’¡ÓkLy[iÐü²Á¶�¹×¢LDÌ…«Ókïâ$ ¢CL BÇš.|ùc+$ÙÌ@�µ´°z*Ød–r V1EæÁ‚óËUeKä?#•5°+êP!PÑ}ªÑˆÊ3-ü€ÚÐ0�‡ËxIrú>‚«¹«ó²v;¸µùÂñ«ªÉ ¯¡5wa· «Ž *Y6¾z1dƒe[ì_b+¬=È$‰ø|Zg§Ówã69]0;s|¹ªm‰.¦nŸÉº‚5–ˆ÷”N]Ù`õÉAZgg=�C>`¶l€ú[3sëŽ/TmL]zdŠd"5§o‚ A¥@¡P¡k9þxÔØÈÕ>û :PŸ�øýõ@†$ñ뱎9ÛÉæ)|û­%óŸ%…IA Ê€¨PA¥ÒEò6™¼Gº¯2(Bõãp`¶§€­LýN¬’çù� Ôýƒ§ïÃE‡çíi§ÃOö0jo[ì[H>Ý:ã;}7þw8Ê @Qvâ‘ãëS{[Ë} õfÜ“…ã°áÅy¤ÐDþ½žŠï7 õ8Sûœ–ž^æ~?+láô 9eE‘oËø×ñ•©¬-JÉâÛßþØ�©]>g�xúÜRnÇà+ <²ü›‘¸Û¹’–#É.–DlÝO2÷¶ ¿¿Å�dÅêó3KÉ;{G4IÒ!䣬Æ:¿,•³dñ¯hn\¡<•F¥mÑÜýÕÂO¹'ú>>¯�µô»äàZÂ;ž±Rè2ûqG—´‘%WhRb `$…÷ïß~úøÏ›â4[÷뙑­B“´�ã “3ñÀ¦(:xGt„4I¢’Ô4²a½øÏ”Qˆ¤P2La�ˆ2 ñ�·W‹?NÞ¸<žeætÉÁ1¡ÀìÊýøÃ·óûdóŽžô‘5Ñ4ÍçúÀŸ¯âæØA“­E4EŒ£x@ý­v-ƒS·ƒË{pöجó rn;A *U&b*‰Þgg= ƒ*óMå&7J'¿›¦6þ�˜A…BÕõ<8Qå5V³ØÆI7Â6ÓHÒÏÖ`<Þ›Ëâ½çsæ�ÐdÁÅ—ôÈ©R BM’Hã{~H !C8ú¤³³žûkÞÑ´.ˆ ke½‰â7Ùw©â�/Ä ªAÅ�i:€ù=ó©ìDâSF[¤Id¬ŠÙUÿæJ{<ÞkÿüùÁ¦ˆ½Òœ±ÑøQ< ­‹ ‡œå¥hc3Î/EÕhá8ÂQÍ¡kµ�xá›Ù(<›S)Äg*Õün\htNhRˆ@™ç_¿#YíIøvV‘±�ÕoNß?#‡/ñΦ’n`ŠHϬ0kFmíùÁ€óCÃʆõâ?ÓFD¡§¢…ãàÕ~)DTiëJq÷èŸÑ�Ha�šÄ�mQSøG8!#…-ӯǽ¬¶HÖ$–’XBÚYE'~å×äpœ"Øz«¾ÚÎ7`âDñ€øÔëeV X¶eW ¹cj��–Ž «¸‡ûZW‹_£—Æó3)ì’CM!…‰ˆé¥{_[ÈnÓ MrÍÀˆ¥~�+xrøJÏm¡n5Edf¿ˆ‡†-¨ P¯—¢ RØj3 ŸQ-|îý¢H¦0Ä:7J‡‹ð`õ/€)20p›<«ÛÅ\ �äž>&)PØÑlÜ­ü’ð‘5ÀÖÐ÷šÁÆéÉÁÆg‹"غM{Ž?ɧµÂgh£5 [íúíÞ”óÿì´0´ƒ0J¹´p™Âá-(S4fÜN•ìR ˆ93ˆC«Éƒ=:¡ÔßO,f`–Õæ­[úy† RéZÎnù‰n\¦I‘$ Yûé5œ•ŽS„±h ŠÈÌ®P„B¤&‡ N|Î]cȆ´4`ЀC;?þB9+ÆW½³³̤¹üa7ݞɢ(3lò„k"?\ 0€ixŠš¦I,N Öt‡[‡¶øtQ…À �†r¾;»Õ¸ï `Úu¿`¯¿¦M“5ÄMþJH—G‡ñéßF¢K<Ø{¶ëö»Pµ‘zïØPUZ°1;ëI C¼ÖGZ+òç$’|‹xí�!† |#g�±Ù+ï_’_™Š2åqCLD¬Õ°ê£9?àëSäKý]ú®ßzbõUàìUÍwg ûw&–U ækÇ)¦÷­¾.Ûù4)å^cí7Gìó�Êøï�Kl=@·•:§ˆôÌ o��^eϱ"˜¢MöÎñOý3KZJL«H Gb Ïš’7ÊnpF* ÌD+êY�·«%z{ãmwRþ�t.al¢ ã¢ÓÚݾ9’ƒ†|½w–á!P€¿þ–(óf ë¼,7ý<,ÑjÅ) rx¦ ©ë$žëB>áýõ/žŸ)âó{‹"ZéöÐV¾^Û\[âAE½šg=ÝëÕE‘ˆb&qþ#ÿ„ª­¾Çå}¯Çô¨Ô·”ßÜ,™½J3Qi`·Ä|çú2½½ñ£³ä‚�ñ¿ªME?Úò탩%eŠ AIƒˆ0q%Ü:´ý…¸I˜A™DÎüß¡ÌõÀÄ{}·åòžÇsæ™,¾0A˜vŒñ8EšehÂgšž½ç-¿ýÅJ‘Ã Š ÛƒÛuI‡â¡šÕº è^/— ´îj]¡ÓsýÿJ ³öTéÓýÕ¿xË‘á-Ïìl Þ½²ÀØì‘÷Ûä’͇[[¡hhÈ<›œ»B: ëh4}üí‰Ký7çîÜZ˜ìVO¸Ç%Ìxh‡“µºvS3 Sxøú„Ͼö⬭þù¯+L]zÃcú], ^¢iþ¾ñreÉáEÐí¡º£ˆÂgÚ°ª-ªâyà²Aàý¥µð¤óö[Z¨Ù!âg°s¾ævž¬Ÿx‘æì¬÷þJ-¯áüðéò.ÆæáñAa"Ή˜™AÙ@C¿šðeš¦:Å÷;PhûÐæ¯ßHÀL”©ÐWòxL¨ö¹C� AÖ½ÖtËS^-— ]̾ϰu’l%IKžJ9WƒŽS„±ÑJ¹Šx]ƒçÿ”–æÕÏy@•ßä‹lتÙà ZøØ®ï&­¥�m#9¨èÞÑ G®¤<ˆØdz¸ã0¯ ³�†ˆOë<±”�ÖN?ÍÏsµpy_¸þ’¿‘Bì÷õàÀzà£Ä„ ñ鯧0y-v죧¼Ôê‘ÃEüùê™±ÑF·ïnçÕ_¢vVøÄ«-ª@† +•"[²¡®hÁß)TZȯ=zeyæ&UR� ‘Ÿ kŸò1âÃ�wÏZaúÕÃpÆvÜ<*¤` gKç%…ù¿qTŠAdv-ò°UÛêÛ>Fúæ­ÍRm'ü>Q«p<ë ú A°ZeCœ¦…È-pÁk8ÿ› U-�u  Sô¸˜åÑž*YïÙPh4 �ó>tB¹Ìk¶=¢• Qæ+(¤¶d§Cð¶áŸŠ‡~ûùÛ­è{, 5­Sßj=ýÕ’NPݼ±½SÚ*¼%I”ÝÂ5ÞD™©gV¶dÅă-x»'GdCñs¢¸?½óÀª „õI G°0L<ÛAæjÙé+ú `XãqIž�`…Î1 ÇüŒpŽóÔ\jÏ4MëzRyÄä‡?&ȬÅ:Ñ¢ ‘¬#M;ÃŒ†Ú“à Š`ëm4ÈÈjÓ5ÝMœj+ÖŠû ùät.rŸ ª´ S„<¦Äú¤69` ¤Ñ”¨Ðól“@Ä9 žåxØï\:&OžëSswÇ“çh4ÍÓ!dÒÚ¿ÝÛÿÑ•[:‡“ßbäw)‘ß¿‹ƒøãÅšôÑà–„š¬%?ŠËʾM6øølîm@[z-:pÎ埩Ì2ÿŽÓ‚P·já8,rà¬p+q‹‡ç°vÊÀœ#àIM˜wl®Hk}‹˜� qž×áJFÕ­¬lbgi~ÿ3¶#89Ã÷'‡³‰d™áÃo^°PIÈo÷0.{KÀ4IÔŽò‰¿õüäÀ¤/ÙòêDÍ.~>—üâóæÂ<œö6-!¬K–²FÀ ̵(u:ìÆâßò‡YÍÖè�s¾ �"e§Ažó¥ìz ë¹x8ñyk«¤"ñ¬›ñÒì3gý9HÇññýþ_¯WŸk,éãy?ˆhTÅ2±'vØâ< Õö\-žÛ@j!’ÅwSÆ´Âx;gvÖ3¾úûlغˆîŸÐ:1…RxKT™WÉ:}E?†¨oˆ/´g¬ÔþU‚Ói_ð�ÓÉYC™?Dxé…}Þ±r'¾aÿˆÖ9¡Ùg cU|IÏüÅá4+œÄÁÁ§¿^¯±�¶u{;Wªú^³Äƒ~Ïk”Ô”ñÐÂtnZe‡.GÕà‡àñßä5Ñå]¿S˜Ð:C:ÂôÌ�«®Ùé+ú1DÌû.B>\’yÆJçA[„ØÇ�ó¿Úüæ¡gZUœÇÿ—æåZ]á$MÓôì—Îüõá4üGA·nU›"Ò‘ÇÌå5‘ã~HA¨¶l8N ! ñ ¨uÞ©i<çüH¯2`+‹wSÝ�¬B­Š¼ X‰æ±6ø³%Û¯Ë »0�?é1Ö!K”¦wz‹Ÿ¤ˆ¯âáw QQ´9D9Ï;®—¾¥f(3.YLÓœÎËC™À¥Ø\Gì´}j~¦PÎ[ñ=¾ä[ê°rNN ³ÎÌ[ßÏmýÉÿEÉŠ2Ë®ð�V¹‹J6lŠÈm^¶(‚•/îÏQú/Ã9Q´ùa+û‡K çÄ`&0˜é¸²0~eþ¾Ó×ò ì<€‰X¹]ü5 *HÅ`Å”Cç!¶zW† Ã�_ýïÿ»4¼Þ5²®­"Íâ‡ò^Öém]Y¼ÝßÎmvsw%Óʺ•½ð³+ˆbÎg¦ »´p~³þ¡ŒÿÆ3¹çÑøù+*…TÊÓ‰‰–›tx~ºŒ ¢Â3VT^CÍÓ«‚ãL३Y;B°zrÞ_¼}qk¥m{å NÀéí\ pŠØÙºÌ6o”A™û�˜%~ÖžúP6 tVÙàÒÂ�užðy{ý¯y”ëÂ'ɘGÛú¿TÊ3656�œ²‘ûoáfÿÎyÆJ€w¦å�,P%¡‚U­O`÷£Èõ'C7—xöi$ªD¢[ñöÍå¶²_Ùé�\=R„±y=cœ�"¶v>Ég÷tú~¹ò�€@ Ÿ‘¦‹‚šdgÖ»´`c`; i0ÝUMª�ò+ºÕ˜‡®ñNú¤kâüò�/”å�s˜ RϰÝtƒØ>É£žöç±îG‘PÙ#Ü“A¹‡a|zäþÌèÆÓö”K?…uÐØê6¶®¦�ì©ÅÃC^‚mMå>±\†$åÑvæTsÆ×K年т¬#Y‡A­œŒ”fÅ�TGo¼W&È7¬ùG×�¾’ò’U@¢Ýi$½ÖÚ5º~Î-|hêwc°*ñ²}+wŽ^O¦Àã1ãÓ3�†R+m[ñ@Ùëàôæ­ lÑÍ6¯m³SPDî=•|ô»R,æñØ#PO#\Z8%zã½w·:‚Z[Gt®}ò±Ó—á¯mí+9dV|]ÃVÁy Ê<Î ªQ‘—½µvËî¬e“�xéµÇc..Þ"k¾ìª¯ìupzÛÖÿü©å·{éÖÕôï(";6ó½x --œÐodƒK gÅÀö¥�í®î‡Ñ®™˜ÓסYÕï>ìÃÅøô¨OÑι…Ûå盼“ƒ�°¤�È<—õÌ=+yøô- I¦‚xõ¹0³ò´‡ð‹/¿ ¢Ó¶öà±³u•¥®lÓÍŸîqã?Фãâ�XeYTõ~õW´°S˜K gÃÝT÷ÝÔ•+sWæê%šÉ€¬ÂLÜŸN#}”�dxÖ½½€\2† "wIW `1Vò„wZn,ùF7üÃ뽋Ã`ˆ‡BRñÎÜ: +å7sz«:[E\36»ÓìÇ¡�NY9ÐkÚ­héOdÃ!-¸j¡,ÜYï¹½ÞÓ³0Ú³0âôµ|g†u‰[º’ÙªölM!¨ J%òC5kÍÞÕEek8:. mͯ=ñÐ5�¬_¸ôéŠà E\N¯",ñ@¬yÙvÚ$Eí;Ù°^úw*窅ò1Ä@ÿvÇ�äµk�•þ�+ªŽÂzùÇäú‡=ÏNÀL¨\n•g˜ VÓ@Þ�§µUq{%À›²&YtM4âå4ýpzwÖþùS+l_3RÝiò EdG§,N‡²¢­ÌÞië¼/�K gEX÷a ‡�u []ãºO%Í\WòÅ©W°*Ó"žavÔÇÛö“™ÈJ93å�Þ—u„C±qy›¦¾Šˆˆ(.zyNõ]凴pØlCwóÎ •@ÎìþÃâ@v…ªK¶ÕÊ8lxUb�ôµ«2�3MB�§j4g'¨ãÝ_¬�¾j¤ºÒEl‡&g.;‡6øÌôN FÔ¥…JÁê— �–µ÷�}#œ¾´jT£d[Ñí¦”v³ý¸rH–’H²1æô^¬SXq-�¸ÖjíL:äí›¶]Ž.-T X°&b �çðÌû›�ìAT+¼ñ!3Ø5b…§âöJIBÂÇUpñÀRÍß ªÆ{üÍWÚ¥©Ù!¢…>—*Î ºÕ8M—dùùBe½œr£@<Ìm¨XÉvooÜ7�±S²¡uTyøpèîý…­•6mU¢?”÷ÊNÆý§Ï�“C`"nšæ½W7.ïy=*Ós� ìß쾿ӷz{`»ƒ¯Öääð¥ÙKe’í·S½½qS_X‡*'‡[c‹w'æÓ+­ç)ÉtÉágøüñÝÞó¹ôÚ倚±ÓRˆ`í2Ïk£Ðcz.ﵸQ)ô­Þé[ëçÿ]¹ãôµTÖ€@ŨTkúÖþm» Tˆ/Ì�*×G_y’YõgVüçye§waÝÁ¦c#@ÒêFöõHÛô�+Æ~¹Y2Ÿä3!£ÝÊ`·)ÂëRÄùÑ·vçÖÚí¾•�›+ýN_KÕqØF^©LGk»Í Päó7Ï)ÝëÝÃËÚªO[=W`Ýé½XGøôñÝ^iÎØh%ÛÊVž§Aμˆˆl¸�LKZ Ñûl‡2ŸäµaÖiß—"Î�[k·o­Ý¾¼túZª»5½(³Š4˜’°a7ˆ“‚’=œm¡­Î‘ I }0Vþcéôެ |¥…´º�?ÌŽ^×?E!�øô(Ò£P�º0üúxŠÔ“‚>L/a—"Î�[k}·×n߈]_:}-UøY8¯rðà?P(‡Ã5¤ fÿ»¤!hèkˆ1OnûÿÊ~}§÷¥ÃøJ ™‘­Â7}¤†^D!‰ =âÓ'™z²”ñùDúôÓ<f—1C6EÜßëßÜ›oâH\5p;qývòƵ§êÕ'ªÓ×RuØh¬€Åy•C‹œ±ø�ò9Çæg‰Ø@˜nÆÛò ¯‘r ¯ÎŒOÿySœfë~’>I ‡²qÙA\ªM=IÐ¥oÅÃW‘§#F·B%…Ó47÷æ]Š8=î¬÷ÖaáU•¬¾”à܃tçÍê8GE™óÃÑÿn¼Ã…Õ§ÝtÒÕòcîNïQ`ÓM¶jéÑïiÁ¶ù¡1@#ˆD|‡ç¸($Q‰D!ÛÈ�ÇTeW¬¡·.EœwSÝ›W®<ï~T/%ÛÕƒM�ŸÊWœ°ö¥ÑÜÉdË–+z<æ“¥>-.eân³—SáˆôÌOiÁ– 1d{¾®¹Å $èâè�ÅÃWŠ(pŠpUÄé1È›½\ꚉvMG�¾–ªÃ~Íããå:$=c¥ÿ ë@Á,‡9‘léñ˜#÷b�æï®?ëpÌþ‡´°nÓÂß¿ÞÝ ò‹( ö±âøZ�F<¸qV¶‰Ëò6q�‰%§/§ê°¨(—9¹›á ž±O¦’ù4. üàx29«N>T×ã]ëË�e_ªÓ»¶êøôñŸ×-h™û¿¥…Í’¹A>Å �¢�(4N¬•Å 4 Øã±7¿}�#Š1®(îAãç¸�jç f)8- o8}9U‡•!É[É—q¬àƒ­H¨Ý,Òn-õߎMŒL=X_¾ä’Ãññ߯òfÓBþ÷´`Û"~, �(Úù~¹¢�Å�C§.EœýÛ­Xƒéçà—`\ƒO±<ô9œÁ!é ëH!�›­ƒ‰Çc¶_û³!ž=˜M-·§âíe_ªÓ;¸*(�~-lÄ�…,*’Çã{§Ùo(Â=h| Ùj“äCmPå†@Õ-¬®@DTØ)3$Å ƒ\føÂº…2úJ-—÷=žŸ><=£ñÞ±géÕÖ­5”J•™{ãô>®0>¾ç´À} Ù‰­ÂÛ³îßEüÊ YþX6؈ÊŃÄRg®Šø†4ÿ Özc9XWãðª„É@þú fû®^ÓGQúg?‰¾Ô±‹²E6-`Ày$3ø»ªVu[’‰f1C6Yæ¸.§wsÅ`ÓW érháH6L{ó1ñDzÁgÀ¢"}|ÿÌâÁ¥ˆï1˜mÈtöðAºãN_Ku±ÈOûs“�<îbJEé»Âóÿÿíïñ˜Âå}áúKhlZÅ×Ä|y˜ýh¹)¼! 1óYùÒ¿}/»‚;¹Üe¬ŠZ²Ì<(§÷tðñý_eÑ¡lP_qU ÓÞß,~LdSb.†Ê?§ˆ…‹F¦iNçq0ÛÖ95×›wúrª‹´³È[>mË õxLx£$ô•<Sâc² ø…¾ÌÃâîGNy±&(Ô:­›B é‚JÎ �$çWÞ;½³Ï…¯´��lÿ=Ï>Ý`<·�ËáW²ÁÆ”˜³ïïã‰òÅÑ=ÎkEø. E¤ö™¦Ô‘ÿ^Ê/éôåT3ˆ=Ÿœ( “ˆvÞá'…ohòaT” iV%pÖ‹Óœ:Ó{�°†FÓjôIˆz¹smœÞße¦žåxnZ°m!ü*"Ò ¿• 6"@Ÿ„Ú”ÄR;ç÷ KK/BØh‘µV ¤ÖÅÝê! è´¤EùB¬ûN¨¹£Æò_NVrµBP¨üØ Mwß[¹6öT_“øô®µr|’Nïò3ããû?^îܧI¥hÁ– Q‰M í8m[¿I¨E¬RÍŠˆ‡ K¼&€€[ɼ§b°b­ÚëÓ’…zÙÊ�E»{Å@r®%dx†+9àÆF ¼�TBV![óеr|’Nïõ3àãûý—;ãlݯeTŠl[ ¿ŠrÙ@&иzÒ1_ÅÄä«É¸òh ±áÅN_NÕÁ™áÈç`ñCõÞË’l}¹‹¬‰d­Ÿ¤Ó;þT8F •¥K6|¶‚4&œí›Ë1HžLþQÙKº 1hÉL@àþŠišóûN_QSAÄDTÈÔ\�$iƹ_hÁ§¥Ç+N ¶-޼ŠA6%r~8ëêEE="è\<ä+,ŽSÄ0ëiJŠRq�­@@¥ƒs¹æøPõï /È껿H‡=êÏú NïþC|x¿÷ç«øñ±hąÂ!â¤làA :%–sà�º]¢õ$ZñÐÜ!SQ¡ðnê²ísúrš -ýÄÓÇ‹8øÐÌ5PÆÐ+çøà+>(fo¿Ú™°ÿúáß×/ŒN ™û[ÅÿªºéGÞD­..eÈœVUñð•" ÙÖ£R¿M³Å• ÁíöþÔ¥Þxoy×ï&´Îá‚®,Þê¶êâ8<}Lâ>�ÔJ-k"žÓÄÀ¹a—)4ŠÙ¾÷ï^X´ÐšM�U›ŽdÃÀ&AùOfT`V5}:U]ñp\E¨´Õªã‚FH 7Þ;˜ñYm˜‰#¤uBëĢ𖈠/nþ’«ÚC´f`�ό҄HPOž­ñ‹ÓÌ`¾)Ähòh®¢©›ÛU;Dœ°¥á׼ݓÈùá<· Y µ¶¥JŸB´ãkîÌ—fç›{sçù µD˜øžˆ¾ Žoò$G`ÐiU24ô¤OOœmb¦³Ì°¿û˜%á—¡Ÿˆ&ýúöH�ö—ñ9&±H‹ÎNŠ# X ÖN4ÿÚŽµ8{IÍ�l…!•-iï³™¨ž€$ ô�S•ZT—ÞÕ-ز!*1»�tÅo„%xÂäÓçŃm©ÒO�2ºUÂ)B!>L�ƒñ…ü©Ò‡¶ÑĤµÛ©‹¹ à-#d¢>ÞÛÊÿM’>}ëŸîdQUZ0Ö;4ú´NhÁ¶Ç÷ÞD±'PTãFD�!V{ÏÃo)âI�«ˆCŠà1(Be–·�Is «¹OP¡½½ñöÛn³º(”Ù¥{ùÍ’™ÕfȺDÖ!Ý~û‹U …Ý]ª°��<Ý,Õ-Ɇ)‘ÄÄjIÙbÜ }V7âá8E<.d‡ùÀ>_í)Â4ÍÇ/FTƃ©Ò‡kL}™ÞÞxm.àÂÂÛÏx‘…Â;Ÿ7 ÿ‘d+Ývs‚ù»‰ð¤…ÿÞžëCF]Ò‚mK\6ФSU#+a²ÅÃ7‘ÏŽÐn…Ö”"6÷¹GT¥¾…|r³döFJÀêÐ^í÷uaYðÑýUþ…•ÖWHÒgšž½ç¿éSAZ`�Ùz¥…£ ÅD'«àm8Ž/â�-ÏÖ�xø†"¸ŠèV¿R„T=ŠÀyïìî€ÂàˆÑ›*¬�ÂÄpATÜ f-àäÓ÷®L컯oÞ" PÔ’øU1Î9iáßohá“ãÏü/liŒË†IH ªÆ›�ºßP/¿¢Rõ(›¿êÄy¯Â¤Õ«͒M¾åyŠ!† •}/?DK?å' •®åø&ÝÊïÓ¤D¢¶ÓéŸæLžƒòÏõÁ† ¾ r5’ 6¦Dƒ'YAöìaýЇï)B9¤ˆÖÊRÞïÁ&V˜4“›·ß±w²0CØ• 5‚}²€ �>�Âé4*íŒü,¦lZ06:2d¥–Õç1[6Dj"lð„IÈ&7ë[<œ Þ/‚UREðrÑR‡ÂÀX®Ï~Z’ùÏÐJ|’p…óL\üÞA&ʬk¼ptdzé{$)ñ*§ýôù¡,µÐ‘nZ°eC1^cUV»§òá}†I±åFßPDa{˜vÙ |>ŠPg¸‰!Ú–,¾³ßb2ñäénbdMÑò%f±Ì޼‚ŸHê:Mp~ØÛ]üþWNO ¥ì]¶~©�Ô‘-�½±™¡ReV§O¨õ©@®QÄÃ7‘ß¶²+˧«³´åZ ¾•âîÑ‹wÝÏ™ƒnë§šÂ>Y…*Ko¾ÞëÂúÆ5ºî+Ð;4-0öMpót´p‡m\Êè« G ü9ß9à˜‚j�¦&—ýåø:œŸ"ÎtаҢ¡Ì›£KËù¯R6Î>BÌ¿ÂZú]r¨5D™AÝ2Růwy«ø¯žºJ×%ƽñR¬Ñ±Í>ù®n�v|wv�BãìÉŠ[ù?´ÍAš�häÞ—Æ=›ÞýÅòé›4Õ›¦Í@ G²!I 8ù=5)–x`Ëó�-¾.졊èm2…*mÅÌ7´ƒ¬>u¾£7^øÁÓfɼ<^2‘ܾOÎÁwg�éÐü«ŸÝßí�]=3JIú�T×ÎÖ5šºš¦Û›¥f Ûx%…ȇÆ Ã"ÖšmAšC<Yªt°˜O�ðì€J}*•"¹áåŸÐÂfÉ|J> …º}ŸTtÒ�ByÖ/nqñóvîyF–¦ëÍD G²aJ S-Î+ب@b�N5‘xøºÎ¥ƒGù¥•ÂO¿†Ž¬/¶ dî§pÓœ ió0ÒðÓýŠ< g‹£¯#ˆÎz؆Z³›§ �\<¤Šf"õ~]«÷„óÊÚZîP¨0ƒ†Üá5ÎÈÜíÃcšM$eOi\6ðþ±Ä4M6ëüìæ1OiÒË"€Wk>}ø×Ì¥\-'\Ôƒç_󹘲îÌ8}7\üíy'ìÁZCfà”o…ƒ©¶w5(ÕCWÕ ±8æ)ñˆ*Ôc€E]R^:¿Pµ²õüRÀº;Ÿ¢~ b*(¤u8wï†øÃÆFS¤.üÚVWÿ] ¿²v—îDúÀ¡ÄÈïñí&F^›¦ƒÌ¾¼ÔNóߑ͒‰ßžøDDÕ%‡úO¥æ¥qll¥‘ ‡Ë¶¥±=þí,è@'DmB¬#kš&™ß_x,*ÒÕµ wÐ;Ÿy³é å:º.Že†‚̯6¿xHxgW@¬2+6)’ ±îg63Ä ]¸>ÉÁùW@¦ H¤`ÝÝ<ç!È fÓÐã&Ïyx2¹o)÷6,"Ô©Žµú<�)ŸÑÜŽâ8ûˆTæÒ·ÌªŽÔRÙŠÑ´¹7\6HÆp¸’â4ˆŠÄö—Æš-aò¸]�>ç^Ðð¹gŠúPsPå}yú¦vkðT8bOcÄxOWžˆèôzÿüà#’é@ÓF™çÓÿ!•ùîì¢A7YºÞCMC….fþsüÉ©¸qÙà7&o!ëôJŸ ‘D� ¶¼ôO Ö§Ö·£h¶ßÛ2œÞõÝÙuz±]üh4-Þ.…vÜË×àñ¨±=›úƒ·{Bt²VÍ¥Ï�äT6ÓŒ ã«BÌLÓœOí9½Ì.N…–Ë{� ÚlaÍÂÁTCÉHc¯¶ˆ?n*ñ°šû„ž,=¼´[¹ë.N�Ç®ïò´(…Å›È3ùtúOî߃�$l$G^Ä ›îh*ñp#ºË»N 7Yº±1‘BÜ3y5Rrü)ªŒ¦[ Þç¹n’!O2¿oçL®‰•EÝdÈ‹1\jÎê)Gg·êî›ë0HôHÃ&KŸ÷z÷06c¨ÅC2ÿ¹m$Ç+²­QN/•‹š‚“ƒuß‘Âkï�Ûòüß|" ¤ÐÌix›÷z÷"€Ìt_óã–*šÝEÞj~d¸�Ë kHŸÀë ÏèGÇŸÉ£'“�ºxÛy§W¨êí9«+õ"REóFô9T˜gv¶e|ÕéráfP¡¢Bü!c™Õ?ÄçÿŽ"ÊMh~5ËÅCÏ^T¤õ#nϾ2ï&-†·=³³N¯� '!ZCxE™ë‡U§{ÊqÙбáíš›_6ظ÷U<8?5opîÀ�¦‘ÅN¯� ç!ÊÉ®�ˆHk Öv>wÞË…÷|û¿ñŒ•œþô. PfSA¥PeÊÒ›ª>«Ó¹$v‹$§?·“˜kÛŒ÷ƹxX«¢xxF>øÃ�‰išêRÑ-ÄvQ•“ƒ7D¡ÂîξL«ò¬Æ—ÞÆµ¼ }Rs¼7>ß¾éÃkÕ·þE ïù3ø°4Ÿºèlìâ<ð†89x†¹Šèº_¨F ÄtG."º²áó¶xðUÅó0òô¨PÀGcsŸ’ÓŸÕEÃÃ3ÌÚ•›@&¾�QYeüñÛˆ%ô¹‹.lpñбôaE=ë…ƒ›±ç@¡-Ø1JsvÉpQ{`löÈ{¸eŠT6¾ògådÃNT¤®l8޹ö/ž‡ ‰‡§äCë¯Ð÷Œ•ZB¹·s‹‹JÊ(TTTißôîzþ¼óqž=ü3"¹²á$â½ñ))ìá•Âæ¹‡Å’#…A…�p®exÇ L¸¨D•yÞh`Ò:l,eÏuÄX~…ty°äʆ˜ð²aqNæ?ßš~Ái!ÈW {”pQeXÓÐÒ¢¢™w‘Rß”ÅH¤þã}�öºÎ±o0á¥Q‘Íž£½äbö¿Öá´29 ‚nŽ“‹ÈD”‰wH‡˜^º—VV£˜Tá *Ó^\rø ìIMˆZ’¥ÑrÒKRÅeé T� Pt/θ™ .j ï�î½¶ëñ˜¢Â)GžþQ†„XT_E�´Y�ûâ^K{R1‰%3g®mYʾoÍñ¡u! *È®`pá <³åò¾ØW’‚âS¼sKgìU›Øz•ج'5åu«~8FQz\äÞÈ™3æA­ä…×óÓ4Gï¢�æô§qqÑ!µ‘Å]Ó4E™{½‚ó¯×ÏâcŸ|�,ôrClÿ›@Ú(Jó8fò ÎÞÙÔ;_8æ ën꣋º‚išs©½þ‡Ï…�0õ…XôÔåZëú§)ŸCFD¤ž ýeé$"1Dçå—§\½eúñêd ñ. ª©Änæ~þ.BÈž}'b†0íË/eOuÊXæc1Ù„GëØÅø‚~åÅ á£:D:06Øï;y®ç0?GP Oïà$ºõ ³KØJ·¶ê¾û¦wWNÑtnQyó1ŒÍá¾·�"‚$ɔĩß0jªhÞ_ýS 1»·›8ÈZú©§ÏMcpÑàéÖx¯—xß…�Txôê×E[©ÂÁÃkÅâüëÍÇ{ãNˆÚ!Œ( A�I,¾ôö×´IüÅ0å©M2ƒ²áövsÑp°:J€‰ˆ5`MÇèôò£1Rùƒ‡×‹1Hã½ñGméYéB|Æ �q¬ý3LoüÃÔ*å.ÖiÂMmrÑб&b]”uï�n9ÍØÐüëŸ4RùƒG·J<¸)±¢ØÌ¾5»{Ãl ƒtJb+Oÿù‰Z8˜LüÝ>šC*ƒŠ!©V“OÙMsÑ$ðéBPƒ 1`4nN=ÿÙß'{|® Ô§%öЗ[ ä�¾üÊcR0f[3¼ú²©6#±ùƒ¥Hæ?�<Ý÷©R¹³ÑÊ^x 7àë¢ Á™A¦ ÈÀ@Ž4TÚ=Q˜Ý|÷}jeüé?1¿ƒl)�Ÿ‘øœ¾öŠa¥ïCí$“‚õ±¹[Ï7Œ“±‰eöqhîR)à“ŽuˆÉðÒ½à¢ÙÁ™!È$•tNh¢B$•ú‡�Ð㽓t6ا¹þ1‰ñ#¹dD‘�ý¥iŸ#¦ZÓ£(�4æ7–¾ÉÙ(D×ß^ž( •G„-.åN€›ùxåÂÅ tNhþÝ7¬ó)lAðžôʃâtêŸÔ±ËøÓfÚsQg†(bQÈ"b㩈1Oi¢egJÒã½ñ(äÃ@ç_l�¯døTÿ08÷ʧ2¤ò¡!ôoÏ·¥"Ü9�´I ?ؘ§,ŠØÃëÅäÃ3ú!ôx¯�‡&yæ?A(D¢^7oÁ…‹/àÌÂ;‚zXQ(ZBBRÙ­™Ý‡›ï6Š©�ƒ§SpŠ4&’xo|ÚŸ™„d².§î.ò}Æ b@&�i°G׋vÏù§äCøé~ûè�HZóÅ<Sè+‰î Â…‹Ÿ…4   ðÆ×ó®•HeW&Š÷â,“� ò >‰ЈŠ@"€ »×½o<‡ýuSb!&梢1m¹RyF´u©QÀV6ÿ›Nýs÷áËÖ°­ s ðŒ¯v\®ïz/ï9~ñ.\4 ¼!*(TTøà-0�ƒ2ÿƒ�o)Êäò-:æ£_¶‰@Ýã1¡éúð 2÷ÇYûÓÞü”ȸ2u–æ3¼Þ¼%3åÍFEÞ¾iJ,ð?Ê % ^2|ƒÔÊc(Äø"ÎñÖm˜uâ=xÿ抻pQ)ðèÆwÍ Ìòn“f¢ÌD…k¦g÷mªvЋ­ò1gšæ“Áâ—,&¤¦½k³žÙ_¼ET4b‚ÁùéS�É,üiòᬇMyiT ˆL 2 x§š(?ìrÂ=¹}…ú‰ˆäü&ÊÄwgÊ9»*MĹê,• Vaø~xé…`Ídá)<¥ŠXDAôÚ5ªt�ûˆNB:�ôqD#€Å�1ë™}¶Fý4 JÅ�Tî¤rÿo'SÛŒqÄ¢¢ñE‡ÐYH†ý´¿“â*_â?¯t²P; p¹2 謇Eø[Ðû>òÀz»ÑVÚßM.ßæµfœ øÜjÖÛ÷ f¸'a(v|wv�^B..ì”*Q¶w"míç\a�>hû€Ñs“Þ顸÷Ñ ÷%zÏ"µ“Ê—˜ÜA•KTn§ÁËÆµKÆ<È1÷frí’�ÛX°‹X?o(�4ÔÁFtÜG úÒáì"7zYwCA.f„ Ñ9¡µ*„³�L[ï¦;nmö6BHÅ…‹æçŠ A* Ñö~Ús“^¿Î8/âœ/¨õÞ&7®Óþn6ÔÅøN·dÀ¸�Þ÷Ñ��èqrˆò@â"ស„Û©ÚÎ%Ä`7½ÓC®ß$]wøða�Þè!7zi×-æ`b�¡õ óÌ.§WÂ… ¿Aç%¼#É,0H.ßÖo^£w®Ð¡.~LàäÐJÇü\QLHtrÅ1åÀ&÷‘ÑVµ�@/“Û½äÚ ÒÙO¥A*ÈT¬Ç(ª .*ˆÔ#>=jS$ÜåØâæ ¹¨wü?_X endstream endobj 143 0 obj <> stream xœí�yœU¶Ç«»eÁDeQlÐ×QÁwdÔAA`×Q}3Ÿç ® b*"0²*6 "# ÍÒ,Ã"K³6ÐM/étö}é$�tγ’t:Iݪº·êÞ,Ìûþ]•Ô¹ùå¤ê.çœËq™áâÒê’ó3dû¿€Íð]¦q6ѺÏ]Ï­ÞSatû‚Maàij ¸ •û¾ÿìùßtÎtór—nw¿¾x¿5ÔYN”,zÿùÑ·î}NÞv÷ä·¬; ñ„›õ{æüa@«L·5·è6º¨Äl;]é®_÷æ}—'œiýM-ô�øå~·×ÙxbÉ‹ƒ 2ÑÒœ£ÿs˪Ì?,^o:>ç±Kg»=t‘àXß§¿6éʪœ›¦o—¦Fæ&ž§³T׎_bß<¥Éó®ë áÛù;\ëÿÔ‡]óršî/—zµv½áÐË*xß÷4û_(Ö8ªgݔǠy9Í%/îv×Àä^ð+¥É¾Þbƒ°V¯+ºñÿŽÓö‰­nM�ïs�ï_¢êRý¹] 7iß¹’Zûršþ³ìužH‡Öåþ¨‹êËõYåäa�sÓèÖT˜Ã´³Ç®‡èhÁºêrŒwÈs}™%rAO½eZw*WÌQÎ{µ¾Îìæ‡h]¶à5—?rÍp�{éµ´®škô˜a¯ ÅÄë:šS5}O[c×5Ù6§xᜡۧÎÚfm!ìøÝG}‡oíÍ×¶èöÜEõÚ9ÀÓÝZhQ×ùmyÓmñË;M{î }ýl¦ãû $¨ëz��‘·œ-ܖ̓˜ÈJò'*à ê‚c4;EÖû‚‹™XÉ6~³OHlÓØ*ØâN4Sç˜Ú–�¡,ââbkÒ‡ðïÊgd«‹5éG®«ÁÈR–�7Áª…Ü™™kM1e^Ò•™±ÌÓs‹¹)U]çgììå ¥X«³Nfg.³äMqØSÅpöfhòq}ª9¿~�p’þl Ûæ:�ëøKXÚlmZÔ›`i2CcÎadûN)ç�ôЦ2²œ.†ÛäÔÇFÆwH:/�qQNGÿ�³ùeÕвqß;dœ—G³>‡;ÏØÑc‰ÌO1±¾]Öy zûyLŒ§�’ç[EiÒ°pßÛ1œ—×÷@ŽÎQ¾aÂú|ü-pó¥²ÏÔ˜¾'rr í-äpIS-}÷½É‚k½öÄÔ­3g ¶ïò}³'©Û/‡§Rw$ç²�^ÀvžP5m÷Fb¿voŽÍP>eÅøT èÇPnÀÌ;o”ê-9µˆ<Ê"1‰ƒ"XM7ódN§,�ª59”ùr½-€ñ‘’ÐÑÿo&r^Þ¿ jŸ%=MnŒ”L°‚f´ÃPRutS(ÚgI—JÂ_fôã=F± %èE )ÂæQÀŽÖÛë¨ �§è¹ï�äÎ à·ýšZ2§F‰ºõ�RkÂOJä“V˜’˜u!oÃߌ‡hÊ v¢"–,! ‰‘ã„Љƒ’æC¸^>ÑÍB6b‘³�΀-Nc`i±ÃõnŠ÷^G_Frr‹ÒµaQLU»Ú�µBVœ<|t_±ŒŒ¼({j‚‹IgUº4yñ2 ðaZi›k)ßyùU‹Í»H[1)¤8@ í§l#ã+¢@iLjIëº}KùþÏãÌ‚¤€îê篜ÜIÖŠ>T;e1ΰ-†€Å‡ l&S PAç£in'jÅ2:?!³ßåh¹×M�YoÿQ6Ykß2#�ZIä¾½©ü„Œ®Ù—rWO5ÇûwgØä30¾Ùy�•#ó8®�ui¤!pým­XB¡ó—çœgì± <îÝÌtÃdotž7àz=ÞRý‹‚Àu[ñÑ[ý�7..O׿™M{&¢asMt&Òeý»0ÖÚ€_µÀº[±[±XíÀ&I\ž?G¿°ú�i FÆÌÈL¤½¢[ìïÂx‹~é"$òy3n#z©t^Sª¸Çݽ¦•pìH—6‘©2ge|‚ 0¡Õ�€º;¢×}ªr^B\ŽãŒÜÎdtUè~3 ï?P˜ÔòFU·;¦û^¡¦Û`òÌÉØ~’¿ï™ÿMI)E,ç›àLHù(Li}c@…gYðj -P`òÌë&zÝÙüOÓÃ"Ýøj¼¹ä¶¼ßØþ˜p$U^Þƒ ìª/y¹bç•—ãÎÙí¨¢ßõÍ[m1-Âyá#ÛúÄ#ByÕl½£ó:¯Œ¸¿tH®tx6à�Ë…ƒG<>y–Àý÷I£nï®ô«‹­©k~(y‚üÚ‰x0Ü÷re݃¬¸ǽlðÐ)VRpãKK»Í*ž÷M#€wé?Wo=Ö`ÜùÉ8ÑÐÚ¸,“¡åå6(™ŽµÊðüBIÿOÞs#ä—ù¡r<ž~R´µÜrèó ƒ;Fÿ\ðGÿwÉ­¯|­==ó:仆k¡)%BL^€P@G.°g£\Ë{(p^Lq9޻զx/§ÓÔúm“ æ-.JE”Ü>ÿÛÝÉ›Õ=[<™ú^9yB¾*�“î]JÔçÕ{æ‡6Ýa  }O ¿5Þ�:<÷YÔÑ釓RÆWÚ4‚úcòòF<˜ìa¦À9¤Ê|Fà¼Fâþò«=âò*¸ŠL›Ìyø�݉H:›p> G^^à ¸ñÖo<ëSm´p)vÜHS�w¾² ¼çÖnQÛ±\dÈ·]”4oUB`[Ïú7…;zàÉË l� Þ⮄û~‚å¼.½Ó§Ìsy:Ù>xOá[g‹¥p-‹>Þ±²%)éÉ•åÂŽ+o?b×!žÄš�uç�¼¦LE8éŠÙÛ”½±ŸQl!ÿk±²b�§4Ïý¸\xžH^a=ä׋4f6Žó:¼ß('Î};ÜÊÊ�¯Ý’c…h]ƒ�ñÛÆá…ï O“ÉáøŸû{tS.ÁùrŒÎ øIÕÀ �ý¨ÜØÉfÑ‚U¢•Fj¶ê=:TxšL^€p#„Ê�“ÏÝ £E\×üî>¤rÊvõVE›| ^Úd�èîŠy'b“„וãdRyÂ~‹ÜPÙµÕ’‹e=ßèšÇ]?@‰8 L84WÉÛΈo”¶ö>ÑS�3ºw â,¹¼aŸœÀvÔ¶ñË8oT\ \ê"ŒÈŠ0 FüÜñì‘�g¢ÿ•¡:oJ䕨þ­Ð’Œó]óèˆûK©Ò£ Wé5‰øÊM['×\ù§Ä„ U&/@¸A²¸]¸Wö )ç¥).Ç-°+Ø e¥DQÌ-%9Š£¥ŒÍFÔI¥òòÛÄgÓì«R ] ‘IGW\Ž«W�G^q�ø¹ík´oD"W:ú‘ÓÌÊå�,êÁŽÔçć¢i Êâò‚äå;;z$*Öî’˜ã ?hþÔI5òJy°%åËu^ƒk)õŒ©<y’[ÿã'÷J̲ö‰<Û0߃:©N^ �SÜ÷´ó²—ã¸rò®Ã©e¬ýèŽ|„v>þ9úRr^Z­¼¢›ŠÍtEN•1—ãVÔ¿e‚T$Cª£ÙŒ•_šþ‹<§^^>s%°#qt€JÀg&.ǽÒHü–×fHœ<*5Ò9ÉçÓm;�~p©ÈÉr8Áq~tW�¢¼^K’Àöæ$ßw“œ—¹¸Çy‘k�âÜî°<7Íü €a¢ÈÉÕa€Ã\~]Qˆª¼nS²}ýÒ¨�Ή£�tˆËqFÄÔ¶$ÅÚê7Åά ÖŠNq¶ßÖXû(wA½FY^¯Õÿ,Gý�–L:�#âr\åbÒw\ÐQâd…T!¯òë8îêFôsšº¼kó’œ&2Ú)´x.Ï~ªa¨Ò³Ê>7$„Þ¤��¼KlÙÇÁOÖ½sÞty.y ¹$‡¤¼×Ó�»p”# Y2‘—÷àÈìnõ"ŽëdÇÄ Œ¥Îí®à&š›.H Š;;8®”ŸöC¥|0’—÷`[Ô}§Ö¦[\î"> sÅ î‘Xí‚ãªùÉÔz3yÜV+ýñ^{ªíé—ã†ó¿ ź‡R’£¾ç¸­ü(U톡¼n>××w"ÍârÜ…´½·T"cïÝ©×õpø8r ÃTÞ(‡¬Ì¨äfKÓú )^o³D1�õ|�ègÐfé�wuª“Î Ÿ‘”b£øRf++ÿ çCŸe*o£?à8}lͭݰ˜SMõrë‘KîˆÔ8-2ÊPÞF¿1ìW²NUM·À ÑÓ¯J‘#)Š˜¹'„>ËLÞ€_pf×ÛÞ ©J³/—Z9#ç;Ñý#Ú#C¥[šÐ§É+Ḉã–áÿg¬=žN�W—Q½œxߤhŠø�0ºŠy›KCTÀ¯¤FGmà¨?‘>�K芋ÅÊ´> 0éD$3�7hN]sD¦ËNÆþôêÊŸ¦^å)�¯Ä*è¾ VìB/vR—7Я¹QóaÄÄU-!«�¦4 L>!)ÉAÊO”¾¦Ø€)?œšÑ…²¼ â6;ï/ß}B©´ éd:6‘N§KóåDäáÇ&5ÿ×?ù ªò&‰ µÍKÛW%E\ÓáÁ¤‹A2 ¯ÚolY¿´¢k$Q”ןRÈÄ�[Y^•t"haíÁ­šHKZJóùsˆƒ�¶-n K«D™¡&¯ÏŸR種%‹¼05c‹µÀ}©I×êøäOÂcêŠ:B;� ßHI^�¸®„ «o;rÍ,&#‘f¦`™ý¢9º¤ ×…VäéA!òYêg&ZA$²ôà)äAP’|ôZòßWϰ|œœ¯ýJcÔ)ÈÛàGeú’úÙ+P;±¸XGõr]v•$¬#÷}µT?튔—<`G¤]Q�·Ax[àÑÍN2ÓÞËJàTmíÊvçs\þ%CǼõƒ¾vî½Â´Äkm¨§ŸZyÄêʹR‰+E‚ÓCÝ´<ŸhH˜î „Ê«ìMú=Ëß~Iß1€ 2S%oƒ_¬f–1uŸ�þ¢Ù† îéz…æåzô·õ’ÞñÔvuT…¼>‰ºÊNÁw¼J¼†u�ÿ`P·b*o–“¦”4 äW,oƒ_bK2£°²A©j”žçHÿò^QªŠ„Byü’[»S¬ü”´dõOªW(ITÉ„ÃÓGÉÛà;%™”iþai€L±��•–À+JzUÉu•¨> äu{ŽËTßB9/Çý[®X -�ÇV”²­Ž¶ &ĉX^�ç`Pæ%"�ðƒäw8 ÚNSxÕ6ETrdí ƒ„òzÜûäËš¹E,k1JA„]îíS¶B_�6ö#Èc¾øòGáA2yqjÊ›Äúôƒ±6ètk‰¯|ËrÏ.…Å^Ô1vµM”I$oÈîÅx•³§X ~ÀÒ×Z âñÕg¥Ê߬œ^õ‹„ƒly›šx;›ˆ¶`V³°ê+Ë߃ϳ¤´Ð–:t� n˜òº}Ø»�‰;/ÇmÀªqôÔÖV(ðÓë—‰SÇ¿þV+(�…%¯×‡¿u©Q¬ÔÏu»ˆëŽ(x¿ÝÛãeôy¾òÔòÔcòz|${F;%SY$©öéÐ)øK�n„6=ÝÂ/+¯ÇGT´Ôð¥dHÜ—÷ßO(ðZwÍ»äÒP¡,©…2òŠ à¼Jº  ¯4 šýêë-Îö,˜iw�äC’òzp:b‰èåöw¸‘xÇ€‰Dà5.pª”¨àîzp-K>$!¯ËK*.€ój¹6l"ß$h=ˆ+ð N°®T¨ŽjÚzÜÉ%°Dåu+tò¡]äîË�ÍxçíóA:`)üË �’¢@EäU$.ÞF×[m ´àüŒ…Ú¶ JxD`Nº!åU(n<^’¡ wÐ Éß"ºÛü2[°¤-ï9®Äû#B^—« 2;Ö.í[•^^Nà‚mÎ_†{6]QÌ7._eBL„@^—G駇úeR¦ã S¾ËwØ.%ðt~¾Þ“™![”‡øBŽŽu-]õy]e·…6‰2�‰”*þBQ�Gów›heñtÐ62¾µ}×7I^�×§üƒƒökÌFÜ„?ƒ� ì:„x„“_¢ª’(´™";ò�#^L5A^�—l•TìØe�w¨p_1�ïrDm™Ýg{@tzÆùU¬qy=^¼é\QjÓE¢Ü¬üîØ™*ðdW¤Î—a¦˜Í4ñsTE×ñè´lL^¯sOql5¹wª¸Ã£î¸(ö…Ù¤ª¦ƒ‰±PP¿ëÛ6Ëëñ)Ùú.™SÅÆ›ù­ª»o”°«,&pÞ“æX_º!uC¯´sn|AÆhx³;/¯Oå]!ŠE¼°;‚]ªÝ—Ç{ô~Žëö—Úø—•Áq33Z‚‘tÞÓ%¹¨Àïþé/¿TË”UMP÷ôÅÔͧ�7pý×·Ÿ�õñ¸î[w²Æå²�7,xÏ7ãï/¨Ás_MY6$¨(â9+Φ¡ŒILÌD,÷­ÝÕ‰…ñôðG+ÆÂ­Q|[Y5`¹¯fc{&ÆÓÄÝ6Ùàçå¸?ʺoX³8¦ ¥¸V'ý`¸—‘éVZ÷mÔOͶP=b®(—žÿõföŸ–v_—m,+Ëi¤ó¦jIçUQw[†VZ©ž‹ÑDo†9“LµŠO 9Ù9/ÇM–èykKÔ]Î-î·Š®×g°Ъ^Ì}Cúe9ÝeHæšSbág§™>\žy®:lϰ4›v:,2 ƒgBlë„uF¯ZÔ�Qœ}”­> stream xœå�ÛnÛF†ïõ{] ôÈ% lË2z‘I ´·�›(š¤I �_P²#ÑÕGÍ,W¤Ò:@ kÌ�ÙÙÃü;‡eáC»þ1ÖXóc±ókÝzsÿañyÑQ|UY|‹¦®Ì—·‹_~0Ÿ¡p¾Z?»ýtÿaáL÷ïÕ­Ù|øò~qvÌû¿g?úøúáË×ûs~~öâú§¥±æââjy½fÓ¸hœ­bÇáÝâåâå.{oÛ¢“­9Ì¿ˆ®�f÷ÿW·æß_n庺[œ½þóÍÇóó³Ëû‡¯oþ¸{û÷ƒ9_ݬVÞúå…¹¸0��g«Ò8oîÞ-ÜFcÎÄÚÑ·µñ­¹û°8·Ö–æî÷ÅÍ‹M§î~3çֆ͗uQÙª©Úò¡¬¬-¯¬-Ûõ ˆqýMŒ>“›»1ò×Öuél8ЭuåL2º¦ð¶j)¹ Ö–—3É|áÚÆF‰ë2>[òUi×^ݚ͇”ÙïJãBüf“è/ƒÂu_Ö¦ Eè~â“Ü>-T�Ë¡mcSºírð�%n€ðÈø¸MÑ~¥f^k ,•%Â5>Aâbîˆw™·Zí²Jp<.µMa™ù•z2ìöÜG¿e¾;áªXï_8;„€MõÄíñ¸B¯©]ænäÑ[8=Âu°&BIM­$ÌQÜl ÔÞŸÔ2•`?HížÔÞcÞkj)aÞkê’ÐTð�vÂ1áR2´M½eP‰4á¦(JÕì—ŠÇ#xɼÚmŠ'MÑ‘k°G°$6EãÑëGOW p„�Uã9 ²qäcL#ÛÌGZ+‚Glu3šJÄfdÀõ�3�Œž„ŒAÓ;až �Ìw�¢ˆOªIpÃNµsÅjsOÊàAгÔ“\_£ÁKOX(.b¾I>…?0cº)'2&Áª·[™Ãsœ=Ix‚ænÆHìiFÆ9P‰RE"èsDÕ Üó•°NR�,ºRæHÉ\x¤NzÈy-N¬¸UGøçÍuUC…=}: Thm}*¸ Š*ô3g*™º yÈZë2ª„*Ú| c®¯Æž«3NÌ´Gò-ÚñЃ:Òo¥hN’>(Ú eˆ@»AÏ\Ë"ò‡â]"—dJŒ—ú1r–ˆ¼‚#3uEÞÍ‘™º"3²¶g¢(9SvGážäÌti´~0E1¡ÌP�-¤/3äê½9Ö{ì2žÜ‘�­&çh'÷qcÎã�xæÂ]6“�âÔBÙ…J²D0J#¹ŸŽ,°Ìx ¦ÞË¡®3–¹&Dyk²ä¿É#úòqÌñž_4ù•¾jgÜíÃ2¿ƒxh*Á­&ÊÒ…½yE�Tý\§= íÁN9˜@Ÿ€ÔOà Û9£Ûèua„¢ÏñËgòO3(Ç8V�G89*E°#ʬ’×#E<þ3 èß@qÕ÷¿Ïzw™ž‡úZ:á-z“ûif ·¤¤ÙQž¼þFwº°"Þ1Ÿ°5«¯jJHYÈxĬïiÁ~äs|ä¼=B]F¨¾ê%¡6BuK¸ôOäÿ“Ó2¾ M%̓Z\½;7A}¹ßcª®HdŸ–:ã…˜'\!Ä»üÓ[ׂm¿½�pÂ÷®Õd9‚m ë}팳Þm¡Ì(Üj±qM¹×º>#\!`SK"àž�+ ìLÞgâ6Dˆê'H%ÈÜRS¬v$ ®j"Xµ¸4‚LP¼é­5ïbáËî}Ÿ¾Y/§è‹ªûÓͧ�u}Qv #nÅö×m­-¢¯WãÙ¯Þšå§GîÎ>qmë¢2eŠº2Á®W¶�;Ü+[eÓ¹ƒÖÜŸþ$t Ò¾ª|eœµ\h·ø Kç붨[ƒqíºãñY÷¿Þô}ýñéѶô…o]<ĶÜéxãCQ†º2ÞÙºh]ìò�ÂãlT²eýDyÔ{G.ÛÒlÛ¨C,léêƒø' º9ð±ù¢” endstream endobj 153 0 obj <> /StructParent 100014>> endobj 154 0 obj <> /StructParent 100015>> endobj 155 0 obj <> stream xœí][o7~ׯàs�¥yxxŒvlûÐÒè¾Ù6À¢I7i ìÏ_Œ$kfl}CžÑh¬Ñª-E§ÃÃsá¹|äPÚr^ÿ£Œ2êoºóט­úøyõuÕP¬÷F±ÍA§èÕ·_W?ÿ ¾¬¾®X“õëgÛO?¯H5ÿþôNm>|û´ºzÇêÓŸ««üñåÃ÷o}ü®®¯¯~|û÷;eÔ›7·wo×lEƇ†Ão«÷«÷ãØë­WÝ?z§^~ÙN+DM�ØQQû1$RŽÌÜs±Ž5±ñ¤r~šŠ%«½I¤h¿j¬Éºù?SÅ|å º6óyñe;ŸÛÇÕÕ‡ÿüòåúúêæã÷¿~ùýñ×ÿ~W×÷ÖØ»7êÍÕØïêÁ)²êñ·mœ‰Tˆ¤ƒmæŸÕãçÕµ1ƽQ�ÿ^Ýÿ¸±÷ã¿Ôµ1¼ù2jo|òÙíÎãn�qyý? Lãín}&÷�‡Ì?Òёႌ!ÿJs¤¤­ñ©¤dÏÆ¸›Wš#[M9™P£ÇxÀG¯R³þðÓ;µù°ö~ʛРrð:cH}^YŸ;ÿ}õA¾LÈ)bÍvhûëåiÁgÖÜüžÔEûÔ•¶ë&ç�µëÆ@Øó’@÷ˆðñÈRÖŠy< K%o, œîtÌ1'Õ®…CÝH%·È}FØÊg%vFîS§vì~æ=Bw(b™@`(Ìnó;@À<Ьz¾[% æaM·çW=æ·5Ó­Òn�Go¨û»†Véªn(±Ím;\•3¤,§Û%°{ b>¥hV˜‡C2z Š9§æ^@®R & Cm£OUyù‰+š’‡š¢;†ÿÞ¨ØÁùMž\å%ʺXy¿ä 2–jWì¬{øm�U[µù¯iwŸ>û$r‼¸íÙ;^Ì{;œ­¨lc >ì·w€Ÿp ü=q‹n< ÄüÄCÝ ä$ùýtºrˆ�!!CA=ÚÃ!/qH%p(Õ�ÁJV#ÐÂv5¾ì·§H&.°ì]1™Àp‡#'Œƒ0 ,ƒãàt½æ�ò”B°‘xÑP#2™¼7úò3—ó¸Ÿ.)N\Á±\tH9rŒ ÖÿACA÷f´â±-¡OÂõ+¯® ³9xP7!ì&f>åÚšÁ“;\•U]·Ex"憸 ›éñˆˆ€Úq»aRXíY¬vpA˜C½xQ©*ä«ë™v:H Ê�-X¥ö:TªËü0Äh;ÝImBˆj½ó£tZwªýoDu2LÙÎ6»Î¡”±a¨Ây VxfÈ�# RÖ¦«¾ŽÓuê1—FYWž‚G`Wr õ: [18Ô„8ŸdÑ0Š×N]UrXáŒíÅËðÄš &ÒÙxJÅEWhë&±> ©PÏ�€†Âp<ìC‡OjLÖX#õQØæÀ”IN‘³:Úõ �µ)x›}v'DÚóRÞZí›óUi}„l"mkŽu¢¤4y›•ÙØí1ªg_Ž9FE ~µßÍ¢ÛÅö‡pfã�N„µ£{ ¸î g¥çâÞùF˜êÒÖžÈù\RˆÃèPSe†0D™˜,Çs14 ‘ìéPX‰p(( $ÈÕ.֋Џ‚¯s2NuÿlÜýÅ—B�Ïp§)8­ó¶äðyB*T½�²D«�·\ŒfÐÂxûº—/,ñ½�K1Š×hÁé—èÂì³Î)ÄP2;܉Jéä}»ÍÔÖø—B"¡· ̾) ö/Ëæœ– %§‰bNû=ªu–íü)¯ÊIÇÈ‘J²`CŠ‹—›ÞÚ¤Mò‚ɲ’>{íˆ�+šþ½ŽêÂÕ ì$�+³Ñ!6ãÌÎH�Þ�¼o³·:ø”‹amƃJKŒwœ²¶9Y[Òã¶Bœ´ˆ&(Íkßçl·¸Åó/…¾÷`œa�=g_’ñe:\÷‰Ï|Aï*5Ý“h~}«} ©˜#å•Ã0Mƈs>V³d„.&–N÷Umâ5$NÎ#†‚^ Ðá`‘c:|:¢¼ÇoøÕÚqG¯ÔŽã0"ÚÌ:©LMdDŸ­ß¯Øãt¥óí/X¯]öÍ�ñÌ„U>:)�3—<« _įÀгà¾ÚM†|*Y¾q°à4%�¼�6)aXyŠ÷‰Ä‰ g#qQ†4\‰ÓUkò�o¶��\>+y]_‘oLÊ7qåôvȾoÕ°[ õ.™¼ß´=„µ×Ì�P'åáŽm¬£œ2VD”4…H X4,þˆJ—õ”yl^7¢`5±ãäŠ~4Tv,wiw B^`ósªPwG$ f_Ô–8ÏÒƒW 9¨�ÿûö~—¤öÚ¬ãSî6¼B{_�äýI¡‘^¤;x§“ žrI_ ؈îÔ aW€Íì»Ã3ƈc�NØ!Bc}bÆ»–è,ÖmBŠ 8‹­Ý¶±e—'FÖPñ «H�™@G•7 ¨V—ߢ‚û´DGìœÊ1EĘâ ¢'°€bOœ%Bo¯Â-{ÈZ÷‰.€Ö°K`ôFïr ¡7”©aÞêàP€°]j“@‡ÓápFûÌ6—âæ”ëT|È@îø¸eD<ðt!*¡PH¸],ä×I°aøÅ‘3GŽKâÃ\3áYʹ» g4yS,IwúF» uÁ”òýÃåžÿ¤t̆lI+K€vÀ}ÉÂàþ,�û‚ÙñKn¢÷å ÂÇõ/�XË^i fs·Ì‹/…>o¡ð)èØü\IAö[ÑÝ9§eßì´a_^ÖËÚ˜Ió¼«xÄ�™c ÛM çŽö.ÑåÉEíšùð~?9ÎYÏÐÿaa.yù¬òr‹?›ýfÂûP޵Yá£æBمϰìXCNxmõÜG›ÚÓõÎ î–ȯS�ï‚-xqw2TA_ËÊP%ã_2Ô9q›¡ f_T†*¹ðYg¨‚ðo§tÖ™;ý˜¥•Ô’[ý'4£´Ï£ÐàÁ­·Ònû Llu²¶9R�~ xs»?Ræ‚jlʬ¬]°eÏ_Àéµvßd¬é/÷�lî[2:úÈTÒ#þµ«)OèÍ› lsy®3¹(ü¥ç|Vå->~tª¹Kü8äþ" ÚPö¡¤Çó¸áÒù=;`—]£Wy iòšN‚ß@‚üpÚ‚ÂëbQd§–å_~koª,¿Èwß:eÞ°t–ycO²/ÒÚ2oX] €:e^aU_‚¦š3I‡L±¸RPáw*ÓaY.ï·�t–ÝåöOù~Ûñ+üx9v"þô¨Ë¥Â_áï[K­ð‡e9ó Xø¥WøÃÒ]*ügþ°º¦¬ðçÆöÛÊXÆ ¶ÿ¬òŸ/>¿ò–åRù\ù+xÒ›-f>'Ò9)‘GèZð9‘ömÍ‚ô �ºÇK‡…¹ì)¼ºçu Õa[Ír áø‡E ±åÒ¿¶C²eÍ.º¢­fÙáž; ¶yÀÓà½ñ#~È^Ý#¶‹lZwØJAµ&M–|f¹ dkþ zœ´›5>¥fáù¨4;Ok_|)Lå% "ÞÀ ´¦{ៈZäOcKéé~|äuÜ (¾DÇjño7Ë­Ú_d+­Ï%m…5åÄe+lΡÏqç¡ó–Æ^‡ZøÖCçEÜ‚xË8ù¦D!Ó.ÒOv·Gô¸Ä)“vÎ'_’å8½ºßµXL)<‰/�WÚmìd¹àJ¯îwÌIÃT´Õ‚7QÚÛK}Þ„=ôhÔ­S2ô FøÛòsü,ÃûÕûÕ×õ4­÷F±ÍA§èÕ·_W?ÿ ¾¬¾®X“õkyÛO?WïX}úS¤W¤ÖŸ:›`X33ïz5Ú»=é6ç�¹ÁÞ |‚!ñP ôV:dÎv:9Ќ䰷ҡè~2ÉmÛ|Bæp(¹ÍÅJ„Ìë\Ô»_W>ÄýCu =»Cõì>Áp(†ê1ïØ#9 âq‡7RæP‰Pr›ÁÖÈÑ#À¡j,ØêVê ÖÕX¥«žïÖ9Üýt¾ëj´{˜3ÀõÑ3mŠ<¨JòîP½˜Ø{Ð2�«N··> 3ôä�G†ÂŠª¬•€mFTŒ•�µC5 ‰kþódCázfÝ;DBæìQÊ'�*ጠö@WŒäxMj v‘i',WG”’òÚ zIóÞŠ¯J®uy¦ã;@Àµ@„ã)L•5rð±d^'9ä (9¬aâ«*v` ÖÕ.Ã^e¨†ª*Ô{YMñpº(r¸^@î0gdó~x=¬Q7ÁZ9" ½.ºÇV¥Èæ,º~r֚ƙ¡šÆÂ„QÈ Q÷äˆö )íƒkŽü˜œ¶ç€úßMt (gM)rà®JôšÓA»ÐQˆ½N6„L%OÁp *xH$ýéx …¨9Jž²´Méã¸�%«�7– „›9ô‹QKX2ÃŽËIyà•¥FÌa!/n¬ŒA "V"ê1 ›Ø ŠÃ‰­„áp"òûÔ?®fœæèœU��ŽÔ$Ù§ßVœNÇœ³{Q]UIóüá# ŽXçèXèç†Í¸-{"xÖÙ'_ÒÁâƒ�8ÆÀ¡p‡�xˆ7'œAá â@#¦;¶ð”ÄÊé5–C “Œ˜•Ø´8£<ñdVc§ƒñip5Ng}†éMºñ7AÊáAhd9ì w6¡#8r‰7I1ú=¬Ph~]ð†È\|ˆ .ÊCXí°Á:p©º.ÁÍ,’|‡VŒ±2Ä ¥˜Þ,/_ëÎ À ~ùFlÏPW‡xô�Þ^· \uvnöÖ!�h`¬Î áŸr%2-#9¦ß®Ÿc�NêT21 žG”¿X¸Qå„Q#2N{“ØPW-{�Çp˜»ëçÑë�À“FT°Ð°×“×qRüaŒvOsk¥ \‚ ª Æ÷ºm÷º#_0I¢'ðP§|þO�§ö;a'íÀÒŽ¥@‹»C¸Lå \¨“¶¢ @Àª9öm³xNF³5fèü;oO9œ ¼s£™˜TN^ûœó ¤BЬb€D1#¥¢0GJЉö2ChjLfVz[zö¾•XLø¥ÐÐöÑÖY]ž’JØç$Úzz†MÞ¾ÓÜý2Û 1ð=£æÒGcmlJYK:3³|#¦õ¹DÉííŸn�áPwˆŸ°ˆÀˆð�¥þlº ‚ø ¤ÈÜ ¡°Ú!ê*"‚OY„G�öNäÐWÏjBÚÕ;ÊÍâ Ž1i¯>¯"çíçßWV”œÊ)®)–ÂösCÙLÌRÐÖ5a̦5÷ææ�F†Í§Î4ƒÕ®Y±a³ZÛ¿¶Cd£ƒõƒaâêŸÖ¨»?ÖÜ ýaß; endstream endobj 157 0 obj <> stream xœí�Ýo7’Àßç¯èçŽæ÷`�,ɸ‡= Y{¯ _6Àá’½x³Àýù‡‘di:š_“ÕÃé™O‚ŠÊM²ŠÅªb}QYWÿô ‡S;ÿ›Š¾ü²ùm³…Øôàl‰*§0|ýió×? ¿n~Û8elxüöõ§/¿l̰ý÷ÇOÃÓ_Þ¼û䆟ÿ¹y÷ÿøõ/¿ýח߇÷ïßýùã¿ß zøðáöîãã4ÙÄÁè·3ü}óÃæ‡yÓ«’lvÿüñÓðö—¯ËŠI™-Úið9(«µ6CÌfZï]ŠÕEmÿ~nXK4%»n×òæ—¯k¹ý¼y÷—ÿýÛ¯ïß¿»ùòû¿þö?Ÿú¿ß‡÷÷VÛ»ÇÖ^ïü`ìðùïó´yfˆÉ¨hKl>ÿ²y¯µö†Ïÿ½¹ÿó}?ÿ×ð^k÷ôˤ‚9ÿðAk«µ/�ab_–1žäþó!ëOÚ¨ä�vLÜþw¢5𬬹Fäà´ö7'Z£³Ê”¬c ÓkœBí#ëûhÓ ŒqéñT¼ùåœSaÜ`²Šñ'ãÛ7Ú©”cŒéeÌ>ʯúñ<üøixúáëÏ’så㔳Oö.§'OU~V<¥Äì�ÿ#aöàðP¦EA~yD[îæ¤¡˜Vâ/rÆ9L0“G¡äùp–žèðco#†ˆWå/î¹*NÆÃä/ÜAòb·¥¤µá!åÝCs ›âº˜ðÇ)w0cŽ“ûýC�£ mIÀU-g«Éxgmvz2Q®cÑR¹k+ymT®b5ÆISâÜx̰æÄxà~ÌÈUÃ/hN­“s‰<Èßo?XåS¸°cPY®Æf¤C£~£ q¶Í0%M¬C1|�þÕš“ÛÊ·hª-Ô4;«cùùÀÉÉ6CcGž¬À æ¤âªÄ)FäR õ8¦‹�J”ÃëÿD²‘¼B¤åUo3<"r�(-‡›‘Tˆ¶™Ü¦Á"=¹‡myÅ&ðÕŒòDy îy›Ýt˜›Qï×T~…×ÿÑäb*οšÀÅ&ÚfdʉÈz‰ˆµ ME“ÎѱzhJÒrg¨üÝó1R®r|8Ì�ÇÒÁ&cÓP3ü˜r¿Y!<è–p`Ãh޳Mþw.OºcÄ1›ŽŽV|ôÅIÓÓg47@[­9Âc†Mƒ>iUÀ7?«€½÷ô8ì�&#¨‰C4 gÜ-!fD)/–ùb‡ßõ`Ÿâ`/bNØÍ ÉÔ]ÄK'·Ì‘VMÝ>ÚHW�®±1ô³Š}Ò«ˆåÞßW52§1b‡40ïÒr9«¼©GS“•Ãb•r;{´{.Dçhgçéþ Ø´ õ‚\ü/ 0äqFS\®<Óé°jÏc]VÄW¨ŽMy·œ\ n«×=Ðc#¶Pä×–*K&»T”NÛFÄ;ÒG”�¹éßS :‹wï²r1'SïµÞ:gssöÑ*Š ó1êwïÒbA?#ÑAuÌÓ‘§.õK•îèeX0=êlÄNkw=Ù&eF³¤:Ÿ:véÇz3"�Rõ\#š‡Ù1:qo»žnÚ%í[Š2:ûÝ#x5cú™1.dåµvUׯCàŒ;ƒØ¥º`$êlÔÕ«ý6½—œ¬$/0šÑ»I$›Ñ?C�‰U¢Ìçdÿ�üŸAD±m5CÇ ßÓä3œâ¾lò Ãý#‡¥'îq1Ç@5Ó¡üŽaå‡Nîb”s.WÌ3J#åÔÅH²¸"�Æ�?.ЯTá´]™»­´e½a:6³‡ ÏDúy+©Ulc&×qð¸–CT&o)‡˜Ó|ywé÷0~w`’"~3š/‹KyÄáß ¾j J�˜A|i_ªÂ;?ﵦS*%yƒî!.)ìù¾Óýéé»@ƒgº¿ÍY•üM‡&NÄL�¦DwÍ,Ò0‘+ å�çÈ�„%Š4Ƴ!‚é÷H«& ¥)™ââri¢Ý ݳØ]7N§ÓôëŒÔÓi"Vcâ4äŽ÷Ð9;ñ5 u¨üÕy8M®Ifx·Ä¯CòÖ©ûÒai–øà…¼ �¯òêû¦BeL=hU3𧳨|z"ùõÁpLT6 ÖØüø"² Ѫ¦'““ŽƒrÁ–A¹bíÓ“Éüå¬'“ƒ!‰�ü7‰t˜ŠÝÝRAM‘8�‘8y�gì[Œ ÒŽÖìTXhU·4ù õOÄÉ_œEÍPn…‹Ca�•¾È‚äk!Seåµ+ƒÊ®<3ýè7 jn`uëfu-G¦Â¦œŽÛ¸Kòä³7¼Ïö¹¬ý°ûçvßüR¸‰{®ú¤üv=®¶‹¥cççÅxÔ¯²ŽÁ”*“^{%Ÿ$Ãca~·A+sª ­žì~PKÐŒKR®Äèk¸ÈYßCAN __Þ5)ªT´±µM\§úÎ^“J®²èÊ´7ø"�jó¢q¹ëåö× ð‚Ü~ì p•«òn¼Wè¸�ön­Áë\|ãt„B\|ÇeèX«¤EK”>Šsšœy^î9;!Ѱ@]ÂâEêÊý˸ƒÃŽ$5w8>Oû Ï’SpU7xFȃ_“òkæ;é•ííV^Ìœ}5Ö§±“߸ּé%«”\2Õ=÷g/ž^óük;|ñ�¬—¾¼ÔV(ùL¾¡B°UÝ2¦©"o0;¼FîÚ¹eLÓ1w¼\‰%œÓ*¦íe¤‚KÀH´{ЊùžŠ½\ò*zë«æ+)Yœw$¼I)§üTÈu‰U(¯VJ¶½ÃÌ(¼HÐËÝ•3¼`Ýs"»8‰º¨~:¾ Õ3Ò[)Oé"jˆ}0 ˜¹ ¼ÿ‹ÝÇma‰Q„½«–Ð%,�Îái±û˜£âé-Ó´:£H¯OªXc|M ^c=¤y¿šë±2ìB/&"Ë›~DŽ–Ì1×ö8®7@²*qÿ«¶,³¦T=4c>œxw€¶¡F6T ¡Ä&æ×1÷D+\.Ú´8T$Ú›d ¢yÌö&ZÚbå6íè¨!89¦]´aNy›H]fQDp÷ š’…|u ‹"­¬ %ÃÊSTrì\¯~ ?� üTÙÅ•‡Ÿj> stream xœí][oÜÆ~ß_ÁçÍý$K2ú�N¤¯�ë(j§v ?¿à®´ÆûñðÐCîÍä-9ç̹ßFh“öÿ5²‘ÍßDöÏ�tóöÃîÓ®]ÑÎÉÆèäE ®ùün÷ËÍÇݧ�J»ýw»ßÞ~Ø©¦ýÿ§×Íá—ÏïwW¯Móþ�ÝÕ?~ÿøó—ϾýÒ\__ýøêï÷�lnnîî_í_•o”t¾}Ão»7»7Ó^/RЮÉþôºùúÃn[>Õ‚šì·¨š(Ÿ·Ò}ƒZJ©ö`ôÉ­j™DûçqÄ^½J¾É¶{ýêÃn¯wO»«ŸÿûëÇëë«Û·_þüõ?Oïþ÷¥¹~|x|ÔRßß477M‹Ï«GÛ(Ý<ý¶S‡ÃU�Jx�B£Sóôaw-¥´7ÍÓ¿w?ðÿô¯æZJsø0']tɬ“ÒÞIiÓþ¶ñê¸�þKž¾eÿA*¬’†@y)U8ÓUZºH!Ù)íí™öh´P©%î™ñx`‹Ž²ß”Ž{6ÐNE1Š©u#¬4©Ñ$½ç’þ'SXDÙØ(#Œ>H½I1Šè\б‰áIæ’ä3·¢w¾c£W`ÁYô�{°`Ñ;¤Gß0ÜG™ô ?žNìÐä!L”¶É¶çøÕ‡Ÿß³Î0¡3T^ e¬‰–8ÄôXÆ„Z„B•OÂz­E¡ �ì-"«€HQ�½C èQr"DÈPö‘Kì ²B Üî³2äìê¡Z†ÒÉ i\¢„bI~’û—ÿôº9üÂÅIŠ‘Jo¢!@Árò$y†.½°ƒ7F œN¶nRž IØ }#L»a’~²ý�I)ж”6CÀßAyŠÄÍ‚ú›±+h‡` _ΖòpW©1¼+¾î�2Šô håA-[O[tPø�| äš-ÿØG›ÐË{»rÒœFI”éô®z èQ ,Ü> G=‚…€ùB�D{�RhWphˆí2Doþ¾¾è-"P­ "i¥,%P!Q®ÅÅ" ÔTâ‘ø!•¸W*6BíõµOR?¾þò!Ó€ #”¸UC47Y _²±«TÊ• ~qQ#µ(gE”Þ©Dâ‹ð /š*‚!I¥) 7hïüJ/”TŽ!1ÖM’F8¥¬K�ri¼-è8t´R('C "ëŒ:Ú l»C�§Pdl ‡ )Tãl/k‚·ÈG Û¦¬9¼è­Ú:½$ç̤\uÐB:mH)p©×ÂÆc8–@×BÆ3hݰå+%ÞÌ�>Ä:5~´B©�"I¢|תï‚é6ø(+BÛ…™²hj$êL�-GÔ³)ãÔ"G; –M”q>© (t­W'·)ã:‰7SÆÃ‡X»2&H´ 2†n9ôAùIC¨×á7øYj—®‘Ú3ͶµÏ¥¥£AFE�²)é½’V^H•œ§Ðµîšmcñk©ÉÁ² ¦�Ùb¿œí)ÁH.´ƒ0‹Âw@•Á.@Á‚ƒýòõí죅5R%+r½;®&V¦Àš‹z” °&ÒÀ¢#�Få üJ \“³˜í™ ]»e¿ÁCÑNØäÚF7‘uº(F‹¨u«î ð”ùP´³õÊ„R¾îbç-ù¥�^Žâ„ £»�¡+Î[Û"äçÙû"X¶¢ ~c�®u…J3SÀoiËJi7k�$N±N;äØIÑ(¿A’MXØg› *ã" 4C*Vø/‘Êùf® kg» òéû½¾×F,)2Ñ÷E@êt¹‘¥ûùŽ¿ë† 2†8tHTM®+5V$p¸€nä‡~—èºTHc«œD{>ÔbØCI/jÉîBº¨ˆ¢ÑƒiœÍ�¸\•˜¹Ä)VîFP4ZnÎÊúµÇ9¨Š�.:· «Íi|©2$`Ù<�C¤1 )� ºÖ]ïaÜ Û5ÁG�b‚ßÅÅNñc©†Þ1a®¬ÞàȶíKÖ”Á5ëA$ÜwÀ¯)ù¶Ú9NÕCΜ(Ø8÷˜†kW>&‚¿ “AÅó#2—ˆ@dÍó#޵è�›·�´+#¬N–¤‰’ó#f:ú`_b›t"fŒ^p°AŸ_ OmÂ3ꑃØàhI~£?ýÅ÷ØÑ®naH  Ò¸FþÊÄÑ)šÌ$uñü¥’Öºè(XªSÄ Ë\…ŒN9•ÑbÓ’3ÏæJáZ-‚•­Õ6 ä„£'h‚ïUIE/é~¿UÆ·»:…l²ËTŠÛŒï‰qƘ„NQë%©}®sòÂkO2î¦EIÂ#´w–Äc,˜Åœ‰$ºá³”²ÜœÖ]!m´'í§E’ç Z=<ÂkåÁ@ ü íÇ>ÛÌX _5ÇüŽÓ5 7ñÙŸK «ìÌØEs³ÙØkK'g·fü¼q¬X0?Ê/·ãW–òG”ÝŠï"€eÆl´W^ÎHÀr©.þÙÜß ¾¿‰�£L@_A+Iv�u”[/Iïök]4Ÿw·_SG¿éðAMhœ°ÊHKÒ¾é‚0É{È�X†‰åhjx\¤Ë¼�B”B9bh‚¾õ¢`ÿè\B1ÓîÃÀ`½ýcDè°ú§á¡Y9µ|­FC´ó¨‰³Âñ~Üåý2YM�ð› U~ täOè7*8aq3¥ó[ã "­À’¶ÒˆäLr,k’mU^&Ƀ¬àÚzc„öÎÒ …- 0 Ãb.æâ=xmÇ1µÚ–s8òxía ÿåõ^Èá•oIÒú¹wa\l Sæl¹í¢®oðZ�?œ)\PgÏâòšÍk¤¢,ö7ŠŠ.™Xºª&ŠX¶߸Ì(�Ç5Î›ê ŽB\ì6™Ú'ôÙ´ßøS% €Ž½ÝrÖñê-p<#ªÞû:ŽŽr8ó³Ê^¡®UŠÓŠ#³D"+ˆeeUðð/+0‡µ�NDai�²°»•:öš»‚ÒiC¹Ú†« ]£î¦áRb¸Æiö1Šè\б‰úR†ÙŸ@Ÿ?.ÒÜ-9¨‡?]‡Ý¸@å]kdçL# | ¨cÝËjÏ…U k¤ã-Ëı¯",}á)ì|e¼9arRÁÁÄì~s~=,ÌÀ…Í»í%ƒCovovŸv²12ÉF;'÷÷¥ÅàšÏïv¿üÐ|Ü}Ú¡´ÛSf÷ÛÛ'¤úÕkÓ¼ÿƒÃÐsjo�’Z‡6¢¢•HÆtÉYuÊ>{ÁbJQE«� ú-Ü�u�à74Z0há,H…¶Ñ‚g¡¾\¢Ga´Ãˆ«€${»èñ«l¤ÇkZùvP|Š�Ž{vjçxµzø-ã;¯…mØ¢ûg÷ˆ$…×n�¯þ©esÿûþííFþ6ì1 endstream endobj 2 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 23 0 R /StructParents 0 /Tabs /S /Parent 160 0 R>> endobj 24 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 29 0 R /StructParents 1 /Tabs /S /Parent 160 0 R>> endobj 30 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Annots [35 0 R 36 0 R 37 0 R] /Contents 38 0 R /StructParents 2 /Tabs /S /Parent 160 0 R>> endobj 39 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Annots [45 0 R] /Contents 46 0 R /StructParents 3 /Tabs /S /Parent 160 0 R>> endobj 47 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Annots [51 0 R 52 0 R 53 0 R 54 0 R 55 0 R 56 0 R 57 0 R] /Contents 58 0 R /StructParents 4 /Tabs /S /Parent 160 0 R>> endobj 59 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 64 0 R /StructParents 5 /Tabs /S /Parent 160 0 R>> endobj 65 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 70 0 R /StructParents 6 /Tabs /S /Parent 160 0 R>> endobj 71 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Annots [73 0 R 74 0 R] /Contents 75 0 R /StructParents 7 /Tabs /S /Parent 160 0 R>> endobj 76 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 79 0 R /StructParents 8 /Tabs /S /Parent 161 0 R>> endobj 80 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 85 0 R /StructParents 9 /Tabs /S /Parent 161 0 R>> endobj 86 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 91 0 R /StructParents 10 /Tabs /S /Parent 161 0 R>> endobj 92 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 94 0 R /StructParents 11 /Tabs /S /Parent 161 0 R>> endobj 95 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 97 0 R /StructParents 12 /Tabs /S /Parent 161 0 R>> endobj 98 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Annots [102 0 R] /Contents 103 0 R /StructParents 13 /Tabs /S /Parent 161 0 R>> endobj 104 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 105 0 R /StructParents 14 /Tabs /S /Parent 161 0 R>> endobj 106 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 117 0 R /StructParents 15 /Tabs /S /Parent 161 0 R>> endobj 118 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 123 0 R /StructParents 16 /Tabs /S /Parent 162 0 R>> endobj 124 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 129 0 R /StructParents 17 /Tabs /S /Parent 162 0 R>> endobj 130 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 137 0 R /StructParents 18 /Tabs /S /Parent 162 0 R>> endobj 138 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 144 0 R /StructParents 19 /Tabs /S /Parent 162 0 R>> endobj 145 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Annots [153 0 R 154 0 R] /Contents 155 0 R /StructParents 20 /Tabs /S /Parent 162 0 R>> endobj 156 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 157 0 R /StructParents 21 /Tabs /S /Parent 162 0 R>> endobj 158 0 obj <> /XObject <> /Font <>>> /MediaBox [0 0 612 792] /Contents 159 0 R /StructParents 22 /Tabs /S /Parent 162 0 R>> endobj 160 0 obj <> endobj 161 0 obj <> endobj 162 0 obj <> endobj 163 0 obj <> endobj 164 0 obj <> endobj 169 0 obj <> endobj 168 0 obj <> endobj 171 0 obj <> endobj 170 0 obj <> endobj 173 0 obj <> endobj 175 0 obj <>>> endobj 176 0 obj <>>> endobj 177 0 obj <>>> endobj 174 0 obj <> endobj 172 0 obj <> endobj 179 0 obj <> endobj 181 0 obj <>>> endobj 180 0 obj <> endobj 178 0 obj <> endobj 183 0 obj <> endobj 185 0 obj <>>> endobj 186 0 obj <>>> endobj 187 0 obj <>>> endobj 188 0 obj <>>> endobj 189 0 obj <>>> endobj 190 0 obj <>>> endobj 191 0 obj <>>> endobj 184 0 obj <> endobj 182 0 obj <> endobj 193 0 obj <> endobj 192 0 obj <> endobj 195 0 obj <> endobj 194 0 obj <> endobj 197 0 obj <> endobj 199 0 obj <>>> endobj 200 0 obj <>>> endobj 198 0 obj <> endobj 196 0 obj <> endobj 202 0 obj <> endobj 201 0 obj <> endobj 204 0 obj <> endobj 203 0 obj <> endobj 206 0 obj <> endobj 205 0 obj <> endobj 208 0 obj <> endobj 207 0 obj <> endobj 210 0 obj <> endobj 209 0 obj <> endobj 212 0 obj <> endobj 214 0 obj <>>> endobj 213 0 obj <> endobj 211 0 obj <> endobj 216 0 obj <> endobj 215 0 obj <> endobj 218 0 obj <> endobj 217 0 obj <> endobj 220 0 obj <> endobj 219 0 obj <> endobj 222 0 obj <> endobj 221 0 obj <> endobj 224 0 obj <> endobj 223 0 obj <> endobj 226 0 obj <> endobj 225 0 obj <> endobj 228 0 obj <> endobj 230 0 obj <>>> endobj 231 0 obj <>>> endobj 229 0 obj <> endobj 227 0 obj <> endobj 233 0 obj <> endobj 232 0 obj <> endobj 235 0 obj <> endobj 234 0 obj <> endobj 167 0 obj <> endobj 166 0 obj <> endobj 236 0 obj [169 0 R] endobj 237 0 obj [171 0 R] endobj 238 0 obj [173 0 R] endobj 239 0 obj [179 0 R] endobj 240 0 obj [183 0 R] endobj 241 0 obj [193 0 R] endobj 242 0 obj [195 0 R] endobj 243 0 obj [197 0 R] endobj 244 0 obj [202 0 R] endobj 245 0 obj [204 0 R] endobj 246 0 obj [206 0 R] endobj 247 0 obj [208 0 R] endobj 248 0 obj [210 0 R] endobj 249 0 obj [212 0 R] endobj 250 0 obj [216 0 R] endobj 251 0 obj [218 0 R] endobj 252 0 obj [220 0 R] endobj 253 0 obj [222 0 R] endobj 254 0 obj [224 0 R] endobj 255 0 obj [226 0 R] endobj 256 0 obj [228 0 R] endobj 257 0 obj [233 0 R] endobj 258 0 obj [235 0 R] endobj 259 0 obj <> endobj 165 0 obj <> endobj 260 0 obj <> /StructTreeRoot 165 0 R /ViewerPreferences <> /Lang (en)>> endobj 261 0 obj <> stream xœ­w t×™æw««º[RK´$„À-¨*Šjaºõl½…D£'’@oA·xu«õÄ’Z´$ž–%°Á¤!ÆYbƒ™ÁŽ}&c&“ÛØ&-o6c;ÄÇÞ¬3›Ä“�9g’Ù�“™s&ÃÙdf7»9ŽQonUIâÉfÏnUݪû?îÿwU�Xƒ˜0ÕÑSP<³õÌo. ÐÓ»³÷P¢¾ààPh"8Eþù€ü €¡c3Rõ¯�s€iÀÒðÔÈÄëÂ3ÅÀÚ `Íù‘àô¬Øà3¶‘ñ“Ãù“ß9 $ß’fF‡‚ƒéÞ`@Øú²ÑÑ¡`ò;¯² À–щ™m¿¶(?�Îñp(8ôËP+À½ à�‰à‰)ž·+i281Tø~ÿÛ€ð-€+› OÏ$&0�­Œ>š:éûþ�Ëÿ¸ïƒ€ƒÖDkÀüЋ›ÈÂ1XÀÁŽ\¸X3 LÐŽÄ&ïsXÆ—l@Rë§�-µ&iW½ÆÄµÿüãïÛ¯Ùþ+«Ãªîþ2=Ÿ=ÿë'\øÓÇîÿeR‘u@’îví`3¦ÁZMöäÁ|”+8˜!¡�báD‚ÙŠB bpâgÎßÑŠ€Àº"pƒ;>83Jp|dt†dl&8N8ppbÌ0�§yºEÌ�ÄLž¸o8Žä~âùgÉóáºàˆ¨?M?À0g¶Ú‡ŽæŽŽfx!!lÆ0l¹ÎAyEZ%PÍJ¦qñxÎãþ3©%cägçò¸?æ~õsš¶þÏç�ó'¼�Ÿyä|0YÅZ6ø*¬÷–ÇR ñ+�" Hü€�wq7ð®â*r5è<¾…[x×ñ#¼‰—ÈÁ‹t“¤à,þ _Á%¼€EÜD6®à:Nã"^ÅO5ü Ü1¤ü Îã5ÜÂü9ÞÁY<‡ëx ·ñ#| /áëxß&‘ûšìf\à CþKx7Aqçp_ÆM¼ý[í²Ñ‰N`Oã"žÇ5¼†?Ã'ø)qâ4¾€+¸�¯â-þ‹°¦K×ùìs+é>øyLóó¸ÅÏã?�ÃüQž')_/Ž•$ÄÑâ„8Rü±8ìIˆCE q°0!† o‰…#b0?!òÄà ñPÁñ`^B<àNˆû] ±ÛÇ¢[BômK÷=ž÷nMˆ}¹[ÄÞÜ<±G=$v« ±K½%v:b‡sAlß’÷(.q·rKlSb«²WlQ\â®Í ±YJˆMRDl”bƒëÅ„X·éЏsSBônLˆ;rbMõïÏÅíÕ%bUišXY+Ê:Äò²ÍbYéÑSì‹ #bA~«èÚæs7ð¢SÝ*ªdž[Ëá± 6oHˆ²T#Jë××牛²âÆu 1g�Etx6äì__².gÿcl–ÍfYj×ýÛþÌ¢Œ¾ô"{_†ßîO-±õ %|ŸÍÏûEþ0Ï­áçù_ð¦5‡ÒúRJ’û,%æ>R„¾4²ßìŸ7“s‡9l6í06Ï›Mð€ü6þ¿€)©ÄÚg*áú¬~Î/r‡9n 7Ïý‚3™¼^�ÄÉó´×Õ·$ºÛhRç~J.Pµ‡Ý½]ýÔ|�¢¯¿/FÈsþs_ü"6ÖµÑç{|·MÀÆ:Œãê»|1Þôœz.¸\.öœž™eu›éw²êdÂ.F"³ŽüÝéòìwH:¤ó,ëÁ^¬ƒ€i«@a‚)XƒLd$K.õ¤+érº’ž™%—&…¤1%Ý?æ(ãî–eß?ÆEëÒn-+û´S Ú8_V&øô’0£p˜NÜãS„»ÈF2½I.³˜!DÌ©¸\ÅéžÂ"’µ6�S6ç›jHI-ç)Þd2¥—ä›”Íi\VúÚM&Oq-ǧxOÜ<ÒûÜÑÎm;OÜë»<Õ±í�lwý¾²ºáÆ-ÙùuûJ†7›vÿôÍÿùbý¶ƒ/þøòOßü—+ÞÇýW>Yš%Ž�ŽÔ‰EGþôôÒß¼8Ñ$—„¿‚[÷×BfØÞ6óbc:‘t%](U¹¿^\ºÈ¥ ñOwñ?¸ðµÙwÖ!€÷w!bƒ×f·Û²„ˆI9¶°8Ýã*..(,R³äRRË•–äesÉRJj‰§x“f¦…ðžÏšÉO|ÁÜêHWðŒwqü“?ŠÞsµ…*–N]»vŽËøÂDå®Ù¦¶óûNÿÇ“ÁoÌzŸ>ûTÍ’Ÿ}òNÜ3}*ÜEª±Í»Î‘³Iä��3<�§FRS“2¦Iq�«¸ 8½²À“‘]YXD<ŵäsÕq‘¬ROñ&ΈWêY»é7yö™àüŽŠ©½íÇë§¾wþ™&=O¼qüå—/Þs5ν:üµ…]‹õs}}§ëw__ xœÉÌMJâ6nØ�™8]¦á—Â"’›)gÉ&Í+öçz6q,ÝJKò9e³™„¾ÜÂýÓýÛî­§;‡¾rt{eäë³¾§÷$SÛ®Ùöºá&ÕÙ6Þtð0÷¶“ûË[K3Ù[Þ �ѧw ]Ìß{jwã1_Q1Ë�s‰{üFá6Êà𦦹×oÞì6��¸�J¨,ðhÕàÉb™¿‘¬]­J±äÖšV«ZCJ2ʶ˜vØíW>˜ñäw•{·Hu¡†=çúÌi{¦/wN¼<\T5ýzø�©ª}‰Ø…Û7¿òÁð�ƒ/ —ùOµìYmêýÓsß™ ¿ÿäÜûáÅÚÉ––‰šv¯%Ñs‹�Àâ¹}_¯ykªk®©i®«÷øŽǹßyc`à�#ó·º}¶ejgÍÔž¶©ÚÚ) &–L¿Åëd¹Âæ"¶‡b©²Ö=‚\–ÑrÏrµé†²X§™\„e~åÃñ­yƒÞ!-”õµ}Þ·sæ�Œ¿‡‰Ä=ÓÏùv8P…ǽY.÷¦ÜMUUkr‹R"ë7$G’„5­A‘÷¤gTV©é«š“û¬ôµë²³”|’™m¸N qyvši%EL)žá¶¦±êÅíG_8ööHfæ{iv‰ûwOöºó6ô�Ýcê°ÔŽ|Ñ7ùÕý o…¹<ïá’Âö¼ªÈÁòÎWO.YËN¹íÒœpvCq[±§·h×h‘ÛðÁš½_êßwΟ‚ƒ‰{¦ÿηÃÑkÉ$æÌŒ lH±D¶ EÏ_æ»Ã ‹½&—#*—Ê¥zØ�J.+ÏNã¸ö£ß|º©ýüûgnŽ—|öW\˜÷LÞqd÷6WÏñݹ­Ûרà�e¿C‘©—òj#ÁÁhh™àÏsƒZê©™‰hëQÚºú}Rc4 óÜm½A:½b…fÌ(Wßë£M.‡,¯‚›5xÜõ¹e™¬H�Ñè` &µ×G½ŽÑ&BýE?ípù:àRdÅ7äÏsǬ°É½�ú*†ý»òÜ1p*Õ®ž8J•ú<@¥�$Q³ª tú¢2%ÅaÀÝ>E¦$èˆÊŠ,ùýñÄ{9Œ[‘óÜ1u1…\èŠyÉ…ž~_Ü*]èõÝæW¨óǶ� ]¾¸êÕ°Ã2$$ �´uûnsV�ß÷‚.hT^Chp(N át¦E/BqNÇÙõ�œl£E/8„â¼Nñ.sóÅ­:nAçÞjp[ŠÛeÕˆú‹Œ7YðZ½I^—Ê9b„¡n ^ë;H"xÓFR‰#¶ÀÕwkè8Yˆ%yqMR·Á¹€$Âp +¸8ƶJ�߯z¡ï�}ý¾7mH%íî÷ûëØ‘çnŒqí.åAZwù(§6ÆH»+àw( 4©�Ò`4D½=>ÆpÈ~‡ì÷7ä¹YvI>eÈ¡øck×F§i‡K‰Í΀+ª'K-Å^•ç¦&µ%¤4åUÊ«-Ô¤†öJ:pQ“*Ù›¢M,‚ŒëbœI�^%µ¨�Îl£ÉÊPMQêV(;°C§˜Å¢ÔQ²N÷s£Ò(­‹†”I¢ÞN߈cؤRˆz• å•:GŒG�,ûד<·ÔC»«!ÏÝÖóv¸:÷û$Í|)m�b^Þ Ü ;9j�”†ÿª�R”zƒ¡€C‘ýsž[i”¢�JP¤Þ.Ê«E�Â~tûÙšÞ~_Ô6¨ *=¾˜× J¡ C ùQHóqCž›ä¹‘çô#£q¬ÊÕÐ0åÔ¸„�€2 #X=>Šy1L¥ÀjœÒʶӞD{F[•ÆAÊ©l©©¾Û'Kƒ~=IЩuŠ•‰¬b’¨IÕ„GíÕË1 jR©I�Ò‘‡ÁѰ‰�åÕ|=W(ïd¹æ“é÷»VX‚ta@ŠJv¥Ja7mq3*¨Ít!díÈÌr� j+]I¾‡ì§¼³)]θ<7å�+;ÑI×C"‰’^ŸL9•™C:¥€_ $Jº|²ì�¨Ðå“¥á K.Öh;u{:û}Ìê`´Ç'S°’qPK¯O)²Cf8¿_÷>Ó‘ÿ­vèñQ8¢Q%J‰Ÿòj“4”¨à¤fg {N:åR‚CT °ý¤à�¶¶IŠêÞaÒ�ŠìQNÕ|É;¥8‡v E• D\TPÓ£Q©2ê[ÄA;(ï í ¸Y²KM’ê C‘™Zä¯ÎsëŒI*c¤‚ª]N:ኴ¨0ÚvéÌVMªDÑí£�Ë,íTzÔE¹ì Šnf<éî÷1盵®@µ% Qo·Ov°Õåz}Fx´õ-l©c9`ú2.»Bk´ìE(/뛢ë«ojÖ.›v%©ÔªÒIå³+ ²…™ó &\Li}�ISW7À¤²­$ƒ¢0^ÒlÒ_€k˜2õ6ñÄ»�>ê (løýl{«¶[¡‰Žê‚™»ÌŒøy®0vÒ¯vµh&¬F'k—EÓ™Ñt“„‡ox/žx×ðœl,g˜•ÏUiÔÝ�ƒŽú]ƒú*³ÑÁ%)Ä:w¨Kû¾Øï“eE¶8¤åT)”h�+Òm{V÷j«ÞXV’&MTXž`(”]„Ý Q¢ì¢œ²‹¬Ì”ÛˆU©`�$¥"Æ %ëX3²§Ú¢!% ê¯æNE…c;û2k�NÒb{Œµ¦^ŸààýZÊ8éq—‘Åúý˜k…~œÕ¤eÙ“VF‹®MÜq=7œÆý˜Ëú¹«¢Ö?l3«Mš¤ÑX7rZÿV&=@­z¸Z9]r«Þ'ZYMG£¬µÅ¦± µ9Ó©àÌ Éj%µ¨•†–I*}ÒEÑɶ¶j ìõ1CRŒ°©)4YµÓ$õ==µS¨EµS³úžCç¢)j<‘ÐôÖ¹u'wi~`—A6VëÙyÜå§ÉjjU›Ø0*)ŨRÛ#]߯Ç4éa¢²"Œ½è•‰ Š›Úëゟ&;%;5©Uš?�)Ôâ”ìѪ±8 �1pjU4š²ÜÿYû_¼Ð>'á�>Š s®¤ý¸¬Ïs·u³ïáž~Ÿb—Èvl×ãÏÂ'Q^õmwTú) Äÿ˜ã×[§6³Ñ•${:%�¨”AI�žÓÜkÐ §HÔì4¸˜ç\ѨÎÇ´·qѶÊ;Ù?Xr…#™ý×-ÿR]sý>²ÄÖS¢Ä1ªœ�™/â8¤œ”)W¯PI:à“Ù«>Ž=9þhTŠJQ…ý?íõéwF$qæ°ïö-³Â¿1ǯ<„°å°Ä Æ·rد҃}Ϭì{\9©Í¢ËÇ1ò¹Û²”#ûõÄ£¼S³%Ž EW„w{GDûY‘ãØÄ¶7ôapZŽ_“Œ'®0…€ÿ fMûS endstream endobj 262 0 obj <> endobj 263 0 obj <> /W [0 [443.35938 0 0 0 248.04688] 20 29 562.01172 52 [630.85938] 69 [543.94531 0 0 0 530.27344 347.65625 561.52344] 83 [570.3125]] /DW 0>> endobj 264 0 obj <> stream xœ]‘ÍjÅ …÷>Å,ï]\4…B´ �,úCÓûF'©Ð¨³ÈÛ—hšB*Î9ÎiÝ5�Vè»3¢G£ÒÒábV'œ”&I R PØÅÌ-¡u×ôÛâqîôhHYМÔâÝ—'i¼úæ$:¥'¸ÜëþJh¿Zû�3jŒTH ­_¸}å3 ²['Q{å·Û½îÿ*>7‹�Nb7ÂH\,踞�”Œ1VAÙ¶m[Ôòß}UÃ(¾¸ Õy%c)«vÊ"‘ò"ÐC¨È"EßÃ!ýõ;ŸO¢EÒ„#;œåÏÑ¢8,¢hïrOóŒ@¬Î¡ö!ò0ö>°ÒxþŠ5vWíëž1ˆÞ endstream endobj 4 0 obj <> endobj 265 0 obj <> stream xœíXolçÿ=ï96ãÄć“8¾\b'ñ?â‹íŒóÇŽ³´�ç/”&1qJgŽKÂöaŒ­C€2‰õBíªiª„öGZ[>lý0!­«ÚJ›öaU·jË›Š¥S§‘x»³��¢­Ó4©šî÷“ïž»çÑ=Ïó{ß{ï| œ‡ã�]ƒ¹Y Ûb}^ß‘ó?²¬Àñ�ÁŽÁÅW§?è8ÏøLbŽ«×ŽlÀÅÉļ¼—cWl™œ>sòƒ7:’@Q9Pôb*™˜pxú@K©T2¡•Šx€BjS3ÙE× Ew€²w�-ÓéñÄ÷‡nÞŠo[­3‰Å9Í[l À}¶ÙÄL²×òÀîÌ2—žÏæÞƒP¥ìŸË$çRÚ‹çü€îÇ”;Ss P.‡ ¹LŸ¢³ÐÊGÀ��Ë›¹wà6ù‘?ÃýzýÀFsm¹6®bsŒæ²œ [”ó&e[ ¶0™ÊR9PÈÀÀd=Ø­×i¿wáž9Vúd ÇÝ‘Oÿ6~Ã/ï_õõ‰\Ûz+W¡© {T ¶h†šh¬w–ñ3™iX&3ÉS°L'²³°@[ˆeЪ¢Ü0ØÔD2�IÏÌÊ%³QZBÀ.°QOç÷t>¶�ÛÊi8Æ4›éˆvöá'°a1¯‰¦–~vô²’p™]‘G¤Ð/”½ \A XP ŰÁ‡ ` $1…iÌ!‹Å\N¹Â#ßR˜ÆlÞ—ûû8÷S…onäFm#¶à¤\…f«<©¾`¬T\° ¸_°9´ãVÁÖÀƒË»£l-¡ÏÛT=€¥‹I¤�ÅÒxŒ#‰Ò˜@ýÈ 7âHbÏa d0Œ$2˜ÇÒ˜… Mð`7|`/RH#‹qÅsºàËû÷b œBR‰8‰$‘TTó  Dl¬Àö°[¡ Û¦*6fí@�èÃÞÿ ‹Ç�þuîW•:ållèÀÒ8¡øëí²˜C+¼ðbA¡G™ù�¢Æ ¼h€ 6,` Y¤ ýÌ+ZžF°!¦è–… �ÀŒœÁV¾±6[€"„å5…]‡­Ðcx@2 Æ:ÁKb f©�Äjf ÓoÖ—ˆzš5�çΞ½¡iêüSgâkìÊÚtë7&'û—ï¼~taáÒ2½Â1€þÆ–° �ü’Qô ¼h”øcׯÓÕë×»‹­­uËwV$·Ê*Ø5¸�¢»#h%Éð7{ÈKæo“äÛiÖyH¬Ñò&+U“•ñ&Qӗθ}uã-ѧ«ý5G…WðD8œªuÙH{bb òHC§½%¥÷»ZëÜ­±±ÒÐ`hìØíës»kU‚ä®®·èëKÝ�»›‡| 8æfKØHœTf%³¦`™ÄÝoôÙ»vhÊv§†ÞeKë/µ&[[“­tbm s«Œ£Xјk<äo=L¬1�Îf’ÏJ¼QtˆrøA¿�É]üÕÝëzåU´x«÷Ͷò®~gdÄÑqõÖÆxCj¡ÉÚ¤ÂÎøP‰Ð"wZJÞwhßú¯:mžN{ÍÙ­¶&Û.± ¡Ü*ý�݆ 5Š‚$“²îóʈ7í¤’cÙ¶ägw5§‰Gu\Õ@UmTÚl�] ½úógúæÃ‚õð›k-íÕڕj‹w ed„hn•Yhµr¹O9‘•x“V'ø]³=ŸAÀ Ù@ôTÏB,öåŽØ¸Ÿ±õ$=Ë÷EÜû=¾á€«[°ÖŽéCóû2ûöœì2XŠÛÍÃîÁ}mƒÎ >P^#ÏŒ1yf·óóQâu’Òo�r*­Î8/âêF÷ ÇãÍ!gÔÉn¿5_œ8¾þ>‰]—ký5är8 ÐKìmf§!ù9¢¹´;ÿd8¨Ì»Û0æU3Š~ÉhÚù ô÷Ç¿ûi³“wíâ…Vý¡aú(²öKÿîmú°Þø°6Z�I©ÍüÙÒ¢:�ýQi´<Ðx¬²üȱJZA ª7+*Z˜ä»à�¦äjŸ‰DfÚó[oÌn�y½]G—>”é�gB¡L¼?Šzƒ-C^ïPKpÐ+çËIJ^5óƒJó)Ä»C4óe3iu¼•Æ¢:®æ�»ó�'<±Wè8Í9gÔQjzêÄî_°„m�ûÒ½ñÓaÁzäÒzFBþƒnѾRm¡+·ÊjØ9Tä;ÚG¢¿�$^âÅ�ãBw\üÖÅmÑ{÷v¼b‹e‡Ð£—‡–ÃE×®Eþè YõÅ¡¼Îí3Ó²|=)è�ÌùÛ²�$�YtxHžÞ%Ôþú�göo·4Û«¶÷Œ¼öÆá¡¡TSb-é¿÷TY#Ï;MSùdŽ÷ð¼Ë<RæÄeZ–Ÿþ‚¼6)ô5ÓõȺÒÃ?ß ŠÙTÊkW˜ùóCêx$œ.L{‰ï™þÎ�h·{µ×9m“ž:?b U½ßtìÛY0æ¼.¿wpOè+ßìç8e¥»Ëzi–½-¯‰$ß§yʘ´äª´Û++ívÖ+VU‰ò/ÿÌn|ÛžÀç¾ü�Ê$õ*LÓW^¥«t‹>föxF¥Êÿ’/¨T©ò ƪTùÉŸË_¢V¾Ûü°Qù¿è犋l°�OðÜ`‡Ø(¢ŽÇبüVùxlá¼;¶éZ]›ŽÛ?O�*T¨Pñ¿ÂÆ5L… *T¨PñYl~‡W¡B… _\°QÜý<~«½ endstream endobj 266 0 obj <> endobj 267 0 obj <> /DW 600>> endobj 268 0 obj <> stream xœ]‘MjÃ0…÷:…–É"H–S'cH�¼èusG»‚Z²²ðí‹g’º�à›Ñ<žÞˆ²>ÕÎF.>¨ˆ¼³Î˜ÆkÐÀ/Ð[ÇÅ�ÕñFxë¡õL”õ©™§Cíº‘å9çâz;Å0óÕÑŒX3ñ ëz¾:—Íš‰æêý à"—¬(¸�މòµõoí\àØ¦6à¢�óæ\6/¾f\!'äF�&ßj­ë�åRJY𼪪ª`àÌ¿þ�¦.�þn¾N žK©d�tDÚ�’-ÒSJ´#ʈJ¤,ARÔËJ¢ i·EJS¢ýB©’H©Bw7éÝÕãIu·…º¤¤HI‘­lOÅŸ©ørÓ%¥%€eQ�tõ5p·‰‰.YZ�…ûÑ/SËù Éš— endstream endobj 5 0 obj <> endobj 269 0 obj <> stream xœíXmL[×~ι;ÇÄØlŒ?¸`À6vðõµ óaIJ˜/§ H ˜‰VmYµüX—DQMS­“6M«ªIÝ�NûÈ�­Ú¦Tj«}h뤥Z×M¬êªEB¬Ê¤Äw;×&!¬šT©Ú4é>�|Ï{Ï9>ïsÞóÞs�.=.‚ÃtoÏhߘ¼Ìä6€þ¡Ñ@ðS—^©èAÓ£c=cç_\| Óü3KéÚMÛº`q>½ÊJÖwÀ¾ùÅ sw~¶þu€¿”|o!“žmùÃú³¹ ¼°�IkÄ3@¢ê–ÖÎ{i`üPѶ˜�I›‡L Àþ—�RûRúü ÿ*=à>çrz)3(ÍÝè€ZW²«kò/!ÄÆÚWr™•ÍåKÿÒöí÷‰|éeþ @@då •܃Ëа»]à@ÁLùM�=í(Ôp¿ËßhJî’»8ËÞ>üUæ û”z“rµ�nÌ/¬‘j è�‚²xÐ[;c‚h¾ý¹õëÓåÑ¿ïã¸÷Xõ;É—$Vþ¹ö ³rW¾�³ðõ4 �´`€xð‰þÁ1Xg.äa�Ïež†u1½¶ +4žº¢*"O€ž™ÍdsÙ¥e&™¦È5”ô9šðD¡$§$@˸RŽç(å÷F¤'Ñ;„ÉõBLøzòói�‡›ô[‘â|¡”&pŸð`ž*pP‰º½H#ƒ3XD벬ü³P7�E,#'ËòåŸÈ?zÄ�X(™c^øR—ISÑ&°“ýE›B�ûE›C7nm~\-Ú%H!\´5ð@W°I5t&­óXÀF‘Å9ä0ƒ âÈb #‡,Z�TôŸÃ"ÒÈaä°Š3ÈbN´Â�C"Œ, ‹5Ì(-ëŶB{–�ÆÓÈ(=æ�ÁydàD~„•»8jpU8÷¨Øíµ ôbc�ßýgß/*:™7Nô`Y|ZioRb·†´#€6ú‘~ØÇ¯Dc 4Ã'6pkX(ÎgU‰å:2˜…ýJÜÖàÄ ¤±Ä<8«wksZ” Æö zJ¡CÌ€hp\"”“Hc•ØE5ÄÈ�ü5Bކøð¹‹_â[{ÿÚ›þ<½ñ`±ý‹óóÛïýàÔÆÆ•Mò&8ÌT ×`€O ډ٤њY¡''ÃRÈí%†cæ‡ñÌá¶Ž#ñì±õ“cG�N�›zjâ,½æìoo*çËN$º'<ä™pDò=¸ßï”@1"oSŽlÁPUç'R(ñS¡NO´�1ªø5�‚ž4ÃIOÍ&;ù°eÐ÷Í[ÄÒptFªœÕ}ÃÞø¤7®åšfíždóÂF«½UçŠy“ãå®6—¡FßvÐežìÌÿ¶×éïu×],u¶:k„ƒ HÈÛÔJ¶P”(Þcdg®.É¥ ¹™æS †#UzBŽÝèïÿLOÿŒDi>CΚ‡â-ÇýÁ‰°oÀe¯ŸÒEWG†r�‡çúôÖýÝU¾±Î®1¯Å®®cûÅÙIÃd AôbtÇg8"í*˜‚*Ñ,C]çnd *;H°’UpÁ‘B~²#̨ܻ½d§#i˜•š�»Í"H“b³ãµÏªƒã’Ñkª0I‡–N=Õ{!åívÑa±ùpÒi;mn8XgyÇõÖ®äËÜŽªV#oìöJ'¼º¸!Tz¢©´´Ìf°ÙB±–ò][H¨kkÅ:!dËÙæ³Õ K!B�D�ºˆhÍÂîGê¹�¤ð¥Ëe‰»w+áÍZá:ªŸŒnÆJnÞŒÿŵëöG ëv\Þ&ÿ ›lݪتיּA,ìN&GÅNO_S2®åRºÙiâÏ¿Ý÷ÈHÞ:°sm ›8¸8Ñh',¬£È¼1ºR^s€?`Õ¯ ½F6óÔ„#õÄ”·2ï,¯’MvªpÉe ÑwIˆ|#ž·‚à}:H–éë(H�»]³IC|6·Ûfs»é P[+°_á�îQxúcó…"ßÂ[d�dÉg>Ož'·Èß©žž ëô«ô•*?þT¥J•*Uªü/ð÷ìKbÊw(öÌG~ùASÙsŸ(–Gh S4ÅN�÷-ÖGwÕ_§) Ðúh ÇiŠ�5U¨P¡â�Ý{˜ *T¨P¡B… *Tü?ƒ¦ðþ?1•h endstream endobj 270 0 obj <> endobj 271 0 obj <> /DW 600>> endobj 272 0 obj <> stream xœ]‘Mnà …÷œb–É"ã¤Q%ËRDjÉ‹þ¨nàÀØAª1ÂxáÛWÒTê¤o˜÷\ÕçÚÙü#ŒºÁ�u&à4ÎA#\±·ŽeŒÕñN´ë¡õŒ«úÜ,SÄ¡vÝÈŠ€bo§ØœÌxÅ-ãïÁ`°®‡ÍE5[Æ›ÙûoÐE¬,Á`Ǹzmý[; p’íjƒ.Ú¸ì.ªùëøZ<‚$ÎÒ4z48ùVch]�¬BˆŠªªª’¡3ÿÎIuíô­ Ô�•P!EI”í%Q¦ˆž2"))ºåî—ÿº?†‘2ÙïS÷1iŸSñ”Š/©x&ÊÓ> endobj 273 0 obj <> stream xœíY{l[×yÿ�s/EË¢(ÑÔEŠâëò!ñ)ñò¡EI$õ²eë-ÑYVõôC–&É–Ýn�—ÍØ–&žxð¹Ý kŠ´Ø£�®ù£3ÐÔmÚ mç`@,K5ÈšfÓä¬Ý"r=—´, ݺaØÖü>�çÜs>žïû~çû¾{î%5n€Ã¹DÇpçHö2�ûºú‡Á37ÿÌÐrç†G:F®}öÒ›9À?½8µ\úDé׺ àsóS«¬e²ÛÍ_º>÷…Ƚ>@�TU ³S3¾¿¹ú$@6Df§Š$…�ûÂâÚµÓ j –�#�—–¦§þHû¹ @Ñ›§®-ó÷èy°\žZœí ÏÝ8#@ ËK«kÙoAˆ‘Í/¯Ì./=}À(_"Ù›Ì?�le ‹ün\F»ÚC(¸\7û‚À�yäF¸¿Î¼Ðt¶-ÛÆéÊð·˜.’Ç+äo#èúü©ò((þühM�¢V?ó²v²,öðǽÆßz1ÌÚ¿«ùå™l[¦™ÓóvE �mÁ!!ðàS]}#0L__¹ÃüÊìE.M­]†EyY UÞ*’=?3»´²´x™™LÓd €>EÓŽåZrA"´„+æxŽRþ "©D?¾ ®ç0áíä•s ¿/+ܤ·ÙŽäý…ÜV€ËãÂãwØ` ¼ð#ˆfÄGŽâ80ŒóXÆU\Ïf啘Lý®Lo^f —°‚kÙlöoéýúCúÜ«Ü׳±Ë_ÊñOÙÍŸF‡0Ǭä‹"Ï×ÊØ­aÍ €u™ý˜Ú•ñËh,"€:xaÁ:Îc yVe,¯b3° KÆm œÀ™KÕ^Û,z96Üp£ïOáI™ÿT按þŸ$Ï’/“‡ÔG‡èWé»ôÆœÀõr¹Or¸ÜC>ÌOðOðwø;üWù.p�ÿ;¬(*p� üsÄ)ÅůàO)î)^+ðÿS~[ñ°À9.b§Zâ왌Þ‡b¨p i¬‡5@Ä2ué¤6"š©&NÞÈlÒâ#WnÜx‘oHü}bê z{çRó¯ÎÏl¾óųëëÏl’×ägÐFº�RhI+iEÎO\¢š(¹hØ*XÞ<ûfzEc-ãË-šU3ñÑ��e²]ljZŒfž½ŸL‚` ?¦(¤°¤ÃVAÔHÂäÝ»äwïÞí¦\W×ÎN7{ºÌn“÷è³8(lNWÔD¤`$¬±†­š 5!Ñ ¶�ñ˜³+‘y�ÌÕNªBM’×sl�¬te:Zgc èaÏÎt5ÌwI«“¢ZI#jBq•œÈ¹D'hzæÎXxóÄܧPÎq6vÆI©‚çèFæ� HÕÎ2驊'Z„™ ¡7„–D¼*ó{’š¨™n@•CW šˆP¡&¢—M 9=dî•ÞÅÖÖË=«çdžGFÏÓ ÇHOçI_æCÒ“èìŽ2?“Ùmª§wàÛçgÈOÄOá8‘‚•:¥Ÿˆ¶"¡ÂDÌÄD™ÒÐsÝtL7¦Ž™Ã¶³Öoô#ñø‚Ýk9!5u‰㙺„³qAö6;|Í~ÑmTשÝõÁ~ŸÏ©±J>s­AU[îKÔ‡Fƒ  oÊ‘-˜àt6? ‡"Q?mj¢tÅ©ì�FdÛí F¢a5eÖ|àëó>ÿ2Ñ7Ì­Q�¥ªsÀ“÷$•\íŒÉ=T·°Þ`jPYãž¡Ñ2k£US­n,· Á“­™×Âi»Qli°T‹å ˜ÈnS#½ö¢’E†Rbä�uã„!#ÚŠ”‚‰�vû �S&†8Î:îIœò·Îô¸“.c¬ÁÚë»U¢9Bïß;k«m]:6|5Þé�…}¢sËlÁ@v›V“- ÙÛ=H« sN F¢:5!§ú®wýØÑظ©ÎÔîj øG}ÇLŽÚiUle`h%æ® L�ÑÆèHÀ®ÛkAËn“¥÷Q›ìÍ£å%‹ú])«$e“km³Mžn3Ç¥”\Íp�=eµ¶YÜ�u}ª›×ûWãVÓ©/í4¶›}�û–ÙnŸA*»M d+‡Ú#?^EJkت 9ºs´w½«ë:º¦Ã”ffÉ¡?é;îŽE¼ÝV“}B[ì_imšëT·ëÆÆ¼#­m#½©²±¨Ÿh‚þÊsQ¿?@5\8j¶\U­µhÍb™ÆqÔvÔ²}íÌnS}úÜŽ´1ÜF$AĽEç©î!ñ7ž.I½ÿ~e$ 6ŽX{UÒ©Øf\qçNòûž˜Iu8–‹ÇãÙmòc²ÉâDÇ¢ùQ,kòuóƒñ¡a©ÕÝY;”TòŽ´jæñgÞìLzd0cuGAØ[hê ›(¬œ¤5kT+qß^.«.åK êåþ¯‘ÍÌì=¢Øc'ÓÞPÙdÞHQ—¤Ëý´�HJ�èÊ�vÊHû_<}¼Ô¤æKkJ{Ç?ÿç§Fˬå|™©làÃw/jÝ‚à©8ÿ�—¿ xuË hȨ‹l¢Zö)¿GmdŸijú+åb©æ°®Dj?Rö½áuµ¹Œ/­V]8ñú‘Hÿ·ŠøŽoñÙÉ÷3ÿd鵋½VRº³UÜˬf•áÙdoŽ­ìL¥!±·IˆÜMf àäÑЧPŠÔíÖY)WBfM”Ý«r“EÄÛ=×ø± ?�ïö¥\®”ÏËòÇ«w8ô»]Õû§_xáÓn÷'šÖOŸY‹F×Μ^oúK»Ù,Šf³S=B?Îv"wÞ‹Ó(+�S/ý¦³¹¾¢õ3)òzX¡Ö”ì¼’’£  ‡éS02ù8 犃ëq *㤅½—~ëDªÛwÜðL§Ú'¤£7ÇM±šo7L>»Žvy­o80Òûè¯ pœ|šünv›ü>ÉÎ�Š}Zëë­¶@@p8§#ð¾’õ�§ñ{¬Zë\qvéXæ?­è ]{\Û¨ª)ìB½Åë?û d�ŸéWk¬z‡«³%}�ÕkY'娋c‰2‡"Ö‚àêÉ{tJÀGÂA!(È{™O�+™ï_ýN|§ÿUþU\D=y+' ;ÂŽ°B¸H|™ï�+õL¢'ÎV{—ö‘ËôÌ3²Ï3£Ói4:�´O¬©Ù4�8û?�¦ÙYþß'šÆ$McpÏuÏžþÜž~òg¬3HÓ˜ i Ð4b4�Mcž­—?u@¶9?Îd'òãÏÑ4ºi�4�ã4Ͳ[o§i4ü§þI(P� T ÿÚ[à T ¨@*ÐcÊŸß§ØþgÈ}÷'2_aíÿžu*P�h×hÿ¯í(ÐÏÑ4Þý7­ròÓ endstream endobj 274 0 obj <> endobj 275 0 obj <> /DW 600>> endobj 276 0 obj <> stream xœ]’Énƒ0@ïþ “Cä…4‹„�R$]Tš ö@-cçÀßWxÒTêKo<3~fÌT]ÖÎFÊÞ舴³Î˜Æ[Ð@¯Ð[G„¤Æêx§´ê¡õ„©ºlæ)ÂP»n$yN)û€ÞN1Ìtu2ãÖ„½Áºž®.ªYÖܼÿ†\¤œ5Ц^ZÿÚ@Y*ÛÔ\´qÞ\Tó—ñ9{ 2±@=˜|«!´®’sÎyA󪪪‚€3ÿöDzk§¿Ú�ÒEAsÎ%/ÉD[�tF* Ì|ÂL±EÊÊ仜‘ŽH é”(;-´å{$…„uÙ9ÉÞ­v¿ŽwÂü}Žh ðÙ¡²Äö3w ƒ%ž‚ØËÌ2 bùþ�\Eºq&9îñ»Š,¿sûcVú¸˜ÞFšÏ2ëàñ|üè—ªåû±É©ú endstream endobj 7 0 obj <> endobj 277 0 obj <> stream xœíX{L[×ÿ�s/6c0ø… ~?À|±M ˜@�Â;uš†„‡(æQpX©íÖ-]HV�hËúÚ:­Ò¢e]þi׮ͫҪM¤j«ZmÒþh»UêTM[™´?Àw:×&#´Ú&MÓ4Éß'�ûù~Gç{ü¾ïß@‰‡ÁáD[ëà¾!q–ÈM½ƒ�бŸ¾¨¨À‰Á¡Ö¡å÷¦»r€w|ftžËçÞhÀå“£‹óJ¬È?™\¾_¯:Ýä•ùêÉÄè„ïÃÓ�d@dr21*òdÙ À19“Zjé”}жe ɹñÑ—/½t (v¦™Ñ¥yþu:`€evt&qàñÉÛ€*ççSâ/!¤’éç󓲕Çü€üe">v�¿QD À_"ƒ³�±_Ûˆ•– ¾ƒ°C�Ìî×é?4.Å çÞ9‡¿Äl!_z¯–ÆJÐ3''SDÏ\ÎÌ'>úÚÖz ²þöÍ野—ìþk>Çýž½þpàGaöü¸ê‘ 1˜näܼ2Ðø�|õàÁ·wtÁ0¾¼�„áäBb†ähjȲs)Y�ˆxtj"1·073ËÜ¥qúòúup0ó$#@‹¸Žç(åwf£µ½­߃Ë™|ðòæ �ïJ×èe†F$dÀRƒËæ„ÇÃRVJÁA Z±=ÄaŒá~L!‰9œÂ²(Jk0m·¤Å&1�Y,`IÅ�ÄŸßáW·óàv7`�yÃX!¥Y™À„¿deŠ||š•94âzVæáÆù¬œ‡8‚YY™è¡�bf²OZç$0…“˜D ƒRt G{1‡ $ЇÌÁ‡6Ì!‰ F XÄæ0 êàG!DЄIÌ!…qIs:«Ëè›0ƒQL#!͸ ,! Bð#"ÍØnÛrǺ%kßrÇþv{­hGzÑôoy¾õüç–®J^1 ‚„ðæ0&éÝRŽR˜G#àŒÄ~ ûÌ¿û ð œÁR˜„H`QÊÜi$0 :¤,¥`Á!Œb†Y°è·ûf©�;@Ãô28@�2hAeU9…±—�¨K'´»™ªì´,ýüÜnÞsöøñçùóó©zy3y´gl¬ø•ŸÍojºú YdU_Ð^º‚b¨¡\(·s~â²+‰œs…­š‚Û×o?=¤¨Tð Cñp)i +›)r nVfëÒ/=µ¸‚ˆ¸N阀<›Ÿ†ëcDiur?±Û”D£6!‰ê”„L4Ï /Þ›°ö뢧×{°ÎѨïw'ÞásÉïô –£Ú a¤uïñ�Åp$P‚i€Zè ëA%¨¬šéUb£+›kgY·7ÔDWP%iÍDh!‚Ê®�Ѩ½„ØÄnâªHã“{´¼vÏ“gy™œr¡P§à¨\ÆÓ•Oî½÷“ÍÔ-c¼ÏðÂ3ϼ`è‹÷o±•Câ:uÑ+𱸪]Q)Žp½ŸÈŽ(e,H31Q�ZIˆ·í‘ð°óH àÓûÍCŽ=®æéýM µmíA‡¿2hî­�ÙšTý Sµ¥BgÔ;”�}ÁÈ=áZï± £©ªÜ VØJíþÈ} (h—„N(7�#Ñr�{ï�§•è”|©NÙó­›t%ý‹H"IDHp3Šfq�êÈLð:›Ÿ„ë#Q?e È]1*„LD£²3°]¡H4¬¤,ŠC]îo_çô>›>(TÖÛö{;&"KE¼ó^jm4tõ[Tf…»Ý;/ÔYTEå µIU7Þ�þ¸¡Ò½`TðZ›¶D[ŠNq�zè hàÈdÐ.·«�\`™3–+W(FXFí6™\c"dÀ¶ßÄ+Wó¸ªýŽ–#Áæ±#ÆZƒÚeÑûtŸÂf‰Ð×M±»‡—[–L­‚¯É¤©x[U Š€¸NKé ¨a“ìmA$¸ÂB&Î0‹s«,µ#‹ÍcaÏn=/_]*âŒ]5åj�Öè7†–ûS-•=W7÷ FÇ’¦âí²Ss k«Œ¨¸Níd#ËëVD2¹5l•×Wï,ü=纜në™ çÑôy¢Ñ uŽˆÉÑ´5[ëj&ͧúOÅZ¦ÛÕ΂ñÊÝÍ–¶�Ðj)S1šY—Hð6J3=wé©H8jÕ¼=TÓm®Ô UúÓódÙÜu,¢*Lz}iJÎÍÈ™ï�­”Paý’EC«QÙUÌm™\Õ¹šÏUö7 õ¬ZÝ&Ÿ�Þ¸v¼Ê—I¿CÌ!¿±"ý"D‡ò*ýŒV“a2þ¢Ò)Ú-yzùìtaÝ*D¢\ÑòîUþ¥çÒÏß~bè7ôFzú­ôÅsMß� ®S3}�í@ 5•=lU©µ[©»pìÄSÄ2•9u–êÅüùÚb~{~~RQ²Ù€Z²§û|8KE¼e°aèP&²ÖfñßM¶r> endobj 279 0 obj <> /DW 600>> endobj 280 0 obj <> stream xœ]’Ënƒ0E÷þ /“Ed I%„”’ ±èC%ùbÔR1–qü}Å M¤.0:×ó¸öXÕ©²&pñéUCà­±ÚÃ8ܽ~ƒÎXÅ\ÂUõ�c¢¨Nõ4è+Û,Ë8_Й1ø‰¯Žz¸Áš‰¯ÁÛñÕµ¨×LÔwç~ ¸dyÎ5´Lo�{ozàÓ6•L˜6×¢~F\&> endobj 281 0 obj <> stream xœÅWylÜÖ™ÿ=’sid]¶®Œl’¦9v<Ý—%]¶¤X·lR¾f4ºìÈ–2–¯:n;‡ÃMë´9ºnÒ ÝnÖh÷�Óºãl7M€¤@ºq€¢Ç?»HSlw±G°íbQ Hbqó)ùHZ,° ”ä#¿ë}×ûÞG@. b®o¨²æØðÂ^ñ¡á»†÷/Þõm€| ÀhòpbNð ù€{“Çç•–ÃgqÀâäÜÔá¿ò¿‚=ó aö£êë¿ <ê? ‚€“f®›ÀÏ=XÅïåNŒÏOœ˜šž'98Ÿ˜!¬E¼!@àQsϸ�Ïò~9feI7áO ,ÿ9ðC€ Ú0†ƒ˜Å1Ûfytñ#HÙ¶ýÛçg"–¤o?‚ð<煮ì<ÅŸaRp ßœ¿Çö¾¾íP à˜‹À¤ïy È \i³‡r/˜Ï5ÿ¯ç©ÿÓyí–ó¿—NRAæùùׂ Ô÷^ ÐC±Š ©«ûƒ¥±·ÿà¡(ìÿðwxq¯â<ƒõ{?Â%¼Šçñs¼‚çÈûøÇ^&AœÅ÷ð"ÇWq/£ðõ®ýHâ$ÎàÃSx/á{øÞ#aœÆ£¸€‹ø6¾/=�<@|üÖ=D®îŽú³žÍØõç²--`î�ñ„58üùûpHz­Ë2ÿ‰9© �Â�-�Æ4€x‰íj)ðé^¹ŒŸº0A6^saÖ¯¸°ˆrX.,¡ó.ìA½.ìEš˜Ù(wa‚,¬uaÙ(ráÀ ýd=²‘åÂ�`³8ŒŽ ³Hqx]˜çσHb7bó˜ÆnLà ¦0�y>o ³˜Ç,¢hÅ,f0Ž]˜@ Gy¯:µ¨@ª° -PPƒ*Ô î–¹ÊòÜ›e·£}ØŽ–?bgéy3· ³˜Ã)¤–}t,V£ †1� (·ÙîG ³8„ $¹ü]8Æ#�åQ(ØÀõÌcGÑŒJTb ¹Ä1Œ¡Iž=F�Å,¦0ƒ LòØçq•\û AGy~’¸ˆÙ_¬;3rßV[>ÝbË_Øb˧ZbòÉͶ|bóùx½O>ÖlËóÍSòÑM}rj“-ßÛ`ËsM×äÙ&[>Ò¸_>ÜxMži´å{£ò¡Æù`�-OרòTÍ5y²Ö–'ªmy¼Ê–“U—䱪)9QaËñŠù@¥-ﯼ ï‹ÚòÞr[Þ±åÑ�×ds£-WÈ»ï´å]lydý:yx}TÒ÷˃º-è—äþ°-÷…äÞu¶¼S‹Èwk—äÍ–»µ]r—‘w¬µåíŠ-w*)¹Cµåv5%·É¶Üºæ‚|×[Ž­¶åme¶¼¥åBìßåÍ-urs}޼©!%75ôÉ� kå†ú rmML®®JÉ•ÝrdcL^_*Éa}ƒ¬×†J÷®»£@Öê÷P>nhðìýèqϼ3@°Ëþ@úØóÖ£0–UZ˜'¦ÖÁH!òNmä�Úªj¢æÚÚ "l!u[ImÍR¬VÚÚa5YµF¨­ÙJÄwI$ð%û•Çß»88òÂ{�^ùø±œÅ_z7Ÿï™»[_»ýÞþý_¸‹üÓ…ß.$®áʼn‰xeìÁ}Ú8½­)õÝù©{/kÙ|œ}·ÍÙH[¼Ÿ¾üPØPxê§ú¿òæ|Åü›_é¸ðö“…­Ç̺ ;’-çúNuT' °·I{þ"r‘÷Cß Ñ›²˜{ïÖTU“|5_¬k¨­)*\åÕֆɋ‹¿.0º»L³«Û�š?þ‰ÔLîØ68¸mÛà ¤|©B(�­(Šƒ¢7ô¹#ùµùµŽRUÔê¶ ,ÒÂ|5¿®‚°X‰µø>É)éÝ:÷õøÝ_ÜS½øÞ†�MÍ#�eâÐ'ß•š'ßx´«<þ�Ôõ^á•ýjÅÀ ûXmµ?�Ú¤^"‚¼–åSë½¾ÜôÖ»vV7Åz¡³Ö¬ œ·¶Ÿ}íôé×ϵ·Ÿ{íôéŸk'JIý®­›wÕ•–ÖïÚ²e¤¾D((<ñöÓCCO¿}¢ðøÛ_üêÛ�¶7kjÌãí…­ÇöÔÕí9�}'¿â(bðžU¾ÔrN#55ËÐE'jßzîayjñ}’Kv{ [J¶˜-«…æ�Çï.©{?¹,5ûÿ zä–Ý�Óîð±ïòFûñgR/êQ †�Ssg0UœãFž¿iSU5©« ë+D7¤PuMXŠ×nÑ‘zÕ)~áêºÄžÁ'¦š[f¿9ñÄß^|_ëj®êÔ «vn:–™‰�üÎô3?»‡ä ›Ìº¦îõ$"×D {ïéh?¹¯~ôâøÆ¶õj£Zº^ Kvž;´ã¤Y=ó£e‡"×C@¶ý�ð%ODbe,�•LI‚èeþV²¥bí`¥š¿j ©­ih,Î!Ü7áìuë/ˆRZEr‰¾«îÀwKÍï¼C‚Ÿ�Êš•ñÙ9ÛOAÀ´ý�”'5óê+Œe‘|oªDƒAn€ÏûÊF·êó™1'òßeñ¿rGjÆŸ�ê{è@=QŠ7nÒÌ©ÅÆ�B~#Ì\}¤'šxnFøÛëmU­ vœbÝÏ=ûÌ×yø¡Ï�}`áþ/ž¹ïôN�­•’"'ÏZ‡RrÐJjcŠBcýÆThÒLP%IcZ‚JZk(-¡UUÍ-W:Òè�´GË{Ò±¾HÿCáá+–Õ®¤cR8‘L0¼] iªå²´övó¦ŠEc‰d<¤©&Ž–kŠÕ¡%”q ’®P iìcr”Í5¬ìqm\2Ò±˜•P’‰�’4C–™ä9n�–“h9¢åžýÈmGÛåzr’ zFÁX\sl?ÞN›º�0I•øÍ4­›™ãOŸV·Ö1N��Ä8Û U7�"A?ïTˆÜ$¤PQçÊ­¼–%Œ¸u*ê�º�^F;ÙˆSI¯pj…JaVk†J…èŒYIÐ…1ÅRò´f�ÝøäílÄ©GßN’ ÖŽ¼¬ö¨Gï¦ IÅ ©&•Â�qk©â¢åT /[¢G"·¨ÔJ† • : ‡.ô+qS‰ÇJ U )Ô3`¨Êd‚k´ýN<ý£‹:a *Û2!ê6”ÉÄ„¦†TF3M'ûÌGéSï0dP„,K³(1©¤w*“ …zÂÔîbO˜ÎE´ÄUâÌž’˜às;ËÉÓêÐT31A�çR +cì–´´„B÷Å#Ô£ç[–²É2®b_¨NîŠG4UÉS:¾Ô‰�¦²$t1Ìl‰–;‚� R�ί0=Iïóé7(üš�8Â~®U¡4hÿ’ˆ�_�Þ¡BqÅ ž Ž,ù^Þ¨GïŠ+46h¨!6[¡Â°á.ŸßŦ†–Ì™&7ñFË^„ê’¿AÇ_Ǩ—_Ùü èÔ¯Ó#*7¹l çFŽ0§�9"w× @Ô™)Ååð@â."é<&稰†©ÒXBc#”±_ï7h,®±ašÌ¼Ÿb3¸jËQÌÒåeÌÏK…kɹ‚ìêâ!ÜLÎâ—�ûÌxNHž[ïf/c¿îfNuV3,ÊGÜ]é�6#ãÎ,¯ÛÁ%É:wr€_ì1TUS}!%I]I&:±’Nl�8Yívº«JÒ©¡“z–�BÛAØ %Ú*h;È2¤]@üZ{´¦´@|”±f”·"ÛJjV2>û ЦÐfö1äå àk{œµ¦aÃ’L^2az"âV±s?YæŸ`{Ò·”I?ãYËLWw©�°{?ñî,Ëÿ¿3æwW“8�u£°ÿO›�êv–«[p4w;}¢›íiËb­-½/‡íÐìp>õ„ h–¾‰úôM®—�Þ¡èg¦ýœÂÑaƒt—MÒ,=�ô7œÒRŸžG½ú!GŠõŒms¿i' '"<ìrÙîl§:ODLš¥w²§~½“ w'Ý]š}[×wÕ;k¸•©-+c/zmY#ÃÒ$[6¤�ǤYa%�Šz3Ïg8H}a%ÏjN_Øð0Ao¶¬àRÿgíÿ*ÿœ„iÝN g"ÑrËò¯ø|Žÿvê NvWyÅò“Ýí�ÕFƒmìû…½›¬*¨G?ó–ÛsøçÄM‰á$¶o¦–°Üû–ZÂldiîRÞ&ù–vçÞF6ÎPIg™z‹½I(Ñߢž°ÊFˆ¥Ž[c5>q?mϰÕ=ËÕ��(ÊÁ•Úˆ– ñ8ƒ•„¤ýaÞä,+¡L$xâ?.%ÑòžAö=<4jhy ÙŒÍÎï�æþY •tcsh“II> endobj 283 0 obj <> /W [0 [443.35938 0 0 0 248.53516] 39 [654.29688] 70 [562.5] 77 [264.64844] 82 [560.54688 564.45313 0 0 366.21094 513.67188 338.37891 560.05859]] /DW 0>> endobj 284 0 obj <> stream xœ]‘Mnƒ0…÷>Å,“EdÇ�D‘REbÑ•æ`ÔR1–1 n_1NS© Ûúä÷žgƼ¨ËÚšüÝOªÁ½±Úã<-^!t8ËŽ´QáN´«±uŒuÙ¬sÀ±¶ýIJ €à`æàWØ=é©Ã=ão^£7v€Ý­höŒ7‹sß8¢ XžƒÆžñâ¥u¯íˆÀÉv¨5Ú`Âz¸ÍŸâsu’ø«Q“ÆÙµ }kd™Bä�UUUå ­þwŸDW׫¯Ö“:É!BŠ|#y!JNDÉ™è,#•‘®”{O�¿y�çSI²ôÕÏäMcRz¥ã"ïÑ´U¹Mó1µx�6ÐÈ©í­acññ+nr›k[?¥ˆè endstream endobj 9 0 obj <> endobj 285 0 obj <> stream xœ­W p×™þ^wÏ!�Ð AwÓîf4ºo�t#�nÁ´¸f4º°u10›#c $8¾*$¶ËÎÆv6ûÆŽí�ÄŽ½±³fSöî&ÞT²[›Ên¥R›Ä[I6Gm9 ^¿î–Øqe·òº_÷½ÿýÿÿþ÷÷ki˜�©Žž‚â™õ'm'õônéÝ«×Wä{#ãá)þ—B!À 894#Õü�÷8ÀSóÃS#ã_±=P ,ÿ!�vz$<='V¸þ‘|ÊÈØ‘ámØ÷à*_ fÂEP>::N¾jÓÒàŽÑñ™Ãu­ö �Ãc“‘pѽ'î×^žRÓ¿'i"<>Tø·ý/öõW>59=£�c ë*:4u$øÞ÷gàÞ'œºŽ4°8ìÅspãà�Ž<p?K;<Œ¦ßÅô}B#€cl>Hjýpõ|kR‘¡qiÛkPx®}Ù¶×íKÛø{§Çi0ÞúuF>{ÿûûÜ䇫oüsR‘s@¸EÝNÂLã™nvpf”`vdt†dÿLxŒpààEìàÁ�3¼†9+ó•ØÉE€û¦EãH®å‹ œ!alOØJ"šoþŸ0ÌLànóófkîèhFŽØ1 ;žà �|ÉPZmcY!s† ¦ýÄx 8 `5ÒÁ#ª±µcû1Ž)DqGtÝаÀ‹¼ÉžþÓO¾>ù[[ñŸqmÿ— 'pÏþ%.²Œ,#=äËä·Ü:ãj±®g¸g¸_ðµ|-µ®ÇŒë}À¸m™¬ ÕÈôú|Hÿ½� è¿ðÞÀe\ÆU<ŠG‘k`§ñM¼€«xßÇKxœü�ØsÄ…“øžÄ9|Wð²q Oà<ˆ§ðcƒ~¯XZžÁi<�ð ¾…«8‰óxOãE|ŸÅãøk¼„×É5rÃÐÝŒÇpÙÒÿ8¾„ç@qNáA<ŒçðòGÖe£ÆqÜ�q�ái| ïãÇÄ‹{ð\Âe<‹¯ !àÏݺÿÈõO]ë?Ù¸\ü¿È“_㔑Õh1Þ8óÿ›ù/ß„~ŒïBìîÇ>¡{¸w°i�Oþç—Ê;WirŸ£ÔÞGŠÐ—ª%kví„�Ø;ì“v~³}Ÿý„�‡VRðÑúÿ |R©³�/åúœ§‰Ü>ŽKãNp¿âx>°‘¹H{}m ‡ÞÝF“:wQr–ª=ìèê§ö³}ý»‚qBÎk§zkêÚèÅžà‹<°¦N‹s\}W0.ðçµéøàóùØ{zæ Cjd>É’‹»‹Â&ñãàô1–‰íV™…¶ì<ðëm<p! +� ·\V’¡dÈJÆ ·\–D’AJŸtã�§œ{«<ûÆ!.vãoª¹.ãa£ååvÚ¨ÑO——ÛvxÎ6cv\ÔGá{p!ù%>É…¯¸°¨¢´¼¤8Ë�iWÖy/ÖTVÖ°>P°eKA~ ]Ç)ýwdLh„Ë8°\ÿ? -x‹?*´B@²)„wØ!8mN.‰CAÁòìªÂ¢ÄMÊTâ(#ǽtý=¾øFû_Ì=9ÿŸo‘{¦ßŸÿiê 9ÊÎqgð6ÿoÂ6C—;à²9ØyâX¢*‰”·�T¸ ß~£ŠßqýyîÚCןç÷·æOüñ¸gæO1]ãúü/„vxP�;n_ÞÚܵÕÕi¹E®èÊUÉÑ$[šƒy^ì+ö/¯*(ÉX^UUX¤f”æe]*q+¥µ\IñZâÎÈÌÊv+ùdE¶².•sg®%%ŵ¤";•WÖå“2&Æ»J†Ûšö×\ÙxàK‡^Y±âÍÔt‰ûFDZ޼ü= }'·óŽÚ‘‡‚Ïîj˜ûúäÎØWZØî¯Žî©è|êȼ³üh^ºt7g;¹ª¸­¸¤·¨e´HÛ0¼gÓŽÏöï<¥åƒ`�þÿ_B;r±*�²fÕªLGT`._q�¯¸ ¸°He†•¤rʺ|n±ÈVò9fù’¹–ãjë¦ZlÔ6ûÆôÑ—gkjf_>zâõqµm™lí›®_“S?ý@ù¾M¡g‡v<òíñ ãß~dÇH|ª~lKý�Ï4ohŽMÕ³³ö>ýþ7v@Àj`U`™,Y®¨ÏåˆDác15ìÉ(ÉP̯å²ÝFȸ wæZΈaY>Ï,ã+®>c妗ÃÃ�ß]›âÚ|÷#û.ØtUnkÛ=Û’™âoiÚ6Þ$Ï–ÿ!¸ ÷±ï~®£ùÌë‡wϾ~º¹ûákº»Î�mjŸkûMÅHWáæñ °"ö[¡>ˆ�ô‘ľbùr¬r9¢wÀˆš¯8£ª dßžÂ"Û’xqkˆ\&—-‰YIqyEv*ǵxõþ¦öÓÏïšyn¬ôú¹I¡dbßæ»¶mðõÌn8[2¥Œ]ÎÜ~î�è†þábkç…7£=�¦¶œ –�>2°aû™áêÎz­,´;=qßµ»‘7ËóL·=ºÌN¢$ÙŠ]a‘¬d”Ö’’â¬l‡•�Ùn¹Œ³}Ûô¶ÜÜíÓÛ·Mo÷rÙ¯}¾§çó×f|‡ïœËîº0±yóÄ…®ìÎ “�ÀäÃsó!A4bhî–T9Ëõ¹\Q¶0©F ³ŒØ·eRn™1G™e‘#Ã4‘4]}žûyåÝ_ùâÄ–””ºñ/ q¬âêºæ‰mM#-~WfËá]mãÍëø»>üƒí_n|à>tíá¯D§¿~¦¹ãsßý¬»ëÂøæÂ®‘ŠùM÷´mž¸À*æC÷˜agÛÓö¤$[¦#º˜=¾â⌅VͬäÒÌM“Eš®|�ì$Ùw® 4äÚKs»O3Kù‹×§„jûWmüú–HÍÚ�¯žjcçxà¿!TU>;à‚ÝI’ìQÞ™l®�Y‡I Qx’­ò²þµù{Žý+)r›?üWü%–¤×GŸªÁ!k¾�§B5V`%³9;ËÍ;¹•öhš3ÍÒ–micµÇ[@¬êÍ“l!¯ÿwæÛÓŠ¶ÝÝšÕ�JœŠcspSÖE²ªðÔ|tŠÿû?Šë÷ô–¥�^Þ^/|ázâÛ B­�?öè#gNŸzàþ“÷Í�¸÷ø±{Ž9<{èàÌtôÀÔäÄøØÝwíŒ „CûöîÙ½«_ îÜÑ×ÛÓÕÙѾ}[[ëÖ–æ¦õbzrR‰»’ë•ú¡dâÉ®z¥ÞåÏ#Ô^O‘vø$è ÊmÝÁÆ�,kE¦*¨�¬‡c‘†æÏuÔS;SÑÖ£´uõ¥ÆXÈ`úóÚzoÁL~å"Ï‚(WߤM>�,/Á› |m¹�½u�­H�±Ø`¼Ú¤Oœ€­þA�vø4…øY iþ¼¸)ro¨ÞŸOY€ˆÔL¹z)‘Ž�D:";•± þ •BÃZ‹?/N¥ÆÝ“@™rØ„CTŠHµ«Ê@g0&SR<ÞTdJž˜¬È’¦%ô7s˜´"ûóâêâ 9Û�³=ýÁD:¨t¶7ø"G¸úP�¿ƒœí &$ЀAå•"1m¤­;ø"ç4ä=‰èœÁ ‚�GͺA$Á™´ts"/›èJ" Áä¤DN“6gJ¯·¤�ˆ$Òç 8j0Í[™@²-à $R¸eœ'NéE[Ày•I/¥�eÄŸãê» r‚ÌÅ“ž„¡©Û’œCa´¹EZ‚[¢HÓLGÏöÝô ¯?øR –�ñÔ4­Ž5^cœk÷)7Óº+H9µ1NÚ}!Í£0”W¥ÁX„z‚L6ä‘5�¬i þ<–]RPò(Z<336ÕH;|Jµ©Çß¶jŽqœXƒÄ¶âRêJ{ÇBI˜ô-Œ]ˆÛ°±¥­±·Q{ƒÇ© ²H½Í¾$”¨oS›WfÝÃBgÌÆr|Ògm�³Õ=i¨;铤ýa*Ô%LC!Ka‰I;½F‘‹ÅÂÒþpبCÆ�ËJ^[7;÷ô•t‰lÄFó÷G±þ,‚ÔàFO•FI(¡ÿ…‹µõPÁËþÁ’+=Éì¿ná—ê1ß§±%6ž%�Qå°Ìb‘À^åˆL¹z…JÒî Ì>õ lÏÑb1)&Åöÿ´#h>“$P˜ÃÎì,³(¿&GSn!¤ä°Ä 'ôrدÒÍyï[œwV9b@±…‰ùÄiYÊ‘]fâQÁkø’@%…b"x­¹c»cýŠ¬È ¬eÓ[ö0<5G3´„ú%fð¿?g¿ endstream endobj 286 0 obj <> endobj 287 0 obj <> /W [0 [443.35938 0 0 0 248.04688] 30 [242.1875 0 508.30078 0 522.94922] 69 [543.94531 0 523.4375 563.96484 530.27344 347.65625 0 0 243.16406 0 0 0 876.95313 0 570.3125 561.52344 0 338.86719 0 0 0 484.375 0 0 473.14453]] /DW 0>> endobj 288 0 obj <> stream xœ]ÑÍŠƒ0ð{ž"ÇöPSk)ˆP´‚‡ý`Ý>€MF7°ÆÓƒo¿8ÓíÂ~8™Q6Uãläâ=Lº…È{ëL€yº üƒu,QÜX·;ÏDÙTí2G×O,Ï90Ø9†…oÎfºÁ–‰·` X7ð͵l·L´wï¿a¹dEÁ ôL”/�íFàc»Æ€‹6.»kÙþU|.¸B'Ô�ž ̾Ó:7Ë¥”²ày]×uÁÀ™ßI±[¯¿º€åiÁs)•,V%ÔþŒR’T’é‚J¨,!U¤ê��*R†:*Ò™”‘(w> endobj 289 0 obj <> stream xœí—]lUÇ÷ÎtÛJÓ²¤K?)³]ÜB[¶t·»­¥´öƒª± ´¥,°k»í6lw›v¡åE«±/šFÐ'£cƒ^L4ò >(‰ F�Æðƒ˜† ‰‘ ávÌÌ®Xªñ#Q£ÉüÿÙ™sï9{Ïÿž{2ÉE¹L£ÐßÖÚ³µW�) Î�Ûzj¼{gÞ(ú{z[{§æ£Aôž�ÑИxU<r%°w841öu k8zxè¾÷_ï¹âR$Üøå¡'AÌ�H$²ù2 š€u‘ÑÄ”£P釼«°ª!]Ì»pl �]6šSß•#ÀM@‹…FÃ]þ¡ç@=²x,>‘Ð?¢Ôð��‡Ç"¶£3ÀU óM¡ÏœR��@è:yPgÅ *‰a3FK  QR¦~/,ó“šQ>O~2¨·è-JÑòuÖÈE–9Ÿo>K‘“Ñ„(„t‰4ê!Oÿ¼&ÂöÊÓŸ|XòH^ÓYŠrÙ˜þªû¤ßx³æ‰A½%Ù¨©ëò-du¨¨�]½�R<<>@q4”ˆQŒ-+ÉI«zrd0��ÆL¯4woèUÒºUî7»$ ‰ �NBŒ%¦ëF�—Žõ¯õ3úÛ)þªbª Š92@‘AàÁÔ[ìÇ+\ W(ÙŠªH©.¯vkGÛ6ÞA#–ª·ºN¼×�xÁÜÌ¢#Ž'ψÜä59×ùEgò<’úu©ˆk”Q åᯠÔ{¤«õoZ‘Óœc7þ½Ï8q�|c÷¾_³ðyW;ì.{�ÛUnË´ïëÈTÝÁ{úº»ëšª:ªÄbφÀ`òcáÚÚ^]�|ÍXÃP6+�“wÚ]~§]4]uâÅöd1‚+²KÄä+@”»ýu#A¾MT—ºÝ¥¥n·ìr­Yã2~©fÈbÈèL58*Ö§mA™¸+mKr¹™¶îåtÚVñ0›¶3HÛ6*ÉIÙ¢�`aF&B‚âdœ´g�0Û'ÎFº 3ÌA¢„§�0ãL0BœµxØ„—›‰'Á€é9”ö¥ü›%ÄÂfÄa¦£áÅCÀŒXª@»­AK«Ð–©Xšµ•ÚØÆæ¿°‹;G¿Ÿ{ÞÔidó¡ÑÊ q5ýëÍÚ%£‘j˜4é!t;ÆcVc”6P�Æ$#$ˆ¤÷3aÖòaÍ/ŒQ·bÔÈ .Õ¦™½Qy›ÿ4[Æ#&ç™ç‹ÿž·hÑ¢E‹ÿ~oÜRi6ï]¿4î9/d�àß³> endobj 291 0 obj <> /DW 600>> endobj 292 0 obj <> stream xœ]�ÍjÃ0„ïzŠ=&‡ Ù—€1¥úCÝ<€,­]A- Y>øí‹W!…$øÐŒvg¸ì®�³ øGôºÇ£u&ââרœ¬cE Æêt'ºõ¬ã²»öÛ’pîÜèY]ðOœì’â‡gã<2þ Fë&8Üdd¼_CøÁ]Áš ŽŒËWÞÔŒÀÉvê ºdÓvºÉþOñµ„’¸ÈÛhop JcTnBV !DuÛ¶mÃЙïUv £þV‘ÔEµ¥hˆžˆÎQ!‰ª‚¨> endobj 293 0 obj <> stream xœíY{l[×yÿ�s/EK¢(QE=(>t)RâSâåC–(ŠâCï'õ¢˲"Q¯X–&+²µ«›Ä š&žâym3¸Þ0à ¯ØÖa]AÑå�BÚ )º"´Xת‘É¢©E‚Xäp.)Û2²®Ã0lø}à=‡çœ{¾ïû�ïûι÷‚Pâ 8œ wŽÅÆÓ8€ìès¹Ï\ý @Kœï¿ü¥ó?È9ιÕÙuúy_è:€‹³YÉÆ8±x~{á­ßW< (C@Q`)9;ïøÇ­§²À·´”œÍej€˜–V7/Ÿ«Tü9PóPÚr~mnÖó¦ÛÈ @¾nuöò:ÿ:]p€áÂìjrÀ»pàx€V¯¯]ÜL¿ ZÖ¿¾‘\_Ê{ñ*€wÈ¿FÒWÿ’ é4ŠAþùV\@û÷q à2Õôp�ô#Ó½�z ‰tGºƒ«zt �É ©½\ºjA/-.m’J +�‚2<èkGs‚äý™ÿ«¶;3Å�_žà¸»¬ù§ñ;^Vþsí§çÓ©V®Š7È}  Nð€íGõÜöÆyT/n$Ÿ@õùÙÍ ¨F^v,…"«IO‚.Ï'×6ÖV/0•i‚ì@Ðh@¦$gá&@ ¹|Žç(åE¤3Æ·aÀvÞD¾sä�$�{ô[‘¬½�ÊrpY\x\‘�) p#†nôb#Ç–±Ž-l§ÓÒn„¥Þ c “˜ÅØÀåt:ýOô½ôßãoføÖî8�ÀÓ†Ïð"iÈÖ t¤ [§Pâ^¶Î!„ײuN\ËÖeHÀ—­çÁ E¦N*¡0…$–±ˆ%lb kx˜C¬aIŒ`kp Ž$ñ$Îc˜D¸ˆe¬á h†MpÇ6,a ›˜“z¶²}™þ6¬J¸$¥ Hâ2’vNø¤k`¸¯ƒ!«…á-–Ú‰(ÂFÛÁŠãÿ~½ì/Iz2i" èÄ<Öð¸Ôß a·‰u´Â.IìÄìý1N �U¸Ð; ¸„elb)kÏE Ë-$1º$Ü6aÀf±Ê$*ÖÍP%ù†Uâü¾‚]ìâc|LJ$Ö“a2L>M^•ø.ùˆ|DÕ4žåëôïéGœ“[à>˃xïâûùþÿm~_f•Ye}²d_‘ýPö�ìƒ(…UFU½ÑE„bâ·hÄ"è©*H~œÚ!¤×Ãûž¼råßþ—ðì§è�Ãó­Ï..ŽìÝýúÙK—^Ú#o€Ã@ºª!°ùD·Ž¨ËóäjV(‰À‰nŸ×c¶ÕQeî‘äÉ–¶ž‘àZßÖ©ñÞÁ�é•ñéÇ&W莡«µy¸˜/І&­ä)Ÿßk?¼×i÷‚ 3}@­ô&t€¬ÎI½ž ݹ“uJ¢.×Ñíók”„Ì´/ Ùž�l;£uU…;¦=žéG�ÞežW8§>5²üJ¼YïÕ:·âc—ÃfAt¸A1ÐFºƒ‚ .;”D°ˆî ñzœÄF¦þdîù®Øs³c½ýsn÷\/Ý鿾´|c(ÚñäX|³ -¥;(”°Uñù\ê[¤$õ¯d€ît½Ñý^7¼éª¦7a”,"ÿ�E^Á+ª”„ŒÆ¯ôõ?3љк*;\ígĦӡº`é3o꓊Ñ/<±òʨX뭮˥.½K½k°ƒ` e5òŠ*ÁkT *Q=sû6ùÃÛ·»)×ÕuxØÍžŸh-•ž)EÓþ¹8‰Ñ�ÿ•z{ØÛºƒZ©·L#úËD• ò©_�sgtœZÕ³pÆÀë§F8™ŒpõggÌ”ÊxŽî¤î®¬�ÊÃuÒS ·©¯¤R„^Q·…ƒ•©¯±gͦôm 7Q ýÃxdVÁ’]ƒ#`ˆ½o#ÚèË\Ýý��ýn骈¿r~åó##Ÿ_9ÿJ¼·s{|l«£ckl|»“ÉX¨žî@q|�m¤ŠyçÂwzWÛÛ/ô\\žŸX¦;õã=±SŽÔ=ÒŽuû‘ô­¢7á`zš-~]æf'q‘Gü2�éª':ʤ�æžm‡»~®%Ú¯÷Ö�5vÚý�ƒK&»aH<Ù%ø´gÃæ–%…×ÞZïhu V­²Qiílr;&_­Qtèª %Žp“g +@�trÀ˜]WBߦüÛ´¯«ëð« °ÔAwPˆœX¦#1Hüe"wï­ÄJiM)_V£Zžx“î¤nµ&[[“­äñÃutˆ¾Œúì}T#i5™›AàœÄ"(‰œ»0¶‰“ñ„Ë+(È �åùy<åxÎyúÜRH®�q²‚!úrj¾Æá2]öšƒƒ{¦F¾x¸FNèZuºV]êCPŒ¦(Gö¡cÖi$/ðù�”­»Ü¤ÒŠ©&ØÂbCI¿r Ø_}�Tµ¸ôí~�¡26b‹LÙ"r®a^g�7.]jÖ5+ŒA[|¢ØØbTÕ([JŒj÷©öÔ�ÂgØ\w%ßÐl¨J@1�> Zº 5L™Õä,Zäâ'ù¢”åHÈ4ZÇÉÃqŽ3NÙ§�íó=ÖˆEh6öÖ Ý A¯Ÿ­kh_ëÛ ÆœSï¨C0ïë«A0’> 5dŸEÕ¯É,«�ØŽõýN_`Jר YZ&]ΉG¿®¾aN؉o¬µÞj�k¢Å?î2UyM  ¤ÈÇt娓¬9š^´°LpÅ#a¤xf³#yÒÖ­çøxTÎÕŽÕš¢Fc‡ÁkP\ݾ4êNó°%¤wÄêMûúj×XËÔ¢éZMö3¨=»yr£×(÷˜5§¯÷RW×ouvÍy)M%ÉŠz8âtº'}ön£Î4­\Þh?¹SV„4““öñöŽq[•ÚWYÇ"y aúC”d"ùxЩ8¯ß¨Þ·MFL1¡L':[|�TÓâ¶SÍEÅAe~´íð=r;(‹€COÚ@}d_z[5v¤½Êý‚M®ÕBvG¨3[$´Úˆ»‚5p�$§2é¿ÙFŽ’†îyo£¥L¯ÓV Þ)±QÿÝßUUº'¼e¶òÒroÓêÙÇÂÛ ½¨Ó‰z�¨×‹�'ãvËŒº¾¤N;úSCÀV{²‚/4ë5Íe|YÈæ²)"*O­§¿!?¿P«Òj=AÇ�‹ü•Ö#Ô‰µµb�àѦ>«µW •<_Ö¨6;XÞšfo%ßf¹/ëÓj–ÄÍÌ™UÓqWŸ89�{¶¨�î¾~±Á?.õ"Ä"v{êËH§q ·è÷¨™L°÷šüKM�Þ®4Hwq‚½Ccû‡HD¢6rþ²•8OòΦ¾@Ìßrߥ»)AêÖ³„ó¦vA¤ˆ¯¢»PevdåËyº¨œ7?€Žì�5úŽ!—‰Fª%û¿éZ�DVC™««Ëlîr¹bK,í��øÈF ê÷·L¸2Q)‰’ )iŽ4}ขF]v<MGå\Ý)Gø”38ßf6rüÓ¶èýôõ}ú×Aƒµ}m ¾4êμJòŽç¯ë­"û(=†&åªëQ9g^�Ô¸*ʪLµþ¤�ì]l‹ævçŸèHýÝéª$û,ÛÛK©EŠ¿c¹°B“ÝH}ÝOÙÍÖ…H°½PpÏÌ,Ì·,™ŒãNk³:Ò7:etŸS8u>�É©SVV””G}mÃõUÞÊš2C™^(VY}õ � l]céZGŸFUfEÚ‰àí ¢ZT '«ºãÂg^,Œ¾ÿ~…Ï%´T—{âéÀ^Pvófä¶€NQÈøã`ú€|Dö˜Ÿh˜7ù²*›o5Û­±†xDÎ×'óçˆ3õ“XÄæ"£©ê «„}¡õd�íÚÆc»6Á÷ÇÖ‹kŠø¢jåúðwÉ^ê]S� ô˜HyªšITCö˜5¢ß"j2·vQ®,™ýº˜„¾~ç±Á"�’/ª-ê�úò7NOKøb]ñȽwž(³ªÕ¶òå~¹®vªÕv ; 4§]ÔBöP#Ù”]£rL5%}¦D(Rh ÅPiñÏÇ.)õÅ|Q�beèG¥¾á·òøNŽos˜È/Rÿfè5 ½FRt¸ß4hgZ³Œr�ì±s§tŽQ‘Àψ‡Üޤ˜‡ÅZ@_€–�_ƒÔ› 8Ë·–IQ÷žÿƒ¡h·cPï²ÍECÓbßÕ)] öÍ3/ozý]v£Ëîu�Ÿ üöó#'�gß¡äý;¶32_S—ç»ÖlÖjÍf: ÔÖ ìš@PúÆÂ]s4�NšÀM°ó¾ÔæÍ–3G*hÏÑ;5Kõ&š`§Ïû}š`>/Õm4ÁN\ˆ&0J˜¦ ŒÐ4�(M`‘Í—m?�·’Ûšmgc§³}×iÝ4�M`�&˜_Ií!š@óò�%G9ÊQŽþÇè(‡å(G9ÊQŽr”£O&v†ÿßÖ!G9ÊQŽrô›Mà�E¡ŽT endstream endobj 294 0 obj <> endobj 295 0 obj <> /DW 600>> endobj 296 0 obj <> stream xœ]’ÍŽƒ …÷<ËvÑ€hk›“–މ‹ùÉ8} W‡dD‚táÛOävÚdbÎ'çÞƒ&ësmM ìÃ�ª�@;cµ‡i¼yô ½±$Tî*®jha²>7ó`¨m7’¢ ”}Bo¦àgº:êñ kÂÞ½olOWÙ¬ knÎýÀ6PNÊ’j蓯­{k ,Ú6µL˜7Ù�Ûø½+�¾ ”&X0ÁY…0C¸�¯mŠ0Gˆé¶;„“£a—D(°­8!> endobj 297 0 obj <> stream xœí{ x[Çuî9s/. HA‚Xy±¯$..$@Ü‘7H")Ñ\DR¢¤R²;VœÄJÛqéÔIäÔqš:mœ—æ5n¿:v³Öv\¥ÙìØÉg7NbGù®“´ �&¯"ð<àf¿ä½¾~éò•31ƒ™¹3çœ9çŸs†€ €[��#­Éáö‘Ü ¯@ÇÀp 8ñžç¾@*àÈðHräü'��€fyúÔ�A;9õFÿKG§OÓ’Ž]€¢£Ç/Ì÷zä¯ÌOè&æ¦g}?<ûN\€ðÂÂÜ´”—h° ¬ ËgÎ?}Ùü Å]û¢ÇOÎL÷§Oÿ €ä8@±qyúü)öq²×À|bzy®O˜¿€ ºS'OŸÉ=<êiÿ©•¹S Ò».Àk {s—>þs9(`ïÆ_�N€”~Û‘ À䫹oBàMý�oažÏþ€dr‰\‚©~óönº‰íjñSäÜÑ…3XPX�¡ò ŸßœPú�ìOîüÆáò¦×‹æÚüRúS-lxÇl.‘mdªY+H�lÓEØ¶Ž¾ÐÍ\X9º£+sÇ@w|úÌ Ð�´0–€¼@æÆ€,ÎÎ�\9¹|‚’L2¸ rÉ@o¾Ä)"@J™b†eaEíHɶÖø2˜Í†¼LX+>uð£â‚kä^º#~óOª�)È……¯€ÌÀ‚,à‚4@:¡á‚I¸ n†‹ð ³Ê\m6ärâlð@4Bº¡Òâ¸i¸n)ŒÓ‹ãè’?ÈýM>“Éæ>G^ _¼ê¿Zs•îšœà÷ywòîÜoÆÇÔ3æ Œ‹‰3NfŠq3VÆJØ"&ÀL² qæ)gl1Ü…ÎBÁˆ%…:\/Ôh�Ïê,øáîB]êRpƒ<_Ç*�À8ÌÁ"…8Ãpn„˜�9HÁI˜…9„8 >HÃ…á8Là ŒÁ¬ÀiX„“pÌP~¨ƒ „! pÎÀŒØs¶Ð—ï�Á2LÃ1˜GÌ܇90CüGì¤À¼Eƒ¹@…ùMTì\5 mÐ ûWp±ûÛo_û“"�t5Ì�„Y8 7ˆýNQvgà4BpNÌ~˜Þ㥱 p�Ìpá ,ø9-Êò,ÌÁ,˜¡C”Û0Ã~˜†eº‚¹j'mæjQƒÜà†>x< ÏÁ«�Åz¬Ç1�â%ü¾€×ñ:±“%r3ùùù_ŒƒigÚ™K̘×X {€½ÈþBR)©•ø%=’EÉG$_’ü“Ô%=,}»ôKÒŸÈŠevٔ콲ÇdßÚË{ùß�ðß/á^ÞËÿis¢h¼è]E[ô“bSñLñ-ÅÏ•T•øKÒ%S%K%K%w–ÜYòdÉ“%ß)ùNɯKõ¥ÎÒЛr“˜»þUy¦ô–Ò»K?ZzUî�‡wåË{ùÿ#ÿ™ü±BþŠü+òä¯mç2íëì§QÄi¬A2`&˜!H’ Œ“ ¬� \"c ’�Û.9ÉÀ»IºHÒ$u$ó…öY’�É€›d`€dÀC2PB2&°Æ ‘ L’ ’ 4‘ ´‘ -ÌGÛ’ DH– c íM;Ê÷“ t’ ´“ ô“ ð$E$-$õ´ï-1Å^ÚK{i/ý;$ŠaÿÑ4ì¥ß}¢çÔ4 {i/í¥½ô_-ü÷é‚ß@2à ˆüùŽB\@c‰ï½1æ+›eáÙ«…r¹P¾^(Ÿ!x�Æ*4¦ø¿¬?º£>ø;äói’�›Þàõe’�HÎ⬙ßòÌ¡ß={i/íLÔvÚì°�‚®û Ïõý{Ѹ—þs%’�WAqúÿr/0P rØ^iQÚ,äÊ1âÐò äLDdz«ˆÝ!6|ã­·~Š­oý‡Öé·“{7Ž7ÞvôèàÚ+�M�;÷¾5ü&0�(Y…2Pð*^Å1~tp ”1Á¢1êû™¥¥œ­0+O›ÐGV7NáÉÈrCÃr${Ï•T Š«„#« p”&>hD�Z*ÓÐB�ÃÃBÈîAåfeæ¯Ss ÑX×`üdÏÙ#Ýý}“K#“‡Æ–Ȫ¹£±~ œ-ÝßÖ2æÆ·…#‚wãz,Õ,B2·NÜä~0HjýDÅ‘Vje~äj¨Q‘†#Zâáæ…ýž¾ÛÆbú@u«+1 M&|]¦€}Vîûàâ}éz“ 7'Ϧ‡Ï·Ú9ÞãÄEV¡$/Û< ä|0ŽBÈ�ÿã™÷t´¿{z¸»w&œéí&«½ï_X¼w[âÆáô™ ¬�}dJÅýÑlæü`ö‹X‘ýGì#«ßìüY' \ UdŠwŒU^Â?Èþ *²×ÈjÇ:²Bn�hÈý`9ÇßÀ¹À ¼R�8”¾µ§÷]£ÉŒ>P•4Oðu[jãûÞõ´iN>tùØÒ}C¼AÐÕæ™×ìûT{ö5³�Þ8⯠” ¼’,NÉk?ø ~øÁ; Óѱ±ÑIß­x71ñ ^I)wÛÉêÆgÅÞ.ú6 YƒØ«Òò¯ä”¡8‰p2†cœ‘Ñ(»æ'̬ir~�‘H�±M5MØ ‘° Y;²´„U§°«*ÞÓÜšÍ"¹Uk�We¥ó§ˆ”¬‚js~? J^)NŒezâÛ BŠóYÍÎÞ^,„#§ðþÛƒ |ö“@ .·Nœä~(ÓN™æwÜQØïMᢷg¥¥e¥'ÿìu¹zƒâ§<}ßñ¥ ~héø}éî䅑᳉ÄÙá‘ IúÈ<1‘U�ïÖ'Vã¦%Ì?Õ½ÜÜ|¢ëôâØðÈè"Yµ�tµðe¯cWk{g„¾E2[ÐJ:KõošGQq³_O�ÅŽ¦.,÷ õ//´^9LV¹¡¶Ö1Oöð@¢¥EÈþЛ}R¹uRMîåÝîˆóù1€o²+)åß„FBWÄú® ¾ m&ÚÖkj§,Ioä†x|Áê5ïç:¸°~ÂÕj�.Èo£Í×èçÜz…KáNÖ|>kØ`á}&§Nî¬ðµÖ…Fƒ€à ~² 2KAß�§³Ïþxöà«T¯‡rë„Ák`¤û§m'ñj-2Gœˆú©ä(qŠJ Buè—¾>ïÇ?�ÕÑ€©9¢5WµzRãž”ŒqÎÝi×¹zc½Ü÷¤GË-Q‹²F­°h‚š³ßm5û[íµ·›ëÍ5\˜Ì­=¹°æõ—“Qœ’ñÿ' Ï!l±Õ2²Ö4ÃXÆ=­ýͳ]î”CßToé¶q�rÎ&WŸªu6Ÿì>o÷�7 C>Î~ͤ„ÁÜ:©ÁkÏ~ úÒsç`ß…öž›{šÆ�.c‹#:ð�F}½F›sFÞ´2˜^ir�10�Œ¬Õ‚Õ šrëø/ä ¨¡VäfszÞA1xKŠ›‹Ubùá3‰¹O§‰aÓm2Æ0l°¶Y, ³»ÝÕ'¿taàtÜb<ø¹�h‹É×n³^3éÃÑñ@hË­^ËKm'âIeÁ" ÙßÌNO÷¹ŽŽßKvÌ„dçpI3�òõûƒcao§Åh�”7�Xin˜oWèJZ´ccÞ‘æÄˆ§Z®ª¥zr€´’ç "�»aEÉ‹æšg,emçTFÞœl|ñnÔ‘òØ�ú²ò¸¢¸-¶ñ3|0.¡>FWÎLÂx ‚РÛԋBÙ*èäZ^ÃÎìZ»C”V ƒ•´�y¤«ÄïvnDgç¬àr¨LF}5'Œó.ÓW/*«‚£‚Ê£Þ§ê–§µ^Ș¨™Œ¼ÉÄ»ÒÞHô°ÆVQ«zÉÜä14T²¥v“¶^ŪZ<Â~�<¥ B½ÎââR½R¯Å}ûø°>ÄÕò_Ë…ôÙ;õÞj®ŠeU.�ÝG϶Iúþ¡¨Ûé :]©¡Ç§�*³r2-al™†±t:Ôäió�+�ŸvFf�d¿�\{ÊëÍ~r9zŽ�¯;ÒÈBʾ¯Ž¾ã™ƒHÎQhÿÖv;X qrŠè›wôDç‘G�…‰¨–Ò,J§²—ÑþÅà+äJÖˆ�}à6d„ì@ ªÉê=RÍURD]¹©>ìOÿé¯B�·Fci”Ã¥6¾#Ô•Êãr%嵑¢?^£zÏ+ymžUí6Ã"¿[Œ7¶Êˆ*è¶úK4¼›oH‡ª-ê>mMµm®µÔºÝn‡¯¿;ûqµÙ³„cn-·dŠ×@½s��"m“±öm‘âÚ°+¼K¢y+%z¼öÿê/´,§RË-ùÏ@‡ÝÞ´;íhZI®4µF"ÑÑ@ @Ä5^\CÄ5í&¥Û Íi5ªÝ¸6Ù&cjøZøã³1Ë€…aßéiÛ‚µo�¿Œ›ÝÍ'ûÒgããÄÇQº×(O<þ‹(ŠK·œ?Ø´—Üê'ž&£¼¤)¯ûý¹uü5®Q�ÔRËÙ´eó9žæ›ÝíÎtJÆÚ2òÙ#èÏ~¿=å àPV7êŽÒ·À‰ ר?cÙåÏ |cøTyM[¦Sœø*®e_³vq\—ÕYˆokÄ5Ol{B¢G³5Ƕ±²”n”•²¬¤¼¨)ÝX´�e¥Å²Æ¾…¥¨T.e¥riײkµIŽKÖ^¿ž/Q—Õ½¢ëòû»t¯B ÑâšèÇD;¼ ™v{�–Ç>u¨¿Ì¨`Ë eÝãŸþëƒ£å– ¶ÜX>xýÕc*·FãQ/þÓë§4~�Æ«¥~Y}.@¸5¢ :‘À]¢P�wUpeÊm)ß²¯üêð9…©œ-«‘/íÿî¾ðÀ3R6ɰ1Ÿ’ý…¹ÛÊu[°lãZ]¿—J©€¨pMŒÎ´ Z4�ØŸ}ÈþŽ{ñ\Ê›}oŠŽ¥ˆ{7®ÑˆHôd•Øô# ჩ,õ (îÞ½µÛyJ©Kªäq{—¡F× ¯4?Â�Ú?ð‚JÑ\¦05¹ð¯RY…¯7b¤‘µ%¹ÊÀ®­S�ÏpoÆ µä|§½�óÑ›—ŽÝ9Úéks8Ú|^ŠFÞj›­ZgµÊî]úØC}léÞ�Ö†s‡&ÎD"g&�kø–Õdâ8“É ÓbT{Qô�ÅØ0N"ô€š~ô÷í�uêæO´áw‰BYºñT›h/¤„Üz:>N„<Ô:¶MÇjº�`[§¯ßðÌ´µLò=—Æ�M†o×¾çŒéðZ^!0ÒÐtÓ{FŒ-rëDJîžÿ-QRÎ…ü™¾k! “y00EÆ’UnóÁfo»Ó??Ò7áêŒù†L^çÑæ¦ÃÑþ˜»Û“X�ëœUa£ß pösÂ,ÔÂVCˆóÙ»B�=j¶ØÓêm¢±²€XÈEúK‹2ŽQƒ-‹€¼O!ƒ’òÚŠOãG³RLdðQ]³NÐþ}k?´AÑÜ:)!é�I�Âï _eÑXdÛÂBcÃX¢Ê¥á[ݾÏX§3ZëÕàbö%eMÄÚ<Û˜:.¯vV†U�5ékíQ«ôÈw~A®phoŸð†TnÉ�Æxä->ì[¥§@L†´Ú¼½GB�³¿*e e"Ž^ÁÞlíhµg\Œóp0v0›–ÛûO÷yψÓaàµ5á[Ž �p wk»«>é x3Éæ‰¥£€¨ÉEPðq&B�JÁÈ~Äê‚ûÃÙUüfKºNËúो©N¾ë¶Ûï›Fô[Uä0‚bÛ§ï¶ßW¹cŸ™pá|¤<1…3"‚ ¿k±Á™¨u6ð&œ\ƒE˜¯46¸Cm¾~ìì7…»Ý¦ ÞÑ-÷ ½I_«ëÖ÷¸÷úôì>w“?ÐïÇ…ÆojðÛƒ\ö©xÐâ3éJgÐÌEÌ…ØZ¾)iû.ÍŸN…ÂÛv"(á1–1å%vôlKØ1ŒƦ£B&eóöNËú�V¹åØÀ±(—p';¶$<É‹›pûˆƒJú{¹u¼>Bos$»°ÀRWg© ä›=°ÛoXëWr¼ þ�z�ZGÇ}…§^Ô¶ÄUQ¹¡\cÕÔ™½þ©ï„ô£ñ‰E±ÒRms´Ç2¨)®Iâ`è¡9RZærùùwµ»D¿ójno$€„z�6ÆÁËÙNZ+JÈ )Ñ=£Ñãy3SSÙ‡ÖÝVÎåâ¬ôò–sëøCò?@G#Úˆ=μE…íÎ)¯Éjêyk$bOÖÔ×N4F‡V!h’6—ð$ƒ�z“+jªñq~GGÀ ÛK"¼ŽGp†ü9Ez _ŽXQMN�j<òò‰/SÉ?ƒSø6ò9Šö(.M·[£ulª*z|ª&VEÊ,J“Ã…S-Ѿ³\�a¼a«Bå4×zèw²;éru•yýîdOÒU› Ö§�ÎêÎcs%»’NCˆk±[|Uz§Ao7]q°SíRz8‹×l´GÝÎfë?W8œÏl´E]µMÖZ­ ÖÙt5VƒÉÓì· ö Êá(,†x)þÙè͸�÷Ö±ô‘GZydá‰øOÄŸ ãòúN%¡,šQüŸè‰ÇEK€/Ÿ#váP{ø€hç¡J¨¶ùP°i$ þ4{'Þ˜}}uñ��¯±_úL¾”l‚M�hŽ¡/û,ÞXGG lÄél}�#rüõ�±vëM<¨~ˆqÅm†:—CS®¯)tÝ6cÀåÐTèu¥‚® Qg©VØ8mg8_©êÓY_%}x‚|�r�»Ð_o·ëõv;éã ŽþÁÿ¸W— endstream endobj 298 0 obj <> endobj 299 0 obj <> /DW 600>> endobj 300 0 obj <> stream xœ]“Ën£0†÷~ /ÛE…/R !‹ÎŒ†öœd�&9Î"o_q~O+ÍKŸÏý÷!©»¦ss�É/¿Œ=yžÝäé¶ÜýHòD—Ù mä4�!ŸãuXERwMÿ¸ºv¢�2ùM—ùüC>UÓr¢g‘üôùÙ]äÓGÝ?‹¤¿¯ë_º’ R‰²”�ER¿ ë�áJ2á°—n"æðxù¨ûo�÷ÇJÒ0kt3.ÝÖa$?¸ ‰B)¥JY´mÛ–‚ÜôŸÝİÓyü3xv×¥,”2ªdª˜Ò×�¬ÙÃv½‚jPÒ –ɶL6æÌAi) £4rÚ#l Sªa³LªgÐϬfÊ£ Õóh‹9Q}—1U\=e9”2l¶å „i턜ù‘eŒzíÿ©÷­¶a·›j¨ˆî4dH9ý6#_Æ .1•E[;ˆ©¹´5±;…+\B[AL޳vñ2÷b³ø\û8ZÞVb[ݯ}ïÞ“ ¼ß¼cÛvÍŽ¾~�uY·¨íûëJÑ endstream endobj 14 0 obj <> endobj 301 0 obj <> stream xœÕœ @Wºï¿¯ªzß¡Y[¬nÛ°�”¸Ð¬¢­�((*K�¸BÄ%î%2&šÅ˜Ä¨ã˜UG PÓjâ21šÍL2.™ÌLâ˜U�fqŒJ÷íªÓ¥ÆÌ½ï½ûî»s_µÝ¿�sêÔ9ßwÖêF@ÐÃr ¡º¸Ì™>ìÔ‚p#T×ͬi¦÷Ëóðlª›7ÇúyÁ›#”E²°†æ)3q£þ=]€*jJMK3Ä�.€qÊŒ G¶ô{ ftc} ÷ÝæÏ°2ëk4ëé0 ½gιï蚈K²êÚŒ¦ºšâ{GŒ ßÀ¥3kîkÖyñ0Ü묚™õé©oP�à=ÍM-sü?Ãzì!Ä7Ï®oîÉ%ˆœíÔ †pP`¡î‡ dP 2 ÀN¨ІÁ) ÄÔâá¿ ëÄÔ¿<@v¥û Nbg7™i¿Jsˆ„|Qßö}ոɆÁ?)UJ1âà9K_�o¶¾Õ/pÆ_ÅL“¿ J BWÒL®(eOË\ÈÒ@J¥‘«(Š¡)FH{ç-G•Y­à+l%eSTQ”Tzú‚Ì"XF¼B¨ŸªF¬Ÿ¬Àˆì‰�Ã`8Œ‚R “a*4Ã\X[�PŠ>�¹0FB1”Ád¨�é0îRÎÁZ˜^—^0:ð×Ð«îŸØñׇÆ ¥cTÀÁâ�&WM�f…4 é08¤0BrHË ùVz¹>êa6´ÀTh‚Y`…TèY� VÈ…¹0fVHƒ4È„<1M 4Á ¨�S¡fC“Ösà°þ*•–©� à…z˜sŘÙðÒ­˜�`ý'¹‘¼fC³øYsB¥ìVÈ�0¬à…©0a´ˆgõÐ"ÖhÔýDû,ºõú±7àQÊJY©‘âk*u‚:AGÐeô›ô›Lf,ó0sä¿â%K”-‘��GÊçÊ(V+ÞPF(#”ÅÊ…ÊOU=T�ªCªCªŸÕ³Ô¼úᥙ­9þ?òuYûワZ§¶â?x½À4@…Ôˆ™†[ÜÌ4@Ó3™x‹i€“Lä†âvÞ‘þk¦ÒB:+t]V載i€±¡<˜ÿ�>ôßr0 ÐÊ4ÀÖPY…²ÍêÍ4À¤PøÎPº}‚f`|(\°ÇÖPÜ[¡øl),^È4À eýþ:˜Lfðÿ¸mÜn§Hý¯Òþ;×? ˜AðWÝå…h�6ØÏÃT¢ GA ´ÂVØGám¸ŒrŒÃ‘ÿ™»Þ}È,¸ä_¸H”}ï?﯒Gä²fú‰“µ‚Ö߸ê_æÿ(�È¼î¯ €¼!�¸L¹A)åÀ,‚°@bàš¬AÖ*{Qö=ÀŸ(ÜA±ù?Q¬Qà…ÉP 0 `4Ã4¨‚‰0 8qV½Z`̃°Á˜óa,…ûa%<kĹe~(v¬€•°„‡à7°†G`Ü­°ÖÀC¡�a-<"¦òh…Ä+Úî¸f=<`#<OÃ3°Öãð<OÀxòVø&xVLùËðMÿaúͰ¶Âoal‡çáExv…Ân‡ì€�°Úa3lCvÁ8]à‡p¾ƒ+¨D5†a,ºpŽÂÑP�¢•ª`Ì‚¹Ðó E,Ç2X­bÝ–ˆ6X&ÚL°)å X²ÀÑ·-ð¨Xþ�°Y,×cð”X~Rö߉a¤~¿®�ûÜ­øVÿm·Ò¼;€‡è„=°^��° vCì�½°^€á¥�E~»€‡öPÚ½bêïˆÛý«X€ƒð*¼GÁûáUñS ;ÇBçäì(¼Çà 8'à]8 gàC8oÂ;ðü N‰çÁçp ®Ã§ð%|Cœ‡/à+ø.À%ø.ø 7á&øá&ÊE?¥`Æ`:Ð…Yÿ5=ù¿åØðë ªߥ®uû·F1Y«ì1z5 pª  ö ;­qáߣS’ êùd{~ŸdÏOIöxoÝy™Ãh·¶ý) �—½´b?¸Ÿµ÷·Z:]Ð*…rð‘y<_ÐVÁ5ðlµ…ã­Õ Ö ‹�wWòXSi¯¨¯¼d7ò‰ŸYlÂQºŠqÜ•ZJ,Ô\áPZ+( ])x‹gÖBžqØsó ‡‘—“SÁ£¹ƒ­h)ŸøY(… ~‘ãàiG^‘E —æYl•6rüE²„Ê$sðÊ;ò2ò²Ûe"÷ùw‹FR J´ÔçßQÀ_d* 0”Û?/'%Ø"tc^æP î,’¢h‡•gJžrä‰A‚£­<”X+ìõöJ{£•w—Tul-ú×Sf÷”ޝ½j%c~qFâÞŠ )žÊSÁ&Y$ŸŠçÃÄó[§EwE—¢­mJ»§¬MÈÙʬ়<~xÍCÃú§$c¡½°Ú^Xc·­…m5¾ÀòÚ¶v·»­¹ ºñ!ûp®Í^V1Ø"Í[±Ä²P¸UxÐ3&7%¹�‚Üv;®)mwãš²ñû�Ö5c*:(¤òªs+Û{ãšÒŠýV·J ¡B pbN„œ¼”RLoÙïX.Æ2b€x^çCÔRB��"aF)Œ‚:CÂÜb˜p¤$D7Ú=ÂX[`åß,®ll«®zDò”ƒ§È£}(ð”}h;Rr-¯¶×çò{®ž-„g“p¹®°çò‰)ÉVa@j«¶×¦$ó GX�´CZÈÒê ÆTØNZ.VÚx¹£Š—;ÆWðª¤J+/sŒàÇ0á]ÍËÃøåu5B9 ¼B¸Vá^WÉ+oeÈËÃy•£ŠW…ràŽBñ¡-ByE�ÅVYc%¿¼Îbã—Wò•IÂM+¦VŠmÙÈC‘ý^Oò”Å 7rV¶…ÙÓÅŽ)wðjÇj*ÇÊ*Hˆ…W Å©$FRhy™£ÎÎËuÕÖýn` ®¬ÂHÕR_ZÁ3ñõâ[m E‚P-Ú¡Ñ©yU?^!ä)hM?¡?ÊŠÊJRxñlu(¯ry�ƒWÅßaÊмÒÁkÃ…²ðrÇj^-&=*dSê¯ý>E‹Š9)xµƒ×9†×ðËkÉõ^í°”.V „&”Ç1ªj®u çiÇ_àûÛGJ²]˜„† –ýn¨l»;€Ÿ�”’¬¼;T'·µ)uÿüb/¥î…@kÁÔüØVŠÞ£ŠÆVEI%!�Iø%Ñ-‰’¸.‰Ÿ%qMÿ�ÄUIü$‰%ñƒ$¾—ÄI\–Äw’¸$‰‹’¸ ‰o%ñ�$¾–ÄW’øR_Hâ¼$þ.‰s’ø\]’øLŸJâI|,‰¿I⯒ø‹$>’ÄŸ%ñ¡$ÎJâŒ$NKâ”$þ$‰$ñ¾$þ(‰÷$qRïJâI¼-‰·$ñ¦$NHâ¸$Þ�Ä1I¼.‰?Hâ¨$ŽHâ°$Iâ5I¼*‰ƒ’8 ‰ý’ðIâIì“Ä^Iì‘D§$:$Ñ. ^»%ñ{Iì”ÄI¼,‰—$ñ¢$^�Äó’xNÛ%±M¿•ÄVIl‘ij’Ø$‰g$ñ´$ž’ÄFI<)‰ ’xB�Kâ1I<*‰õ’X'‰G$ñ°$ÖJ¢MJb�$VKâI´Jb•$VJb…$–Ib©$–Hb±$Ib�$î“Ä|IÌ“ÄI´Hb¶$š$1K3%1CÓ%1MS%Ñ(‰)’h�D½$8IÔI¢V5’¨–ÄdIL’ÄDITIb‚$*%Q!‰q’+‰rIŒ‘„W¥’(‘D±$FKb”$FHb¸$ %‘+‰I¸%‘-‰!’$‰,I ”ÄIdJ"Cý%á’Dº$Ò$‘* §$úu "gõpT+”P­€ÔJà¨UPïS«ÁI­‚&jì¦V _«Q÷ÂeñÓIÝ»©û�‚ÝÔŠ`h³ðI-ŽZ¼º„ZË©eÂ׎Ô2pSË ™Z4µ¤ƒË)÷QK;rì~jµ¸ƒc 9ÉÔbȦC%|¶›Z ŸR‹ÅkÂdj!|J- &S àSjPðu ¬?›ÄO£ðIÍŽšå`¤æƒ•šïžKÍÆ¶‰ÎagQ9ìÔ”Æò)) åõ)\y]JmyMzu¹³:»ššœ>©œx<Õ<þ³ñÔØ”òòìr“RVž]†GÊp‹øÏ›RZ^’R\Þ\ŒÎbÜR„ÍEx¤›ŠÐ]„…)åù)yå¹)9ån5«Ce(ÜOÍ ¦w¤³n5]<¡:UÚÂ÷R-€à¦îíLPèöQ÷vô°ú(º£g/ÖGQØׇõQ ~‚n‚›7:z$±>¼Nð3Á5‚\%ø‰àÇ‹“õáß\!¸LðÁ%‚‹¾%ø†àk‚¯¾$ø‚à<Áß Î|Þ;�õaÁgŸ|Bð1ÁßþJð‚�þLð!ÁY‚3§ NuÄ b}ø'‚Þ'ø#Á{' Þ%x‡àm‚·Þ$8Apœà ‚c¯ü�à(Á‚Ç^#x•à Á‚ý¾ŽèÖ‡¯ì#ØK°‡ “ ƒ �€'ØM°‹à÷; v¼LðÁ‹/©mb7h›Ø'´MìãÚ&ö1mû¨¶‰]¯mb×i›ØG´MìÚ6v­¦�ý�¦�5ÆbsìòXª9fy åŒÎŽ.ަÙ(gTv½%jw厲°…Íæåæ÷ÍŸ™™åá¸Õˆ¾À‘Ncrj¡/pÄm7²½ › xØ€�è·èwëéÝúÃzê°þ�úOõ´[?4·�~ ÅŸ³â:“äñ)^¯,™ÀãÞQ&|ºKÇóò5<”�ŸPÑŽøpe;Rycx“ðTV>>> ®×‡�‡‡k�Ã6àðAàp p¸8|8lW‡+�ÃAÿ. úwiпK€ÃÅ9Â碠‡=|_ÐÃóƒžôw[‚Þ�ôjSЫ³‚^�ôꌠW§½:-èÕ©A¯6½:%èÕ† Wëƒ^å‚^­ zµ6èÕš W«ƒ^�ôꤠW'½Zôê„ G+ƒ­zt\Уcƒ-ztLЛޠ7KƒÞ, z³8èÍÑAoŽ zqDЋÃÞ+ z,7豜 ÇÜA�e½5$è©AA/e½40è¥A/e½”ôRÿ —\A/¥½”ôRjÐKNà°pÿºÞû_qTþ« ðwD ?B~wÉèe A,¤AÕ~°ãS)�ðüÇhTÆ*a:PŽnP¢Ëmd(ÝF£±OÌS±ò'éƒÕ‡q{ú00²»?é~/»û“‹aY΋èü¸ël—ñÊqS–³ë�Ó]i©h²™Ä·YOÙöWzFÿ~Tf¸Ò{R˜!„÷êGeôJ1ú›#èŠn†šnÍ�RÄpòÙëúŽœî¶'N}ª>Íïs¤é¢¬aal”^ÅÊ,×ÏË,7r˜Ú›©¯RÊs6ß\™Rä²p®Ò)Ýߺ¡taaÖh½ðÛæÍô5™LÐ!¯=&þ n9„áö½:¹Z-nw›Xy_]L—Ã!�>§È‰?'σì‹ÙbݲÐxöt—)Ë–Õe¼òFZªX%›Éf5™åŠž4-ÖËäJJ…K2“¾6|õá¹þ—qî­Ÿ�1¹¨ïWуFû:†Ô KHê[ÒR´ïÕ§6àêIë¹þ2‹ÿÓ6:Ô©#±»Ï0WOÿ”ØÌÒîÓKôô� U�Ëô9Yô€A�ú=#…G²8�£öëQoÏê\8ˆáÐbPßNåCv÷Ù‹ÙÝg'^DãÙ.ãÙci©¹Ý ¦þC)WzdTD?´÷ÒSæ0Wzæúܳ;ýßú?ônüó6 Û8¾ê‰Æ�ï�óô°´ô`þ³þöjÖº;!±`åk ü~‚€‚™LœÌZˆ„>ûð�=FêÌ‚EÕʨðsªó—JbJ¡§'v‰æcDó�d9+çnxüØÿWXŠé˜r°ÿ´­3žjÅCÔ¦I;_0Ö)³øßðï~èȼŒ›€ðÍË, �´v¹Z¸›•ÈjåçT*”�£rÔçñ¶ ÑxöãcaY¢÷Ñd‹°‘7ÍwÇP_v¿C±Ý]T†Ì²Á?}ƒ¨ðËÿ“ô.™TÐw­RPr¾èÖ)ÔÔç2™Ï+sy�}+ó+o�e¥¥"ÉÖn²Ñ»ºÏPúîï÷Q]ÌJÅÝd@È \¢”¥@"äwšmy·A8(ñ˜[eëñYxx|�DFï)þöÀ‡†½ñ¹ºozä õ|}¯ Ãeƒ_wkí²–çb£¾èiÎïãCÝ^unúß�Ø+ÛÙ}V(�ØI²ŒÂÈÝ•–*ëGß²›0÷(z¢0ðE“â]–ÄS�O7¤KVÌŸ·µÊ0‹K�˜Zœû›%Ô Ægï6¬ÖÐð¹¶d^*�°ã‡�[¯¼Xm¨˜n�_”Ù/yÜJêkÁ¸%¾2eþÑ6OI›`Sh \¢ÏËR  Ûãá ƒpHÁc�ê™ñÐ �#n­)²(¡ï—)á2[®Ú‡‘{4úod¡Á=,+«ûl’PÕc]§¯ ML½úQ Bå†RýûÉÉ@Г"¾<ÂÜSNŸ¹æpKÿ)“Çôòœ?vÁ(û êEËU8oÿrÛ¨âQ¶QO=µ.ˆµ3±ŸRkTíìaµdŒLËð Jë?¤¬yTÞýõCå½rkdTÃØŒ‘ƒÓú-f«±ŒQfĵ%Œ*�Ìyy-6˜tt¿r\.íÂ�ÅýKöø—И•7–0+7 ¶™¸D_—Y Jè€Û!tb߈ŽÊÑä„}NúF¶8vÝ®y†Ée]˜™arÑׇÌÛÑ´ðåéiq¹SG>¼ºOÌØ½(Ï=w{=Ýts˨9£ûl‚ž,Ü�`jePBš;’bhT‚U.W©å”’¡s�ʃÈÎve ãƒ0*Ä8c£O¦»N¦»ÒRUhGZ™Zþeÿè·0¶Ä‹²R¹ùˆß�}/PиD¥ý`'xöDD¨P|Ô®³%øðm·A•ª}­Ð {õе–Fø�r«Ì¦ŸcK’¯2^2>wN Ë"“À±®,S–3-Õ– � ™ƒ0£¼½—\‘1”[º‰¾Ý¬3ÐÆûÒı ‹]{öÜòç*l¥ãkÓ'-5lwëÆõN—˜6n\Z"m‹:ˆïB> ÆwÜñ¶c¸¿°¨Ðû޲wa2­Ì„B,T*k2�¾§¸ê�Ì’ìzŒ%óžP�,§s¢S–ñ¢Ée*#Œ�aQYN§Ó$,��‡Ee»ŒÂ Ù#B]P�æÈ(YOúö¶,s€0c’OÒÐlHœ˜Ñ?>Á¡§ÃC“eF¨×Ò-=جÆõã²gYÃc‡F¥gÙ×= ,_¸cVzþ°Øøhí�¾áqš¬)ë+ù±8£›~|UÙ½=¹)þ붤hu†õžâÔþ¥â$Ò“ì3G¯¨rYÌ=ÒÙøtJMõrOšw߄̄‚ÉYÃg¹´½“R£rf¤F%»Å )Õʇoš†åôL˶ ¹G¦Šì›”D³©%YûàÑ}ö4Zñ·Ð'd­ ÎvƒF¹´¸Ûm@mŒQ#»Q¢/Ó”‚Ð6î·lv“0È Ã”]»hWzd}b׸Rû�ÜÑ®]»ä‰ÅÅÞä Û©sZÂ�%ƒ»d­þ)›Óòú†½âJ\I [*ˆƒœWÁ€Ý ¶»õ*T¡J®èɨ®*JÕ>ìãV›ÝFs‘~¢‹!ûâ'I³E§ž\m$“Ÿ°ì—Øá¡Å�ÔÃðªÿCü“nþG ‰KwDD8ÒãB¤«ÖÝ|nýzDħÅõH��ˆˆOï—/ì¯ö0 ²VPCî~Pâ…N• Ô‡ðP�»…ɯ¸�ÈhTÅ”ZA3²2&d©°¨¬ì�¥Þø,L\yÙì(Ú ]È$|çOÞµ _ÿŸHÅv!k½¹ ßñ§Ahwñ�¬UØqíma ÙB-ÚÎÐeb3¿£òwVýΪ2W¹¡]/ü™;Œ`´´R ¨=.ZøJ;V‡RîvGétýœò«}K¯ö*‰sÄZŠcKu’×ò²H·Â,畬Ó]ÆÓ¸k3Ýš¥ìwJWiÂg Ò3†(“¹W‚ÓºEaˆ6…YRm[[•±iýõ.Ý/ÃÝ÷5êç`»>:³2§{uh@~¼ÞÜ|a÷"úÂᬒ´¨iMBðÜí�Ú+í‡(p¶S‘B{��Ð^µQÑD•jJ�7%P,¬°„¢/ˆ…T2Ó wë3Šdo±7ù™-»*ÆY‡äŽJÝE_ØÖ¿ ¯é_÷½ÔŠy÷’† T.1jÚ/íT;Á =±SÜ©ül(±_“yooñï\�IƒüÝûuîâŽ{g옟-±#qä̼ÑMÃl‰#gä DÿÜוwÿ‘%s�>4*oÅ‘UšèÒ°zÄÄ߈Vþú:í38``§NmU ŽUǃ8‡F(uñÚØnc‰¶XUn?EŠ˜MItv q--BDþ“UH&}ݳjÏÔÔÉi»žÑx^®ûå*$uškíVJùÀ›«rÕZ•ì�§üj r˜<±`”¢ ÓÛ©°ƒØ.îûÛÝFU¸™2)•^ª½!“Ü'LDw9]é‘ {¦ä¾·¶È*_±é·rž.+±óŒIåé û§W¿}bÕü˜c‡t/Zÿ¾À%ú í‡ (ÛÉØ¹×ÒÛÒ[ >ÜÛiRgÚ @oa“SÔ;áª)Ya-QûPæVoÑìÖPý5…´º½×…e9�Òƒœ^ñd·‘)Ì ·'‹ˆÛÏ&¢zÒôÁÞC½k� ;¼»Æ.¹/<}ê„ü–1© “¶Þ7hÝhïc™9•¢#²¼• GÚ0,cLN¿žú0óÖ˜ØülKRB_‹ÙU8ÉÝ—›¥3>c7Û�KrbbtlVa…PÓìÀ÷ô[²ˆ‚Œv£NèÙ‘j…BePF+ŒÿЪuÅp#Ê|�-R\'Åqä´ðPHœåÅå]|†øe€ø'´´{kÐÒœ×ø¿Ä˜]øºHKsêì¡zƒnG;¥}Í)þÃ�ú©Ó F¡‡.Ñ'è  )í=Ô :ÜíÖ«£(ˆ(Ö®+¼âÐ"uÐ.2 Ø„‡6ñâæ…<ÈqÑ'6ÉSJKJSžÙ¼k—uHÞ¨Ô]bçÜç£Öu/ý2ÜY2„z ˜DúhàT»]é |åîi·SV;‚Žf´*µB®R+òbšfJ…»§;³]ä:]N—ñxºñxºÇ[±‡B¹š6XÜZQ¨)”Û½hLZ­?f\²Zy¬ ©d(W1B*Q¨dw§Ò(AAÒˆB¥…Ý ¿ÊI r?Q¨5w§,£B» ]*aîHüÒÅÿc¶ú×~ŠJ¤?ô¯Æeþx ô/ÅûýÂÆù«™8úDC‰[g�k˜ ##cb#|�ÏöFF˜ÃJU>¤Ýµ.€© Êdž›ÍÑB·KOwº²³²†vÖÉ.Ï}Ì{2ýdº°Í½$m® øÔ‡‰ó¿œqï[ëbûÆDö�K-‘oõ7÷»îù–¾pséƒÇ— ¦¨Í´¬G67Œ¾Ðݸi+õ8 &û«èZÙ ƒ¨�’~(­VÌ„±���Î.ái-Š�jD�ÉEýìw¥Íì\^ï_|숿 wP²W¾ÿ~þÿ ¿¯üc 2þ*úž;óܳG£ 3‘§ðè#!3,È8O&Oë\SÿúÿÙþòîŸf|õÃõ¥SŽâö/ðo¸Xü?Qü Lƒÿ*Ð`ØKSôOXÙÑy’L½LÃ�§™Ã: �¢yš“µŠß.Ä¿ ~-®¾v«”*™¢ … üdöIq:í:+ ´�¶Ñv?í±=Žªí±=NÖêOÂ3ÂPø›yú²,¬�%¬B^ÝcŠ1Y…ߺµh3ê~`”`®£¬>´´'>{†©ãBÇ:£1‡Òd…*W$Ü~þc@}ùæïÐ[Öx�96sìà²5YÕ#Ž.÷HcVŸÒEc.R‹6a‰÷¾º Wê¸ÜøƒZFOê_ûp¥gù²5¥_üã€êæ endstream endobj 302 0 obj <> endobj 303 0 obj <> /W [0 189 549.80469] /DW 0>> endobj 304 0 obj <> stream xœ]RËnƒ0¼û+|l‘Í+ B"DHúPi>€Ø µT 2Î�¿¯Ø¥‰Ô–f<³;ËZ”õ¥¶ÆsñáFÕ€ç�±ÚÁ<Þ�~ƒÞX„\å7„§Ú‰‰²¾4Ëìa¨m7²,ã\|BofïþRèñ;&Þ�glÏ_®e³c¢¹OÓ `=—,Ϲ†Ž‰òµ�ÞÚ¸@Û¾Ö`½ñËþZ6OÅ×2”F�æ©UàZÛˤ”2çYUUUÎÀê÷ ¹n�únª£œgR†2GT"ŠSDÅQRªH":Ó]b—­^úWý&A™,¨.y%U $‘%’AHdL$õ D¦$B2ÚB’ò “2>y&r€©{B'd?ž�L)RAÊð´MEs¬¿q]÷cGêîX�o÷²nÄXx<›iœV×úý_卨 endstream endobj 15 0 obj <> endobj 305 0 obj <> stream xœíX{l[çuÿ�ï^‘z�%R¢H‰Ï˧Ä÷¥HY>ô´dI~ÈÚ²l±m)Ñ«²ÜÄÞ’®�[ i¸N€E‡>öǶ¶À²vË-¼µX]ÝÖ 0¶¤[wX'mZÏS‡!�y×{I¹’‘¶[² ¦s€{�¾×ù�ß=ßù> @‡_‡ÙþÜÔÐai™èŸ ÄO^ºõ—s˜�:œ;üòû¿è7 žY*¬l¼Ü °Ë~õ\áü*=€MÕç/žýcÓ�#€f¨;<_,Ì…~ëü@³’óóÅ‚ê‹êçêàž_Z|â¤úÀô‡€nïâÊ™‚T|ã2PÕ¨½K…ÇW¹ìÔO}½À±\X*òï€u­®œ_—nT=P›Ü¿ºV\�W}ôC~@ý'$}è9þ @ IB=à®Ñ¢g ’ÿÚ&˜¼¬ôãªYéoêG¹…{¡ô#€åKR;æîàkÒ×·-rM™Eªßýø�¶??]ßûãjŽ»#÷Ü>ôù=òû_­Ov”6JÝ\˜wƒAö`mBµò—QyºÁ;7¿N ÀÂza‘ä~=xeÀ”§B…é*À¾RA\ üàðøaXÎ\\[„åÜZñQX ë˰@UñÇ Au¯tla®¸²¶²´ €gyºŠ*€=ÅòÒ¿aŸüÆ �Bœ€Õq5ÏÕ0þa–rƒýûñ8æ2O¼›nÌ‚žQn°gå¯TF]Ao§¬`�yÍЃƒ F?¦PÄ#XÅE‡Y’”ÙåöC(à±&·Kße)FÒW¥¯J_.뿸ÞäëmI-ž”½ò5>JáŠM°‘¾b3hˆ¯ØÒ¸Q±yñ‰Š]…<ú+¶ ~XÊ6ÑÏæR4ÐUìðOwpEœÃ,¢€5C 8‡y¬c +¸€5œAXÁŠ8€5¬ „Q¬£€E,à Ž¢ˆ5œÇV° b#Š8’èÁ‰ PåòúR6ª`ŽP˜:iãÍ&u˜—ŽšŒÍv*ÇHU“«®Nûá®ö¬7èoÏŠÓ=Ù¢5a‹ �¶°}¿=ÖÚsV“ëìÅl)�'Ñ2Oî‰w:lAk¤Í5DŒ¡_úX i“èŒr¤&—·3‘f²c1%rBJБ/žÌ�‚‚5›ÿi|:06Û•˜0ò†t!SÍ{gZüÇü!s¿+0š´õiNO÷¯ŸHø�}%˘/’�†_ð9C'¢ƒýò}ß­Ä|Mp—£Ô‚A¬'Q‰V¦ÕO³Î„Wp©êÉF¤‹Nš¸ÆìÓ> 癉L÷�r#�Ö¾„'ï Zršv{»yýQWln&·~,–õäc#Cñà·½™åi“Ùél²?…Wö3^åˆÄx2eÒ ÙbOtjaOvÆkŠzÆz…ビ.»w^==2°8Ù‘‚.§«ï`äÀ~¯5!Qá/¿Ñvþ2ô¦~{_™À±&Nï�¸ú€Á`ËN}ŽÓ×ïw=L!!#m2-݃GúžÒþ­r{²ü[úŠ´IÍn¤ävg"™22´-͆ºÆ8¾øYíkkŒó»ZBƒc@“ËjÍzz)}ÿv]s�GÐi{ôúòoWÖE÷bQ-VJBe¯<ãv»Ð£æ¬9�ËKï˜[0~ïø0c –hëÈØ^Æ ú¶ˆuˆ6ú=_°Nìµ-�¥OÐIMcµ¹Éï/}z›¹Å3ÝC«ÂóÏ¥¹�ÖðÖÁ‰àC,ÓÆ«hŽÁ–6YÝCœrVmet¹Æ>(J½ž�Ž…&‹]ù5'úFRŽá´W~j’³™ìâÁ`r6“Y:ʺÓS‘‘©òLú‰$2óV�S?`R91äTO†U§ê©L5ç�ÇO <~ <ÑÂ5Ú¿Ö>œ�kÎ1Ð2ð7ìKûÜâÜLþê¿mþSDÕœÀ:è ÛÙ*—U= ™&¾uh»3¦·5úZºÞ+Š´ñ‘ÀP@«é×ÔÌî¿/¯‘’6Ñ=´—÷yy³%;aò=t:¨šŒÍ¦ÊÙ k?8d º qÀ¶'0>?>kï°M¥"ÉtwhØ—šÑ4û[c~¯ÇßboÑ™â‘>[Ô±ø=—×XïNø9cÒ&s°EX·r9CB†‰jQ-¨w$´8¾·Š‹^©»æÎµÝÕÞ�q,pg-fûqÍDZokxuOÕ‡?œþ�¶©.jÒ¥ f9º.i“yhCÎ'Se§lÛ'†rådÏçä<ïæT~Ol.–™(d´¼m`\3�lö)Pz©ÑÙàöeRÔ]²È)Â1€ Ó´€È‰™Ä4¥ "}}y¼¯Z«æÚ›g²ô"m”¾'Œ Â^YJS`Ë´Wy¦Q¥.Ï44«šÊ'ø¼ÉNAÇê©[3ÎñZSýêd-c¼Î¤]ûfAEÄ×èêk¡�Òw]YAȹˆ/½!d!#�½dy]èõXÚý-¯ËkÖNʽ"åMe°Õ&Á&Ÿâ©öÕ'tטԼƯ=sâ¥�ÊÖ˜k«jZÌ5‹÷_Yiˆ5èõ+wÿãBc´Qcm«»’nI6BrUÜQ§wð¡cÎf}‹Æ¦·…-¶‹cYµ^Å7Dû@é�™}_[�RUƒî(Ý)ÝuL9�SÒßßèvÉØ•ÚH¿°ÖMw�ò|÷µ¥QâÚ�¦ ¥ÑžÖ¤{5­:ªJ—ž¯©¯öºtšn]#H©©_¡ 4lì¬éätt)¼·ÙÙ,:sƒÚümuÌϾئOé�cýô|ºTWXá9i“FñqùË—Ïá­=þ£6¡%`¶ºZü¯ÍÜÑê³µt´Ê1|‡.Ðuöeùnjð¥åKiå KVf¾¢ÉNT“O'L6ÑélOÌÒ…�q2qdŸVïjóˆÁPêÔ°¼’[¡+ì–âÛ§D9‚&#õ|ò72ý±¡_øÓHñþ3…Ïd}™?[þRé@eôûìд ±ŠL.ƒ£±Õ`mfƒ£±Ílõ³> endobj 307 0 obj <> /DW 600>> endobj 308 0 obj <> stream xœ]‘ËjÃ0E÷úŠY&‹ G^Œ¡qjð¢êæiì jYÈÊÂ_'� ˆeêFGßh �ë�eB‘CV–e™3tæ_|Ÿ²n­þj½–9dB(‘m‰vj&¥Ê{&ÚžsÈ”�'¢ƒH±Uyø-îK32Ê]{ò²ø­9_I¢RIÜ'ñ˜ÄcÏI,’x!Ú&Ï£zt�jο<¯f™§¾‡€.Òþh†óô¬ÃeÅ~ðsÖüý@O—ë endstream endobj 16 0 obj <> endobj 309 0 obj <> stream xœ�V{L[×þÎõ5†0lÞÆöå^c ØØ×Ì£€ÍÄGº¦IËËà„‡l²$ëšNmšiI“°uÊÖ¥„lêÔ(iK¦¬tZ»-«š!–uSíñO¤HÝ4Tå�í�µÅ^ïÅ'�¦œŸ}ÏïÞsÎïq¾ï<@dà9HÐëﯲDýÝÈ õ4 |òª ßÐ1:=–œ“|PWœŸŽ„d¸ ubêÈø'#í6 ¥H� †Ç²§Ÿ}éK{½ìÁ``xÇUH€²àtôðîi7I€»S¡ÑaKaõ¯ªÀÑéáÃa¤ udãc€^ûB{1¥ý‚u"Új>|>¸ð´ÜõŸÔ�©bÃõ» ³PßÉÒþã éÆÇ)í©#Ò@mÙ&HßrÅg¨¯O£‚¹ýÑá)"DŸ ZŒ“"Y÷âc¦¾ür ~ €¦×ÈYHé+R+@J7kÉGO¸JKÎg»´ûýíð@ƒ#›9¦ŽP& È?h§tI˜áûF 'duKþö(BôDOÈŸ)"ŠJ”1j…Z¡nS·%E[â—ø%—%—%Ÿ B׉>©Dƹâ<@œ�›jdA‚LhP lhA;ºÀ~L!ŒYDq$3¸¿}SÝk�ßFŠ ñ_‹òn²|é ½¶ùOzŸ| ý+œ¢×ðÁÿ·úè…^ÉD}Š^ÛôV“Ú’õ£ôÞØÔ‰7ñíôCìµ&êùD=˜Ôö.€xV@�øt w:� Hè2ñ~B—À‰: C ]ŠB´%ô”A·© ª„.G:v$ô,ìЇ¦1ŒxÅ0¦°£x\D|ADÅ#!Šº B¨DŸˆù¦0ŒYìF³ˆ`¿Ø®�fT£5÷�Öl�×<0~»=Úá‡í¨$Ͼ=Ì[ Bãf·rÒÀ"z³Aƒ#zx¤½˜EÀ¨8² sˆ"(²= ÊE‹Q„�U¨Âö‹=æ03Fž†×Iã¢õ("¨­ßó;�ðj÷”Éø:½Oz�a2‰,“0:No&z3q“Z;ß@øbµ¨òÔ$Ï*~ft)2±£L©&yâÏj:Òû–Ó*XvÒÛ2ƲÕryF†\^Öš½“,[‘¶œÞÙÐpeúÉïÖ9û‹Š‹)*.êwÖ}oÏþË� =äíæƒ£Ùı#>b_³Gx~„eM5&ÓlsðJƒ»ÅZYù�ŽŽ…]«»::ŽVVZ[Ü®K ‹ÿ‹Þ+½Ž€•h•Z‰Üf ÂÏö¨Yä©Ä,öJb夜ÊkÕëû¹æ ¾Ü‘�­ ™YYŽo~,ȱæ�ï¤õxœSÍÝðù}¾'Uþyžojâùy¿ªwžç=žŸfè�ØÝH÷ <�cU$ì¾àdz†ÜGEEÒÞðÆr®¹Ð4Ù0~Ánw8ìöÅ`ý„Q]«J»Dý…)+ wWû5ÅŠ‹¦Äkê ³eLlˆJU±òüŸïFTydÕëí+ÈϪ,>´±®ôŸåù¦|ev­šJÓ9rrr=vþ ˆpŽÓ5t”ѥȪÈ6w,ª<ÞL$‘CËÍ$ui%›g 3­¶a{Aqˆî™x¢hþó¨·-»Š5Ú�é?OÏXx:¾N¤0Â.À§H^vú¤dShmZjl%v‡ÛÌæov˜×ë›ó 6u©GmðkÈùؘÔûìÌÆµ±—** ©©2eæóôN©T–[�ß×Hu�|¶Æ:éã´S`#ÙôC"Ó �-25!RoØh¬Ï¡Ø›±Z«c·n’?ùv0ù�\fM�:»-Öi//ÊHßÞh>ö<µòùÏæ6””%Ô9:]¸;ÎÇ×i�ôw(€õÂ*KBR™œ'ëºw\%6ŽœdŒI1QÒ�ËýV8ô–Ëíñ¸ÝK¡ð›.—gc§ÁÈš›FuŒ!•6™u#�®!kN£ìT%yËÛÙÙåóÞZ*´ü{üG5zDZ¡Ž™\¨)ã]YÈK® wÿA€6I¯ÃhmZ"b›¼L•Ö¤X7é(#JÚ´Á’ü(ÇV¸ëê^› ±®0e̤×õ´N˨ w{bÌ9òºëHCñ¦Ç_¶ÛÝn÷Oö¶Îè9£�až¶Wô›«fÚ7>=‚wãë´_º$œ9yI4ßæ?“¼oÅ—£µiï¾\PUTÔbn›bY=£cƛ羯XÚáop/<½Rçp¸ŽÅ€ÿ°É@ù7”Ô_9•.==Ãbª8ÔÚyÔTQõÜ3�X,o“çgÁ™kžÆ6®€¼píË éÿÄUà– endstream endobj 310 0 obj <> endobj 311 0 obj <> /W [0 59 600.09766] /DW 0>> endobj 312 0 obj <> stream xœ]’Íj„0ÇïyŠ9î–Ä¸ë¶ ÂÖEðÐj÷Üd´�CÌ|ûbF,ô�À/3ÿù /ëkmMþáGÕ`€ÎXíq^!ܱ7–%´Qa¥x«¡uŒ—õµ™§€Cm»‘å9ÿÄÞLÁϰ»èñŽ{Æß½Fol»[ÙìoÎýà€6€`E;ÆË×Ö½µ�²C­ÑæÃ­lþ<¾f‡ #'T�5N®Uè[Û#Ë…¢€¼ªªª`hõ?{"IvïÔwë£{R@.„E¤c¤cJôDt&º•‘¤ˆ”�ˆÎD«�<Ï’¨":FJ)Ãù™(‹”Rö”ò¥¤K_ˆN±‘µâ­þ­_)©Š›Q­òB�"«Ö$ZƲ¬o›¹zx�6ÄÇ9/6·oàF·¨–ó ½#žÓ endstream endobj 17 0 obj <> endobj 313 0 obj <> stream xœíY P\Ç}ÿí¾Ç�§CÇq¼ãîîÝ»Cpp|#àø:)BˆÀ’@P„%㦎jGÎÄ‘êq“ØQÝ´ò´Î¸�IÓIëÚn§õÄeê8N¦ö¸cy’*-ñ8;CH&‹»fߨqZOÇIgÊÿ?¼ÝÛý³ûÛÿ×î¾@� àp"Ò6Μár @{ÿ�×wìâ×kzÀ‰¡á¶á»¿2ÿ&@NðL-L.åŸ<Ð Ð%OÎNže%“ݰov~uæïß~ó@= øÆ\jrÚý½s÷d @`n.5©ó´ °Î-¬Ü}ú•Âÿ e@QÃüâÔ$ÿYr/�çò� “w/ñÏÓ“n0Ÿ™\HõJ3W®  ú¥Å³+™ï@ˆ�õ/-§–æ—.x€òi’¹øUþ!€€d2(øËäçpà ì×â@Áe«™—áîèG¶…{=ý@“™–L W~§ ™Í…}r{‰ü4€žŸ�[!e@n ÊôAŸÛDñäcñª4Qúé>Ž{‹5?ñ”ÄʯüýéLKº‘+ç­ ·±`?xð±öÞaè§V—硟]N�†~~rå ôPäd)T9T$3 zr:µ¸¼¸p†A¦I²†<€>H“z²%9ZÀås€K¤&W'0’ý¹:…7su­x.WçáÁå\=IruPeë¤ *cHá$f1‡ awaSH!ŠEL#…,cn$�Â,îÂ<&±ŒQ¤°Œ³8‰Eœ�õð >Є9,bSrϹ\_¶¿ ˜Äi¤d‰¤p7R0òÄNæ[Ì9æ;P융 1DÐ�¦±ŠÝ¿~ýÜ_‘q²ÙD˜Ñ†i,âãr�¬»,¡^xq^f&oÉxdm,À‹Z¸`ÆyœÄ ærë9+ëòR˜†í²ÞV`ÆaLb�Í`.Û‰Í\.»ˆCæ |_Ã5\ÃûxŸ”Ù$ó Y!+äqrƒüd'S‘ž¦�ÑosJÎÅý ÷ îî:w�{Ÿ÷òƒüýü³ü³üyyѼTÞ}yÏä=“÷¶{¼Çÿ .üȾ=ÞãÿÃÜ­8w_R|UñÜoˆÿy�÷ø#ãòf÷1ú8äC…"hQcÑT[¼D($A»Nl!‚‰jÂäzz��.?¸ëÂ…§øúÈ�"“Ÿ¤�lÍ7~jvv`ý­¿;~þüCëäep˜¨@× �Oô‰¶D¡Ô²BMNô$¿ÍI4Û•©g¢©C M�áÅîsG†»úzÇO �lô]3·7Ö÷ò‡c­£ò‰@PrmÝlŠ6K hËlR½#�Wå¡’?LD_©Né!B•šhKŒDô‚:5!Ís‡�½Ÿm:fð–Gj[Æýþñw§Ék›VyÆ>9pòÑD½I2˜ÛÎ%†îŽØÑíÅ@kéögõ’]‡švÑ&’ßCœdìO§>Ý`r¨«gÊç›êé¢k=Ï�|äp¬å®¡ÄJ–ZD×P ëV»ÍËäóé Ó?&½t­ýåŽw;@ e6©–^�E^ù€I‚$jÔ„ &.t÷Ü?Ò–4xËZ¼ÍÇĺ£­Uá¢û_1¥Tƒ_<}êÑA±RÒWe¥-z*ž~ÇìÁ@~‘C$‰A²h�¨�¸z•4Wë÷·êFG]ÃÍ-ÃÎrm ¬ŠÅÚ,@#ô_p0k»]XÃIA‹vÃ9µÆ…b£hnk¼~™èiaÓ‘ú…au~¬ië]r5œ‡ÎŒ™È|ˆ`h½¬”[\'j…\N­²Ùem5_)kàîHÅòo›“l ’šŽi©Ö^l2ÊiL¬5}ó^M™oD*v–•Hu Ç?YMšD£Q4E“I¬=”p&´Õ« ƒß7‡œ•‡Jù›IW_Ì·:¥ÃNUTã¯ô÷Ôäç4ƒ?ì>ì%eð Ube¥X%ø éÏ\åBÏ×jmn–!ÇÙ»6Ù·YVÉùt©V#h˜yJÍx"�«NM$ü!gÌI¯=¶&8}"ý]"Ä£.Wú/‘Éà(@§/Qao ù‡êØûÌ ‚{®ýÛ·ÛAäˆ.§× Éz †m%¥Ûnðù¾ÄŸýÜïÔº*´–FÕ‘Qr#ºõªTW  «4ì¿YÆ ÌE�¨ËBÖÝ.ã¾µ€Æˆ’ûVÏ~­è%üå–’^]EyuYo­r8vw_Wú 2:RmK™Œ:œ¬¼¥²�’�óìTMLÉÛn«†¬Õvi&mÔ@6þ§{LëB4ºÐš}zÛm¶v¯7n·ÇsÑZN ,‡bÞá`È7Õ�ó“(Ï!ç'Ý6ÒÛŽ)è´Å»óÓxLÉUqGŽxÂÓM–~ ÇßçŒÝJOߢ6;š{çÂã±'ˆbw~z ådE»ôŸ�3¥æá˜’³-E+¼¥ÅåÖÊ`ÊEÖÏ6Åò :ò÷µô¦‚ŽÌ&U“ –Íwí<Ô.Ç×®\WªËm;�ŽO¸lŽ™h¸¹ÀòMLÌL7ÌYk,ÃG½6Ú=8fñ�PyŒ£ÕcT—•–ì/‰šú«Ë¥²Šbs±I(Ô8Õ5m5Ì®ñÌ&­¢÷±�”Y¤™R µ¢VØ™ŒìHŸ¹T{ï½Ò€WhÐYºTâÑÐz8ïÊ•è�!£j(ë�}™Mò ²ÎüDǼyÛ—5¹|ú³±Ä�Øìˆ×$¢J¾:©š>A<é7ãQ§— ¦õ#Ž ûš@«É:N,6¦Ö`±È|kh©°â@¯^êÿ&YO¿cí„N+)Ië!¿õ ëìÌ%ÞúÏ"ên�!Ø=„)$˧�ÊžÏ+ÜJ4î+âyE¾²±wîTƒB¥à*E€¬§×«Ú¡­êæÍlIôiý[úN�§Sÿê3^j'ë¨�W›³^ ÙZMï?(Ðì׈­E…?:¯6ò*T§¿VèÿŽ‚oãø&·•ü0ýs—Uè²�[u}.¶v4+&ëÈg§;b‘,ZbÑv�¾ôëäñô×Ș‹œ�ºÒŸ‰2Y–w.“uv¾“ϺAüäj4Íü”eŸË·ì’E&’,X¢¦ÏÛ:++ô‡ õ’öñ—xúÿµXÝ|@m Õ’¯GÓjwOÐÈæ˜”Ï¿÷2ËdO›ad©ròéÏÙëJšÿ> endobj 315 0 obj <> /DW 600>> endobj 316 0 obj <> stream xœ]’ËjÃ0E÷ú -›EÐ+O0†T‰Á‹>¨›p¤±+¨e#+ ÿ}±Æ$Ð…%ÎÕ sÇ3L—çÒ»HÙgèM‘6ÎÛcè Zç‰�Ô:J§éê�0]ž«iŒÐ•¾éI–Qʾ uc }9Ùþ+Â>‚…à|K_®ºZV݇á:ð‘r’çÔBC˜~«‡÷ºÊRÚº´à£‹Óúª«gÄ÷4•‰º1½…q¨ „Ú·@2Î9ÏiVE‘ðößû³n�ù©CŠ9Í8—> endobj 317 0 obj <> stream xœí| \TÕúö³ÖÞsá> ÂÈìadJDÇ"ÁpÔÐ%›ñ 2‰¦‚‚·2;™I¥æ1K뤧Neuª ¢�fGOvõ†á-QSKÓ,5MYŸ{ÏhPøýÏ÷û~Ú¯ï›g3Ïû®õ¼{­µ×Úó²gÏðÀࡉæÅy{Sê`ذ¬A¶ÜÅã.±õ@ð’¢ ŽòÎÏ ªˆ @~ÑÔJaiùî©@`. ìú`ù˜ Óîzó ^ (Ä1ŽŠrDÀ R{š1ãgî‘"<,üåcà!`eìÊØ­±uŒIGûk‰eETøä7ã!Ü“d€b¹¢;@¢Ü–Û…iˆZAý”<•À{z¾‰AeË`�[§ø²9�tW¥’‹4‰Ì=R©…Ô02j)9¦T¹è2K;(øc|Uü1‚j¥âå6Ðnð!ËHD˜4S®¥Ü§ù)eе¤¥\KÑ\M¹–Ò­«>X«Öð¸*p›®Zø¿IšóÅŸÁ‰ÒÛéƒõ‹9ñj®ô’f¬óywˆˆ9,¬}( 1èÙ£W¯ð¥²}hXws¯ž=ŒF:®¬~jsóÚ÷››§Ö—�xwtÃóÏ5ú]îÊäúÉï77ú~Å—“ŽG>ßÐðüHq$H‹¶Ó2}hâ¯mµnAš†K+ÈûhÆKŸÀ‹=>E ÷øFÂèñù1 D Ðã+ “1ŒÇ äcJ0‹2L„3º f ’Ëe¨Ä ”£É-ö0%ƒ)&#ù–­¸ƒ0E˜Œ2T  ¢�³ÿ¯-ç{z{¡Þ„€|”ÊþoÇ$ e˜Œr™¨¼Ù9Æ£] K®wü_¶”xsd†¢ ã1åfL ÀDOÝÐ}Ð Ï,צc¼gÞÆb JQ)ï%ÍB…€2üŸa'1�ÿÐ2…¿Â¬°(fõE7Ü�ðjñ ¹DgÑYt6÷)ŸÍ2ˆ¹xVšm|‚#$’$’ÁdíLËèËÜd¨�nè†bŒÅ|¼€Ïpˆ˜ÈZêOë¸Wù·ù_”›Y ”0âEüÿ!$‚¤‚ìÃa4ñ#�$�DOî'��GÈ,ò y…¬"o’Z²“ì$Mä9O.�_((¨’FQ=�¡1Ô@'Óit }‰ÖÑ:º“ž¦—¹p.†3q=¹ÎΕq“¸yÜ"n·†;ÂGòu:”.m½¾‰%øßâ]d#Uñªø=Š4ö4û íq7b° £q/Ža¾Çqôç6¡{ó}´šes嘡8Œ<öÓ_”²ñŒ xM¥€CeR¶¼¡Õ§Í»h^xá…^ü‰À%݇o³¾æ6÷[“n@޳\8:.‰\8sáÅ…c!Ž\8”rœTSv=v6Ž�\8ÎÉŠ… ¯YÜÝââÂkž’ÍêqãÍrÑá.Œ�‹«°»í <·ÍàKv‡uëá®î’á¶wÅ»mH¬Ù)Yßó¦ô0. ;¹0P”sa ôcVrí!ríA9¥§ÆÂ…¬îd4¯ØÈñ 务c›8RlN÷¥ŒžEtô{zÆ­Ð3«ƒÍ+Òï¥Mx�6a#mG›h=B�`6mAmDmÄŠëv#mDmÄYÚ%m¤�ô0=LÑC¢‘H"�Ä(z+®ûéAœ¥¡¢éAhè×Ò¯s™%?�~ J¿¦_CC€Ðô‚è~ºŸîg›è—5½û˜×ÉŽ)Ñãèb=Nx”Ç 3»èîšË�u.ztµ`Ò­LïJë!Òzé+0Z ­‡@ë‘KëQHëQNë¡D!m@9m€“6`mÀJÚ‘6@ \¯Ñ\¯èt„ëJWÚ m@.m€šî¬L:­«1fèÒÃèú¡£Ûéç²ÝF?•íVú‰l¿ Ÿ :º…~Z­Cºý ŸAC?…†~†Dú ô?«;…èXz0Ý݈Dºit#Ó�E7b!Ý%ÝHcjŠu!é~ôlQ:ZƒS²}¯¨a§³3˜-‚DÆä{Ì!ùó a…‘ZŒK—™-‚DÆ‹ÍA"ããO›-‚DƇç˜-‚DÆñSÍA"cñ8³E�È8|”Ù"Hdœo¶ƒóÍ.úòû�îÒõüÒƒè4t¥Ó`¡Ó�K§�§Ó¤ —yil/ÖÄÅé\t¹ÅÔ9Nç\Oœˆsq¾Bœ%Ä9‹8çg qŽ$Nqj‰3š8-ÄùIº~¾8‰¥¶U±�%‚8·ç;ÄYAœFâŒ%ÎNÄ)�ÞÕ× è.«lV§Kï+ª_}Oª9(=ˆê‘Fõ˜Mõà°‘êQw½Ää’…êW 1îàÑ’�Y—æ.wI6—¥÷§›1›nÆBº‡éfðH¤›QH7£Žn‡ ºi×µQt36ÑÍ8{=žÑÍPâ0�¹þ.Z(s�A"�A�Á(ƒÙ4gi ”òpÎR=(ÊbVÔzdüLvÑß�!2d)!=!]’xÈR ô…“GŠ˜ÕWµž¬òHC†lÈ€©rJÅDXÇf¹*****§TTN‘&ÜͦŠ[Ád2YE‹#«¢Èã†æˆiyÃmÕ*•U´J‡$&ߨóó³ºØ&we—¡9b²TÉq7¥º©ÎÇÇøûõŸâ±™Ò»ÀI?XM,ѤvNŒÎɧbHN¾çÎþz¬�=TØaª¬ &Rq£ yØpû�Ž÷Æ«rŠÇóÌC¥Çº÷2ÁTqc:n¢¢rŠû2˜G$(8ŽPB¡8í· ?«ÔP³føÀ‡]ƒ/|åûÝ~ìüáÏ®!ìeB » ‚Ø5#ˆ]E‚ÙU´C»ŠP´cWÑíØ/C(ûáhÏ~AÚ³+è€pö "Ñ�]A"Ùheîˆ(vÑвËÐÉ, #» =tì2b °Ë0@`?£ôìgÄ"†ý #bØ%Ü»„»Ñ‰]BgÙ%ÄÉlÂ]ì"âq7»ˆ™» Ž]D"Lì¢ô„»ˆnH`¤g4ØtG"»€èÊ~BO™{¡û ½Ñ�ý„$ô`?¢�ÌÉèÉ~D_™SЋýˆ{ЛýˆT$±‘†>ì<,Hf瑎¾ì<2�ÂÎ#)ìdáö¬He? iìúÁÂΡ?ÒÙ9 @;‡{eÎA&;‡�Èbç0Ùì,î“y0ú±³ÈEvyÀ¾Ç™‡â^ö=ò‘ÃÎà~ bg0Læp;³Ó°#—�Æpä²3ø òØi`(;�Èg§1RæQ¸Ÿ}‡B cßÁ�Øw�Ø·(‚�}‹b gߢaßâA°S#s)F°S‹‘ì$Æ¡��ÂC2�‡ƒ�ÂŒf'¥gdØI”É\Žbv“PÂN`2ư¨�¹¥ìLÁXö ¦bûÓ0ŽÇt<ÄŽc&°ãxÙq<"óL”±ãxåì8fa;†Ù2;QÁŽa*Ù1<†)Lº�;•Åã2ÏÅ4Ö„'0�5af°&<‰‡YæãvU˜ÉŽà)<Êšð4eGð f±#X€Ùìb;‚E˜Ãñ,c�XŒ¿²Fü �³ÃX"ós˜Ëc)æ±ÃxO²F¼€'Ùa,Ã|vËQÅáE<Åá%<Íáï2¿ŒìV`!;„•XÄáXÄâ<ËâU,fñOü�ÄkX¾ÆëxŽÀXÊ`žgð¦Ìoávoc;€áEvïÈü.^bðþÎ@ÄËìªñ2Û�¬`û±+Ù~Ôâ¶kð*Û‹µ2¿�²½pá5¶ëð:Û‹õ2€Ul/6àM¶â-¶ÿ–y#Þf{° ÿb{ð¼Ãöà#¼Ëö`3Þc ø"kÀ'¨f_áS™?C û Ÿc5«Ç¨eõØ‚5¬[±–ÕcÞgõثǬcõ¨“y'Ö³zìÂV�Ýø�}‰/ñ!Û�zü›íÆWØÈv£›Ø.ì‘y/>b»°›Ù.ìÇÇlÈü5>a»pŸ²]8„ÏØN–¹_°:ÁV‡&leu8*ó1lcu8Ží¬ß`«Ã ìd;pRæSØÅvà[ìfÛñ¾dÛqZæ3¨gÛñ=Ø6œÅ¶ çdþ{Ù6œÇ>¶ ?b?Û†Ÿd¾€¯ÙV\ÄA¶—pˆmÅÏ8Ķà2³-¸‚F¶¿àÛ‚«2_ÃQöšqŒ}†ãì oN¿9ý‡?yNÿî¿Îé§n‘ÓOý.§Ÿ¼EN?ñ»œþÍ‘Ó�ÝÌé“[åô£·ÈéGåœ~ôw9½IÎéM-rz“œÓ›äœÞÔ"§ù]No”sz£œÓÿ„9}ß”Óë½9Ý›Óÿt9ýÏ~�þçÍé·ºN÷ætoNo;§þÿ@N‡ô,$yÁO­þÍßNyq' jÁm©þ>>Þuùð?­K€¯¯ü·©^ÜY¨[p[j�ŸŸw]þø´à¶T�¿¿w]þø¶à¶Ôà€é™}/î0þ§uiè]—?~-¸-µ½FéQ-/î,Zp[jDHÈ­/×¼¸mjÁm©Q¡¡·¾\óâ¶AÓ‚ÛR;J�ëy×åŽ#¤·¥ ·¾Œöâ¶¡] nKÕwèà]—?¡-¸-5V«½õe´· a-¸-5N¤ÿøåÅF‡Ü–ÚÅ`¸õe´· ÚÜ–j6!ÿw4/î(¢[p[j¯Î�oýñÆ‹Û} nKMŽ�¿õÇ/n -¸-5Ól¾õe´· w·à¶Ôœ¤$ ý’Zp[êÐÔT üŽÉ æÜ–Z`µ‘wtH^HjÁm©Å99·¾Œöâ¶!¥·¥þ/a> endobj 319 0 obj <> /W [3 [277.83203] 374 404 604.00391] /DW 750>> endobj 320 0 obj <> stream xœ]�ÁjÃ0 †ï~ ÛC±“vcè\9tËúŽ­¤†Å6ŽsÈÛ�8¡ƒ$ø�~éç§²¾ÔÎ& ŸÑëtÖ™ˆ£Ÿ¢Fh±·Ž%«ÓF¹ëABe}iæ1áP»ÎÎèövLq†ÝÙø÷„~DƒÑºv7Ùì m¦~p@—€!À`G¨¼ªð®še‡Ú K6͇›lþ6¾ç€Pf.V7ÚƒÒ•ë‘pÆÀ«ªªAgþÍO«ªíô]ż}À+™ œ/ÏxùtÞHf’o™^O+­w· ˇ%‰‡}=ň.帲åŬuøH4ø°¨–ú\¦wÁ endstream endobj 32 0 obj <> endobj 321 0 obj <> stream xœ½W{tÕyÿÝÙ™ÝÕJ–V²,É^Ù3£ñ¬mf%ëá‡üÀ^K–,[½íÙ–wµZI6–%¯üƒÀœˆÁŒob w!8 M(h^¥>ôôœ�¦=)äœ&œ&isZÐnsï¬vœ4ý£�™;ó½¿û}÷»ßÌ€ÈÃ8mí\Z}`sô—€ wvmèê�Øð4@žÐŽŒ:n ô¸3zè€rýæÀ÷Ç_Œ4÷|�È{p026Š9ЀwpïÑ�¿²ãÀóà|q(é_ìøä€ŒX14‹ä.‘nH €…CÃŽ´lu_ˆ_ÈÐÞ‘hD9¿€Íï—¿—¿492êøÐËæ—@ÙŽ•Ú8E@PFGƤG5@Œ?��žœ¸ùcÀ½�nx0 ®ty`¹èÁ(Â.HàÅRœ„7òNÀÁ¥ù‘þ:³y�ƒîÓÏžÓ_ä|ù™ç4·8óèáÞmÙúºº+oí¿»³Ýœñ“¿}ûwìùáÍ?}þ‹œ‰§<§ÝLÛ aÊ6�›Ï �ß÷"8<8t€d÷�È^R e(‚ÈüÉ™q NáÛ\ óÐϹ¢ø[áÛ�©F|À9û)¼‡jákãô±©µu¹‡ì¸Ý)á€<Î�6I—XÖÁjIàQÛs'ü)‚­y ¼| lDšÑ�vc/F0†Cé4ןäôc{±qÆIÿüZçäûÿîXš9»ùyâŠó¯ÿç“d“ÒB. n¡‚Ÿ„ ˜ð??tTðsà,D¶t Elˆ(ÒŸéOÙ3U”NI—0Hÿ ÀsøÎâ,žÁ¸qûñ8îÃóxßÇ0,œÃMø*Å1<…Ód5îÄ9< Ÿá$Ž�&œÄ1œÃy|¯p퓸�àq<…çAñ(žÁ ÜÒ1Ü‘±Æž_㸀gp Oâ"^ ܋‡ÉjìÇ8îÆ}xOã8îÂ=xˆÃ/â3Á­8…3¤ G1Îyâžu¾í8&yP˜®Î;žßÃ[“é ÿßVöÏ:¤O‘œ‰;åi\j»’w…^Óçý¯ü{±C|;,ž„SªÃa?ÎLò…ý¸ÀåêpAü­-ÇÇ¸àø¯i\<ͳðÛ™bÖï;Ë øû LP€73°7’Ø�JœÊÀ"J±7K˜‡Ž ìÄ<ÔÚ0rÈÀ”e`ç´M29(ÊÀ¥È�'χ@F0Œöa3 ‚½Ø�(nÄ✾Û°ý8€!lã=dC8€VŒ"†}èäºc(GF°ýØŠâÃnŒ`Ô •¨DÍ”Ž2¥¥LiMK­Á&´¢›°æOx™|þ¡ÍzŒ`GŸš«‚jTò¡  CˆA¹æ\ÚÇö †(×Ú€ƒ<î�‚ÅÜÚŒb «y�Än.q}¨@”ç’QG0Â{j < 0†¥|^1îËö¸$˜>¶öh÷QóPm«|°6-¨½(�­xOޝHËûW\”GW¦å‘åiy_M¯<\“–÷.»(ß´,-ï©NË»+å¡Ê´�AÅ š3w]QºgvUAw~•·»Àôš³ªsº¥j±;ÇÍ<ñ6ñsÑ‘—Îíήöt»ª�ÝdºsM�é4/;?w 0Gp^Âç½ YÕînGµÐí63O¸Mø\pxá%’$÷Ó.£9éJw4Ó¬¶í”œ¢z'»Û{¨óEwÏöP‚�¯š'OŸÆüºfzgèe0¿ÎLB}{(!:¾jÖ�Á€acc08ÈÃÈPí;™q‚¡|Lò¦‰¶ªaSg¢× �Ià )F ûºHÒAé<(„÷[^§Ï—ÜqÕFue)DMÍW«ÅiY1H~Mõ éàwRç¾Lõ‘ý+éx=õÆ®×N=}òçÿ,|ü»Ô«ÏJ—žL½õ›'Þïÿ²é× Üú€t Ù˜Ìq;R¶Sˆ“Iù«–ÖTV-!ùêä) ¤~4ñ�ÔÉ ¡ž,O|Eº4ñ]ázdlµI—�‹yÁ\‡àÎ¥Y3­¯bƈ‹›ZGV•Hm© ©ÛO0ƒòZ™ÜKB)Aê�øéÒDÔØj�›8:™öÕ•‡Ìæº rrróó„¸'wÆ\ VUV‘j±hNa.q•hùj¾¤±œ,_æú¾G·¶ÜÒD^L=—zòéÔɃ½ýçNÞ'] ¿ý`ÿÙ!uâ„P5qYº”Jì 1¿;ÒŸŠû�…(ÆBèÁÂ|OÜ‹x¶G–�®øìÂ’d3ïù55öͨ¬’Ê„|oAMõR\SA–ç«ùÚ"-WXY½båòe~­Ì9§°HþêWŸ½ÙvÌ”=Î|RýÉšYó·™w|ÐÑ*+$:)%2YØR¡¯#ÿùéÍ�ßy&vj~áöš`÷ÿsñc{ÜÇ£åz×ÒoþÀ!,.*šŸwþ‘w>øÞ’æe×U.Ü`¬or´íÙ‹ÅbÛ÷°š¿ˆÏ9 1¾`î<Äóæzâ¢4{v–kª.ŒÊ*’_ètÕ¬X�sòÕ|6÷\‘÷³Þ…Ñ# G¿ÙŸºÚ±cO uÙY˜únçYyuSY÷«÷O,N9Öýôá‰_; !°ï ò3'ûÛȃ÷[¢Çጠž8 ãïX?ÈWóg³”95žbò~êò#ûú66D"bïOˆ½äÒú­Ý6to]oÏž¼Ïmå¼* N¸{Ã3MRå,œŒQÃcž3.åzâùYY¸2Æê¢ÉМ ¨)®Y'8|¯ücêò¶�÷¤.¼$áM'ıïþØé�W&~-öÞ·º©,SÏ‹cȇï·äºâERöt—Ë´² �•nMuQ�TÈ*Ú. ­Ì)>Ü|ßn=ôî­wþöùÇ~sÏ—_Tt´Ç–.è8:,TÝûÁC--}pïëD¸ë®Têõ}g[ZÎî9³å;6ÇaÛÜ଻<@¨³žº8‘¶ ¶‡ÔæŽPÃFŸªš>M¥A*ê lDú­è$Ã,€ºê©“™hîÔšÛ{BJƒæÌò@sטͯ�âe *Ôw…h£áSÕø&ŽO¡MW±7O²5…¢Í²úpè]!ô%¤ú{LÚj˜í34U ÅÌò@Â�µ+\_HäLBDÙD…z%éE_Ò‹è6-I2POˆ*ᳩ<�€ S~u&±\;bÃaªD…:u­¯-d©”„5_ïi*%Ÿ¥jªbšÉô[¥LZSË u �œjOɩΞPÒ ªœê ½,¡>\g&’Sí¡¤äT�Q‘! CÐLš;B/ n.ïKAÇ9WäŽG“œf ½A4)Ø4¯íÈϽ„€hR´9ÁIiѤۦ�ÛÒ‹3ÒnD“^Æy åLûH€­LÐ#ÝÁ¬`Ž0Kð%#½,ݯ ‹à•2‹øãB}''Éx"+èKrKÉqdFŸ¢%0±†LÓôT÷tÝ=¡Wr0‹øøÝ4Í:v”Â�†6]Öí!*è r£6}CzƒÒoEi°3ÄdÃ>Õô©¦¹±<ÀªK i1Ÿf& ­Ñ†„×[ßlÕ·÷°Zã–ˆ8ýaòKŽšæ]] }sTk ÓVC£¢NE}3uèÑ­J˜ö… êÐo£ÕȪ"¤Q”z‚ˆ:Y‡u "8s¨G‹ÕÑl­nгëmŽ“q\Z%EvÖ´¥d·Õú…ÛBƒ¾3B•( j*ju¾„ˆ:U5KHy@iHàFccy ¹=l5Ú¶‡ž Ų6*‰ è�D# ߨú4Õʰ´�Í ŠEƒ‘hا© &.h ŠÕ E”~l§¢®PtjìW¡‡étõ„¬œ~­_ë %‚A+¢D#>%jú,3Ê3¾±<@Ê(HÓÝ)Óœ¶çõèô¤‚¾°ÖgØî¼š6x5a€*á™4m sÇŸ„?­-ZC?t6"ýÔQßR•~Ó.´ñ¾ñG…È !…:tnÜò®™ÄH£�:t‹^‰M¡�l„©¨WصBE?«¼�J÷øè^Ó˜‰Ðñ>ÅR¼Új�ݸò&6ÂTÒ7Ññh„5''«=*é[èxT õùT“Šþư5Yqå*ú§<Ñ}Æ&5…’®�J�…CÇÛ”°©„à %í!Uõ)Tj©Ê@„k»mvËÒ,JL*ê�Ê@D¡’Ÿ:ý›ÙCòÓQC‹Ä¨fþ”HŒë6*–�fÍ× ©f$F�çRô+I}ìµ´ˆBw† *éùV�¥¬²B¯a§TôG·† MU¼J£Â—:âÓT–„Í 3×”lÁ,� RIç—Ÿ‰�.}šÂ¯Ãvs« EGˆ¶MЏø%ét¿A…âZŠ<éè ±ä;yW ’¾9¬Ð`GHõ1m… ]¡ÌòpýÍLÕ7¹`¶šP\ËÛ.{-ª“óͶçk;uò+‡_Y:uëtŸAÅâÚ ÛÅ™.‚aƒMÚÖqðéÚ8tæJÉpx á "ê1“ý:TXûTi0¢±áK¦ßl Ñ`XcÃ4™{7wÄ4¸iË6ÌÒådÌk¥"ãɾ²Ùµ™‡0“ìá—‹Ï™ñì�¤+ŸÉ^2ýf&sjæ`5â¼;³+3û.æ£C¦Ñok93\Q¢¬sGÛùׯö�ªjªË§D© +шB; +jÇv·�Õ-vw`UI54Ri@(´&ÂnP(Ñš¨ 5‘)H{Yqkµì‘¥Õ&⢤ˆ5#ï¬+ªYÑp¿ý¢n QÔúÖ²O#'_è,¾¶‡Xkê I>Ñä%㧇�LÛ÷CÆÿ0Û“®ÉLºÏšbJÜÜa»6ü™û!Ã}M-Ëýç9sgV“fqëF~÷Ÿvå°h‹½\[Ûò»Ola{Ú²XkKìÌe;4ÇŸO%õ諨K_•™e–No1(Ú˜k7§p´+ÄÉÎ,›žM=º—féoÙ¥�M]º—:õ·|¶ÍÖ“é4Ÿ·-m'á°ÁóÀ® ;£mWça佑�0uë�ldvRvf—æ\Õõ3æí5ͺ’©Mc/zmÊ"Ã$Gï ‰>ɤ¿â¥}5ϧ?›ºüŠ×Z� .F@b‚¾Ú²²'û?kÿ¯Að�K˜ÖÕzÜ(X–{Öµ9î«©³89³Ê³¦žŒ˜Ùžzš]Ͼ_Ø»)‹@•ôãïfzÿœ˜‘Nb[q&µ„åÞ5ÙFŒIÝɼ ð-�ѽŠÚ:NE�eê]ö&¡D—J~• K÷Æj|ÄÈ|èg«{7w‡¡(»#T¬'Z„†Ã V" “vûy“³¬ˆ²;á}ˆÿÆ””š;Ø×qgOHó*d-ÖÚ?CZæ?#¤PQ­õ­2) 'Ó—šv«ôMltYŠâͧ$l)”DèIžÞ Oã4M¡NFŠEpÒ°,[ŽÍ>G°š;©ègdžZŸ‡ýåMþ`=lü)¶Âô)Ñ’ÒŽ¨,IôjGU*ÔkTQv„TöªOâ†RÓ²K±4ö7µ5dß“$QYʾØ·Ì”üüRS»‚�SÊ /’L_,e?NÓ~oŸò{X;Ê!kÒqƒ×tËJŽl· �Š~Kµš=ÑŸñmí°z4US“XÀÜgæÃðÜR“[‰$ÓgØ„þaÉ,â endstream endobj 322 0 obj <> endobj 323 0 obj <> /W [0 [600.09766 0 0 259.76563] 39 [740.23438 0 0 0 765.13672 0 0 664.0625] 53 [660.15625] 71 [632.8125 590.82031 0 564.94141 657.22656 305.17578 0 0 305.17578 0 657.22656 619.14063 0 0 454.10156 497.07031 0 0 568.84766]] /DW 0>> endobj 324 0 obj <> stream xœ]‘ÏjÃ0 Æï~ ×C±›¦Í!к ä°?,뤶’Ç8î!o?"§ì`ÃﳤO–¸¬N•5ø‡T�ZcµÇq¸y…pÅÎX¶I@¢[õ�c\V§zö•m–çü;3?ÁÓAW\1þî5zc;xºÈzÅx}sî{´+ ÐØ2._÷ÖôœÒÖ•FL˜ÖYÿE|M!!ÞÄnÔ qt�BߨY.„äeY–C«ÿ½g1ëÚªïÆSô¶€\ˆD3%QšF:FzŽtŽt$Úîˆv QZí%Ñî…(ÛS‹Wzw~4šf÷ò”=ÓCe³Xps7#ñÅ¥ƒ}4K³X~þù¼¡ÇXÕÍ{´�ÖH£œ‡h,>6í7gÍçÎl™| endstream endobj 48 0 obj <> endobj 325 0 obj <> stream xœÍ› `eþ÷¿¿™$M�½h!À$„J[zQ \MO áhS )ì1-E�VÊ!‚R‹ˆ«xº޸2- A<`Å[\QÑu=«¢î º²¨�¼™yò ¢»ÿ÷Øã�¡ù|žßóÌ“çy~óL - ft@DÝԪ̜ño.» -êç×·é¾0\Ði�4.Ydÿ¤ôÅI€ÑèãšÛæÌ§-æ×Ó< 2iN}{úÁ à(ëœyËšoÔíz­¢×·4ÕË_?—ð @u†·´4ÕGoã``ËüE—WÝèëáô¼ÖÆú™ßÀø1@Wͯ¿¼Íä¥gœ`_P?¿)1'ëE@¸ Qm­í‹ßc@}Õú¶…MmýåÔg€1@²QˆB<"‚AX ÎýiÔC�è!ÀŠL41qx‚ÖZ;§°ÐZÿü @òìIš­kžÑ]ò‹6O³ÈçMw}wë­[Æ|gŒ4j{?µ QùâÚ—†ju—^`„¾RÔ5ÓFèaÔß®ÏHb¡Y€1Rˆ6D ‚NtjÛóßrr•Ý7ìØÆÆQ+|ôâQ½M]í u~j4:lS×vèBnG*r0 P�*LG=dÌÁ\ÌC+Ú± Û‚A­�Áÿ ÕÞ*ø)–b¦Ÿ Ÿï]p6þÊšþú�™êhu‘d¬;»š¹3„]DÆ„]+ÒîGú¹ö->MXˆvÌE+ÀŽ, E>²`Gk³‘aG6²1ÅZ›v´bêюɘ‹F,ÔV¥ÍX„Q°ÿ¢•ËA²�/š0‹µš…xè\ÍHØ¥7Ö×B´i¯õXåPØQˆy˜;¼˜‹9hÁ"´k¥&´k3Z‚&Ȫ­Ïòp>ð³óˆzR¥v®þ—œGÕS­ž¢Q4Š>í\-®÷ébÂçªóÎÃÿ™Sïø?:=úÅÿ×ç@× ¿‰uÍÿó�®kÆ#ÿ¤îîó¼õ<×ýoî£û¡kÆÚó|þy>Ì�»®Ûtͨ½ ŸÇþAÿ£ÿ]cÿoºfºýߨwº®™þã÷†®›�ˆyâˆ@íU^4£�¸÷ã0)—&£k± �b?^Æ 2P?šô¯…Þ†8 x<°2øc0UÿMàH Ö�4èß &ˆGY�~-bÍÁS�•�wƒ©ºgµAšƒ©Á‚FÞƒn9â‚©ÁÓúfýZýƒúCâˆ@ªúwÿÏ£øÅ1^\Œ&4ã4cÚp j1 ³!c.ÚpÚ±K° W`9®Ä,År\…«±×`½öÙ²4\»«°ëp-6à:\�p#Váj¬Å:¬Ç†päZ\�µ¶jkq�vEçy×lÂfÜ‚-¸ ·ãlÄ&܄͸¿Á-¸õ\üNÜ¥µüyüÎÚþnlÅ6ü÷à^Ü�ñ0 Ç~ŠlÇ#Ø�.Ü�{´È£8ŒÃèA?â ¾ÆI2RÅQÊ¥±4™¦  -Ú*Õb6`1Z±íÚ8V¢kµ¹]©­ÁJmÍÔõa£\…5áX¯­ÁO+p“6þ-¸[×fܦ�Ÿ�ýwZŒÍï—³Skï;Wÿkó¿ç\›‡° º±»ðÇ#x;Ð�]Ø�GðÄCáù=…‚®pÛÝZëÏ«Ûñ‹Z?žÀ^<‰§°~ìÁ“Ú+�=�á2+ídz8€çð<^À«8ˆÃx/àE¼‚Cxojåwñ Žã|„/ð5>@Žàs|‰¯pÇñ5Nà$Ná Î €3dÐò”AqÔ›ú‘‹r)ÿ_³“ÿ#Ç-¿ ôªpúl âÜSL¿V¿Y+L‚'P‹ZÜPÿ%cÈ2DëÐ�h}¢ô6áµà)zÓð" ºÄà)Ì@à/_<{VíE3k|ÕÓª¼•S§Lžä™8¡||YiIqQ¡»`ÜØ1£Gå�1×’¬ö1“‘n/uÚ•ƒ%N»ŸfVúœvåúg�]9¦ùdÍu)ZÁTâ¬q82ÒíöÒä–»BuöR¥lIKgi]IF:uEG;‹›¢2ÒÑ]ì,ŽÎH‡2ØÙÖEƒÇ‘&ÂàÒQ]Œ&õmÑUZ/+•¾Ò›ÃQ£ÅP¬õ¥Š•­/û\uÌØ`ïJß×y�ߊ†º´Ù)××ú±¾&#½S,íì\§Ä¦)©Î%õŠÏ’3ÒK›”tgI©’æ,ÉH÷xϽ)z—Õiïü Õ9�ýy¤>1¸¬ßAUuŠç–I¡zîP"Šƒ:?‡CË¿ 饣ÒÇÊv4غáÎL«Q„:µf¯I¬Vk:x͹Ëëœ5U¥uá?KZ’•Ž{Fº¢KÑþ¸�«ÔYjWÄ”º†Æ•õM�Î’¶nÓ|Š»Ä^ª¸ëÃs-íÊÊ,u–Ö×)T7W]†JŸ’élSœE¬�§ÒgWs0·Ê§]¾LI(VP×¾JÉ,-QÇe/í¬+aTûrVúö 7øq×0»mg.†¡F‡Ò«Ø§ˆ)¥�>¹Y‘êl²b¯k¶ûlÅ]£P}�Ó×T£fÉiUR?¶9Ô£&|•ÎUzAkÞX�y„Ëh÷ 6±FÍ–¢sÙË�ËY4F‰pY+ª-c÷‘ ¼™’úq¸…j?ëGçRDWq¹Z%ª——Û5vü“!ÙÂcÒ»ãy}YýOcbïó‡ÆZ«Jµ—6•œ7ÀŸuª0ÜÛ¯�SP×"üÆŠÞeTÓYΫD—]ѹŒŠà*.×Bj“í *ì>g“³ÆÙbWÜ>unêZkùõT9=•3}Z¶ÃwÉ´Ÿ•XýÈsuaS„âi>¥,ÍÆsª•ÇkåsÅò ª'ðj{§Ñé©êT{v†;„½nÑ¥R&Ôo7,#�Êœeuβz§Ýj/ë¬÷;:»ÜîζҺ–QjÎ r§³Ê7Ʀ Íë»Òv…úVqð�gZQFz—€¢.'­¯ìrÓúª™¾=VÀ¾~š¯[ ¡¸®¨¦k ­¯ôí±n-*¨Q5¨ìjAíÉëëŒZ{Û7СÕê´€Vnô´˜‘Ç�~�Ŭ<& Ñ¯c1·S�ŒôÒä§G}Ö–Úe57+jZ:ëjÔ�…^ŠàR)äEpŽë"Á£D9›Š”hg‘/Pã,nPãÎ"…zQFº]} uÖ92Ò•—6b÷¡¨vi÷ƒÓ|Žƒ¶c5ÅàªU ®™>%2­Æ®è]�k¼úU§\㕎Æzu¨ö©×F¸&4Ö(Æs*×%ÒU«D†{P"\eÚ5꽈j_£ÍQSïÔTéh´9”Ž¥&M}SßÜí^¶*(wŽR )¬O}ŠúF™5�qÎmc\J”k�ŠH×DU>±)‘êpjØ"EÄ(zW£S1¸ëì{ÜС±Êç?H£l,ÒTéSt)MÚW”-\ uZ¢+Ú¥DU"Ô>U�ªîG½+¢¦† ^+­ 7P"]V%Ú¥D¦œ·”á £K‰vMPÇ¢\ë”(­é~µ›J?¼ÎËÒVTë)B‰r)&ׄz¥£�]­D¹œ#ùÅFõîã‹F¨3�qMPD×4ðç2ÇyGFºSýdPoLØönÔt^P.JËH7^5iáÎN£é×/`ëe4�£´—Î-Étê÷Htf½ "" !µ{à¤Ûº3,&? ÛeµûDy(ëJÁ^:€xdÐ��Q}‡§˜“{0'7;+’œ”K6"]C äD`ÊKÔ§ÂK6v¿œ¹1 A¼ Ö�‹ûÅìÈ„gWbb$I~RºMŽA~zÙm‰ÌŠy•ì@ô±W&úIpG&Ä~ß§"ý”΋‚cáõËœ—¯®_Ï[zòcó3³³ƒÌÄnèá£)oXŠs€!"oœ¨®`b¬è`ú ¹9ÃGˆ.�÷¡YÓ¯˜êêyÿõ…‹«ïó9*g6ä\tSÓðÎÓ/n°{è˜;¦¯«,OŸÜ2öÖí¾šKSœwÅ$ÅEö®˜vv½Ô'«xH¿¼Ôä S!`¾:#ýZ$À�a]1ÑêtŒ¶D?ítÇb€Ñ¤OþÁê�®Œª’¾ÓW¨SÐnÈ|>úì¬x-Ó½’bsc�áYŒHè¥5VKýü²U»[³feì¸Ó0ááÆé«g¤w_ÚP´¹2­%÷†­ÔÓñµãcLtÿËŸ¾¤¹|µùc;—,¢7ýêÏfju b£1 u¸þI˜©©˜L]�g#:]Ì-ú©Ëmš10{FjöŒÙ©¢#i/½ŠŒ¡WÜ)Žzk| ¬¼ÌûŠq`YºhŽ2*3–ë‡�~kÔÔÚW†Wê;]�Ö±‚c±qùù™™³TÄæ[�ÅæZ�åhóì‰KÊÏÌÌŒ�Ë·ž|>.)ßÚcU7bbÏ¡”AfJL蕤ï/þô`>b¨È_Ù9I]u¤ r™Åx-£ÚvÔ ‹í}¥ü–M3 ØãûLCFÏÊ‹rG-{¢ãŠí rJÆ÷IIŽ;$¾_btþœM>WIšwV¼yMÕe¥ýå9�iÉQyöQS³†UŽèÇ)ÎvÎ>eUm®-¡oŽ”’#D ܳÇ_~ÑðA¥çOX�30-+©p^VRzîèµe”ñ†3±ã ûg8ÆŽÒGö’–&JY#%ç˜)CT=´'ã!ý&D¢ Ÿ„…΢7tÔå6GR$E"úë"OETFùi°;*ÁmM(OÀwâTû0íX�¶°Õå¶öh5G^ø‘¯Þòç=ÞéTàz—ÒμGÇöËq%&ºrú…)ÖngîE%íÓ²ÍÞvùè�S¼›‡ÖŒHNÌoöÖ\1ÉAqyÓ ‡ö7Ç%lëݧ¤À–6hˆ-!·l¶{ˆ<=ßd½#!>Á™i³¥§¦&÷É/󩹨Óõ�"nSB|2ìq‘Ô«Wï>‰þàÇ»{%&ÄUFúIt[¢LAÊÒ‘az|BB²z/äädæäç� zŽdŸ>¹ÉrûÌ9˜£~ü˜ÅsÓ'Œ Üø¤ñº~�‡ó.»f[cŸ!½{ ë—U5±Äh}>�;ê+ñ虫®}~åA¸[Ô÷-�Ç‹G϶ܹM¸Ý<. ß)Î.}o¿@Ýg‚Ÿ†t÷÷FùiH*Ø�’yàäóÙYtÁŽ»p ¹ÒÈ!½{)ÙG IN2Â~AY \XyÖyaDé�Z±A&$u›Œ‚Ÿv˜�é(( Ìž·Õ¿H vØ8aDbâ’„ï¹Ùówv4Vب¥í‚~ÙÉo¾Y:'°*0ôËÀ´§"] Vu~Ÿ»vEGLÇüŸõ™`" �˳ͧƒé—ì\ßôì¾À•úC�ê³ßÍûòÛ®š³ŸîýœÞ§jž7â }ìÈß#=¹»wlïX»ä§OÝ1ä°š¾Õ‘Ð(Øýd났ýýO½uŸW7ÞÁð}›Jy4NdOvCÄ q”^T 9Äg~GÞª–Q }†OSµ>¿nâþŽ7¶ä®\>혰üNªð^ÞèËÍšQ”2qtû”ÙÃn¨ñt¬\_ùÅØqWd2M´û� qAX(È%Àå,—¹üÀå{.§¹ü�Ë).ßqù—o¹|Ãå$—\¾ærœË1.G¹|Åå¯\þÂåK._pùœË.Ÿqù”Ë'\z¸|Ìå#.rù€Ëû\Þãòg.ïrù—w¸¼Íå0—·¸¼Éå .‡¸¼Îå�\^ãr�Ë«\^áò2——¸¼Èå.ÏsyŽË.Ïrù—ý\öqy†ËÓ\žâò$—½\žà²‡‹ŸËã\ã²›Ë..;¹tséâ¢pÙÁå÷\á²�ËÃ\âò —¸ÜÏå>.÷r¹‡Ëo¹l㲕Ë]\îär—Û¹ÜÆe —[¹ÜÂå7\næ²™ËM\6qÙÈåF.7p¹žK'—k¹¬ç²ŽË5\ÖrYÃe5—U\Vr¹ŠË•\VpYÎe—˹,岄Ë".í\riå²€Ë|.ó¸\Êå.s¹´p™Ã¥™K™K#—.õ\ê¸\Ìe6—Y\j¹\Ä¥†‹�Ë .Ó¹Ts™ÆÅË¥’K—©\¦p™Ìe"— \ʸq)äâæRÀe,—Ñ\ò¹Œä2‚Ëp.y\†qÉå’Ã%›K—L.CwªR8B¸²°Õ€°$¬†,¬A5^Ö€�)¬A«°;„5꯻ WƒpB{Í®ÆájØ!¬ EÛÔW¡²°2tu…°ÂJõ×…•p +Ñ&¬„(\Ù-Vû…«º ƒÒa¹°¢[–,…é +Ð*¨¿”¶CX��„Úµ+@¸X¸ W@ÀÅÂ2|$,ƒ€¯…ËAب½¶j¯VõUXYXŠjX…¥° KÝ‹……T(µŠ…Ò¡Pš›ÑR='£¹º)C®nÌh¨®Ï©«Î¬+¨.Ι]-Í|f¦Ð6óã™ÂôŒêê‚jš–QU]PEûªh«öÇ›QY]‘1µºm*eN¥­åÔVNûÊ©µœÜåT–QZ]’Q\]”QXíö º#-e{„yÂ¥Ý9’Û/\ª•ƒû„æ�‘1e¯ïÚAp —íÌQæö —u÷u”ù±»ÿÉ/ ÔÝo°ä �‚ †³ g~ìî›&ùé†ïN3ü�áÃw ë¶eJ~ú–ᆓ '¾f8ÎpŒá(ÃW eø × _0|Îp„á3†O>éî3RòSÃÇ 1|ÈðÃû ï1ü™á]†?1¼Ãð6Ãa†·Þìî=ZòÓ ‡^gø#Ãk ^ex…áe†—^dx�áy†ç0<Ëð†ý ûžaxšá)†'ö2<Á°‡Áß�\(ùéq†Çv3ìbØÉÐÍÐÅ 0ì`x”á÷ �0lgx˜á!†`¸Ÿá>†{~ÇpÃo¶1le¸›á.†;î`¸�á6†- ·2ÜÂð†›63Ü݉a#Ã� 70\ÏpÆÎî¤ñ’Ÿ®eXϰŽá†µ kV3\Í°Š¡ƒa%ÃU W2¬`XÎpÃ2†Ë–2,aX̰ˆ¡�a!Ãe m ­ æ3Ìc¸”ᆹ - sššd†F††z†:†‹f3Ìb¨e¸ˆa&C ƒ¯»WuhÿÍ`˜ÎPÍ0�¡ŠÁËPÉPÁ0•a Ãd†I †‰ ÊÆ3”1”2”0312¸ Æ1ŒeÃ0šaC>ÃÈîĆÐþÁ0œ!�aCnwbEhÿå0d³`C&ÃP†Œî„¡ý—Î�Öï’ÔìkHíŽSŸÉƒ1¤0¸2808ìݱy¡ý'1ôgè×m- í¿¾ 6†> ½’’z1$2$0Ä3Ä1Ä2X, fCL·ÅÚÑ Q ‘ F†ƒžAÇ 2 ÄwÐâ‘Ô¯€Å#�µx¤3�ô£Å#ý`ñHß[<Òi‹Gú»Å#�²x¤ï,éo�ô­Å#}cñH'-é„Å#}mñHÇ-é˜Å#µx¤¯,é¯�ô‹GúÒ⑾°x¤Ï-éˆÅ#}fñHŸZ<Ò'�ÔcñH[<ÒG�ô¡Å#}`ñHï[<Ò{�ôg‹Gz×â‘þdñHïX<ÒÛ�tØì•Þ2{¥7Í^é ³W:döJ¯›½ÒÍ^é5³W:höJ¯š½Ò+f¯ô²Ù+½döJ/š½Ò f¯ô¼Ù+=göJÌ^éY³WúƒÙ+í7{%÷–}f¯ôŒÙ+=möJO™½Ò“f¯´×앞0{¥=f¯ä7{¥ÇÍ^é1³WÚmöJ»Ì^i§Ù+u›½R—©ARL ÒSƒô¨©Aú½©AzÄÔ m7UH›¤‡L Òƒ¦éSƒt¿©AºÏÔ Ýkj�~gj�î15H¿55HÛL ÒVSƒt·©AºËÔ Ýij�î05H~a½»Ýä�n�i•n‹i•¶Ä´J·Æ´J·Ä´J¿‰i•nŽi•6Ç´J7Å´J›bZ¥�1­Ò�1­Ò Ñ�ÒõÑ�ÒuÑ�’µµõéè#´õîè-d&$OM¥¤Ì¤‚$qkÒŽ$Á�d“ÊÚ:^Oø8A×OÛ¬äîÛiMÏ*ó÷¹�Vi@Y›…ž±Ð�æ­æfq‡ù³ðŒù�æ�Ì¢Û<®¨L|Š´ÿf¢�˜–æñG½ÅXq‘BëW•úꮜ©Ö+¨žy‘¯‹è†š.Ч)±êoGhåµ×_�~E¥_•¯[ܶ­_Q�GéPÝíÖ<¨:Я¨&­}ÑâöÅiiííí”Ö¾xQ{û"¤ýÿÐ{ÿžiiíamoo_´¨½=-­}Ñ¢Åi‹ÒÚ�«JkWkµc‘ZZ¤ÕÆíi]Po¦0(ˆ�²@�@¦ d @¦³�éGÈôdú2�†L‡L§ Ów�éo�é[Èô d: ™N@¦¯!ÓqÈt 2…L_A¦¿B¦¿@¦/!Ó�ésÈt2}™>…LŸ@¦Èô1dú2}™>€LïC¦÷ ÓŸ!Ó»�éO�éÈô6d: ™Þ‚LoB¦7 Ó!Èô:dú#dz 2„L¯B¦W ÓË�é%Èô"dz2=™žƒL Ó³�é�i?dÚ™ž�LOC¦§ Ó“�i/dz2í�L~Èô8dz 2í†L» ÓNÈÔ ™º “™v@¦ßC¦G ÓvÈô0dz2=™€L÷C¦û Ó½�éÈô[È´ 2m…LwA¦;!Ó�évÈtdÚ™n…L·@¦ß@¦›!ÓfÈtdÚ™6B¦!Ó �ézÈÔ ™®…Lë!Ó:Èt dZ ™Ö@¦Õ�iU(¿+Cù½*”ß+!ÓŠBõuy(ÃËB¾<”ᥡ / ewQ(»í¡ì. eµ5”Õ¡¬Îeu^(«—†²zI(«sCYm euN(«Í¡¬6…²*‡²ÚÊjC(«õ¡¬Ö…²zq(«³CY�Êjm(«…2Zʨ/”Ñ¡ŒNe´:”Ñi¡lzCÙ¬ e³"”Í©¡lN esr(‹CYœÊ^Y(cE¡Œ†2æe¬ ”­±¡L�e)?”¥‘¡,�eix(Ky¡, e)7”¥œP–²CYÊ e)2 …üßÛ½ÿŠ£æ¿=€ÿ·#ø_ÀÏß» endstream endobj 326 0 obj <> endobj 327 0 obj <> /W [0 189 549.80469] /DW 0>> endobj 328 0 obj <> stream xœ]ÒÍnƒ0 à{ž"ÇõP%@ZZ !1Z$ûÑX€&†E…ôÀÛOØ]'íÒ'Û$¶e}ª� \¼ûQ7xg�ñ0�7¯�_¡·ŽE17V‡»ð­‡vb¢¬OÍ2j×�,Ë8ÐÛ9ø…?f¼Â†‰7oÀ[×ó§KÙl˜hnÓô ¸À%Ësn c¢|i§×v.°l[pÁ†e{)›¿ŒÏe£#º� ÌS«Á·®–I)e㪪ªœ�3ÿâ‘¢²k§¿Z�éIÎ3)c™£J”:¢"Ší(íI éHÚ£ªÛG¤Š¤P*&¥$E¢TJ*IgTJ'ì(3¥ÌÕ¨ç)Æ&ïÝÄ¿½=f¡è’ª SÎX{¤Û’?Ü?AEëÈÖÕ>ö¡oÞƒ ¸ÜÁ:}ëàñ‹Lã´V­ÏÌb¤Œ endstream endobj 72 0 obj <> endobj 329 0 obj <> stream xœíX[L#×þÎñ`sqƒ/\Œ=¾á¶Áã ‹×KÌr[.»ëÍ^À€ƒ 6¶ŒY ÍJi.Ò6e·Úf¥¬òÐö¡‘²ŠÔ݇FMšô!UU5‰©Qö¥ÕV‰Ô¨ªÔUCÕ>¦™±¡m«}¨ªVšï“Îü3çÌùþÿ?ÿœÑ €Z<æúcÓ'føU@~`hbÚç¿ø“·”U˜›ž‰Ílýfe s\ ÙdžöP@32Kɵ<€z;*—2[O}Ïý‘`>*ÌéTrÑsÿòóÙJ§SI9W!ÈqÖt¶¸i¿Ç¼4v Ý™ÜBrí¹Â1 Z T²ÉÍ<ósº `»šÌ¦N~+ý@ï´6Ÿ[+ò¿½ÐŸ/¤òiùöK_ùö'Š· ÿÒ]æ@@xu s�ü.¬B.œ‚ ²’É ?p¤¥+²{{þJ?Áwò�2ÇÑ1ÌuA •âuµØêA7–ÒEÒ€–Æ}o>ù7\çÿ6[wü¯•2ÙçÂåûSo…ãgmß\ä;÷zdÆ 9è?ý@%€0ƒC£3hYØ*dвTH­ %“,®¢òòX eÙ#Ÿ]^Lå ¹ìªà.MÐ÷PЗiÀHéH.ÁOœ­‘UÉ¥ÌÑlÄû'ð°(–òÁXÉ/ç@¾/ > 7…Õ³IÅÌ ¹�•sÂ@Pj@½˜qƒ8…$RXFEžï,][À2VQàyþ÷üûüûü»û|ÈʨBAPaªl“ú²M`À_Ê6E%þX¶eèÁݲÍÀ�«e» t–m9¬P–lÒ¥‹`{ÄyΊ^/!�"¦‘Ã: X@ Èa)œB9xÐ�2XĤPÀ–‘Ã*XtÁ‹NøBiäPÄ‚Øs¹ÜWê� ‹$V�G<…6‘ ?¼‰#k³êlYŸ=Ð?¬à ú1�È#y¾ü÷J·E¯,bXDób¿CÌQyôÀ6Dz‘<ãcÏÂ':ÀbË(" SHaMÌÜe¤°Cb–Š`1Ž$²‚ÛtØ7¶@, Ò›�¡ J4@p*“ÊÆùˆ¥Ž„í:®�XŒTe¡ {¯ÿÐá`œÏÎξθ�·Œë—èÍ/3çÇæç{ç§ùÙHäö;dM¨æ!€è6ªK³q~Ѩk‰ÅÎù{I0à%n2ôãÙkãc/?él ŒºÝ£�&º=ø�|þ»Ol8.Œ�Ÿ³�b ]tʯÏâ&çín2ò‡'ÖN OÌŒD#ÑÈݶ_˜�÷ý–L…ü'(¢üÕ‘]àtf/ Ba/µ˜k‰ÂÞKÅ9U»¥–Øý¡p°–jÔrß?ìxõ®¬ÉcnêäôóȤkh1´YÃØž¤¦ž–áIVeT:]Ó‰j«ªÑÔΩ ª®…ѽϺõŽB«zŠÑšµuÚj ð;ÔBvÑ&ìô‚z/áüZ�ÂK1Î ëj 9;~eøÔ £‘9ã`[Pïê·ZúœöXk¤#«Œ®OM­Gm†óêFóãn÷ãf}ãE›>~‡ÖÓŸA ³0ûþôœ=È•¢ Qí‹i .­EçƒÎãMŒâ•ÍYëp³»QíÔ¶z[ýÊooMûôÍc·¿àZ­›šæê Qßð aW —ã°ŽCX¹Â4)íGÃ99veøäåþ±t°‚î]%×e ¬ƒ�権Ë�bš\ïí[TÛªôÇ£l¿Ÿ‹± ªs­Fð<Æò.ý‚¶“ÓäÌ5Oi—ŽTOv¡+BljñjT•à�\¡ŠoÖ0ìt÷Ìø+&‡ÁÓBô³ÞÌ¥½�‰ÑïmmÞ{ å¬9É.ê`<�P¥ Ý�‡tÄŠñx1VjÍ�ÎcÛòª”Ú�Òº”ZA#ÎÇE ��1ݾ§åÇÀÜn·è4�Jr…Æ@â›52㘣÷\gt¾ÛÔ×Â(Në;ZÔv¶É£ÓxÞ¦oø[-½…ÑÓ›}ú–ÉÄjˆqžˆAÓü�ªE€ZÉ.ç¥Tfr…ª¸©”Ù–#&§Ö ³é½çXò �TWC¡ ìí� Èïˆyu‰ud‹  x©]|d¾V³Z�� qGÿó¾>O*äl¯iõÙR‰gžÈÚûm3N�¡>Ð7zÆÎ*=Æ m†fUMÝcÊJí象Óîæ„®©ª±FÝX«ê8æôÄݺúùÚN¯¢¹´"Qb öNÃi,‡‹êʼn‹®g_hÜúä­×ÚÖ©m1M(Ãó±;Yù­[k?²y5Õ•OW«„ù„ú¹Mom“Ê4©ˆöWä<¹²¶'dëCÚK®Ó/Pá©âÓ¨å¤ÃÕÝír‡Ã´·Ëáä8§£«ôÎtpì_0÷PÞÁüŽ4’‘2Ïp‹¼I>%ŸR +%þ‡øŒD‰%J”ø_à á/,â‘C  áðÑAÂ×Þ#��–�4M |¤ü!÷ÄËcãåó"M Hâ?, $HøŸÁÃö0 $H� A‚ $HøMàÃjõY endstream endobj 330 0 obj <> endobj 331 0 obj <> /DW 600>> endobj 332 0 obj <> stream xœ]QËnƒ0¼û+ö˜"Û$i !¥$}¨4öB-csàï+ÖI*õ`[3»3^�y^•5ø‡U�:cµÇiœ½Bh±7–É´Qá†hWCãÏ«¢^¦€Ce»‘¥)ÿÄÞLÁ/°9ë±Å-ãï^£7¶‡Í5¯·Œ×³s?8  X–�ÆŽñüµqoÍ€ÀI¶«4Ú`²»æõ_Ç×âÂ2N£F�“kúÆöÈR!„È -˲ÌZý¯~Œª¶Sß�§n™A*D"2BGB‡!kÇX“9¡'I(9Dt¢[n~û»ûcy¹ÛS÷>jO‘|‰ä%’E$K:ž“›otZ²þHIÍÞ£ ô+”Ìš‰±øø87ºUµ®_ì9�¾ endstream endobj 93 0 obj <> endobj 333 0 obj <> stream xœÍ“_lSUÇ?çÜÛ®Ý–Žº²ê†p¡ƒýéèÖvȸ?ΠÀ�ÍQ…uíe�´»M[a˜Hx£žà£/$1øà ‰Fž–È‹ÆøÀÆÄHÔ„DþQ“¹kîi�‰‰&ž_rÏ÷Üïïœß÷|Ï9ÀÇ14&úGŸ³g4×€á‘ÑÎØ‹\Ú2 LŒŽõ�ýðãg1g�'S¹d^Õ `ûT²˜–wÏTöÈ�+w¿›Ýbb3Мɕfk>æ5Ð6_f­TÒõ³ë<ÈÏ�—rÉÙ<¹˜Œ™dÎÍ;À5r2oKö×i+>_0ó÷ÉÀO@ÕGÂ>ñ¡~ ¶©ÃÙ{·ø•vR¸Õ详!ÑÀ¾çš°¿ ð”ÿh×n‚L,\µ#Z»vƒ9ûÓ%Ýj–p_(vdÞÞ_·ùžGÓn8Ä·»/>áôß?~4¼pua“Ö®7£áF.®-ð¨Q@}›‘‡§2%á‡éR2+~ºÊY®£&Fåå ö(:úÐðö1SG Y§ æA³ÉÒ �¸+µ$µxÊkØãÈé´i¬ÜŒb¥rÃÑ¡©Œ:ÎùT+}‹³¶íxþ'¶¯ÛŸ8qŸkºLÈ˸@¾)ömžuz†Ä>b¢ d�æÕtÍ+õÝîá³e¿õfqeqZ‰¿%ϨʎÆöÿ ^PqtI\tNœV™øÛ�øß5™ ´o{xŽ}­ »ä4¼ÔòË!î_í_ï¡:±¡%ß*B«¤¿UzÎ]ZÖï¤Óïêáuï­-¤å™ß³Ï'&'›ææ^Ý?<|~NwnNȾ+W‰yü¬†àšˆèéÞ"㱕byÀ'[b[dO÷ºÐŸ\hXšìé|.³qh²·sw&²"ÖŒ¶7Å[‚±Ú ©ÁÁ™‘ð†Ôà€5Î7u µöö5u ¶õö!œ=É­bžzˆ×«âN�†`UD„Ö¸ëĶI˧7>³ÎèöEýk¢Sâ¶8ÞѪ©>äõìÝù5¾òiq‹Fշă+E0¾Elñª`¨%"ZB>Y'|×Ko´yêÝzõêš�·¾:v*ì©÷º«ï°7÷ø£þe=¾=¿ý²×ßð55Öî-Û[ÍQçåè^à¤HT°`¥ØTÁ’Ñ\ÁÃ|SÁ:½\¨` vU°›.uß…î‚ÚòËԽ¯^qGÕëÀ"Kš=˜L3E†Û(‘$Ë4)F±x™)L±Hc²‹ëç.ÍǤ@‘i,f0ˆ¡‹½ô‘Á¢DJ1‡*\™ï#G’ƒ˜*ã&³˜ĈЫ2–ê0•-Æ¢ã>5K«÷3Ä#ôýë==|íVô¾RïÔŽcÐO‹IÅ·*�KäÙD'�V!¹˜Qåè¤� 3M‰ »1)*‡a*EÃÊÍ;I’s*�.Õf<I4Í endstream endobj 334 0 obj <> endobj 335 0 obj <> /DW 600>> endobj 336 0 obj <> stream xœ]�ÏjÃ0 Æï~ ÛC±“Žm‡`( �ö‡e}ÇVRÃ"Ç9äí‡�ÒÁü�>éããu×td#ðÏàt�FK&àâÖ œ,±¢cu¼SîzVžñºkúm‰8w4:VUü '»Ä°ÁábÜ€GÆ?‚Á`i‚õî�Œ÷«÷?8#ELJ082^¿)ÿ®fže§Î E·Óµîÿ6¾7�Pf.v7Ú\¼ÒMÈ*!„�PµmÛJ†dþÍŸvÕ0ê› y»�P Q ™¨¼dznwj2½”™Îç�^óÝû…ô!%ñ°¯×�bŽ+[Nf-á#Qï|R¥úE ww endstream endobj 99 0 obj <> endobj 337 0 obj <> stream xœÝÚ |Sõ½ðßÿÎÉ;9I mÚ´= !-%MÓ¥´@›¾„´”²´DH郂 ÕPD©º ·ø˜›S7Ùä:Ô霞dAV¨lNñ1ç6†Nݬ8Cš\Îù¥Ø®{ÜíÞÏçžCò=ÿçù?OÒ `‚>` hôÖ�n| €Üá¶µ­ÝšuÚRrµ­ïuäýY³@› À™:»W®uìÌ0ÍКW¶ötƒ \ð˜W®¹¦Óý¹ åÓ“]­í§NL<@Â0½««£Uÿ(c ³`r×ÚÞ«;¦àŽ0Á5W´µ¾æ<â`'�ÇÖ¶^Ý­ÛCŽÀYp\Þº¶#Õ8­ €�ÝWôôƧÂA’.§w_ÕÑ�3¼>�¥0�:Ð� Ôñ8ð ÷ý´K� fðA@Û¿ªäVŽx6Pr_xî£ ËØÎøkñ“ìM‘çÆü¶cÍÀ÷]ÎÏúL£Õ( ûNÚ§Èþ´ÿ¹¼øk±{“ê0ÐM”dØNúp á¾Å�L”yPÐh©^­¥”e(+ç=ÿ– �ÏØ6uˆÒ±Ö3§9»<2J ¹r¬Xx¦€XЀ¦B.B94ÂR¸Z¡ :`\ÝpôÂz¸vÄãJ=S”œ³/ÈÙuqÎøIh�mñƒ BmüWålSÚ’¥t!ë/FúÂã>ØÀxU ©¡Eî «€vØ™¸Æ™Àk Øž¸f`„×,¤�˜¸æ Ò×*H€j¸.‡¸Ö@+ô€ª”ëvXpôÀ*%‡ò!J!Pë`•’ÇPÓÿ¢Çx- `´ÁUp…’Ú ½PŽ/É/§B>äCñxÜÃãq3ÀñWjÄú®‚nå½zmÎTÂXX«`%tA¯r·EÐ=JÿÖC´Cž2Ž›ÿþ“$ý ÏÈ4™&Ó­ÊùKfÞø¹�ÙÎX{{ûû—Ê¥r÷þ¯œ/ýÃç¨*WµPÕ­œ»ÿ±S�ñœ³Õ³Õ—°�°pl«°�c/ýÛ +þuµýë¶Ö&ìOØy^Ú6¶îø+e¶]äî„3¦$tþïõäß{°�päßbf;á¶“°�DsÞ½·ü{ï ×þ›ê[SÔk˜’Xè¢,—Ãõp< Oà 2�Ì «ÈØwÂ>8‡àu8 q2‘Ô‘0ùêÿ´5œ’â¿‹­ŽõÇs¸�cïÄBª”¸Š{�{‡9�i\?LˆõÄß�­Ž½Ïa_Š…â êŒçÄ?¢¥`«�½’å8n5×ÏE¸#Ì%±$ùêïþÍZ¦|ªÔÁMÐ7ÃØ ÿ·ÂÕ°®ƒ›á:è‡;àëðM¸î�{á{°nƒoÃ6¸nƒ;`;Üß‚oý°î†áûð0<�Âá1ØQxöÁSðcxÀxƒïÔïrÞG”˜ÇA‚ì‚ݰ~¤äßOÃ<až…ŸÀsð3x^€Ãð"¼OÂSJÚ³p~rAÊnåž{Çï:VÏ�ñš~zQ]/Ã+Êw‘cðü^‡_¯à×ð¼ oÁq8'áø-¼¿ƒá#ø|Ÿ*%ŽÂ«‰'”$j:š¨ëâšN™@¬dñ�bâ!E¤„Ì ¥¤‚øI¹Žl![a3ôÃ6ØwÂwàvø:Ü Ûá~¸vÀ×áx‚G£öˆÀN�ÆÇo"ã£øìQú¾&z¿W/y ~‡”q�Gû?¬Œâãñ³ñ«WàçÊÈ\8>ا±QûbÌÞ€“ð6ü>€øŽ)9ßRÆï]x>€×ÏÑ·•{Þ‡ß�—�ÇöcøDÉu~“È%—=?×)%ß§ðGøœ�³#@(a G4ð‰‚Oá3%õ4üÎÀçpF!q%£äT Ñ]â~_–,·‰ðÄL,Ê칈ŽˆQ¹N&iÄNœÄM²I=™M ÈtRJæ’yÄGŠI )%e¤\™á*RMjÈ2�,$ d¹’t‘nÒKÖ‘þÿv_Þõ—Qty�ž�©ÇŸb\?÷ f6½ þ„ ·ÅäŸÎÔªé*=è¸?�ž«3g§/ÆÿHލ~ zU ›ÿÀ/._vihiKs°iq㢆úÀ—̟7·nŽX[S]Ué¯(Ÿ=kfY錒éž#WÓ…E®«%¢Œ¨R“ZÒ¹%£{n«Ô·Ëë%�Û5c¬°F~@èu c¬Zî¹Á=WbÜ‹£ñ‡\×8Ï;¼¹.ù“A^˜`ß à‡æ�‹#¤¥o®æâX£=0 1þõ8^ã¸K=^`åß»°©œPƒ¦Aè)p’§ÁFÒ²ÛlÖ¤©÷“¯…‰dhHÐociÚ ]eÊÏÏ2ßk4²ªíLe»�TCÅè‹#–RóˆµÔ÷¢ùÍâ{cäÍóè!K©oäèHA>±8-Êk¢‰ºÔ.¦¨pzñ´<ê!ÅE…™”‘c'åÑâiåT³©g‹™ÒÑ%´%{îªJÕ€áÚ¹U­Õ¥%W=°ªð´%3;9yJ¦Å’9%99;ÓÂÙϼÃÙ?_ÍZ>?E\ªÎê'´*O˜‘c»» ¾ktgrV†Ùœ‘•œœ�n±¤gË¿O^Ÿ9Ë@)Ü1HhuSpWvv:ì£0 ¨:¢MÏz’¤Av|h·ÉZ—�%Æ' &pÎ*Í>â-˜È„ˆŸ«[EÚ‚Ñc#ÖÒÒÑcžâ;4rtÄRê+ȷ¢†‚üfe�&eeg2E…å´xZžjldR’ò×$Mš˜©bÎnî]9´,¯½£Ý'®(O/iéÙÐÓR2ãê§ú³›8—4,rW¶”¥•,í¹¦gi ÙvÙwWÚÒ?1§'lSË\ù•…SòÊ–lX¼``ålµž×œ0Lä5IîéΜ™¾߬%ë(¬�¿Ï¼Îš`2À7£•–¦wE©~—…¸=QšâôöxZZŠù2²ÌYTÃdeeNnHù4³>oÔ¯Z¤ts¤Bî¦où²K­¥ò �ßÈÑÂayÕäÛý™ÿLùÍÎl3¶|fy]¹&©ÔÅåD±$KbÀ’‹ §—0•C\Ü6sáúúœÙ×í»¾?¹`aiËã‹æ>½òÊûW~úÍò%ÓSëk‹.¯êŸT:5%oQ¯X·1X8;»"×–ã>˜‘åYrÃ’ÑyäÛÔ¡¼r^­¼–úã2ϰpÁ58:—%uµƒÌÄ¿‡·3c™%c=ì#%à‚L2-âg�Oþè±åË.U†ãPA¾}ï?X® ¿Ùm"_ì ä”¤<’X&T^B%Ì3uß^|ÍÐÍsÜòì5m[¦—ßQY³f^öÔkªsæÔffg¤WÝ8týÆC·\’d&å-Z'Îímðh-ÉF ÐŸÖÈ�•‰`0¤@”òg¥¼ßšâ<̲S³>I¯7Æ Ú¸ßúE+å –;WøFbkø-#³² Tj§Òþé%I_L°<§êé8Å,0Ìh{ÎüUþy/Í…WäõFûjj6 ®]ó`wÙiâ(™;5´^Oç¥Ö»ª;k'§¤Ð[Mêªö_·éù;ÕW?èŸÕ\–~m·<‹Û˜7¸~H�fìá ^µ�êAÉT¿4)  %{ü–zm£¦lò‚´–VßÑóèpA¾}÷—ä’WªešÜn‹ËRdQ—3¸>éû›Ê¯¬øôSƒàŸ·dÚÂÞ…Ùô®‡Ú—Œ^ÇõÇvFÝ3§$]zSÃè ò�¹Ç`dÀflåS £òŸ$mÔâ·f¤'e¤¦f$¥³™‚-㌽��’ù~#Ï µ1ÜÄ3þän£7åuS1Rh±’”RŸÏç3�ÊÏiû_±ñ§Ô“BœÅN‹3ÉYì¤'lž²I“fzl6ÏÌI“Ê<¶ØÇ±4•¸ÏÞGª8“³Ì“šê)s:ËrSSsËbúýgíß?>¬ ’aéEs�Dõ»A“Ü �­_ë7×ë5Ú¯µTy.(“ ·Ìù²lÎBÊE“pD%T/l™qÞ$0§ïÊö{m‰) Ûb=l†ÒÆì±½1jr3u4å‰�Q?%]n€ÞZ¯èš\gýÜØÓ«¢bÄb-M,˜¢‚|û®¿™ù¼O„óšÌ%s–L"ïp6#pëЕY—c]h¹eyalÞÊ©åWVd4å–-¯žLM·¼°¥R§‰õpýJ¯êúÜ·xý%®ö%±½)?¸ˆü·Öš ®HÌ�Q»�Z@)Ô�&JÊ#ÆŸqQ¢öëüÖú”�> K ±On÷¦QÛȳ±4O¹—‰m}^/ÕL*å�ùÂôžÚ3ohS+,›±`CC6C×–ÖO³5wÊósgv¹×VÜõ�•ò šŸy…› ©cs³Û’ªå­Qjñ§´:­N›f×ZϘ |â©Éñó¦E‡•ýPZêó™‡G‡ÍGåíç¿,ûyO^‹¼þKä`I|Ö¼Ruó¬ö;–{c§ˆå Ù[W¿lÖU>o�º¤?D>ÚOØÊؾý±I_ižh”ÛžÀ.bNƒ®Â¶û'¨5 uà8­ÎÈep”g¹hüe¿Ž#5C@äa,ª(**²–ÎX¾ìR¹ù©¾¢¢4ÛáÂÃòèÿèï*V�ßœCˆsBJÉ'={7¶–˜�T”¿JTÌéÑ¡'#´NnŸ€­cNƒžM´/KÅé´ÔµHËj×"�FËi9-z5e„Œ:ušš2êhü#3¡¿õjÍž•“‘ã\^‡03/Ý» mú¥;7ÎḆ³…;<Ø#¼Ö%'÷h€Ñ¬…%PQA|EE#òê$YÔ2ÍZNJRT4i¢5…þñ“OênzbͶƒÃÃc¡É/ˆùÂøÊÒm�ÇV?»ô‡@à�XˆiQêNß rܯÕÃk5K`­RùðÑÂBù;{²Õ2‘šˆ:{ºµxÍ&ë>û¨î†Ýkn掼ËŽ�º'öñG¯´l{œÜsü7dçc„Äz˜ .jÈŒ0*ˆ’WýZŽ;£nbÏÐ5P1R!xcXù™ IþÄ Ô;B¼±uÅþ3³÷!šX31QaUJ s†[CÏ@ÓuÈŸ9ÅN ÑOìUjˆõìçî?ý ØBÝÌ[\?X`öVEŒ¼¢ä!ÿ-Qôj1k,Œ�10 m„ŠÃòò²––ZŠä“ø†G‡�‸&¨³½¤$…)bJRŒD�M·¿’þyI�½Ûñyú+gÛcï[ûYê&Å»»á†Çv“âØóxDþ[sš+ÇØót/¨É©]6›�¥¾Ýfp’Ì(Éõk3¨š™àhç Qâ‰ø'´áƒæP…5¥t¤�˜�9¬|3²þ= ò›‹ŠI93öu8;ñux¢‰òÄ™t)þʪR«-Oô.øêÌš^ÝÞ~Åì©õëæï§Ù»IñW®o[ìuWdTÏx0°¼ üµe ·ôõÍyâPè‡³Ì ¦NùÉÑæ×©(°êGc¾‘c#òú.ÈŸPìL"ÅΤ~&tv'¢78[à€¼‡*ß&ƒÀÉ{ˆ¥ÕO†º*†‰oø�‘‚|-ÍÖ²ŒÞ?ºì^r*faƒ£Ï�þô»är/T΢7C;í‡&ÚÚ~ÚaÚ}çÂ;Î…‡Î…�Ó~Ѐ–Þíô«Ð/Ó¯�—é�pœÞn§7�ûè @ ,¿Ó>h§›¡ üt3tÓÍòÿo¢›!Ÿn†0Ý ½.Ò^Ù¥×G*ãBåz-´ÓMJ#6A>Ýaº 覛`Ý/+!ÝËé& ðÝqåê‚üôh§¡ òéFè¦�*ïÒ¹ÐGt#0 á%%þ-z5èSÞ—+ï ¿ÓõÐN7(íØò颔ûl3Ý;èÿæ*R)\Áø„Ëi¥°ÊÛÕ´ÒÛÙÔámojó®hj- 7 a_˜./\Öt{ ©o!§Zˆ¹%¿%ÜÂ,ñ65 5‘¾¦—›èbocÓK�Dj$·7scw#½½‘„eyšê½�¦p€Rã­nªòV6ù£ôòˆ–÷Ò5ô²H¡à�ÒËviyqhí~z宂Ñ¥WFÒ�b”Î�8\B”ÎCæ"u!KˆÒ9ˆˆÔF2s„(­Aª‘*¤ñ#H92™…ÌDÊ�RdR‚LGŠ‘iHRˆ ùˆÉ‹dQêEr2ÉA¦ ÙHâF&#.dâDˆ€d"Hz$½XˆR;’†¤"6$IF’�‰ÈÄŠX3Â#&Ĉ=¢C´ˆQ#*„CX„A(BP q$†Œ"g‘Ï‘3ÈŸ‘ÓÈŸ�?"Ÿ!Ÿ"Ÿ #@>BN!"#ÈÈï‘ß!ï#ï!ï"¿EÞAÞFNFì3…(ù r9޼…¼‰¼�üùòKäuäÈkÈ1äUä(rù9ò ò2òò"ryyùòòSä'È!äYd9ˆ@žA†�§‘ýÈ�‘§�}È“È^$ŠüÙƒ<�ìFv!d‘�Ç#iÕB”<†üyùòò0ò}ä!äAäd'ò=ä~ä?‘È}Èw‘ï Û‘{‘o#ßBîAîFîB¾‰Ü‰|ùz$µFˆ’;�¯!·#·!·"· Û�ä?�­Èäf¤ù*rS$µTˆ’1tCÄ&Ó‡lF®G®C6!×"‘k�«‘ ‘”KÎí¿õÈ:¤éA®B®Dº‘+�Ë‘µÈä2d5² éBV"�HÒŽ´!+�ÖHr˹ýF–#Ë�K‘²iAš‘ òd Ò„,Ž$µ�Û�È"¤©�Lt�Ûd!² 2Á}nÿ]±zÎí¿ùÈãEáS^>áEác^þÀ‹ÂG¼(œâEáC^FxQø€…ßó¢ð;^ÞçEá=^ÞåEá·¼(¼Ã‹ÂÛ¼(œäEá7¼(œàEá8/ oñ¢ð&/ oð¢ðk^~Å‹Â/yQx�…_ð¢ð/ ÇxQx•…£¼(áEáç¼(¼Â‹Â˦€ð’) ¼h ‡MáS@xÞ~f Ï™ÂOMá'¦€pÈž5„aS@8h LáS@ðŸ2U O›*…ý¦€ðcS@xÊö™“¦€°×¢¦€ð#S@Øc O˜ÂnS@Øe S@4†É7†„ÇŒ!á‡Æ�ð¨1$üÀ1†„‡�!áûÆ�ð�1$cHø®1$|ǶV ÷V ß6¬¾eX-ÜcX-ÜmX-ÜeX-|Ó°Z¸Ó°Zø†aµðuÃjáÃják†ÕÂízŸp›þáVý5Â-ú•d>Cȸ=ƒ‘Ò‡Òi4>äoI÷æ‹Bº/�òéBúíé÷¥?žÎm¶“·ì§ìÔo· ¢ßnMýv�Qô§LýiÙSEšÝ)úÓ¬)¢?Mg©ËSi½-l£`“lC6&lë¶ÉÕﱕU‰ù)D¾Ó„k²(%%S°š­ÝÖ>+«‹Æ‡vY3�¢œn±¦¤‰s¾ÙofÀü535É©æÂb%µÜœãy^ài€_Î_ÁÇy–çïãçŸæYÞÏO/y“`¢•òûÓ¦—Lo™¸ SÀ´ÜÄÜnºÏD£v%ŽDÉ×7z<ó£êø¢ù’¦~©D¶JîFùÝßÐ"©¶JÐÔ²48HÈmÊ/ãKù(áþ[o…ªŒùRFcPÚ‘Ñ<_êk J~ù"Þ” c0ªš{z×-ëñ,ëé]ç‘ßå7Òãéõôô®ëñ$ŽÞu=½žÞž^ðü8ÈÿuþðxpV{zäWoo¯<ÓÊ•g|ºåµÐ#нòÊÀL==òJñØþ ‹ö⣠endstream endobj 338 0 obj <> endobj 339 0 obj <> /W [0 213 549.80469] /DW 0>> endobj 340 0 obj <> stream xœ]ÒK‹ƒ0ð{>EŽí¡_}€V+xØëöØ8ºÂCL~ûÅü»]؃Â�Ì$“™xyUTj°Ü{7“¬ÉònP­¡yºIüFý ˜ðv�ö!÷—c£™—WE½Ì–ÆJuKνê‡Ùš…o²vºÑ–yo¦%3¨žo®y½e^}×ú›FR– –¦¼¥ŽyùK£_›‘¸çÒvUKÊvÙ]óú/âsÑÄgÕÈ©¥Y7’L£zb‰B¤<)˲L©öߺDÚ­“_�qáaÊ!‘®ò÷NqèæN{º@X‹C'è��Ø3* *¡È)ö¡=„ZG§#j r§ ‘ñ  Š™9�q^ˆó ì"²@dxqÍyt!øíɳ‡’¢·B='TžáâÁñ±’ÖV¯Oâ9Gy7†”uïÆÍn�Ú èù´ô¤×¬õû¿ö¯¾ endstream endobj 146 0 obj <> endobj 341 0 obj <> stream xœÝšy|UÚïOUoYzÉF1T‡¶ƒ˜4ÙYÒY ´HÒ!Ú�¨I§‚‰$€ÆQAww* jãŒêˆ;:Žã‚»#ApH÷ÛU§ƒËûþqïÜ;÷s«“ú~ë9§N=už: °`D4MiÈ/šðÖÂkº @SËœæN¡WTú Àì–ùÝöOª_<ÐoôÉm�3æÐm–W�øí@\úŒæ®NdÁí{€mÆì…mï¾p¡HyˆËiom–¿}!õ€šŒloomNX'<ÐXg¶Ïé¾bÜkú—ݹygw´4ç5d›ç4_Ñ™ø5íp€ý²æ9­iE/¢  s:;ººÃ?c@g¨í�s[;ËÃvg|dxA�x¤À‰À õÞÑ =üÐC€ ùh“ñ­·¶…�a- õþåF€þhÿQºX×99©›õ›>SYä‹ÖǼϸÄ:öSœIkxúÓ̳U¾¸ê¥á‘áéºY†W˜ ÄÎum´z˜ôwè‹’Å7Ð&À'$âA' :µïé—œÜ`·Ã ;6²ÜŒÓ�g/Ògª3£�¡ÞŸM„j=Raƒì  3Ñ�¹˜‡…؉hç c&æ`.ºq…�|yÿŸ–ß™#¶-ú�}^Ãk4˜–ПÕ��û,¶‹Ð>cÄ1âñIõ£+Ó­`Ä4uftqd,Ž9»3æ,¸,æ"Š06æ:Ø�s=òNõ7hñóÑŠ¹èÒfö2ØQ€á(Eì¨À<ÌÄlȰ£…‰J­O:0ÍèÂdÌD æ¢C‹µ¡çÀþ›^j¬(@ ¼hÅ ÌÓZæâáS-£aÿ�ÑØXsÑ©í›ÑËr8ì(Çl̆^ÌÄ ´£]ÚQ+º´;š�VÈèÚàã×µý7OÂÿg›® cœ£küÓï[׆Ϳê;Mí¯kÃôÓb/ÅXÆÇŠ×`ŒjÆÙâ¨ðtüró¢ ]èÁ-xÈDÅ4]X…�Ø‚ÝxGÈ@Ytî¿ãõ™H"‡ÃK#'"Ãôß…?O7¤G úw#©â!Ö¦_…Äp[äXxiø½È0ÝóáéÚ"Ã"G7L|Ý"$G†E~Ò·éWéÒ¿!Ž Óîðžÿ…´&ËKЊ6ÌBf£³0ábí-Õ‰ËÑ…nÌÇB\‰EX‚˰‹p®Æ \ƒ5ÚºYk]ŠåX�Õ¸×á¸7àF,ÇÕX…ÕXƒëb‘kq=nÔúªc¬Â5Ú=§�³ëq nÃí¸wb-Öá&¬ÇÍø#nÁ­§âwán­ç/ãwý�ýïÁlĽ؄ûðÂ#Ø‹ý+ò(6c+zq6i‘-8€8ˆ0Nà$¾ÅQ2Q<%Ó *¦q4™ÎC+ÚµYšŽ‹qæ¡óÑ¥å±˰J»·%Ú,ÕæL�–år¬ŒÍÀmþ57iù߆{´¼Öãv-–ûŸ´»¿ßÞ�Úzÿ©öß»ÿM§ú<ŒG¡ ˆmØŽ'ð$6c ¶"ˆíx›ñ Âñy [  7Ö÷q­÷C§µmýMkOái<ƒg±!ìÀ3ڞǞÞØ1;Ú�ç±/`/öáìǼ‹}xÁxoiÇïáÆq|„/ñ->ÀA|Ž/ð¾Á!Æ·8‚£8†“8‰0N’A«“‹’i e‘“Š©ôß³’ÿ¯l·ü6$èá§þ°ñÔ[L¿J¿^'œ DŽ`:¦ã†°ú_ ‰†C‚þ¸þ[$èK¯Ï^�£· Ÿ!Î�ªK‹Ãî ò%_4ýÂi~_ãÔo}Ý”ó&Ÿë™4±vBMuUeE¹»lü¸±cÎ)=jdIþpWÞY9Î3C¤ŒÔ$›Õœg2ô:Q äU;jšìJN“¢ËqÔÖºÔcG³]Éi>-Ф؛íJÍ/û(ö&­›ý—=ÝÍv¥íW=ݬ§ûTO²ÙÇb¬+Ï^í°+û«öM«÷9ìÊõU¿]éÓ|²æºíÀ\åðgg»òìöêŒö*»BMöj¥f~{OuS•+�zâ+•­ñ®<ôÆ'T:*\yPÎrtöÒYãIá¬êsz˜ÌêeÑYÝ,+uõ¾êªÌìl¿C¥6–b¨TŒÚXö™jθÎÞ›·«ç!M¹‰²CnžîSÄf¿+¯G¬îéY­$å*ÃUʰ+?ËpåU·*yŽªj%×QåÊóxO]€½Óæ°÷ü…š}‡~iŽE NÛPU½ÅSÓ¤P3w(ÆJÅ Þ_v¶šËu!7®¼leY½�ÛÈ Â�ŸëW„&µeoIkT[–ñ–S§79²ÕRU7žæ·g(ËvWž¢ËѾœŠÎYí¨¶+bNS ¥]esk�£ªŠÍÛTŸâ®²W+îæØ½V÷äW;ª››jš©NC½OÉwt*©Ž ÖÁSﳫ5˜ÙàÓN‰�¦¤V*hj‰�¥äWW©yÙ«{šªX‚êXŽzßG>îaÏÜVŒð«y(*}Š˜SÝã“Û©)SVìMmv_f¶âö+ÔìwøZýj•6eØÇ™Ùêæ��¥sVÿª7ï¬Þ¹Ñi²û„LѯVKÑ9í5ŠÎ騫�6ÅÀÕŠVŒµû(¼›2ìãXÕ~1ŽÎ©ˆÎÊZµITO­¬ÍÌög³íH)3–“Þ©˜N˦èÿ•»Î›ë­&4Ì^ÝZuZ‚¿TK06Úïç)¨s»°¢wšÔrÖò&ÑiWtN“"8+kµ�ZÅ »‚:»ÏÑêð;Ú튻Χޛ:×Z}= Oý4ŸVíØS2õG¬}ô©¶˜)BåTŸR“›ÉkªOÐŽOÖþªy"o¶÷˜ž†udGl@؃p‹NÅ�3±ùºÑÉ#\yTã¨irÔ4;ì6{MOs(²,ÐÓëv÷tV7µŸ£Žá˜(÷8|c3µÔ¼¾%™Wª—J†‡¶bpNW Îi>%.×oWôÎIŠÎ9AýnR Πʲ–f54úÔs�Ή-~Åtj@Åàœ¨Ä9§+q±£³F;G}ÑèkÉÌö7;4U–µdf+ËüŠ?W½¨o¦_{–m jç(†6¦>G½P¾¿'ÙQ¤-LƒS‰w®V眤 ÁÇ"™JœšŽŸM’1QÑ;[ŠÁÙÒdßá†- ¾ìØ‹4>“EZë}Š.§UûŽÏŒ5B½-Ñ™`ŽWâ†+FuLÕ†«ëQï4úý,yíhu¬ƒç´) N%.ç´©Œ� ˜œJ‚s¢š‹bp®Vâµ®»ÕaêCð:®PH›Qm$£ïTÌΉÍʲ;?A‰w:Fó“Mê "!6Æ5ªwžèœ¨ˆÎ©¡ÈƒŽ…Ù§m®<‡ú“A}0‘¹pÃßóë€ra®+Ïôë¨Y ÷ô˜Ì¿›/“ùÕ ½zf• Щÿÿ­³è3! …˜¾º=貚C4b»Ífd|ŽŠ …Ü0�¨ØmÓ æÛl¶³Þ>Èp«Xnµ‡(kûYº[¨eýö¿ZÖÿa_ri~åpð�ƒ¶£{“Jó¾ðöÁÂJÊNÒ¾S-‚ÃèZ\T2b¸�K%ÅEƒ*�¦Æ‡ JFŒt–““D_¿N¸Ô^1£V'æ®=ûÜKÝŽa3oo- ‡œ…æt{r²”n±¤KúÌãŸë3O”ë'î¾r5–½çä Wmq¦\\?£ÿ›bg¬_r²=ÃØù^<®_…ä °7Azš¶ÂÐ6·-Õ44Q?°ßZ×0ä-“Þ‹²â¾²²¾äR²½óöAÛÑ=…ZúCr†&'Ç“š»qÄpÁ1Ä"“SqÑxA<^½ô‰¹þ§.Übò<8ÿj_^0½è¼‘ÙUë‡Ï*;§¡P0-yáÚ‰CœúIáEOµ6Ô®Øq唕—¤Ö� LMÏñ¯‡€9‘Ãâný*¤"#zB¤M™i!ÚæN“YŸqÜæM¨�o�~Ðס¬¯LËTMõàÛ{–¤Œ/ HO*Nr µ�:¹£R�•4œC sj–?ÞQp‘kë]†‰�´œ¿â‚¼à¥�Šõõ¹íÅ7l ƒËö];!ÑL_ôܬ¶Ú¡EOl›ßMo¦¦…ÔYœ9,ÃŒapoKLLCˆžØ&¥ Ó…èIwZÚÙÒþu¤Ó�}æƒêÌ�Çl^”õ¿Ó§&™QÙÞ9ºÇöÁÁ¤Ò|uR Æl5µñ¨4–i‰–ü`Á826»âAè/Û¼)ÏçõØ'lkZþÔ‚Òqó™=sSGé㢽R®(½¸êl½�ë,pÇýÆDkÜ�©kVí¾rÖ³7N­Xø˜·²£Î•W×Y ö[S]¦~R�в^½)DAw¦%!!ш‰iý±«É”Ÿr±¤©ñõ(SSOJ.Í/-î+"Û^Û;¯&—æï9úBaå8†dQvZv’#)»$»Ä–]”NºÌk[¾¡P¸¶7ü,UÒ¦ö«N|®û4똲®”ðÒºh]F¸KÍd³ú[Zý:Ä! åÏÀJýõº-qGqã`]Ü1c}|ˆÎrǧºm©µ©øAœ‚²¾sûÊÔ\ÞÙ_ZšŸo;¨-²ì’ì¤ì´ì’씢ÁÂéKŠŽ…ߥ÷(÷äû4i\V‘3-ÍY”£8}íÉû×­Ó#-§0댢œ´´œ¢3² sÒ@˜èÅ0\¨íÍÊÑÖà 3©p9B´Õ�n6Ï7;».åØ�º,ç Ì)ƒêÍõPg¬¬,¹´´¬¯¬/)™Jó�–¾}Ðö¶ú\f'�Z1ŽÓµ8}¼X\4 MÝ$q¶Ñšž”:dh¾}ƒÑš‘”lZ�½q•iPáˆ1gÖOÍ^â>ûYá�ü±KÆHyÿ"á¹QU9–ÔÓjú‰‡v–Ö¦ÏêQ?*+üA¿¤þ¶LÜ'†‘Žü^a€ºêÓ‘@[ÝÖÄô éõ õ¶Æ:LA™º–øš×ÏLÍ7'–îÆ;�yÞ)Þ¼;7lñ]`W1¹`‹xhӈ곓ž õ_.,ŸyJ~ÝØþ6˜9¬‹ÃHÁPœùŒúªA*Ó6w|üY¶Ö9~R_5}e}ÚÚ=È_2§-‚Ø,¥¥ÔE¢‹¯X¼|ö£ Ê8ƒÃÎ�Sy^Ç„ìaçήRIáyÏ_7¹òê]Kæí¾nråò]+/ºî¢üqm«']ô� õw‰:“–WQ¯�ü4õ"&êuÛâRR…$“ )õ‰'ô|JÔ‡ÿW“BÅEŒŽ‘|J^Ú ÷?æ»ë^ƒ"6Ô9&x¦(â¡—6½¼oå‚�£Î׿Hýw„²ÈwâKzÒQÒk3«ÏЀx£Ñ”n5em?&Æ›§àDzêObìuQ¼_{ÈßÞ“\jÓÖ›S}A䔨k-i”ú°'±—šøÒ˜«ÊŸ}*ü% ÜBχÇuuÌo±šío¢TWxçMaaö¥V›ú,D‹ûÄCW¯õYH…™¶º-ñéÒ¦$N±7zµ‡˜? Ù£ëjµ«'¥j¯«¤bqß]W}]½ëÎ{¶l±�«œ\°E{ ž kû¯ú2%¿nœp5€n˜x x«×a E¾rv8»ƒ`u‰qñFC\ü£Ñ0EuõDêÕ‹òËŠÙåçÛöÙöy¼¾íâEk¦;Q“x� /ÙrW[öØ–¬6íñc´ÚKO†8�ÚK“8ý¯{©}L0²>šÄ™`txñ›‘`d×Ó$>á×½Ô™‰#GÇQ1é†}>þþ ­ _ÿ™H|7¼š–†—ÓOô}ø*º:¬þ¸Å˜p“.K<„ Թͩ)°'ÇÑ€¥…"?> -5¹>.D¢ÛoŽP�Ž ç§¤¦f¨cQQ~qYiéhõñH.-­¾_ægì)´¿hQaAiUZÂ~"�¢â”ôQ)º¬ð#%—_³±eÐÙŒÈ*h˜Tewì Ÿó�xèäU×î]:Vîõg”ÉÄCýíwmnvÀ.ˆÛã2h’=$\ˆ bB.a.ý\Np9Îåg.?qù‘Ë1.?pùžË?¹|Çå(—#\¾år˜K—C\¾áò._sùŠË—\¾àò9—ϸ|Êå.¹|Ìå#.rù€Ëß¹¼Ïåo\ÞãòW.ïry‡Ë.osy‹Ë›\Þàò:—׸¼Êe?—W¸ü…ËË\^âò"—}\öry�Ë.Ïsù3—Ý\vqÙÉå9.Ïry†ËÓ\žâ²ƒKˆË“\žàò8—í\¶q réå¢pÙÊå1.›¹<Êå.syˆËƒ\àr?—û¸lâr/—�\6p¹›Ë]\îär—Û¹ÜÆåV.·pù#—›¹¬çr—u\Ör¹‘Ë \®çÒÃåZ.k¸¬ær —U\VrYÁe9—¥\®â²„Ëb.‹¸,är—\æséæÒÅe.—.—q™Ãe6—K¹Ìâ2“K;—\Ú¸´r‘¹´p piæÒÄå.s¹ˆËt.rñsñq¹€Ëù\¹LåâåRÏ¥ŽË.çq™Ìe—‰\j¸Tp)çâæRÆe—1\J¹Œæ2ŠËH.%\Fp)æRÄ¥�K—|.÷©R>J¸²° �€° $¬€,¬D#^V‚�/¬D‡°[…•êŸuWƒpDÛç Wc«p5l–G£�ê^XYX=»NXŠeÂRõÏ^„¥p KÑ),…(, Êå�!áª`yDÚ!,eÉZž',F™°‚ú[…ÅøHX¬�»„K„+ñ‘p%\",ÄGÂBøV¸„µÚ¾CÛÛÔ½0²°�° `¸ç s©\ê˥˄ri¦«½q†«­±Õ%7¶¸�ÍEM�ùMeMÂ%E7JÓvN:§}˜™/…èŸ ß1e8Âð-Ãa†>†C ß0üƒák†¯¾dø‚ás†Ï>eø$8h´¢ƒ 3|Äð!à gxŸáo ï1ü•á]†w0¼ÍðVpà)Do2¼Áð:Ãk ¯2ìgx…á/ /3¼Äð"Ã>†½ /0ìaxžáÏ »v1ìdxŽáY†gžfxŠaC(˜Q.…èI†'gØÎ°�!ÈÐË 0leØÂðÃf†Gax˜á!†`¸Ÿá>†?1lb¸—a#Æ{îf¸‹áN†;ng¸�áV†[þÈp3Ãz†›Ö1¬e¸‘á†ëþÀpCO0}‚¢kÖ0¬f¸†aÃJ† W3,gXư”á*†% ‹1\ɰ�á † óæ1t3t1Ìe¸œ¡“¡ƒá2†9 ³.e˜Å0“¡�aCC+ƒÌÐÂ`hfhb¸„áb†‹¦3\È0�ÁÏà hŒ®¿ Îghd˜ÊÐÀàe¨g¨c˜ÂpÃd†s< “&2Ô2L`¨a¨f¨b¨d¨`(gp3”1ŒgÇ0–a Ã9 ¥ £ƒi�èúÅ0’¡„aCq0­.ºþŠ Y°€!Ÿa8ƒ+˜:$ºþòrƒ)Îèú;›aX0Y}'ŸÅ0”!‡ÁÉp&ƒƒaC6ƒ=˜T]Ã`†¬ ­*ºþÎ`ÈdÄ0�!ƒ!�aCC*C C2Cƒ�ÁÊ`a03$­žèúK`ˆgˆc01 zƒÈ 0Ü«GR¿ÃV�ÔoõH'­é„Õ#·z¤Ÿ­é'«GúÑꑎY=ÒV�ô½Õ#ýÓꑾ³z¤£V�tÄꑾµz¤ÃV�ÔgõH‡¬é«Gú‡Õ#}mõH_Y=Ò—V�ô…Õ#}nõHŸY=Ò§V�ô‰Õ#´z¤�­é#«GúÐê‘>°z¤¿[=ÒûV�ô7«GzÏê‘þjõHïZ=Ò;V�tÀâ•Þ¶x¥·,^éM‹WzÃâ•^·x¥×,^éU‹WÚoñJ¯X¼Ò_,^ée‹WzÉâ•^´x¥}¯´×â•^°x¥=¯ô¼Å+ýÙâ•v[¼’û¶]¯´Ó╞³x¥g-^é‹WzÚ╞²x¥¯²x¥'-^é ‹WzÜâ•¶[¼Ò6‹W Z¼R¯9 )怴Õ�¶˜Òc怴Ù�5×I�˜ÒÃæ€ô�9 =hH˜Òýæ€tŸ9 ýÉ�6™ҽ怴Ñ�6˜Ò=æ€t·9 ÝeHwšRHXãî2gKw$vH·'vH·%vH·&vH·$vHLì�nNì�Ö'vH7%vHë;¤µ‰Ò�‰Ò =Òõ =Òz$Û ê´l�Ð9pÙ@!?£,cJ†(¥ç§—¥‹Ò·¦ îôL©¦3uYêë©§ê–¥ÐF…"»¶Ùò jB‘]n‡MRÓi¥�VºÑ²Á²Õ"nµì´;-¯Y>²ˆnËøŠñYÒþœDk15×2F¼ÅTw¡Bkgƒºw×OS k4N»Ð×Ktƒ¿—„Ê©J’ú¯×Úñªë¯GV…GÉjðÅ�³*üe™ên·æÕ�¬ nW÷¼®y¹¹]]]”Û5¯»««¹ÿïoôŸNàÿ̆ÜÜ®˜vuuuwwuåævuwÏËíÎíê>Õ”Û¥¶j[·zÔ­ª�»r{¡þ]CyD! d� €LȆLý�éd:™~†L?A¦!Ó1Èôdú2ý2}™ŽB¦#�é[Èt2õA¦C�éÈôÈô5dú 2} ™¾€LŸC¦Ï Ó§�éÈt2} ™>‚LB¦ Óß!Óû�éo�é=ÈôWÈô.dz2€LoC¦· Ó›�é Èô:dz 2½ ™öC¦W Ó_ ÓË�é%Èô"dÚ™öB¦ ÓÈô> endobj 343 0 obj <> /W [0 84 549.80469] /DW 0>> endobj 344 0 obj <> stream xœ]QM‹ƒ0½çW̱=”¤V·-ˆPÁÃ~°n@šŒn`�!¦ÿýbF\ØCoæ½7“^6UcMþáGÕb€ÎXíqŸ^!<°7–ÐF…Å[ Ò1^6U;O‡Æv#Ësþ‰½™‚ŸawÓã÷Œ¿{�ÞØv÷²Ý3Þ>�ûÁmÁŠ4vŒ—¯Ò½É�GÙ¡Ñhƒ óá^¶Œ¯Ù!$i5jœœTè¥í‘åBQ@^×u]0´ú_?%Õ£SßÒGö©€\ˆD :U½$¥)¡+!ê�“è»:l~ÛøSié‘´)i/T¼Q±¢"13A¾ÄÌhŸŒFŸ/ë0²_޳侅¥žÞ£ ñsb@K4Æâönt‹j9¿ì”‘H endstream endobj 147 0 obj <> endobj 345 0 obj <> stream xœí› xUúªzMzK:kª›¦! �¤ Ðlé¬HÒ!�@€$T˜HXd"DÀQÐQ\@¨„ÅTpdG‡E52¨3‚£ é¾]uú :sÿ÷yî�{ç>÷¹ÕIÿÞ:çÔ©¯Î{–ª"€– 5%åά¡§æ?€ fòÌÚ&ö~v^€“çζ~UøÎu€"ª¡iÊLܨÿ@W ‰›RÛÜI`€‹`œ2c~Cþ{NÄVÄEM­¯¾?jþ k ïÔ©õµëÙ(ݧΜ}ï®+Ñ#ý˜ë3'×ò‰/°~¼ofí½M:€[`½»vf}LVÆ;Ì"ÐÔØ<;ð3¬À.R~Ó¬ú¦®BÊ!€ô&€x ° -Dƒ*H×þ&Ô‚ª@ Á õ‘Qp ¹´¼®Á:¹ô¯7P\í¼Š¹†à™à-î®*ó&Iùº^ýÒ&Õ$àŸÔµœqð¼¥—ÄwZNôž Tsw)ß50á#Y®×�ÔŠ§.ä Ù� �µ†‰Pj†cN*{ç)G–[­à+l%±©ª†FÏ^TX¤–‘��®OJ�î€D0Êíc…,È…"¥0ê¡ æÂ|Ø ÊGJyù0 F€ja Ì"yÁó°:øöíÏgáÏäÑjwn*'EÁi@€EaMŽ!š=ÜÖ,dÁ °æÀia­€´Ûå•rº÷,h†iÐwƒ2 7¸!¬�s`̬� ™Ðòå2ÍÐ3 ša$LƒÉ0 å´˜ ÀúO¥Èm‘� >¨‡)0GΙ/ßÎéÖQ©k4Éßµ0;eo°B.Ì€`Lƒ)0fC³¼WÍòÍ…z ·Ü> ßwà4c).ÃòçùóSάa>cØv{žSpƒ¹ÆËçEšb®â¨²»²»òªÊ©Z¢úB� .P¿¬þZ“¥Y¥Y¥y[Û_»@»Gûµô‰ðÿÜçA®*i'æä_mXWs 0“k€\œ¼£ÌŽ;ô_¹Èä`×n®6‡Ó_á ‘k€1á:¸ÿrôüܸhá`«k8¶9áô‰áô\,ç`_X� §Kí±5\öD8?'œ—wGýÿ“×÷ÿ·ÿñÆ5À£ªl¿@õo²|ÐÍÐ `œA5ºp$4C l…�ð¼ WP‰I8âß…ÂQÁË�%Á›ÁÅ� �je\P©ø8hf/’˜õÐwAÌ€&¸ ªaL¦AÜÍ0[^IÀBX wÃ$Êe°"Ü«ä6ø¥‘ãߛ帅'åøIì¿“ÓÈõýóÕI¹/ÜÎÿW×ÿÜí2/Ãv¡vÃØ¯ÁØ » öÀ^Ø/ÂKðr¸E^…� B[¸ì^¹ôKwäíú§\?€ƒð:¼o�öÃëò7M{Ž„÷ÉÞ[ð6�£p ŽÃûpÎÀÇpÞ�÷à#ø#œ’÷?…¯à2Ü€/àøÎA\€¯á[ø.Âeø®ÀU¸·àà*eŸÒ1 0 èB÷¿g$ÿÙ6üsS‡ï3×;ªÛ³˜¢Eñ(;˜¼ÕP ¤'”He†2BqCñ=D(²A«°0¯á)å_@£4s1Ák0êVËnô�*)16¿Rd“ [+…‘¯±¢µ¦ÁZi±‰ž*k«ì•õU’Kv£˜ò¥Å&mUá£8GáoJÓÂÒ•«jk%ca«$·DÎa-9‡=o�¨rE%Ù•Íd­D ÐbbÊ—á’úU=œCdùÅR+š_l±UÙÈö_„d Ǥpˆê;ê2ŠŠ_b"çùï†FJK¥X ë îðW•*†kû×q2R[„O,*jÉÎbšÅ:¬"çP‹Œ#¿XN’\Œ·ŠPj­´×Û«ìS­¢§´Rº6©­e½åvoÙ¸JÙíp/ý«=’ßÿv^X‰LþèJ±(ÕB=•÷‡Êû·w‹“=Œf[[Õvoy«T³=\!XÛÁÃ:Deò°ÚÕý£ú¤§a‘½¨Æ^Tk·­E­µþàÒºÖ6�§µ©°fê©û0¡Õ^^9È"‡æ«\lY �* ¼è�—žÖÆ@^›W•µypUù¸ÊýFëªÑ•í 2ù5yUmÝqUYå~+€GNe¤T)QÚ±J;RM¾ÊvF-—·ì÷,•s99AÞŸìG�ÓÔ4 a²Ÿ!iFšÆÀd?GÒ@T&“:ÉÒ‰œU­Qö,y`*¢Ö±R‚Æ1\„òJ’b5R8U¤‘T‘¢Â1Ù.*“k¬û=ÀÁäòJ[x"ÕZHJ}Y¥È%×Ë¿ZK8¤Ëb:­¨é-ª¤:%Ñ[� ‡ªªŠ/ï­ 5£á5Éw4eøQí#äXD¥c¥¨•‹¾%USæŸý^å•kR‰Z‡¨s «—Ö‘ã#D­ÃÞŸ¬–&ˆˆpGHªJºòHÇ0‘uŒö_´Ï·Ý±¥§Ù¥•Aê˜`Ùà�ªÖß&ˆãSÓÓÔ¿MÕÉÉ­­jÝ¿>€´—Zw›R¢µpZA:'½#áô ° 2¡z?ØñÉötƒÎ�}ö�êDÕ›˜ D£Ô€èò9F·Ñhì™ðd¢ò 6×`õcÒžžÜ̇œÎÏ;?ÈéüüR”Ûy �ç:Îv¯3¹�GOwdf Éf’ÍzÆ®²÷pee÷éͤb¶+«+ƒY±1Rz·ÞLvŸ! §¿5œ­ìä˜éÖ¼)Åœ œµ®×ˆé{Ê´'ë3~G¦.ÎÅÇéõq¼Ârã‚Âr3—«»¹™ù6½"·Çæ[ËÓ‹]ÁU6¥ó;—#\.*ʯ`¤7A\µÂ*Ђà‰Ò²œ†S¨Ô XUJ�VíG½§ òšžåZf Ã0 §Ræ*"ÀåCŽËi’r\Qnç„(w—Óx) œ.WbüɬÅ+�Á033lvÖÆÚÑ�\õïÇw~Y½Û¬>w“ç–[Ï2; ¥7¾ÕÁ+ìyE*t��»õ]ºÆúñx»"IçǸ=%zÔ›ü¨k׿ÁAŒ†.�€ú6¦r:Ï^Êé<;áÏvÏÉÌp(íV0õ¸²bãbz£½›ž‰1G¹²úöcÏ?³#ð]àc߯O¿©xèÆqÕ�OíÿÁñÑO ÍÌE/<h«á­»z¤.c~ èa—Zl&—¤°@$ÄBÏýxt�Q‡:³Ÿ÷hÕqÑç5¹æoÔù�s)GãôÉo³ž³ÛL6+°²Ï&—•KJò4B>ädåä¸ÜîÅÎEÎøtv8;²Ln·² h7¹0:]ì•oËïÞv§/߯:QÙ930Qa¹u+p†y›¥ï^朊tˆ†Ðýu0Ëgì*uwmÏ„¿òìß* nww§ÜÛ=’é+jJSšªOo† ½®Œ+kÃ9Ë×¼1í¾ƒ ùÖ¼>í¾ƒ‹ï·�Z8vôüQÉÝG.3zAI2³A ‹eãwüãé�/–Uo¿öbó¡Öe«N›}èÁe«#½�f¯+, ‡8è-�Æ·wÔf•4°fáÒ…5ûÏÝ¿Ô6²d¤mäSÅO® 'bÝ„‡&ôVG5;ºX-Ù#2³½3û .o™ýe„^½56®aLöˆA™}†TÌ„1œQ^Ï’Ú€‘f�‚Eî‚2—•»@:�]=&O[v“-ÛÆ‹÷³¸å7sË7Jm33x™½¡°@œÔÛŸ‡Ðɽ=>.7"7ê+ÒÛsäɽã—+Ï6¹Lr÷î›mr±7ÏÝÞ¸à•é™íIyÓF<¼²�ÏØµ0ß3çùz¶ñÖ–‘³Gõ|þqv’t>i­SX@ ™žX†cQ V¥R£U2jŽÍE&r!'Ç•#Í2ÒÜ’à”–U×É,Wf†íèB "W(¸uK}h!÷·ÖȰ÷-ÁËì[l¬à ò~Ûu¶~|×cÐdD¾�Vè†Ýº%ZËbüÈx4fÓω¥i×8ŸtµÄsiu'‹Ú‘·ÉíḬ̀õ #½ï@Ìî“lï¦Tea%×cLì/C¾o?ÖÁù^ž0fA‰£ãÏΚSñB¥­l\]ÖøGêûî:—;qPRTOOïAO�YYVœ6rêà'¶WVMO¶?ÑÓ·htç<‘˜‘ß+);%~X 0°5ø#{CÑÑ� ™müAÜjÜí1šÕ=" �†RMy·Sj…r\—䇯³§;Œ¿t×ä&—Iõë)Je"˜½Q¸d߬ªãwª½ÛëÆÜ_™Ö—5ª¯­`XYo×]ƒf–g2êÅGÖÍ¡Xx ¾¼xùþ%+&fÇd– $˜ã’«„ÍÁØì H‚þíˆóãkíÊ®z?j<š%4DýQ ~T½Ö”„I‰7XÈ70·ïbNK71RCöoïbbåfÝQ°vÄå@pøšF­’»²8Þ¸>mÏ mâHL@æú¼ß·zc¶uã]5­c÷íµZ¥{©7(ZÀ 6èÓ!uµ%Æ�»=&è¦Ö)âo}eÚrþ'E©ÜÙåéŠ:Ÿ™ŽÅä2ÙÃ= ‰Ç$õ™EËö6fLHßµI9ì•Éc–�MkŸ^—÷hYêT×Ã[°céñ‡FêpÛ�…oÞÕP¼Ü¿pßî¹³ñ�æ¿´ÞÌ ^f¯°è )àÙ~Ü·›�Iáüøš'&¦r-‡׫ûG‰¥º3‘ªkF™•¤^n¶«GŒç:äŠf¥Ê&…6„éCû*™–T}ÃŽ³W¦3gÇsi•>¯uèîšeæ¹ÏyeÆ´çÝ{Yk¾�çžXÐKÁ¤:²bŸzAiЬ5'µ¼µà®7֎Λÿª/¿±4=­´)_ú—ý‰�jÎÌ` Œ€Xó:è±R`$¶½– ilæ@Ö�mÝØî™cS2ÇŽÍLamqñ}(€Aøž'ÙVkŒùÞSw/JcÕ}¡‹ÔEêÚ¾O(©~¯oiÎG]ÆÈëmÎ%“¼ˆL�`r/™\Ò�·p”4Ïn`�+Z œm†i¾ˆÀ]F&#7cJõåePF—ç_f ›Ý$MmÒä`—g Ö•Ãß9¶Ì>8o”kçNeJI‰/mÃó̲ÙÍÑÎÒA� Š–À”Í™ù½¢^ó#ߤXH‚Ü×Á€��¶yôÔ F©êÊi®©Ê´~ìéÑš=Fs±~bK çÒç©—rdSOJVÉ’cËßG‡ïh¿Æk��ñSL½õœ”刉qd%…ÉV¯»õÂúõ ˆIÎLê’•“œÕ%)39X¨f§*ÖC ¤@ÁëàÀN°@4¶½Zs/S/¥Æ�š½ZÃÏÊ1±rˆV)DkôO@Cì<+uF4ž=vŽ„h w´ì®¬¼$Ú²ñ7±²Åƒš~×0|�›êÑ}Öý3ãúmÈo%Oû]ÓKü6cb”fÝClé:|�ÆM¯öp=- …¼ý Æ‹»5о‰Ÿƒ XÜ%-±xÕcD.BSÂhU,§(çÂNGŹsÂNý2Ê-Ý¿Úì(ûŒ.äz|HÛ¹ßþ:�Â$v~­h¹µ ß dBøÉæ#E‹ô¼´_öÒöR+{ gØry˜ÞaÞ�ÖÝiwmíÍÈõÒŸƒÁ8.’ @:·%ÅûqW{¢%¤;"ü¸Ë§Óõv*¯õ*�¾Ö­4É‘h)I,ÓÑ^åv“iÝΫîÓÆÓÒlm3Ý^ÛìwJWéÈÒw²3T†8“¹[§u‹ÊoвöȰmmQ'föؽlt|ïlO¯7˜�œƒìúø¾U¹� ™7û$ëÍ}Æu.d/r—fÆÝÕ(�áÀ¹NolâÀÙÆÄJã-"¤ñÏ@\YD™ñ¦ªTêAÒ CÇ›¼¼ÐÈLw ¼­O«Ò|%¾´§·ì¬kœ72c'{ñ¹>…½L¯ù;ïa–ͽ‡ <` :x™Ó²úĸÌÐwËO,?Jí×¾_Ð'£KÃoŸW´y‹Úï™±}^e{ʈ™ù£‡ÚRFÌ(�ˆ�9o¯™ÿáÅsÞZ=2ÙáVOpnX9|ÂC2¥{–@{ƒ €Ð·NkUKÆj“A^ycÔºäÈÄNcid‰¦Â~Š„˜C&ytvHÏ Qî;n]dÿŽK_ö†wÅži“2w>á}eò¯ï]2îr­ÙʨxgEž62P­xà¥)ÿtçrˆ¼oàÔrfµ1Q± ¢A�m£&Ú̘Ôjˆ.‹¼© öE¹�î߈®¬X•½/µïÄEÕ«•›žUŠly©}¨wt†È^Ü?½æÝã+æ%ô3¸s¡Ôû÷/³ÙdCù~HÃÝ{-Ý-ݵàǽ»MÚ¾öÐ]z4‰J(îÞãš)Me-ÕúQáÑn‰ØÁD诫è Ô/O(§;LÒ裯aä9Ij&iëñËbwû¾ª+וevâ›PçlØî«Ü9fñ½ÑYÓÆ4�Îè1që½×�ò=Ú7·ª_|Œ»ÁWµ`„ £²Gçöîª�2oMH,ȱ¤öèe1»Š&zz cÜ:ãÓæh³Ýi±¤¥¤Ä'º‹*¥+Í þÀžP¤Cd·uÒÈŽÕªTê8ƒ:^eüG¤VW7ãÌ×Ùð­�ë¤<�œ–^é‘ÞéÈ7…ÉÒ¼j3õ“ßÁ„oO ¼/÷��o0a'¾ÜÜ”1kˆÞ ÛÞÆD>‚æôÀ¡GÌŒé£4Bƒ—ÙãìEˆ…ô6¤jîòèµq Ä”D–n¨|òÔBh™Pì=ô¬|v—É,ßZ™\ìñMÊô²Ò²ô§7ïÜiœ?2c§<8÷ù™u�÷}í,Ì<(ý—Ä^5¸=…ÁªV±¬F»€EÖüУaUê2¥R!u¬¬,gŽËÝyê!¯OfIÝK~u‚ö¼cײûýx(0÷öbçÔç¶1�Ý2ÂÀ@�|Žx(õèÌÑñ`�Ò`llBbŒ?øåÞØsT™Æ�¬Ç Õ1ƒCå˜h³9>|FWŽÛÝ?üŒÛ?|æø#®Drj ÊWNsû¡ —x%ûž¶NNì•Û')£|x�5Ðx,àð{ñÖ}[2ˆa6³Š.9ÂP)ÒM[™Ç¥¿Qb¯(ÒÁ niÕz}o‚)ÁdåýxÞ‰6£îïœÌ“«-m Èïɤn}L2âd¸O§`6aÉ™RÕƒLÒ2k@{åÖïÐW>u€9±ï˜Aå«Ü5ÃßZ:víTwϲ…£/1 7a©ïÞÉ•®Œ±yÉÃ6�šØ§îá*ïÒ%«Ê¾ØV†Ý£‰ÇáV?ÃP�T@X`�Š�Tܤâ?Sq�ŠPq�ŠŸ¨ø‘Š¿SñW©¸BÅ÷T\¦â©øŽŠ¿QñW*¾¥â*¾¦â¡â<_QÑAÅ—T|AÅçTœ£âÏT|FÅŸ¨ø”ŠO¨ø˜Š³Tœ¡â4§¨ø#Qñ! â*NRñ>ïQñ.'¨x‡ŠãT£â(G¨x›ŠßSñ‡©8DÅ›T¼AÅëT¤âû©ðSñû¨ØKÅ*vSÑNE"»¨x•ŠTl§â*^¦â%*^¤b/Pñ<ÏQñ,[©ØBÅ3Tl¢âi*ž¢âI*6Rñ¨xœŠÇ¨x”ŠG¨XOÅ:*ÖRñ0k¨h¥âA*VQ±’Ѝh¡bË©XFÅ*î£b1‹¨XHÅ|*î¥bs©˜ME3³¨h¤ân*fR1ƒŠéTÜEÅ4*¦R1…Š*ꩨ˜LEµTÔP1‰Š‰TL ¢šŠñTTQQIÅX*ÆPQAÅh*|T”QQJE £¨IÅp*†QQDE¹Tx¨È¡b0©pSÑŸŠ~Tô¥"›Š>T¸¨È¢"“Š *œTôÞ-‰Ü~Ì 0-PÀ´2ËA`V@|Ȭ'³™°‹Y!ý—æ~@¸";™ûas?0°‹YJm’¾™¥ 0KBG—2K`)³Dú/7Ìð0K ‰Y,³¸]È­ð3÷µçùýÌBfQ»ÀrÓ˜E�Ã,‚FFú"»˜Eð³H>v LbÀÌ``3¾`æß3÷Â:ù»Qþ6JßÌ\˜yPFfX™yž9Ì,ÌåÙ\þn&—Ÿ–>µbJzCE}ºP19½®¢6«¦ÂY“SÃLÊšXÁ�;4Ži÷å8fLzEENŽN/¯È)ÇÃå¸Eþñ¥—U”¦—T4• ³·cS1.ÆÆbôcQzaEAz~E^zn…ÇÏÜÝ®1ígf0ÓÛ³x�Ÿ™.ï3 »5‘EdšÁÃܳ;³_‘ÇÏÜÓÞÅVägØö®Ýx?Ã`{ROÞÏ€ : nÜlï’ÊûñÁÏ× þAp�à'‚Û-NÞ�'ø�à*Á‚ï .\"¸HðÁßþJð-Á7_\ ø Áy‚¯Úûó~ì ø’à ‚Ï Îü™à3‚?|Jð ÁÇg Μ&8Õž0�÷ã >"ø�àœ$xŸà=‚w N¼CpœàÁQ‚#oüžà-‚ÇÞ$xƒàu‚ƒöøÛãsyé½·Œ}{ öì&h'h# vì$x•`Áv‚W^&x‰àE‚m/‚2‚R‚‚Q# Fx † #(&JPDPHP@�O�G�Kà!È!B0˜`Á@‚n‚þí1u¡ñ×� /A6AW{Lihüed’Ä 'Ao‚ôvs·ÐøK#Hm�v„Æ_/‚”ö(iNîIЃ ™ÀAÐ�ÀNÐ�ÀF`m7e‡ÆOЕ ©ÝX],‰ ñq±1f‚h‚(�‘À@ 'ÐD¶¼¡ñA %Ш TJGÀ0Hž ÁËK¿ƒ—ï4xù[/Óàåo¼üÏ/Ýàåÿaðò× ^þ'ƒ—ÿÑàåÿnðò?¼üUƒ—¿bðòß¼üeƒ—¿dðò ^þ;ƒ—ÿ›ÁËÿÕàå¿5xùo ^þkƒ—¿`ðò1xùó/ÿ•ÁËw¼ü—/ÿ…ÁËnðòç ^þÏ/ÿ™ÁËÿÉàå?5xùO ^þcƒ—?kðògô>þ´ÞÇŸÒûø?ê}üGzÿ¡ÞÇÿAïã?Ðûø“zÿ¾ÞÇ¿§÷ñïê}ü ½�Gïã�ë}ü1½�?ª÷ñGô>þm½�ÿ½ÞÇ¿¥÷ñž�‡õ>þ�ÞÇ¿©÷ñoè}üëzPïãè}ü~½�÷ë}ükz¿Oïã÷ê}ü½�ß­÷ñízߦ«ãE]¿KWÇïÔÕñ¯êêøº:~»®”EWÇ¿¬«ã_ÒÕñ/êêømº:þ]ÿ¼®Žÿ�®ŽNWÇ?««ã·êêø-º:~³®ŽFWÇoÒÕñOëêx?³ÊÓ¬³ñOE6òOF6ò#ù'"ù ‘�üã‘�üc‘�ü£‘�ü#‘�üúÈF~]d#¿6²‘8¢•_ÑÊ?Ñʱ)qi"Ó”°4�qÆçėij|œ3.'ŽÝ·+ŽñÄYø¢&óRó‡æ/ÍÜÒhÜjDððncZF‘?xØc7òÝŠš xÈ€kõ[ô»ôì.ý!=sHÿýzÖ£’Wľ�òåÄu0:ÕëW}^Q]:^ÄU¢£\úö”�•«D¨7¾² ñáª6dòG‹&é/•åý–5k )Ï+&•W¶³[·&åUyÅ¥’öxd”4@R^Ujóì9ÍsRS›››1µyÎìææÙ�úÿ†ÿéþ÷l�šÚ–ÍÍͳg77§¦6Ïž='uvjóìÛY©ÍR®¼Í–öfË»RáæÔ6�þ†=7Ȱ 0  ‚À `'x¼þ ^ÿ^ÿþ^¯€€ßƒ€—AÀK àEð;ðo à_AÀoAÀo@À¯AÀ à_@Àó àW `ø%øø9xü3øø'ðSððcð,x< žÿ~~þü< ¾¾¾ žß�ƒ€Ç@À£ àðmð÷ à[ àaðø&øø:x<îý àk à>p/¸Ü ¶ƒ€m  î_w€€ÛAÀW@À—AÀ—@ÀAÀm à àó às à³ àVp ø ¸ || |Ü>n׃€ë@Àµ àà à°|\®[@À àrpYÈß%!ï ù»\”+}/ 9!—\!—²B.e†\ʹä{ƒðŸ½ÿŽ­ê?ÀÿÚðß^Žè™ endstream endobj 346 0 obj <> endobj 347 0 obj <> /W [0 189 549.80469] /DW 0>> endobj 348 0 obj <> stream xœ]‘ËjÃ0E÷ú -“E�üJC£`ð¢êæiì jYÈÊÂ_<“&Ð…$ÎÕ<.3B5çÆÙÈÅG˜t ‘÷Ö™ót øëX’rcu¼Þzì<ª9·Ëal\?±²ä\|Â`ç¾y1Ó¶L¼Áº�o.ªÝ2ÑÞ¼ÿ�\ä’U7Ð3¡^;ÿÖ�À¦í.Ú¸ì.ª}F|-xŠœ�=˜}§!tnVJ)eÅ˺®ëŠ�3ÿþ ʺöú» �U¼”2•RŽ”'DŠèˆTÐß�ètFÊRìr¯·ÿ«þ4³Ç0y¤JÕ­‘j�+“‚DŠ,R³»‰Ïžlå)‰'$’Ÿ"!“¶ÈÈ:‡u_�!ë[à".»ŽÔ:xìÝO~ÍZÏ/ïœ endstream endobj 148 0 obj <> endobj 349 0 obj <> stream xœÍ› `U¾¯ÿªê%I¯YH  ÕMÓaIB–&@ØÒY 4[: ˜„JX‚„EÔ(ÆPG7†ë.B%,6 #€ą̃Ä}F@qFF�tß®:]ˆ8oÞ}ïͽóªèþ¾:uêÔ©ó?çTuw°`5xÔM¬ÌÊ}4å'€6¨›1¯~Aù½'³úÀ[3–,r~ZúÚ8 FtñM fΣ�–·K “<³¾eRáp€mæÜeMÍk $g ×Ïj¬—¾}9ñS€ê ž5«±>nß úÌš·èÚMËS²� ð“ç6Ϩ¯[=жyõ×.0Ï¡ý.pίŸ×˜”›ýÀhØ‚æ–E¡Ÿ° žÊþ ô’úïÈ@J±ˆE á0¬P®ý8ê¡C tà`CS<Þ§æV—ÐY¬W*€ËtgºÎÐt¡)|,|A˜ó«�XˆÌF3æÃ‰l D>²áD«­"Á‰ä`0ŠÕ<-hÆ\Ô£ã13°ÍjZaœ¿Ê¥¤å"ÙÈC�˜‰Åêž…xêâž¡pþƒÒXY ±@}¯Ç¢h-‰BÌÅ\8ÀlÌÄ,,B‹ºÕˆõŠ– ªí³üës—­G/]ÉG ÿ²õMNäfsA>™¯ú 3…çÔõSáS�¨»Z]×;ôÓÔõ­ÿ™ÕÀ8ÃÃu†õ†7þ‹ëߌ½Œ…Æêºí¿ºÆ þ/¯õÑuMÌæ˜ý€Ð„jm8M¿Bæý³á#4áÏÿd_³Ð„)ÿtüý¡ ­B6 MxX¹>¡ ‹•ëš0=š¾õ’¼[£TÒk/I]hÂn¡ —¤yþ —óß¶M8ÍH›„&jšÈ(4ÑÖÿý‘ÿ'ç  ¡‰¡‰j„&r^rîGÿ•牖™þßPæä˶[q+ކ¹ü�PíeÙhB Úp/Ç12’—Æ£­ØŒm8ˆ7ðé)•Æý+j¦s Ÿ­ Ÿ÷×}ú"T«Oëu„ù“lŸ®¦PSølhUèÃpá¥Pmú¦pÿðwœF­a9âÃýÃ?êšt­º'uGø!¡þÊ ÿ_Tk<¸ �hÂ4a.`j1 Ó!a6à´`–`®Ãr¬Ä|,År\�p#nÆZõ>·4ºwÖàFÜ‚[qnǸë°7 ·`-n‹¦ÜŠ;°NÍ«”ÑŠ›Õ#Ú.9fîÆ½Øˆû± `=6à.Ü�{ðÜ‹û.¦?ˆ‡Ôœ¿LðŸæX}¶ø-¶àQ<Ž'ñ4¶EÓ~Ny[±íx[Ô”m8†cèDçqßâ )–â©yi$�§ hÄ,µ•j1ó±ÍX‚µ«°­êµ­TÛ`•ÚfJû°Z®ÁMÑX«¶ÁÏ-p—Zÿ�xX­×ݸ_­?«û¨iìú~}uÊÞÇ.îÿG׿åbž§ð dt`vb7žÃVlÃvt`'va+žÀ“x*Ú"Ïbd´GóîRs?yɾí¿ÚÄ^ìÃóxÄ<¯¾ki/âPt›mÄK8„—ñ ^Å[8Œcø¯â5¼‰#xO}üâSœÆ9|‚¯ð->B'¾À—øßà$Nã[|‡38‹ ¸€.�^�S&ÅSwJ%y)ÿ_3’ÿG–{�Ä5Ð[Ü�]!ÃÅYLת»›É�Âß¡µ¸3¤|ê2é³õqºsºo§ËC¬ÎÁ½>Kïë?GŒ>QH ŸÅh|£¥«¦O«½rjMuÕäÊ@Ť‰Æ�ó�S>º¬´¤¸¨ÐW0jäˆáÃò‡œ—503£_š§�»·˜’h·YÍq±1Fƒ^'ð!£Ô]Vç”Óêd!Í]^ž©l»ë�rZý% u²³Þ)—ý2�ì¬S³9™ÓWï”›.Ëéc9}s’Í9#23œ¥n§|¸Äí ÒÔŠj·S¾£Ä]ã”O©>^u!MÝ0—¸k\®Ì §³4eV‰S¦:g©\¶dV[i]IfµÇÅ»‹c33ÐWì.ŽËÌ€ÜϽ �ú�"U¸~¥ÃÚ9ÍÊieÞSZ/É“*ªKK.W�š†bµ,Y_,Ô²œ³•:ã6g{Æ�¶Ûƒ64Ô¥›$·T_[-óõ5™m|i[Û-²=]îï.‘û_÷yJfFi£œá.)•ÓÝ%™þÀÅ�¬óØÜζ S�ûÔÉ_¦ÔGSôÛPT¹Ä‹Í$S½æ� Ų^¹>—K©ËmA23\òêŠj¶íDƒ£¾¬ô™«SöÐö$U){Vk{.^çv)¡*­‹þ[2+E^ÝàÌÌ�…4õŸG<¥îR§Ì§Õ5̘¥°¾±Í]RÂÚmrµì+q–ʾúèµ–¶gg•ºKëëdª›­4CEµœå^ 'º‹XEµS‰ÁìÊjõ�èarb±ŒºÑ£ä¬Ò¥^ÎÒ¶ºVA¥,wEõxÃ'Ú9;¼„¥r·âj™O+m«–šd±Î!Éκ&gµÃ%ûjdª¯qW7Ö(QrÛäþ'.e©‰%xJ/Ë­eV®Üà1:«9_£DK<Î2Yð¸‹FÈ�MÖ³M%¢E#œÕ䀖Mî"šC±_”#xdÞS\®ìâ•C‹Ë®[þI•Ñ:é<²ñ’²l²îç:±óü/«Ær+êï,m,¹¤‚¿(T­`´´\ONi‹è‰e�Ǩ„³\ÛÅ{œ²à1Êœ§¸\MR¢˜â”1ÉYínt׸g9eߤjåÚ”¶Vãë¯tû+¦V«ÑŽö’É¿Øbû‡^Ü5™+ž\-—¥;´˜ªÛ£Õí‹›å—í£ív¶ÝþÊ6¥dw´@8;àã=²>mLýmCãefP™»¬Î]VïvÚœemõÁðꆶvŸ¯mAiݬaJî1R›»²z„C­Z z¥ã:åTñð“rQfF;‡¢v7­­h÷ÑÚÊ©Õ{l€síäꎸ⺢šö>´¶¢z�ð©©œ’ª$*NeC))PÝÁÕüŽ=>`µºWPÔíA‚šfÔÒ3‚K³iif–æSÓ”%3£4e–ۯ̵¥NI‰ÍŠšYmu5ÊÈB7™óÈœ‡dr�‚̹Gµ§7ɱîÆ"9Î]¤¤(é,]¯¤ÜE2u£Ì §2!µÕ¹23dƒ§bý�WŠtÃáÉծÎS5.Yï©•õž©ÕrLz�SÖyÆÊ‚g´òª“õžÑòêõJ=PU­kðŒ™Q#/(ë=cäO­-A6xÊÔc”¾ˆªêWM½[Uyõ ‡K^]#פ+'­ž]£öe›Œr÷0YŸÆÊÔ¥)'ʪi‹wçªSï‘c=·(ˆñŒ•QYÍRrŒR�ÖH“¬óÌpËzÏŒ:ç̨¬vE'ÒXKi¬¨–…´Fõëˆî„rY¼'Î+Ç ” J™ŠÇ TÆ£Îc¨©a•W·n‰f�c<69Î#Ǥ]Ò”Ñd£GŽóŒQê"ë=·È±jÖƒJ1AÜ×ʤ¶¨Z’AŽõÈfϘzyu;>NŽõ¸‡j• ".ZÆ!–jP®Üä#óžÉÁðîe®K–Ì ·rgP:&{jÚ.O�¯LÏÌ0^žjV“ÛÚŒæ|k/£ù"•Dgéì’Lå«èj@°èàa€ˆÔî�›îïÈ´šƒ4h§Ífìax‘rÁ!�|0‚Èë³ œy£ÍÖ¯ûý=ô÷ñ…Vg�Rwöî¥bt}ÜõvA×ǧâó³NQÖG�Ç;mg^±çgu¾|´3'›ì.»úJ´pnƒ»¯77oÐ@.�ò¼¹½8Êí–¤¤÷Èå Å – cùê.�»ÚY4³\�ô ×wµÏÝöý�9¡ 'ÇœìŒ�“-–dQç8÷…Îq¾Ph8ÿ0÷ufUa߇/ܘYîuHÞŠ™]ßx=Ñ|ññÎ À)ß, ©:Lè†~{zy§ÍLæÄ =ê‹5&'|S˜ø•±§ N‘íxçÑiJí-‚Ûew9Á«µ¶{�Bjª¯éžC+C_SåRæ¾As6Ͻ¿•^䜾õžeS²tŽÐË¡í·X’w! ¤|cŨs@§DH '|1 =W(|Aê¹ÈvüpgNv²{í.þÃ.Û.n¸Îq~%ÍáÓüºL䡬= ûè�I‡vÄöœ¶—¬è>à3Ù»•÷ðUf‚ÎU¤n;ã,Ñ•  ëø©‚øüü®ãéÊÅêÎbÜÜ-¹iJÞ¸9ƒFU-)ßÑ 6�¤¶ƒ Òã¾OÂúB¾§r)ë•3¯äd“Ëî¶»ò\‚-´rgh%¿W¸ñüJáÆ�J4[çùƒ|NdÁ¿3))†Ä ÉfWß ½á³Æd›Þ"'zSïÞ=œIAâ|1‰öŸzLÊ8+”fgí“5->ŸûPg¾=?+'ÛÕ×B¬;NyƒÒܽõ†¼Q¼ÒBIvÞÝÛÂ%%öâ¼¹ƒ‡ð!ðÔ´)×MôtþéÝ…‹««vULmȽò®ÆÁÛ?*œ>"5¾Ÿoàˆ¦ÜRQž1~ÖÈûž©®¹:Íý�)9>®_`Åä®qôz�ìâ©yýSÆL‡Íá¿ñçt­H@rÚãÄ}´F€vøl‰Æ¾&]÷.뤘ÊÞïuxOœŠÏ'Ûñ£�¶ŸC›Ö×îµF‘R]à�œR_ƒ�›?Wºj÷š½Wn3úŸi˜rCuFGrî„Á®’1½s²GÌ«ÌáŒ+_¾uLo�nlhùÞÆÊò÷\7ñ¦éyI9#BÝ“Ójîááð÷üVþR1´ÃŠä =סïe RŒ/f••¬ñ?ÅMB� Ï-H¥Ôçø€Ò§�RßXKçd{”6ëyÝXÇSÚµ›Ú¬[KÖ�; �½yï‚ kGÞR^¼tê ö‡F·ŽòôèNÜ�K׿ïÖýñÞ¢·®íŠÝ»œNel+½A׊D¸0¨Ý§t£#)H;|vô6šu)çl�¸ŠØJñÝ$%üjëåk‘ÏÉNˆÖÅîµ»£=`«�]óÊÖìjΞ–¹ýAý˜§gL¹ñŠŒŽ«Šî®HŸå½óê\ýê­£MfzüÜòç4•ß\¾{Ç’Eô^bRP髋çùïøz¡?|;L¦$i÷1©¿¤ç|IIÄÃë„}Žô˜d>f2œµØVæTµÙβ}Ô©vPJÔ\JÕFqC’´¾Ê†°ap4âüw×U°uKFuÀï½£nÍÞ¥ù#?=wö–æü]¼³X*ÊŸ^2@Ç¥{r»mzÌ`²Æ¬Kì^Özðº9/¬›\´ìÙ@qó¤ÌŒI ŠÁ~ͺ H@" ÚuÆ uø–¸8“ÝLIÝÙ8«Ñh�M8î¬}rl ”ªÛãó³ò½§rÉöŠíøÛñùY‡Î¼œ“MiîÞ©äJŠì<›+7™Ç­3¾¡`¨¼=ôÓ–YןÿBø,õ¬¼¡k÷ú†ÇiCJ¨EùUkz¨VHäCŽq¨ÃÏÃBmè�ñÔþ\â2øœá|�Ú}æ+úä\Ñ?çŠ+rúó®ä}ôJ0‚Þô¥¹êm ¡²ò²À›Æ>e¼q0ʨÌXf¬<üè°‰µožTp¤çõP \@~VÖ4ö|Û)»×¦\ÌñΣ�ñÉùYYYöø|Û™Wâ“óm�6åFÑ‹’¢CÐBI‰Ý’u½øŸomƒ‡ äµwÖÑ\IÄ‚˜7(­¯ÇÂ'¨³Š:%«1ä[zŠù³6\Q0ß™ÐcÌ2úW]é¶lïêëž™Ÿ[2ºGZŠi䀄Ԥ¸ü™ª=%=hnÏM•×”ö’f†Î¹ÒSbóœÃ&fª’ª‘Ÿîž6xšZ¯#±g®˜–ËÅr½}ÓG_{åྥWå�™ï5õIÏN.œ›�œáž¦äŒ5ÞyÁ>º°WN�kä0]L·é鼘=i¨è1a€Â>Ã'(¿ÃnøWu­HAV»5N™¹Lm÷YÉÔݧ;Ÿ4ÉRW¥o\6o¹Üve’U¦)·:wñÞÜnIü«Û®¨p�,šàݶMßâÄ@ƽ�rkµ$dMÑÕ¤k Í|8§x@üsApÊ/&üÝÄ …ÏÃJ]è�Ú}–Š¡½¡—sÖP¤~¾ØDŸ-±<?ðQpêãôSjP+¡¶uª�+®<—Ý•äÊs%(Sþ%'t6ô}HéþHcG¦æz’’<¹©Qòµë/<¶aƒIi9©=sÓ’’Òr{¦æ¤)÷V¿VÄ`Àµ^öh½bÕzá_©v¹K*ri5.=­pvÝyÓ† [œ!Yí\7¥Å“§´¸)9…CrE\…í¼a&*÷Ó‚­ÅթΛÌÙ~IÓo~À�˜Èxà‘mÕW8G�ÏÞÆŸÜ2¨t€ý¹`×5Üš%×°¦‡Úði!–!}Ñçyå…Dô¢¾ØØ~ݲNrÿ¨ üüÕùóSÇÅi*ÚÅ“¢]^ˆ-ZÑqÍÜg–hìè?n^ñ„æÑ®þãæ–(¤Ðâ—n_|Ã�•‹Þ6¾xÍ�›¦Ý6-kdÓ-c§Ý®„×Á¨Ö+·�‹ßGíH€‘Ú}¶˜„DÎn4"¡Ât^§5‰2=]Ö(äÍífpÖšäõGt5ÏV?ø[½ÌWNr�öOΖù“{®®{ãÕ›–v2ed×r%»Ã§ù}|y¨Üƒ Ú±ËÑÇÑ'AÚµÃ;ؽ—€>ÊcZ|÷ò>}ÏÚ3 ÎI±AÒùb‰ÛÇÅY~4h7ÈŸŸÖŽvÚ•~ =~öNcÏkƒ•¹¡ïÏSÈÅûf/.¹Ïïë3*0­!«é™@õ¶)+¯MÈ�}eIËäì¾Ó7_;|ý„À݃ k†¤$å7j®ç¢ø¼É…{Yâ7wïQRàHï;À‘è-›î MÉ7ÛHLHtg9ýû§ôÈ/«V®´ ü=ÿº.ÉÈk·™ƒ´Ý×-Ö`0&[�)ÛßM±æ‰8Ÿœø#½uy«=úè¡ø|›:÷«7ý´Sø„/9Îf²ÚcƒÙlˆ1NÔ*8ªˆWºEn�WYãó³’ó‡*‹×Oùݳ¼Þ”C¹ í^{|¾Ýk÷¦Ø.&°ÄœlâÝ|_ïæ½ ÉCÔ7¡è®÷7¤ºn;¼áéÉñéw­|(Ó:�?y!‘mšjàOvMÙØJ/…Š[ïà¶+-|:ô4w„ŠÐ©{�Èq»‹wº[ƒ”Þ®¯@Á)åãÕ+�9ÙÉÝØ}BPê,uÚ[7&#µOªÍåu» sRG.Ûuía®[º¯ÿ€A¹’¦¥¤Ž˜:²òþ%eG›Â§¹ÃÑQìn×urÔau'i@G¯@l�´cÅY‡ÔgñËfÃËgGÎ+нû€¡¢sÈ€””Cœ—mó¡Ëwv¹/OQkø4w„†#Ýž‡Žãa(£=V™RH—Ÿ8½÷ÈÌ=2Göv�P8‚†÷8ÒÝ›môv�Ø 2Ò;üt®<ì<ñ{ȂҠ‡ÙdËOïzš›Bï< ޶†Os;u­à‘ ·2Ã}1t®#�‚”¶Ã@¥ò”ó6e± Žwó¿j�MŽM½æ8²ÝIIîlGÏì>II}²u­çÏ úó×$õÉqh»9}’@”ªåtG`Fr‡ÙÈiÇÎXÃnð$¸t}3iˆŽ÷òžd°$ôUòºn¡Îò†—’#e]wr”…ÞâË—î =MSö.¾oÓâhJèéýË7‚S~ó†ëp@Ä–ÝBÏÔ�OÜG³‘žfû’¨G÷n—”lv˜É1:±W¼ ·iìncœÉ*ØôAšíË0Ä8{u7¥¾ß-Áß³Gœø‚`Ô‘�OñB¼À%Ym6Î`+4sÊæ‚éӼѧU¯WyNÍͽ(d;~¼ó£äüN{r¾í�úxqühr~§MIÈÉ&7ïNP_y^õåå] ^Þ›äæ½®/è?ñÜã {îñû´Ïû'zßå"ô¾ÇýÁçî÷B¸ÃpSsh{Ý@Óo ±¡ÝÊë†ÐšÚÂdŒTªŒ8xÚã(HÏúLzA0™�†Ø.ŽdywåVCqXý„ýh |"ć–n -¥[·Ò­t,4‹6n¤ß„®V>ýÓ¾“ï®~ƒ•â‹5ð:ÒýhàT†ôqeÊúEßé¼ð(_«¼¸›ïٕϰ·†¿ãïС[]�¾ÝÁñ@Á¡h¿ób(™ø{çuÕq›çu}2}>—Ãå4‡|Ê<}$üÿ;zttz'€xvô¡�:s²†ÄP_:2—ÛÜU7—sñŸ5w½ÓõÎ|:`œ¿3&…Æ:ƒ§ i‚¨PX“�&]šœ×äœ&?iò£&×ä¬&?hò7MþªÉ÷šœÑä;M¾Õä´&§49©É7šüE“?kòµ&_iò¥&_hò¹&Ÿiò©&�šœÐäM>Öä#Mþ¤É5ùƒ&jò{M>Ðä¸&Ç49ªÉûš¼§ÉMÞÕäMÞÖä°&oiò¦&ohòº&¯iòª&¯hò²&‡4yI“ßirP“šì×äEM^ÐäyMöi²W“=š5yN“ÝšìÒd§&;4éФ]Y“íš<«ÉVMžÑäiMžÒäIMžÐäqMÓäQM¶hò[M6kòˆ&iò &h²I“û5Ù¨É}šÜ«Éo4¹G“»5¹K“ š¬×d�&wjr‡&mšÜªÉZMnÑäfMZ5¹I“5Y£É*M®×d¥&+4Y®É2M®Õd©&K4Y¤I‹& 5iÖd¾&ó4™«ÉÕšÌÑd¶&³4™©I“&�šHšÌФA“zMê4¹J“éšLÓ¤V“+5©Ñ¤Z“+4™¢I•&“5 hR¡É$M&j2A“ñšŒÕdŒ&ešiR¨‰O“MFj2\“|M†j2D“Ášäi2H¯&¹šäh’­I–&w(R8„»׊*€kq7BânBÞånRž ¹›ÐÌÝ„íÜMÊŸäs7€ð�úžÅÝ€íÜ à°�[I] ¼s«!q«"GOâVa5·Jù/ Ü*ø¸UXÀ­Ï­ì� «‚Üõ…aq·œ[Ñ!‰Ö n ¸hæ”?ŒßέÀ'Ü õØ \Å]‡O¸ëÀá*n>á–�÷ܵ ¬Wß›Õw›òÎ-�Ä-ElÜR8¹¥¾ÅÜB*›ùBq>W(ÎΜU53³©ª1Sªš‘ÙPUŸ[W•UWPÇ]•;½Jœº*·`ꉩܔ̪ª‚*šœYYUPI*éõ_ ³¢jRæÄª)k"=RN Êé@95—“¯œÊ2K«J2‹«Š2 «|An~GŒµl7—»º#Wô¹«Õíð®iGŒ©ìÝ}\ >îš9CÊ|Až®² Çwôê-9Ž�:Rû‰A*(Ìbèb¸Àp¾£gº¤s ?1üÈðw†³ ?0ü­Ã‘%é¯ ß3œaøŽá[†Ó §N2|Ãð†?3|Íð× _0|Îðç=†ŠAêd8Áð ÃÇ 1ü‰á� `ø�á÷ 0g8Æp”áýŽîÃÅ ½Çp„á]†wÞf8ÌðÛ o0¼Îðë ¯0¼Ìpˆá%†ß1d8À°ŸáE†žgØÇ°—aC°#¥PT~}Q±›aÃN†  í 2Ãv†m Ï2lex†ái†§ždx‚áq†Çeø†- ¿eØÌðÃà 1<ÈðÃ&†û62ÜÇp/Ãoîa¸›á.† ëÖ1ÜÉpÃí ·1´u$�ƒt+ÃZ†[nfhe¸‰áF†Ö0¬fXÅp=ÃJ† Ë®cXÆp-ÃR†% ‹1´0,d¸†aC3Ã|†y s®f˜Ã0›aÃL†&†F‰aCC=CÃU Ó¦1Ô2\É0•¡†¡º£[Udü]Á0…¡Ša2C%C€¡‚aÃD† ãÆ1øÆ2Œa(gÍPÆPÊPÂPÌPÄPÈàc(`Å0’aÃp†a ù C;’"ãoÃ`†<†A ÞŽ¤I‘ñ—Ë�ó²2dv$öŽŒ¿ †ôŽ�¨|§¢G¼2'÷cèË�ÆàaèÃàfèÍàbpvØó"ãOdèÅ�Úa+‰Œ¿ž † ÝR’º1$1$2$0Ä3Øl V ƒ™ÁÔaõGÆ_C,C ƒ‘ÁÀ gÐ1 <Ç@ ð…­~Qy…¬~±Ëê/Xýây«_nn37ˆ�šÄÿ07ˆ[Ì âoÍ âfsƒøˆ¹A|ØÜ >dn47ˆ˜Ä ·Ö×bv‰›LÍâý¦fq£©Y¼ÏÔ,Þkjcjï15‹w›šÅ»LÍâS³¸ÞÔ,®35‹wƵ‰wĵ‰·Çµ‰¶´ Çê܂sY))Sx19+¹ ™$y{2çKvˆe W'¾›x"QX�@›m ØaËÈ. †øÜ6±wÙ+í·Ò:Ë#–í~»e¿…ÛoyÇò‰…÷YF•ñ/�ú_aA´“ÓýAC8à—�“®”i­ì©TÞ}SeýZUS¯¬n'º³¦�¸âɲ]ù«Hu»õŽ;�Zä—S+«;øÍ›S‹jüòjÅ}>ÕÊ©E5é-‹·,NOoii¡ô–Å‹ZZ!ýÿÿ…þÝøïY�žÞÕ–––E‹ZZÒÓ[-Zœ¾(½eÑÅ]é-Ê^uY¤l-R7•Ì-éíPþ^¶0Ìñ�8G�8@¢0$ A¢.Ht�ƒD?A¢!Ñß!ÑYHô$ú$ú+$ú��DßA¢o!ÑiHt �„Dß@¢¿@¢?C¢¯!ÑW�èKHô$ú}‰>…D��è$ú} ‰>‚D‚D„D€DB¢ßC¢ ÑqHt …DïC¢÷ ÑHô.$z½ ‰C¢· Ñ›�è Hô:$z ½ ‰^�D/C¢C�è%Hô;Ht€Dû!Ñ‹�èHô<$Ú‰öB¢=�(‰žƒD»!Ñ.H´í€D�¨É�h;$zm…DÏ@¢§!ÑS�èIHô$z=‰…D[ Ño!ÑfHô$z=‰€D› Ñý�h#$ºÝ ‰~‰î�DwC¢» ÑH´­ƒDwB¢; Q$º­…D·@¢›!Q+$º ݉ÖDâ»*ßë#ñ] ‰V*ïË#^‰ðµ‘/�DxI$º‹"Ñm‰Dwa$ªÍ‘¨Î�Du^$ªs#Q½:Õ9‘¨ÎŽDuV$ª3#QmŠDµ1U)Õ‘¨6D¢Z‰j]$ªWE¢:=Õi‘¨ÖF¢ze$¢5‘ˆVG"zE$¢S"­ŠDtr$š�H4+"Ñœ‰æÄH4'D¢9>ű‘(މD¯,±¢HÄ #óE"V‰ÖÈH¤†G¢”‰ÒÐH”†D¢48¥¼H”E¢ä�D)7¥œH”²#QÊ‚D!ýûFï¿b©ùwWàÿmIþv·+ endstream endobj 350 0 obj <> endobj 351 0 obj <> /W [0 213 549.80469] /DW 0>> endobj 352 0 obj <> stream xœ]’Ëjƒ@†÷ó³lÁñ–Áh½P›0z´Beœ,òöÅó')t¡ð͹ýçâde^êÁJçÃLMEVvƒn -ÓÕ4$/ÔZ¸žl‡ÆÞ‰ÿÍXÏÂÉʼº-–ÆRw“ˆc)�Oê‡Åš›|IÛéBá¼›–Ì {ùrΪ�pªë<ÿÐHÚJ%’D¶Ô '{­ç·z$épضlIÛÁÞ¶ç¬úóøºÍ$=fjš©¥e®2µîIÄJ)•ȸ(Š"¤Ûv7BØ¥k¾kÃî~"c¥<•0홂T€2¦¶(ô˜ö{¦h‡,°E“Ÿ‚°�@)(A.Sê2…G*„ðLCx"çñžÅgÊ ÓC\ŽŽ|ÄåÊrdñO<œûÂÇLž3tÑŽ‹ŽCTñ³Çlx � ¹zvè1ÈñY{� TAktW€šë¦Ö‹zžAs5†´å³ãÕ¯K4=/sžæ5jý~$…¼¤ endstream endobj 149 0 obj <> endobj 353 0 obj <> stream xœå› xEþ÷¿Õ=wæÌABBè† „Ü„+““ÀI&&œ9:H$ܨ€Á¸¨ë­°¬º*�p8€ ¬^¸º¢®ëªD×cW@p•E 3ÿé®)ÄãÝçyÿï¾ï¾ïóö$ýùtUuwUýªª;$€0c5xÔUTgåŽy{ùí¹@]ãüúVn? ˆ�KÙ?)}y< 3êèæÖÙóÉýæ7“ÐÇÏ®okE2œN°Îž·¼ù@­Šz ¢�sšêů_Šý u†Ì™ÓTµ™·d$€þsæ/Z¶ðÓ¨�€:à¾�×ÒX©Ï…L€¿ 7ϯ_Öjò‘C®°/¨Ÿß—›ý2ÀMÈðÖ–¶EÁï± }äüÖ…M­}ÅÔCÀÀ Ám( ä¶¿€z¨Q 58X‘…&À�·Á)¥•-x›¥ô�7¨Ï÷œ'3UÍ¡wBWT×ý¬Ìs4åó¦î]»_›eù�N¯S2~š4HæËí¯d†Þ NW]§y€\äL^ÕL6A �úAµ %ÿš9èô\”FÏq*žSÉe¯½å„j»ر•ÖM;�ãXíùÓê$¹g”3äöÉ©F¨à +xp°#Õ˜…¹hÅ2l …”3²•´zÌÃB9-ô)‰¡”Oã/ô޼i1U¾‹J/�ÜqZ–:3DœG.FF\+Ò#®FúÕò%}2š°m˜‹,Pj—‰|dÃŽ",Æ\̃;r�ƒ!(VÊ´¡óP�6LÀ\4b!Z”´f,ÂpØVj¸ÒÙÈF|hÂl,Vrâ©«9Ã`ÿ…«Ñk-D«²¯Ç¢H-3aG!æaìða.fc¡M9jB›Ò¢%h‚ˆL¥VþO|¾ø÷}H%yŒœåFqsÝüNþ´j¤ò™­z]­Wר·«·«?×LÓ<¢yO«×.ÓáÿÁOÜ¿øÜª{V¯TÍÊœP6Uó/ŽíÿÖ¦jFË¿ïjÿ¾MÕŒvU3¶ªšñ¨ªóUÍX,·[ÕŒ™‘ôהݡjÆÔHút™‘ôWTÍØ§jFA$¯HÕ —ªeÿÑÆý²ýwÇ©2Ö×án@;�œþ“lšÑ†Ü‹'ðÑ7™€6´c+vâ^Å9¢!Édü¿£ê$D¡³ÁU¡Ë¡Tõ7ÁÏ‚Ó5ñ!�ú½P,šæ©Ûa 6‡.Wߥª^ NAÓJ �ã<б+¨V":”º¨nV·«ŸT¿Å ¦ÊwÐ>úߨÖø0 MhÆuhÆ<´â:LÇ Ì„¨<%o@a –cVâ&,ÀR¬Ä͸·â6¬Wž+K#¹«°·bnÇø6àNlÄÜ‚v¬ÃzÜI¹°Q)+_£·)gt\sÎfÜ�{q?Àƒx›°wán܃_ã^Üw5ýa<¢”üqúÃÿ²ü£Ø‚­ø ¶á1<�'ñ4vFÒ~HÙŽØ…N<ŠmJÊN¼ƒwÐ� .ã ¾Æy¢#M‰›Œ"ÈD4aŽÒKÓ1 °-X‚6¥«°íJÛnRú`•ÒgrÿÐZ®ÁÚH¬Wúà‡¸K©ÿýxT©×Ýx@©?­ûo•4Ú¾Ÿ·NÎ}üjþ/µÛÕ2Oa;$ta7ö`žÅìÄ.taöb~‡'ñT¤GžÁNH茔ݫ”~òš¼]?Ë àâ9<�#`?žSö,í�Ó£#xGñŽá8^Ç ¼ƒ÷p/ã5¼…?âmåø}|‚³¸„�ñ¾Æ‡èÆgø_â+œÆY|�s8� ¸‚+â Ñ(qÊ Ñ¤7I&.â&ùÿž™üd»÷çI\y�»ØÔ^]ÅÔíê»ùQÜx tÓ1wåŸ>ŒšlM”ú’úkD©ó`P'qo„.�·5…^«Š ]À4ž1⬙3¦O›Z믙Tí«ª¬˜8a¼wÜØò1e¥%ÅE…ž‚Ñ£FŽž?lè�¼¬ÌŒô�)®þÎ~BB¬Íj1Eô:­F­â9‚ôRgY�]J©“T)Îòò ùØYo—Rê¯I¨“ìõv©ìÇe${�RÌþã’žz»Ôü“’ZÒsµ$±ÚGbdFº½Ôi—N”8í2µÊï´KJœµvéŒâW¥(¦g­Ã‘‘n·—&Ì)±K¤Î^*•-™ÓQZW’‘N:£ ÅÎâ&CF:: QÅÎ⨌tH�­�dàh¢7°tx'�I¾­Ä»JëE©²Ê_Z’äpÔ*i(V®%iŠ%­r-û\¹Î¸ÃÞ™~¸ãW+êÒŒ¢S¬Ÿî—øúÚŒô¾´£c�dK“R�%Rꊿ&d¤—6IéÎ’R)ÍY’‘îõ]½‘Ô.«ÓÞñ$Rçi¿X­äª”å¸1@ ¤éXAc€£iV–Æ¡1 ¢i%MÞ2ÒKæ8½òZ[jåØÜX;§£®VžYè%q.‰s‰8GC✣; §1JgS‘å,’Ó äôš®‘ÓµÎ"‰ô"évyAê¨s6d¤KZ—I„ŽC^¾¤= Mò;N$�©uH×tIãšê—ôiµvIí'©\cäï:Iã#­n¬—ë�¿|®Ö5¶±VÒ]½ ¤q�•ô®é’>rIë*SΑÇ"jü�IŽÚz§¢ÒêÆ$‡´ºVªM“oêŸ[«Œe«„rçpI“B¯©N‘o”UÛíÌU&¦Æ%\ëdè]ã$TûiJ’¤—«SK;Ik”Ô®F§¤q5ÖÙ÷{ BcµßYH I4¥©Ê/©Rš”oCR$r³xW”É é3%­|MÙ£2åù¨vikkiå•£u‘’Þe•¢\’>åš®Œœ é\R”k¬\IãZ'”¢GäËTàs.“ˆÒ£Ê•´’Á%™\cë¥Õ ôü(Éàrc'ëä"*r�£4U+·Üè+ñ®I�ÐïœË×léNùÉ L$í<¨íøi‚4--#]÷ÓT“’ÜÑ¡3ýò ´¿t¦«”í¥sK2@ÿÍPeV'�‡r0}?œä�® ‹)@ï±Zu‰ÚH.8Ät Äí±ª8ÓýVëÀÞ$jîã -öIÞ3Pu/)FAÏG=oô|t&:?ë Éú°ûÝnëùc¶ü¬î—Nvçd›Ã¦|Çš9§Ö9À�›78“K#yîܾÉí'§÷Ëäò�æTæ+ãx�Š»Þ^4»\%jn4þz�3uîM9Á€+Ço�ŽâÍæxA�té3uÒåBUÃåG¹/3j CR „{Œ¶^å}‘£v¤×ž(óßÕ%(èy÷LAt~~Ï»igˆõÝ£Ý'ÏÍÉ&‘šÈëKܹ£¹¼Á™¹rÃâã2‰³Ÿ&.¶¯†ÿlüúCmƒgÏšÔÏ{péäåœ#êV®^Y7bØ’ý«*&8&¸Ïœ‰Î'ÖwOv[KʛۦMäêjgrr}µ6(þRéª} kLÛ©óno˜|‹?½+>wâGÉØªL÷uÙ#çWçpº›^º}l?—z\på�¦êò[÷¯¨X;3/.§jd°wl|JíÝ x4ô ¿ƒ¿„d ë² >@žíÒô5ˆÞ£_e!–èï£* Úg[“Irâ%Þ'�£g”íéœl—ÜÇ £¦4r¿öRºuGÉÆñgƒ¡q·h�¸~táºòâ¥Sw>2¦}´+±7á..ý}‡·Wï'ú )ûöÚíà0_ êvÄÂ�Á�Æ(y(è’âd·Ç†~:“:á’ÕUe¨¾SWÊáWz/ŸE>';&R›Û挌€¡´>6eHÏ/[³·%{FÆ®‡5cŸnœ|ë”ô®ëŠî®J›ã¾s é^}üö1FyâÒÊ®k.¿5°rßî%‹Ècã‡Å¡³ü9>ˆ¾H…g·Ñ‡Ù·[ˆKUȳž¸¸A‰�*¢R êÿVb¥é£ö‚ÕGgŸ¼º(Ývþ¨õÃne€’X�Ö!Wm474Ž�U:ý´C"çÏq\OÁŽmé~Ÿ×>fwÝšKóG-~zÞÜm-ù{y{±X”?³d�šKsåözðq­Ñ¢ßÛ»¬ýÈŠëžß8©hù3¾â–ÊŒôÊÖbÐß晴ԛƒXtªuÒåI2GEµèeŒ3«/DYt:›!æ2¸ ¶I†*ÈU·Eçgå»Ïäë1ë»oDçg=ÿRN6IqöK&Ž8‡Íisä9ò¬ŽÜx¢Jº½ñ+–wŸ'ÅdÛœ›/¦ú4ù‚´¹g(÷Êæ'Èæ„`›üû”™ÁéªX>ˆ�:lxfÒ�TL �Ïæ *�ÏÁH§Ç4¥ΔԜ)SrRyGüAò:J0’¼æIqÔ[c‚eåe¾×týËÒyÝ”‘2]™®~Ȉ“Ã+¦¿6¤²à­>“åáq¦@n@~VÖ ¶|ë›Û*7æÝî“ÝÑñùYYY¶è|ëùcÑñùÖn«¼à÷%q‘)h&q±½âÕ}ùù!C3y¶§ÍGhó§ p™ùeUQ–S%†|[!Îæ) ì1‰cG�wÕ4÷ðåV¯Ø¾ ·dLbJ‚qÔ ˜ä¸¨üÙ›ý®’D2¯‡¿gmõ ¥}ÅÙÁKŽ´Cž}xEöડɌüLçŒ!×Lw'ÅöÉRr9×Ï3stñ²iC”ÎÊ»Àm쟖_8/;>Ý="E.iÐÝyÅ6¦°oN�cÔpµ¾× ´4^È®&8GN$³ÿˆ‰òSf+ÀW·#Y�–(yå2d—ÇBŒ½­QêËq•æê¨*Ècã'ë–Ãi“Yy™r*kïÎíÇß9¥Ê9ªh¢{çNMjE…/ýÞǸ5‹Úb²*Gö4«Ûƒ³Í)ýlœüïüü[êÍÐ#…ÏÁBzÐ*Òé1뉞è5Ú¾*ým•!@z ±kly,¾ã+Pp棴3JPOÈ¡¶v+nGžÃæˆsä9bä%ÿšÇ4¹|�¼OÒ®|@Æ�JÎuÅŹr“#ä§oºòøæÍjÄ¥ä$÷ÉM‰‹KÉ퓜“©_;ô´_©—-R/ƒR/¼ÃW+C\[�ko«º°ñ²q³ü cLTF>ˆ ”w&'È®®D‘‘አ�]žx“)3KsaPeÌ…~•ɮĤŠÄ*‹@t~>â$?ë|þÉnëIy tØ®>1œ×ª;žEÞ÷&ü<­%ÞÛo@–}‹Ö’`‹¶Èvlm×%æ Ñ¿jRBfžgÐóÜ[Y#�æ„!µ…=+¹†–¤˜cO-ëYÉŸ>”_™]‹<ƒö¸ØØáƒˆGV'×K;ñˆ’ÇŽ1>�C|UT•õ²¶(�×m6v”E›ÕÌvÍ Úú�6ÝWáKhËNÿû¨¢ Ù;ùÓÛ—²=è¹�[³ä:ˆÀazè¬ÊÀƒèÿœü¨E,ú’݃a`ïï-•΋jå]�>·ºx÷¹ºàFz).2yU†¢»n˜·}icWêøùÅ[Æ8RÇÏ+‘I‚‹_¼cBñ-‡oZ|äŽ Åk¯�qÇŒ¬QÍëÆÍø•BùM ØÌ_⃈… Ãv› v�XC ”çYœÎ”bLì±V+ô5ηi è‚E²º­ïž):ÿš%€¿ðF0„¿ä]»gnö¬œ�EyŸnüñAöuî [9Ým/¯-2ƒÓÕ·=9ûgï‡@ð  Ò)}˜ÛÉE$�ˆ�Žtz¬ú˜XΦÓ!¦ÊxYÍÂ'?~@âÎí¥uaá{e‹ºöÿÿÑH|u¥sŒwR¶ÄŸÞ}Ý«Ç×.í=tò¨ž•òèß:ËäƒÈCõ~¤“Ý{“ú'õ7 @ö8 ¿übÝ»¼ÿ€ ¶t­½Ò j�aKÔ®(.Ê|QË^K~x¿=Ùm“g ³Jî:å wˆ¼"øaá¾ú¶Ò—‹ïËóû�öÍhÈjÞîóïœ|Ó²˜Ü¹ÓJÚ&e˜¹uÙˆM}w)¬š—ßì«]1ÞA¢ó&fö5GÇní�XR�”6`PR¬»l¦g�89ßd}(6&Ö™•””žšš�˜_æ—[Zú†E��xäuZMòÌîeÐjuñ]‚ÖúO£ÁT�Ëñ±ùÈ ƒû„²Žœ<�oUž¸Ê«VJžü´µ •W[ä5ë•7> ø齓¼ÕÖš½p´ÙbÚÞÉï"±ÁCw¹y×[¬ò �å�ó§Ñ �ä Ùå1â9ÄU+,—´>eia´›.(Îf^¹»Û«¼°ØÜüñ‡5U•U=ºs§}Tñ„ì�ÊäÜà6õÜüELVå(îAªdþ4tÈ÷XÔ»NËózà žð�Л=¯ÕUi4jy`åæf¸ó‡Í�׳ÞYnwb‰Ü¹òðЉã&΢cò†~{(¸äeþtÏœmOp÷\‰� P)¿§Ûä Vi4Fc”Ö`ˆŠÒëTÄf³ò*޳X¬Öh˜M*UL¬Ye7¼:[è,¡S0†Ny⣬F‹Í ÒšLZ½®B£­âHU´R«·ü‰ÎÏŠÏ&onV¿„£¹2mn[t¾Íms'X¯&ÐÄœlÂ;ùZÞÉÓ&È;UÑ]ooNvÜqbóÓ“¢Óîºé‘ ËDþô•XòXó¼`ºgòýíäÅ`qûn—«nRÊ»ct~¾õŒ•.-nkwî/=?R�¾¼<5\±½âI¦ò¦Êä6ÜûÏÎúŠÇ‚;ï½ØY_ñxpO¿b{°i°¿ÀYtË‘;„ÑÉä÷¤QýŠn=‚uÿ™ÚòwkˆA /x¢´<eÔœQ«‰*@úìÖ5èùIì$" Îä*?„Ðww÷Ñ�åd§’<‡M=Àå¶9øÏ®¼F*ƒÇ=d냤ÿ6þÀÓ÷|py ˆüÛyþœ:vä<···­·Í.ȧ#qXMÿPéÛÈÙ$©ô>òR|L^aÒÍä“�™|ÄäC&aò“?3yŸÉŸ˜¼Çä]&ï09Éäm&dò“7™ü�ÉLN0y�ÉkL^eò “—™grŒÉKLŽ2y‘Éï™ar˜É!&/0yžÉsL29Àd?““g™ìc²—É&»™t1éd"1ÙÅä&;˜lgò4“§˜<ÉäwLž`ò8“ǘlcò&[™laò“‡™<ÄäA&0¹ŸÉ}Lîeòk&÷0¹›É]L63ÙÄd#“;™l`ÒÁäv&뙬cr“v&k™ÜÊd “ULnfr“™¬d²œÉ2&K™,a²ˆI“…LZ˜,`2ŸÉ<&×3¹ŽÉ\&s˜ÌfÒ̤‰‰È¤‘I“z&uLf1™Éd“éL¦1©eâg2…Éd&5L&1ñ1©bRɤ‚ÉD&˜Œc2–I“"&…L“aL†2Â$�É`&n&¹Lr˜d3Éb’¹[–¡Üm¹vÔ\;w+Dn-jð&·YÜZ´pk±‹[+ÿ™4w Î)û,îìân‡]œüHn•÷ÜjˆÜªðÙ•Ü*¬æVÉFέ‚‡[…Vnxî¦.±°&ÀÝÜUös+¹»DÁR˜Î݈îF´pòEïânÄÇÜ�ʹ7‚`·s+Àa·sËÁákn6)ûeo•÷܈ÜRÔÀÊ-…�[êYÌ-$…B _(,à …¹sjfg4×4eˆ5� 5õ¹u5Yuuܬܙ5ÂÔCS¹Ö©§¦r“3jj jȤŒêš‚jr¸šlQ¾|U5•5­$«‚l)'­åäp9i)'žrR–QZS’Q\S”QXã p ºô–²ýÜ<îú®\Áà®WŽC‡¹æÝzcÙ›¹6x¸vç -ó¸ºú8ÊßÕ·Ÿà8 Ò•¥ø¤+q˜ ݧ(>¦øˆâCŠ¿P|@ñgŠ÷)þDñÅ»ïPœ¤x»«÷!@þHñÅ› xƒâÅë¯Q¼Jñ ÅËÇ)ŽQ¼Dq”âEŠßS¡8LqˆâŠç)ž£8Hq€b?E +¡P�ÿ¡`Å^Š=»)º(:)$Š];)ž¡ØA±�âiЧ(ž¤øÅ�S´x…¿X¼Â¯ðg‹Wxßâþdñ ïY¼Â»¯ðŽÙ'œ4û„·Í>á�fŸð–Ù'¼iö 0û„7Ì>á„Ù'¼nö ¯™}«fŸðŠÙ'¼lö ÇÍ>á˜Ù'¼dö GÍ>áE³Oø½Ù'1ûÏý‡Í>á�Ù'¼`ö Ï›}ÂsfŸpÐì˜}Â~³O˜}³fŸ°Ïìöš}³OØmö ]fŸÐij$Sƒ°ËÔ ì45Ϙ„¦a»©RxÚÔ …H>�Hº!’SÉÇÉGɇÉ_ ’ ’?C$ïC$‚HÞƒHÞ…HÞ�HNB$oC$„HÞ‚HÞ„Hþ‘¼‘œ€H^‡H^ƒH^…H^�H^†HŽC$Ç ’— ’£É‹Éï!’#ÉaˆäDòDòˆd/D²"Ù ‘tA$�‰‘ì‚Hž�Hv@$Û!’§!’§ ’'!’ßA$O@$�C$�A$Û ’ß@$[!’-É#ÉÃÉCɃÉÉýÉ}ɽɯ!’{ ’»!’» ’ÍÉ&ˆd#Dr'D²"é€Hn‡HÖC$ë ’Û ’vˆd-Dr+D²&ßUáøÞŽïMÉ�…ò~e8ÂËÃ^ŽðÒp„—„£»(ݶpt†£ÚŽê‚pT燣:/ÕëÃQ½.Õ¹á¨Î Guv8ªÍá¨6…£*†£ÚŽjC8ªõá¨Ö…£:+Õ™á¨ÎGuz8ªÓ­ GÔŽè”pD'‡#ZŽè¤p4}áhV…£YŽfE8šÃÑœŽâ¸pdž£WŽXQ8b…áˆyÂ+GkT8R#ÂQÊGiX8JCÃQŽR^8JƒÃQr‡£”ŽRN8JÙá(eA$™ÿs³÷ß±Õþ§+ð¿¶%ÿZRf© endstream endobj 354 0 obj <> endobj 355 0 obj <> /W [0 189 549.80469] /DW 0>> endobj 356 0 obj <> stream xœ]QËnà ¼ó{LøÑäbYJ°,ùЇêælX»H5Fü÷�¸R°šÝ™]˜¥¼©­Ð;‹ JK‹Ë¼Z�Ðã¨4IR�J¸ ·˜:C(oªv[N�fRôGµ8»Áá*ç�„¾[‰VéwÞ mWc~pB퀑²‰¡üµ3oÝ„@ƒìÔHÔN¹ítçíãk3iÀI|�˜%.¦h;=")c¬„¢®ëº$¨å¿zUý ¾;ØY c)+=Jνd]«ˆb§‡&vØf<Ðò<„s´ù%&o1Éc²z¶÷á’†ä-Rn±–±Ç°ØÞÿÀ;½Û#VkQ»°Ž`‰7CiÜ7ffãUþü ZŽÉ endstream endobj 150 0 obj <> endobj 357 0 obj <> stream xœÍ› |Uú÷Ÿgfr¿§é5”Ii)mIÛÐB€ÒôJ!@Û´… ¶eZ@ÁVÊE„ VPWñÈ*ÞX˜–‹ä¶Vð†+ËÅu]•ê¢î ®² 4y3s2ˆè»Ÿÿû÷ýï;“äû›sΜ<ç<ç6§) èa)ÐP_VéÊu2žÀõP?mvCkQΗSðxyÚü¹¶ÏŠß  ¬�™›[§ÏÆõú÷t³T±ÓÚZ!pŒÓg-lÞßpå;€A°>8£©�ûæ ËgX93f45hÖÑ&ýgÌž{ç‘e±ŸÈê¨Ë³Z¦5ä¶­ Ïà=³îlÕùñ \Ûí ³›¢³2Þ žÀa­-msƒ?Â:ì#Ä·ÎijíË¥ˆYçÔ †(P„B`¡ì dP 2 À.hКáPbjñ^†µbêŸ »Ô{ §2Í¡S¡kÌ­¿H³Ÿ„|Ñ40`8z‹aÄ÷J•RŒØ÷¹u À7Ûß:¬cn•¿ J "wÒL3®(eOÊÜÈÒÇ¡™¥ŠÒÈUÅг$;É1®Òf/ØlñÄ6EEIÖÓçdV¡fÄ;„ò ¡Z``ô0@� �i0² FÁh(ƒJ˜­°6ÙâC!1$‹i2!J`4ŒÓ4À’&ô9<“`2<zý†ó£ÐG¡igDjªï/êôÆcl„M¢RÀ$ÁZF,Žh’Ñèáöˆ¦! FD4FH‹h¤]O/Ã'@Ì�6˜ -p;Ø �2À0fÂ,àÀ™� 9P(¦iƒ˜ Ðã`&Lƒ9Ð"†5Ã\¶_¤² 2 üÐÓaž3^º3l¿’Ék´ŠŸ 07bå °A>Ì‚Y`?Ì„é0æB›xÕmb‰æCp0H¬ŸE‘óMˆóÅóY ( Ò"gÕM›#ç=âÉÿ;N&ž™Í¼*“Ëšd/ËÈw)dŠ&ÅFÅÛJ—r–2 Ò«ôªÑªjPSÏR¤™¦yõà´‰v,�¥Ð.–ín±–ˆu&Ô±r¬ˆÔÀ*±~ª�‡Eû×ÃÑ®Gà Ñ~bûoÅ0R¾_–Nˆ}þzü¯•óõ4/Á+ÀCì€�°^…­° ¶Cì„]°^€á¥H�ü¶�‘´»ÄÔ/Þ·ý±Ø ûà5؇!{à5ñS ;Ý‘kru^‡nxŽÀQxŽÁ)øŽÂ›ð‡? ñúCø .Àø¾„oàcè�³ð|_Ã9¸ßÀE¸—á\ƒ \C¹è§t4c<&¢Ýèù÷ôäÿ‘ã±_Q�ø.õCoPq}“µË¡s©±¡‹PuðPPx’ÑÊ3äÙÙ7 ‘eƒZf¥Þ ]Æò¿‚Jna¢C—a"4xGq·L�R7yRmMuU¥¿¢¼lü¸±¾1£KG•ä{óFæŽ>Ì3tHN¶kPzÚ€$gG?6Îb2tµJ©�ËšBH+v”ÔÛø¤zžIr”–¦ ׎ŸÔpC@=ok°ñ%?OÃÛêÅd¶Ÿ§ô6Øøæ›RzIJïõ”h´�€éi¶b‡�?Vä°pRE�ÃÆ¯.rÔÚøó¢'j&I¼Ð9jíöô4›­8nF‘�Çz[1_2FGq}QzvjÔ…ŽÂ&uztª5…ŽBMzð­�8`$Š‚P<¬“¥NøZžv7p|yEMq‘Õn¯àPÌ‹—ò 1/ÛLÁfxÀÖ™v¨ãÁ€ëSµœƒk¨«áé†Úô´º¸£c%oJåSE|Ê]�KO+nâÓEÅ|ª£(=Íç¿þÈËœF‡­ã{à±ÞqþÜÏC"!r§ñ{¤PÄëÕÄcƒ¤�Wòr¡|v»`Ë/4¦§Ùù¥5äÚ�Ö.ðºRkyª^ˆ9$ÅDW 1K¥˜ë·×;ì‚«Šë#¯ù3âø¥�¶ô4žI_Nžq;Šm<�Tß8m†À†¦GQ©·ªÞ[d+æ½ ‘²wf¸ŠÅ õ<ÖϪ¡¢†w9Zy‹£€$ðUÔØ̬¬o‰ÜÆ[ y¨Ÿ¹‹w vÙŠ;ꋈ�B^ŽŠš=à�él³îpÃ`¨ìàc kx:©¸£†kæÙz+ÇÛê›m5V;ï­å±¡ÖQÓT+xÉaäSÎXíÂQ¹‹qß”ZJ,”\áTÚj(+]+x‹gœ¶žq: Fð §‘—“KÁ£#l5h)Ÿr&’BP?ˇqò´³°Tˆ¢…[ K­öZ;9þ…IÖˆM2'¯¼!/#/ûÉ&ò=ÿ[ÓHjÁ [qSÑ þ,SYÄÀHn¿n'%ÔEä‹y™S)¸³TŠ¢�6žq*yÊYX* ^Œ³ñPn«q49j3l¼·¼F(›P×¢}•_ŤÑÛ‘VRõ³+?ôz\DñTaU _’j•|*^�¯¯_–Þ=Zжu(¾Ê!gG$C°u�—vòò¤Ñ  5NOÃGI½£¤Áa3ÚJ:¡¥��^oGkqýŒaBŽÑ\‡£²f„U4Í_s·õ.á«ÌàC_UAzZ'�\UÑéÅU•“jöl«ªjº(¤ ë j;û㪊š=6¯J ¡B pa.„œü5]”RLoÝãX*Æ2b€x=-€ †)¥0„iŠ„¥0 ¦æÄ#=­8n†Ã'ŒµÅ6NðÍâÚõµBÏ‚žrò”ytŒžrŒìDJ®åÕŽ¦^ã(Âó„ð<.ÂŽc0=Í& HõŽÆô4^á¬+’vH YÚ¡PU�ý˜õ|­�—;ëx¹sR ¯J­µñ2çžqŽÞõ¼Ü9Š_:­A°ªk„{ÎÑÓjyåõ y¹s4¯rÖñªH¼ÂY"Þ#´E¨®™fµ×68DÉ/�fµóKkùÚTáKkfÖŠmÙÈC©c/O"yÊ’„/rÕv˜YbÇ”;yµs¥•s •5$ÄÊ«sjI%)´¼Ì9ÍÁË�Óêm{¼ÀÀ´Ê{d U[IHSE Ï$5‰oµ5 B±h§F§æUƒx…�§ 5ƒ„þ(s*jk‰ñâÕÊH^å4ò'¯Jº¡*#7ðJ'¯qŽláåΕ¼ZLzXȦ"~Ç�<Š5*æ¤àÕN^çÝÀ/m$÷kxµÓ1TºY) šHÝ$T!”\ëÍÓΪ@èÇBû GzšC˜„† Ö=^¨í¸9€Ÿœšž¦¼9T'wt(u¿~©/¥î:…@[ñÌ¢tØ6ŠÞ©ŠÃ1¶EI%�!I%Ñ+‰«’¸"‰%ñƒ$þ)‰Ë’ø^ßIâ’øV—$qQßHâ‚$ÎKâœ$¾–Äß%ñ7I|%‰/%ñ…$ÎJ⯒ø\ŸI¢Gg$ñ©$>‘ÄÇ’ø‹$>’ÄŸ%ñ¡$þ$‰$qZ§$qR'$ñGI—Äû’øƒ$Þ“Ä1I¼+‰w$ñ¶$Þ’Ä›’8*‰#’xCÝ’x]¿—ÄaI’ÄAI�Ä~I¼&‰}’Ø+‰=’HâUIì–Ä.Iì”ÄItI¢S¼$¶Kâw’Ø*‰W$ñ²$^’Ä‹’xA[$ñ¼$ž“ÄfI<+‰M’Ø(‰g$ñ´$ž’Ä“’xBë%ñ¸$“Äo$ñ¨$‘ÄÃ’X'‰µ’X#‰‡$±Z’¸_«$±R÷I¢]+$±\Ë$±D÷HânI,–Ä"I,”Ä�’X ‰ù’˜+‰6IÌ‘D‹$n—ÄlIÌ’Äm’¸U3%1CÓ%Ñ,‰&Ip’˜&‰FI4H¢^·Hbª$¦H¢N“%Q+‰IL”ÄITK¢J~ITH¢\e’/‰q’#‰Ñ’(‘D�$ò%á•Dž$r%1\I •ÄIäH"[ƒ%á–D–$2%‘! —$íDþê>à¨v¨ Ú©åÀQ+ Þ§V‚‹Z-Ô ØN­þÌFÝ ÅOu/l§î ¶SË¡­Â'µ8jIøîrj ,¥–†¤–€—Z­Ô ©»»¸üêuOW~ˆÝC-¢wq¬!?�Z yÔbh¡„?†m§çÔbñÞÅ€p u|JÝÜB-„O©…@Á7Ô�€°Vül?�Â'58jTƒ‘Z6j�w5óÙ:Ÿ½�Êgg¦Ï¨žžÞ\Ý”ÎUOKo¬nȪ¯vÕçÕS·dM­f'œDµN:3‰š�^]�W�Ué•Õy•x¨7Š/zEuyzYukºÊpc)¶–â¡Rl)Eo)–¤W¥V¤çW{Ôí]*CÉju[Wë P·‰×¡CTó•¶äý}T x©;vd)ñ¨;ºúØKÝÕ· (ìJÀ(�!‚ A/Á5‚«]}RÙ^!ø‘à‚\&øžà».«‹ à?¾%¸Dp‘à‚ ç Î|Mðw‚¿|Eð%Ág þJð9Ág] CÙöœ!ø”à‚� þBðÁŸ >$øÁ§ Nœ$8Ñ?œ à Ž¼Oð‚÷޼KðÁÛo¼Ip”àÁݯüžà0Á!‚ƒö¼F°�`/Á‚@W\>ÀW vì"ØI°ƒ ‹ “€'ØN°�àw[ ^!x™à%‚ ^ ØBð<Ás¿%ØLð,Á&‚�ž!xšà)‚' ž XOð8Ác¿!x”à‚‡ Ö¬%XCðÁj‚  èèŠÅð~‚U+ î#h'XA°œà^‚eK –ÜCp7Áb‚Ew,$¸“`Á|‚ys ÚæÜAÐJÐBp;Ál‚Y·ÜJ0“`Át‚f‚&Ž`A#AA=Á-S ¦ÔL&˜DPKPÓSî &TTTø *Ê ÊÆŒ#Kà#C0š ”`A A1AA!AA>�— �`$A.Á‚áÃ<C»¢ÃýoAA6Á`wWty¸ÿed’À Á ‚ô.K¿pÿK#HíŠr†ûß@‚”.³0& H&H"pô'pô#°غLÙáþÇô%Hì2…û_+AAVx >¶×àc¯|ìUƒ�½bð±?|ìûOƒ�½lð±ß|ìwûƒ�ýÖàc/|ìEƒ�ýÆàc/|ìyƒ�=gð±_|ìß >öoû•ÁÇ~ið±_|ìYƒ�ý«ÁÇ~nð±Ÿ|l�ÁÇž1øØO >öƒ�ýØàcÿbð±|ìŸ >öCƒ�ý“ÁÇ~`ð±§ >ö”ÞÏžÔûÙz?ûG½Ÿ=®÷³ïëýìô~ö=½Ÿ=¦÷³ïêýì;z?û¶ÞϾ¥÷³oêýìQ½Ÿ=¢÷³oèýl·ÞϾ®÷³¿×ûÙÃz?ë]Hïgêý콟ݯ÷³¯éýì>½ŸÝ«÷³{ô~6 ÷³¯êýìn½ŸÝ¥÷³;õ~v‡ÞÏvéýl§®‘åu�ìv]#»M×ÈþN×ÈnÕ5²¯èÊÙ—u�ìKºFöE]#û‚®‘Ý¢kdŸ×5²ÏéÙßêÙͺFöY]#»I×ÈnÔ5²t�ì3ºFöi]#û”®‘ P«¼m:;û¤¶…}BÛ®׶°�k[ØÇ´-ìo´-ì£Úöm û°¶…]§ma×j[Ø5Úö!M»ZÓÁ>¨é`� Øš°4�j�_O¹âòâÊâh6Ö›KoŒÝKyc­lI«e©å}Ë ³4 71:´Ã˜–Qò:Œl¿’V4àýFýv=½]POÔÿAÿ©žöêG”ÐûQüy ®…ªT_@òûxeùdWñÎJáÓ[1‰—¯â¡zÒäšNćj;‘*¬âM®¬xݾz5$øøÄÊš.zӦĂZ¿TÐ^¯¨C‚H,¨Mm›;¯m^jj[[¦¶Í›ÛÖ6Rÿÿ?ð?mÀÿ›RSÛ"²­­mîܶ¶ÔÔ¶¹sç¥ÎMm›{=*µMˆ�¹ÂÕ\ñRHÜ–Ú Â~}~ˆ¢�£(à(Žà0�Ã^àð*px8ü8ü8ü'px8ü8ü8üpø-px 8¼~^χç€Ã¯�ÿ‡¿¿¿Ï‡??{€Ã3Àá§Àá'ÀáÇÀá_€Ã�€Ã?‡‡?O‡§€Ã“Àá àð�Àáqàð}àðÀá{Àá1àð]àðàðmàð-àðMàð(px8|8ì_‡�ÃÀá~àð5àpp¸8Ü€ÃW�ÃÝÀá.àp'p¸8ì;�C8Üþ8Ü ¾¾ ¾¾¾nŸŸ7‡Ï‡›€Ã�Àá3ÀáÓÀáSÀá“ÀáÀázàðqàð1àð7Àá£Àá#ÀáÃÀá:àp-p¸8|8\ v‡÷‡«€Ã•Àá}Àa;p¸8\. ûwIØ¿÷„ý{7p¸8_ø\öð°‡ï {xAØÃóÃÞ�ön[Ø»sÂ^m {õö°Wg‡½:+ìÕÛÂ^½5ìÕ™a¯Î{uzØ«Ía¯6…½Ê…½:-ìÕÆ°WÂ^­{õ–°W§†½:%ìÕº°W'‡=ZöhMØ£Ã�öhuØ£UaoúÃÞ¬{³<ìͲ°7LJ½9.ìÅ1a/Ž{¯$챂°ÇòÃó†=–öVnØSÃÃ^ò„½44ì¥!a/儽”öÒà°—Üa/e…½”öRFØK.àppÿ¹Þûï8jÿÓüßqÂÑ„ß]2z™hP ™P·øDWºA'ìÿ�ÊÅÌ ¢Ð J@t{� ¥[o4ˆ"Aþ8�o°0qçæ1,„¼ÞOzßËëýä¼Ùã:�®�{N÷/1y\=oœìÉÌ@“Ý$¾-zÊ¡p$»³²¢R1Û�՗¬˜h!¼ß *{ðHŠÑ_C×ô2Ôm¶‚é¥ 'Ÿ³vàØÛ¼Ž”™O4eÎL]¬ÍlfcõúXVf½rVf½šÏ4^Ý@}•^�Ÿ¼áÚòôR·•sWLïýÚ팤3›mqz ÔL�Ì Pç5«iFÅÈ”ªl ¹J­  ÞÛ‡¢iÕ•| µ‘¢(ŠQÈóe2…Ÿ 2…�çv™ÄWžÛìqM1{†º]ÆóYïr»âŽeݽ²»#Ḭ̀;h;í@w”™ºßOî=S·»¾«ûøcL ~.³^{–Ú×[,üêzýƒÌ &è )PØŸ´Ÿ9˜ñ¹]:¹Z-‡>ç5±ò�ºø§S÷¹"?ésy!ä�Ïk݃ÆÓ'{L—ÙÓc¼ôFf†XÙv“Ýf²È}iZ¬q“;k$%Éú‡Ñ+Î ¾ŒóqWÓœì[J~7¢y| +wÚ¨äÔ�åm¥»_{â1\9u7Xf þþÖõNuÆØØ;`”»opzBNEïwYåCúG΄ºÐEúsY*ô�á;ô}úÆ›²D]cw–éQo–õê؇QÐâQßIA^ïéóy½§§œGãéãéîÌ §ÜaÓà‘”;+&6z:úé©h‹Ù�•3„þü™­Á¯ƒø×ÿé¾ÉO—ŽZ?©î73†¾w´êÉQ™ùèâg‚�õ¬m{rJñòý ƒÁ`²Cø%ÿ1z›Ì *¸“V)(y_ôêjê3™L�g•ùŠBÈ#µˆÆÓ—Þ0v{23Ðn²GÛM“�ÞÖ{ŠÒ÷~»›êa–k~Ó»Wf„‚Ðú;Y:¤@Ñ‹böáfˆ%v{Uö�Ñg¢¢’ú¤0ng™ð¿4ìJ*Ðý½O‘à0¡¼¦È×õœ¼tÄ,|ŸTÒ¾”à£!&{¶Ý¤§¥n!T}aô““glnžÑ¼±%*--Åü÷¥L¾ejÚ}<^1é·g;j6Žf†'§ŽYy íÎ+J…ZŽ›éå¢úZÔUÏ_Þül¨s ÛPø5-”Cv¡JÃ(åÜâÕhäš³ªB|NåCÞù¬¼óYèºtªÛøq·P#ÙB�Ø£íÙvü0x‚ÖO`úµo1�iì±kQë×B&“-þ6´Õ›¨Ó*•µÁl¢i@¹Ì`ˆ²È˜8EåUy �П¼ñ¥`h¥B+—kÌ&�6_­Ö ‚Fèg‘^æú™9Ö3T8Ü&3zr]nw\w–Gèrqƈúš´ƒNÖ #Ê;$ÊÍdoKÐä^Èeb_ôžà=Cö|H»Ð³»÷üîíàžkŸÊ¬AË–-xNh' è‹2+èÀ³•2µFè‚2|Îk�ëòi5­V*òå……�—•—çöxîv-vÅå¡«ÇÕ“eòx#�ŽG‡É�Qñè¦/~\~û–³xÛò-´ å½³ƒSeÖkׂ§¨×°M‘<¡ ŒK–Q� ý_‹ø�}ñ9¯Z= þo†ÇW2±ÉˆMÅ%Œ¥J�¤U˜G¢0€*¢nl:Œ«rõþ™÷ì[4¿úµ™÷ì[œ»Ç1~ÑĪ…ã“ú�»kBÕ]eIÔc|^¨˜¼õŸOmCx¡¢î•Ë/´ì[ñÀ¾™sÞ?¶â�½ÂFxè}V–ÙPÒ™û°¢ »w¨ûä$íE$‡yµ¦˜Òä�_¦GÉìêÆìÔèÿ.‹tk³ÇÓ{:U°¼»çä¥îÈ�Ôo•œÝK³’“ÆÝ—"]]mé+§ÏŽ]u°mðô[ªúùö-˜°pœcxý¢¥‹ê‡�¿g©}\Ù8û¸'KŸX ÄÆ)N¤ÔU[ûجÙc3³}Ã3çV¶Ž+¼·i¤\£WnЉmž�=vDæà‘ÕÂ8% ä�2+(!ÓC14*Á&—«ÔrJÉÐùHB>äå¹ó„–'´·x—0°»�e¹33Tè@7Z™Æ`ÑÅàø·0¡Ü�V2][ "Eß´‡.Ð‡é ØÀ¾�ÑÑ*·Ruöä¾í5¨2´ï¢ úa¿~ ¶ŠèR^•ÅôcByÚeÆO†¡þ„ù… Ý=“Ç•™aO–¼Ÿ3³'9úÉÙ#i¡£MôOÍ gídü/M™pW™³ç/ïÏ™Wý|�½bRcÖ䇛r¶œ?uD¢y€wЈ§&¬¬(M7#÷ñWjjoKr<£�5køWõŽÅ·2 &f§Ä�. 6…¾£¯ÈÚ! ’ ³SÃîÃí À^£E™¬•Å÷ÊU•ýN(e~ÈsŸTqN2þäú¤d“Û¤øy³U˜Hc ¯/Ù=§vïämJß+�î­IëŠÍŸc/]1È}kƈٕ™”òî7îÝÏ)\´·©²tùž»ÊVL͎άŒ·Ä&Õ>BßÒ[é+�C» +ìxËûê¨òª–Ð`þQST¼Úšˆ‰ Wh?ˆÃñõ9è¤0 u Ù7ÏA1bµn-Z3öB04æ¾½­ãW�Ì_YZ¸`ÒàÎgFµ�t&Ä#õÂßwøbâ·ôcÝõwï²Ù€‚ÙBk�µƒì0¸S«š‚ÒÀ^ôSêdqWŒ~M…º’ý^V.¸_¬=�äùÌŒ¨ˆ-&·ÉiCˆ=&±ÛÌ.Y¶«%cJúö§å£_ž6aùÄ´®Û ©H�á~h#ö,=zÿ(­·\YtàÖæÒå�E»wÌŸ‹´D„1h^è}‘Š+ï­6¸{�ÂðUotô@öØf`ÿã åºSZÅe£ŸôpaΫíR·ñã±�¢E®° ¦�¤†DKm•tqENÄãôEŠêÍÛº9­Æï³�ÚQ¿lïOî¼—gÍÜÜâÙEÛ ¹ÏÔ¢�2*Õ™óäó ­AµÆ_Ò~ø®[÷¯©*Xø;aKyzZyk!�ÿd¬²uÈë”)Øåµê5­b´ÑzÙe�A©4©£®uÙT¥®€<Átaúõ¸Ïg¡ñˆñô{f�«[\3%9ú%bdÞ϶gíY±ÈXïŸö5‚¥�ÁýXˆ›gÜsõ,óyâe~]ïê­u[p]\°MXÃM Ö1:Ãa,ÔÃê×@��ã°óÕLФљÃévzuûgNLÉœ813…¶ÇîÃw¡Fà;Þ${ƒ1*XRZâGÙ¿$�Væ@ –(K” 9ÃO+«{'§<ïxŸ âl�'ÀãrM`òÏ›ÜÂ"Th/=æX�Ëå2™=ÆKG̱c�Q˜6úbt¤ ê1Ú+ëKÿ´ìÎ2ˆ–>IC³G#qböà¤d§žŽŠL.Ù‘^K·õa=3ÖM̻ݕ0z*}K&»‡-Ü»ô®WnÏ*•�§Í•­ñL_Wã,JÀY½ô£+*ï(îËM^±§Æ©³mÃÊ2W I”HOuLÉ¿¬ÎmµôÉb“²(5ÕÏ;udá�“s’‹oñŒ¾Ý­íŸš›?+#6Í=tÍ4*¿ofž=w˜L305•f3ʇ²Žã ì?|¼0³o �ÊÚ!\��0rip»×€Úx£Fv5º\_©©¡mÜ4nÙ&a�†)‡8vÑhú趉ŽÜ‚ñîmÛä)eeþ´Çž£–Ím‹r•�èm–µ§oÈ,h~5”¸Ò:.[*H„ü×À€½ vzõ*T¡J®è˨.+*ÔàU[¼FK©¾§Ë ïü'©çóD§\m쥄e¡¸‹†üœðrðüS¯}„cr³œÑÑάÄ麵מ_·NÑI™‰}²’¢£“²ú$f&E˃uô Ù:ˆV²¯�{Á QØù*¨-M媪v© ?Ê'Ĉ&ÚmQ߃d"éMh<}äcb¢)ÒвûÒl“=o²•.ÑúÛæ1«=ì(ߨþsî Z(÷Í&Ÿ»–4ó·­Ã¬q[Œ fÕÚéòµø¼d·T@Ø À$ËÚA {@‰çv¨T >€Ÿ€hÜ.LöxÉkDF£*£Ô š‘U2O›c=yO¿qÆìVWvŠ~F72ÉßÓ¶mÃ׿¦P ½_ÈÚ¯=�ï3!²z>.kž(öˆ¾4E|©} §èJ±›Þà¼]w£«˜Ëk®j× ÿ– “-„t(íLŒþäš CéNM·{cuºA.ùå�åQ—û•':¬e :©Õš=2, ÇuÉs²ÇxR˜7ì¦ë³¬ãFéŽ% YøŒGz–Âk²ôKvÙ6* q&³-9þ©]™�9xxÿŠª¸AÙÞ�û©ã®}\Nm~ï"êÀ�¢$½eð¤’ÞEô¹ƒžòÌØ[[„>ü¸×)õ7:±àê¤b„þ ¡¿icã(ˆ­ÐT¯*Ê…$ÌuR':É2Ó oÓSŠ4™?í©�Ûj&Úr Æel£Ïm\<Ðôj ÷jÙü;HÇ êB5”ÖÓ€;À}q‡¸žþÑPîøA濾ž[ë ÍòWWÓê‚Å]wÌzeAžÄ®”±³ Ç·Œ²§Œ�U$ƒó^`\὇îžwø�q…Ë­˜òÀWnóÊ1S)¬ž‚Íô:pÂÐ:µM)8V�â Z©KÒ&ô˵eªjÇ bbäÑÕ#<”ŠÏˆÒ"Jt௬¢rè+¾;gfÜ’¹í)�ïåi?_EeÜê^½‰RÞ÷抵6X'»ïÅé¿XC„·¥X‡Y�”yvŠÏµ�^£*ÊB™”JˆªÐ^•Iî&Ò›ˆî¬…#Grß[eµ¿«yúY9OW–;Fùª2xúÜžÛêß>ºbAü� ¹½‹„Ö¿;t�ÞG!*÷@îØeíoí¯†îÚaRç8ö"@á�Ã_Ú?ù²)Ma+WPæUoÔl×Pý i)÷Ós‡°!âq‘Ç&=CÆ$¡š„Y,ù§É.ú§gïØ¾4½¯ÿHÿ”FWó+þšmî¾3*kæä¢¶ªŒä©›î¾v¼ÿ‘œüÚ!qÑžfí]cíhήÊÔWo¶lŠO(ʳ¦&´ZÜ%S½¹ �ñ)K”Åá²ZÓRRâ<%5BIóBßÒoÉÒ!²;�:¡gǨ e¬A§0þS«Ö•ÁÕXËtd‘å>&Ž#'»Í£¸J—§IÙâÁq—"²4}kø=ùû÷¿Äømøz0·­5cÎH½A÷J'¥}-éÁƒ©Y·ŒB ] �Òç Ò;)z¨t¸Ý«WÇR]¦-3\QøÅ¡Eê =d@q$ ›IÙ&·ÉB6*ÜôѧåéåéOmض͖[8.c›Ø9w¨µ½÷|å*Ï¥žvL˜Dú(Áã5Èä6¥‚¦Uê»h¤¡÷½*Z¡¬�ËeBÃÊÊrå¹=C§�ç/²µv,Kh^âƒ=: Ž\ÎòÝÁàü7és½36o¡½f'S þëZo²Œ‘˵Z�B­ÖhTJM&#ÍP”Á`4šA¯c˜(‹ž±©„΀)t ¡3  �ñÆjŒZƒIÍ(t:…JY&WTPXa­ž Å�¿÷#âÚ�0¹Mf�Émº¾/a"§Ø{…½ aƒ‚Aø` >±.ÑþÀ±u/W™S¾û™tÃxúÜ5 >×<+ØHŸë�°¾_¶¯¦¶ -§€I¡Ï�Nt:”�ÐWÞ¾es èhF«R {˜e …¼Œ¦™ DÁB=’ºÜ.·ñH–ñH–Ï_³“B¹š6X½ZQ¨)”;ühL]©ï6Þ½RÙ] C…T2”«!•(T²›S i”  iD¡R‚Âá‡_ä¤ù>Q¨57§Ú– *t«„Ù7åËà¥àw=Ø\ý)*‘þ ¸——áø]ð¼7(ê<õYÿgú=lGè÷¨ãƒ¿:þ|ʶב÷½8õ^Ü-¼ï nÆ©ÁÍ€°€>+³ƒ<;ä¨Vð€W£ i�V~^&C&€}v(Ut:‘#;Ò¾¹XÅîžî��df¤`¶Ý$KvºMvúìµw°> endobj 359 0 obj <> /W [0 189 549.80469] /DW 0>> endobj 360 0 obj <> stream xœ]’Ïnƒ0 ÆïyŠÛC•X[$„D¡HöGc} ‹4 é�·Ÿ°»VÚ!D¿ØŸóGäUQYã¹øp£®ÁóÎØÖÁ<Þœ~…ÞX(Þíï„_=4yUÔËìa¨l7²$á\|Bofï¾ÉÚñ [&Þ] ÎØžo.y½e¢¾MÓ `=—,My ùk3½5p�²]Õ‚õÆ/»K^?3¾– ¸BÈ�[˜§Fƒkl,‘RÊ”'eY–)Ûþ‹Ç¤ºvú»q˜¦<‘RÉ)GŠb¤`�ôÅD{¤#ÅTND1uFŠWj¬”�)v@:eD!º»û8ü¹z6aš¤[¢€ÜÑ-’JDd$�H�¢ÃÃ{'Üö$� j€Jy-‘2ª¢Žd’ä'„ÁÝ+¹[ê:üÇÄôÍ9°_Ni��±ðxDÓ8­ªuýß“«z endstream endobj 151 0 obj <> endobj 361 0 obj <> stream xœíšy|EÚÇÕs䜃ˆ‚Œlua“!@@ "LN#B&Dg0ÂdR A‘d™€"(QA0.Š¢^ ë}ÑP/`EÅûD×uPQw]YȼÝýL±x¼ûÇûîûîûy?Û$óýÖSÕÕÕõ›ŽÀ‰X�P[4dÌÛs¯Ø;¢�4´a Û°•F6ÎiW?®Üz�õ)`Ëkn›v[é| p~dõšÖoC_xìàž6cnóÖóßÿ5`ݰC-M bïs=?XÀ)--M 9×Yzl$€“Z.h¿Èñ¶öÝ€r`FkcÃÀþþ÷KÀ.½ á¢6Gˆmp€:³á‚¦c‡ Ú (C6¢­5ÞÞý=®Ø FÛ¬¦¶_‰�Þn w d#Ç #•‚ ƽ?ƒØ� Ü(B�›‡·¡˜£Í£û–æè °í?¼ŸM±6§¶¥YÏûÙ˜§©òYSáÒíES]#¿ÍÌÊ4;žüÄókƒ[½80µ­»Þzžý™PŽšÝbž� +™}Ô«bÖ¤R¦ 6,õ ®N5um‹µ™-ƒ ™¶›mÅãDË›hV�™¥äسÅjQ¬ÆØ£—;¾VU€Š5t_õŠ"ïÜ²Ûæ1¯iœ‘�ÉÆê¬Yæ§�V@®À‰™i·`F¦Ý 7 ÓnCá‘ñv³~š0 qLG+fBÅ D AEfc:f@˜w=§ ÜG+f qŒÇt4bZÍZ3Ú1êÏF�0÷oaBhÂ4Ì6{fáþ#=áþÂl4×,´™¯ hO¯r T”bf@EÓ1 -hGÜl5!nÞÑ4A` ¹?óþýë_òk-ºX¬N›d€c0ê7ÀËV%ü.G’ ]ïvgöÉx† �‚cX™`¬8à¶*Ž•nwÿãWõ±ßd)u©IÖw}ë VŽÑ‡?:üÚèÃíÉ+)ÚÊ>ÜùîN÷þç{”í|î��ƒ±ù=ÌïžNÅ›á=¹xȰ¡•6¬xȯ6ä¸c�ú‰•aCG)Vç¡q–ða«r¾Z6­Ú*ì³–ýúŒóÞÓW5 îNú;z©yy¼—ÓÙ‹Ûþ_Öf,6žG c†åÔîúŸt‡ÐŒ8:±÷`ËdÅl<âX„5x›ñö1;ëËÎøg¬ÄæA�úª{Aê`j€íëî]Ýõö^)»í½TOËnê³-Bnwsê@÷‚î÷S¬Ïv×§`oN HíSÈ”3Xç!/5 õ�­Ù¶ÈvŸíMË©ÝÌ;¼ý¿°¬ña*šÐŒóÐŒhÃy¨Ç¹˜�éhÃoG;æ`..Æ<\‚™¸óp).ǸKÌ?W\˜î]€Ëpã*\�ßb)®Áµ¸ —cc ®NW®ÂR\kŽ5æX„+Í3:�:ç:,Ç ¬Ä*ÜŒ[° ×áz,Ç ¸+pÓ‘ú­¸Íùãú­ÿpüíX�5¸wâ.܃ûðI×þ^ya-ºp;î4+�`¶a'ºq‡°ûY&Ëfy¬+f§³ñìL4¡ÅÜ¥zLÁLÌF+æ n®c:°È¼·KÌ=X`î™±?´Ê˰0½KÌ=øû\o®%n7×µ«ÌõÓÚgÖèþ~~wFïÝGúéþï<2æ~< ¬Ãz<†ÇñÁZ$°�â!Ü‹ûpzGÆ#ÐЕû¨9ú¾£úÖþ¬7‰'ð$žÂÓØŒ$6à)óUÖžÁ–t›Z›ñ,¶à9<�ð ^Å6¼‡°/ãM¼…·Íöûø_álÇçØ‹±»ð¾À—Ø�¯°û°p‡Ð�CÌnæägyìxÖ—ùX1+ùç<Éÿ+ÇŠŸ—”{EùîpwÆ‘O1Û"ÛrËéÊ@jêQ�kº�¿UæÚÙsl?Øö"Ç6 Ù6�òZê{Ûþ)²ì=­Ç¦àlÄ€À1uʹõçLŽ„ë&Õ†j&N8süÁqc«ÇTUV”—•F�:}äi#J†Ÿzʰ¢�þÂþý|'yOä½{öp»9ÙY™v›Õ¢0Vz«¢ªÖ/ªYûy««ýFÛÛ jýŽ*D5µAÕª~÷·0Ô¸Å#Û¤±éÐ2Ê5»qùùÆZ®Nóæk5aj«ˆyD4%jôl’=ÇÖ=²çÈéQo¾Ue4ý5§¥·ÖSý…šµŸùåÓ¬¾Jo¥ªYúEc�-š:½´o“ÂZ B­Ô é{­ìTTé­lˆj,:ÝØ†š°VämÓzzËh@°&¬L¯ ›§¤OÓz–kˆ6¦ÏÒŠ*+Œu©•�Ñ Z 1—·&¼Å©]CUϺb EÄX‡v\yX³ô«ì ‹f�G=BS£ÍjØ“¯"kˆxÃM#%¯[°Ã“o‘ôYV_åOFËÁÆ�gø2Õ°â±DŒ´4«O­Ò¬>oÙH-ÃçÖìÔ4-©†™r˜6`Gz„a?šÇêÓ,¾òj£ËbœZ^íÉ�äÓñ–äI¯ÉæÓ2�šË­Ùþ¾&ºÎº4m,h€ZÙTqÔ4©-½Àôl¿¼NÅØ‹ô…5›/Óˆ³ZvY|ªfõejН¼Ú,)öV5LTÃÞ&oÄÛ¢j�‰aãÞŒ½6ó Özƒ5“ÃfÚéwɤµ¨ø‘¾´iJù¤°VUà‘™ší1fûH³ú'Ýce·Ú™é Öv3{ÓBM `ñiö~c®ž7Ô_Ȫ¼UQoUƒWu«U� ÉTG¬³+èl«Œ¶Œ0æðŽ�ÞÚðH�¹´PøÏÅÆ¥òdÁIeþÂ.e]^¶¤¦+À–ÔNopê’Iá„”òhY¤ë$¶¤&¼AfU1ªFÑh¨FØ)N(™æxφÐaöZÍ‚ÙnL2˜µLYchL*TsËš‚Ƥ•j³fþÂÊÞ-Þ ñY[© #›ù‘–ÎhÄx²pœ¦ø4ÅÇ4æMñŽêbŠ=WËö6•i9Þ2£>Ú¨�¦ºÝ¨gxË4vóªÆRgÔój¾0<ŒÞ‡cJ5™JM ç¿êÙÉ×ì¾zÍî›Ö² "ªfó�Ó¬¾1ÆwT³ûÆh� Æ:P6ÎÍð�mŒh™G&Ôì¾±Z–¯^ËJÏ eøªÌsŒ÷"êÂ�žüHƒ×T­£Ñ“¯uD´H�qÑðôˆù^vk¨öŽÐìýhN[?ãBE‘Î<ïóÁ´û´lßbY¾qjÃTñhYÆr"´I¹šÍ×èÕì¾Æ¨º!+kÃùéÒlUšjšµ_“ù�íIw¸-‹/Ç‘­e Ô2Œ9 Ïh<�6_F$B‹7[‹Ó´,Ÿ[ËñiYýŽÚÊô Z¦OËñ�5Ö¢Ù}‹µlsèfcšš$BÞ‹4fî¨9S†–íÓ¾± ZGŒÎÏѲ}ÞáòäLã"'=Ǫfwžë«Y|“’©{½só�:ü…^ãwã� Ï €HçO Ú9þÂÌŸVf¹³3ÓñË'Ð~e:ŽÐ(ª•Ó+üØU±¬ÏêÍÆ©IE‘¤ -,%¥[Êa)¥ü å{)ßIù›”R¾•òW)ßHùZÊ~)û¤ì•ò•”=RvKùRÊ_¤üYÊR>—ò™”]R>•ò‰”�¥ì”²CÊv)IùPÊŸ¤| å�RÞ—ò)ïIyWÊ6)ïHy[Ê[RÞ”ò†”×¥¼&åU)¯HyYÊKR^”²UÊ Rž—òœ”-Rž•ò{)›¥l’²QÊ3Rž–ò””'¥)÷J¹GÊÝRî’r§”;¤¬‘²ZÊmRn•r‹”›¥¬’²RÊMRVH¹QÊ R–K¹^ÊuR–I¹VÊ5R–Jé”r•”%RK¹RÊ") ¥\!å2) ¤\*å)ó¥Ì“2WÊER.”2GJ»”¸”YRZ¥Ì”r�”RΗrž”éRZ¤L“Ò,¥IŠ�Ò(%&¥AJTÊT)S¤œ+¥^Ê9R"RÂRΖr–”:)“¤„¤ÔH™(e‚”3¥Œ—2NÊX)URʤ”J H-åt)§I)‘2\Ê©RN‘2LÊP)ÅR†H,e�”")×Rzªr%„²u€²L¹BYˆ:¼¡,C‘²­ÊB¬U?¶T.Ã>óµH¹k•Ë¡`­büØ¢ÍxU: ”úÙ•èP?V  ,@›²å’„(­K*—&JS|ƒ2O™ŸÜUZ¨ÌÇhe>Zã¡k•ùØ®Ì7Ï�†©ÊÅØ®\ S•¹Ø®Ì…‚½ÊE`Xf¾¶š¯nãU™¡\ˆ:¸• ¡*f+³X)oµ”ò™J)Ÿîo©›æo®kò‹ºF¬®aH´®(::ªL2¥ŽOÞ8Yi›¼c²r–¿®nt›ä¯­]Ë6Õ²ÕæWÈ_S7Ñ?¡®m+šÀVW³¶j¶©šµV³@5«òWÖUøËëÊü¥u�¤23‘åªÚ ÌPÎO á�¤r¾ÙNmRš×eåV½ñ¤C@ùͺÁ§V’Êo'äW%KâW'ò¤¢X¢ožT`‚¥݄ÄC„ƒ‰ x’ý@øžðáo„„o MxŠx’}Cøš°Ÿ°�°—ðaa7áKÂ_&|AøœðaáSÂ'„�}†ó$ÛIØAØNøˆð!áO„$¼Oøá=»„m„wo'Ž?�'Ù[„7 o^'¼Fx•ð áeÂK„ [ /ž'·•_—ÛÊ—å¶òks[ù59�|iN'ÿmN'w÷am}:ú(mÇw¯õÝ{Bo ïUÔkt/Ëê^k{)�^^ÕÖ³£ç=wô´vÃÖ¸Y2µi�»pPU2µ)àuó«Ú\l£‹]ë\í\ë´¬unt*�¯;·;-稲*ËÓÌü¯†`l&“©PPËœxŽÆ–h¾Zã5P3Y³/ÑP7ùœpc×Dº˜R>Iëaü«¬Ù^´t)ú–µ¾µá„eÍš¾e‘ Öax `zÊp oY¤ Þ>;>»  �³‚øìöx¼ÿ÷ö¯^ÀÿÌ�‚‚xZãñx{{<^PooŸ]Ð^o?ÒU7zÍ£Ýhµ›Mcp¼  ƿח¦ „¢@( BKA°nv‚„`?@°ï!Øwìoìû‚ý‚}Á¾†`û!Ø>¶‚}Áö@°ÝìKöögöû‚}ÁvA°O!Ø'ìc¶‚í€`Û!ØGìCö'öû#{‚ý‚½ÁÞ…`Û Ø;ìmö{‚½Á^‡`¯A°W!Ø+ìeö{‚m…`/@°ç!Øsl {‚ý‚m†`› ØFö {‚=Áž„`O@° , Á‡`�A°G!Øz¶‚% XÓ ØZö0{‚=Á€`÷C°û ؽìv7» ‚Ý Áî€`k Øjv»‚ÝÁn†`« ØJv[Án„`7@°åìzv[Á®…`×@°¥¬‚]Á–@°ÅìJ¶‚-„`W@°Ëô|èù^ªç{ ›_j¼ÎÓž«'|‘žð…zÂsôtÛõtãzº³ôT[õTgê©^ §:COõ|=ÕóôT§ë©¶è©NÓSmÖSmÒSzª�zª1=Õ=Õ¨žêT=Õ)zªçê©Ö멞£'Ñ 뉞­'z–žh�žè$=Í�žf�žæD=Í zšgêiŽ×S§§8VO¯JO¬LO¬TO, '6ZOët=©Óô”Jô”†ë)�ª§tŠžÒ0=¥¡zJÅzJCô”ë) ÒS*‚`!þuOï?ãˆü«ðß;zÿLó endstream endobj 362 0 obj <> endobj 363 0 obj <> /W [0 189 549.80469] /DW 0>> endobj 364 0 obj <> stream xœ]�Án„ †ï<Åwн“.Æ„C»›Ú}„Ñ’Ô� |ûFÖØ¤ Ã|ÿðós©E.Do:L08²g¿DƒÐãèˆ%XgÒ^åÝL:0.UÓ­sÂIÑàYUðOݜ⠧7ë{<3~�££NOÙ�ï–~pBJ X]ƒÅ�qù®Ã‡žx–]”EJ.­—§ìþˆ¯5 ”¹.^nŒ·8m0j‘UBQCÕ¶m[3$û¯¿«úÁ|ë˜ék •¥Èô~PÇÐ›ÌØ­ÉǵØéW{f‹ãøƒYbDJ9³ì{sì�Xƒ›j[¿#d|Ë endstream endobj 152 0 obj <> endobj xref 0 365 0000000000 65535 f 0000000015 00000 n 0000716786 00000 n 0000000310 00000 n 0000739552 00000 n 0000742650 00000 n 0000745717 00000 n 0000750159 00000 n 0000753781 00000 n 0000759791 00000 n 0000766575 00000 n 0000768828 00000 n 0000000347 00000 n 0000773430 00000 n 0000780751 00000 n 0000792659 00000 n 0000796848 00000 n 0000800453 00000 n 0000000427 00000 n 0000000505 00000 n 0000000952 00000 n 0000001819 00000 n 0000000583 00000 n 0000002238 00000 n 0000717201 00000 n 0000006208 00000 n 0000021759 00000 n 0000024763 00000 n 0000030521 00000 n 0000032762 00000 n 0000717519 00000 n 0000805178 00000 n 0000812806 00000 n 0000036577 00000 n 0000036225 00000 n 0000087147 00000 n 0000087340 00000 n 0000087625 00000 n 0000087812 00000 n 0000717892 00000 n 0000092125 00000 n 0000099795 00000 n 0000102558 00000 n 0000104217 00000 n 0000114562 00000 n 0000116912 00000 n 0000117099 00000 n 0000718275 00000 n 0000819314 00000 n 0000120105 00000 n 0000132745 00000 n 0000136818 00000 n 0000137033 00000 n 0000137315 00000 n 0000137591 00000 n 0000137792 00000 n 0000138175 00000 n 0000138564 00000 n 0000138828 00000 n 0000718700 00000 n 0000143270 00000 n 0000151284 00000 n 0000153775 00000 n 0000163280 00000 n 0000166687 00000 n 0000719030 00000 n 0000170159 00000 n 0000179576 00000 n 0000182917 00000 n 0000192514 00000 n 0000196125 00000 n 0000719372 00000 n 0000828369 00000 n 0000198595 00000 n 0000198834 00000 n 0000199068 00000 n 0000719738 00000 n 0000201973 00000 n 0000213033 00000 n 0000225701 00000 n 0000720056 00000 n 0000229220 00000 n 0000243782 00000 n 0000250749 00000 n 0000270762 00000 n 0000282857 00000 n 0000720362 00000 n 0000284937 00000 n 0000289388 00000 n 0000292362 00000 n 0000297009 00000 n 0000300612 00000 n 0000720669 00000 n 0000831299 00000 n 0000302983 00000 n 0000720976 00000 n 0000306561 00000 n 0000390351 00000 n 0000721271 00000 n 0000833422 00000 n 0000393073 00000 n 0000414491 00000 n 0000422166 00000 n 0000422402 00000 n 0000721647 00000 n 0000425883 00000 n 0000721956 00000 n 0000429661 00000 n 0000439795 00000 n 0000442070 00000 n 0000455660 00000 n 0000457912 00000 n 0000469806 00000 n 0000472072 00000 n 0000481565 00000 n 0000485890 00000 n 0000500144 00000 n 0000503185 00000 n 0000722323 00000 n 0000506085 00000 n 0000515610 00000 n 0000518098 00000 n 0000528407 00000 n 0000531142 00000 n 0000722636 00000 n 0000533892 00000 n 0000551401 00000 n 0000557672 00000 n 0000568529 00000 n 0000573506 00000 n 0000722949 00000 n 0000576027 00000 n 0000592135 00000 n 0000597806 00000 n 0000612883 00000 n 0000616214 00000 n 0000620298 00000 n 0000621821 00000 n 0000723276 00000 n 0000624356 00000 n 0000627126 00000 n 0000661835 00000 n 0000674138 00000 n 0000693790 00000 n 0000701404 00000 n 0000723603 00000 n 0000842139 00000 n 0000850589 00000 n 0000861989 00000 n 0000872811 00000 n 0000883103 00000 n 0000895449 00000 n 0000902258 00000 n 0000703746 00000 n 0000703967 00000 n 0000704196 00000 n 0000724036 00000 n 0000708370 00000 n 0000724429 00000 n 0000713021 00000 n 0000724774 00000 n 0000724896 00000 n 0000725021 00000 n 0000725144 00000 n 0000725220 00000 n 0000732371 00000 n 0000731135 00000 n 0000730882 00000 n 0000725343 00000 n 0000725264 00000 n 0000725492 00000 n 0000725412 00000 n 0000726031 00000 n 0000725561 00000 n 0000725944 00000 n 0000725641 00000 n 0000725742 00000 n 0000725843 00000 n 0000726360 00000 n 0000726110 00000 n 0000726291 00000 n 0000726190 00000 n 0000727345 00000 n 0000726439 00000 n 0000727226 00000 n 0000726519 00000 n 0000726620 00000 n 0000726721 00000 n 0000726822 00000 n 0000726923 00000 n 0000727024 00000 n 0000727125 00000 n 0000727504 00000 n 0000727424 00000 n 0000727653 00000 n 0000727573 00000 n 0000728083 00000 n 0000727722 00000 n 0000728004 00000 n 0000727802 00000 n 0000727903 00000 n 0000728242 00000 n 0000728162 00000 n 0000728391 00000 n 0000728311 00000 n 0000728540 00000 n 0000728460 00000 n 0000728689 00000 n 0000728609 00000 n 0000728838 00000 n 0000728758 00000 n 0000729158 00000 n 0000728907 00000 n 0000729089 00000 n 0000728987 00000 n 0000729318 00000 n 0000729237 00000 n 0000729468 00000 n 0000729387 00000 n 0000729618 00000 n 0000729537 00000 n 0000729768 00000 n 0000729687 00000 n 0000729918 00000 n 0000729837 00000 n 0000730068 00000 n 0000729987 00000 n 0000730503 00000 n 0000730137 00000 n 0000730424 00000 n 0000730218 00000 n 0000730321 00000 n 0000730663 00000 n 0000730582 00000 n 0000730813 00000 n 0000730732 00000 n 0000731220 00000 n 0000731247 00000 n 0000731274 00000 n 0000731301 00000 n 0000731328 00000 n 0000731355 00000 n 0000731382 00000 n 0000731409 00000 n 0000731436 00000 n 0000731463 00000 n 0000731490 00000 n 0000731517 00000 n 0000731544 00000 n 0000731571 00000 n 0000731598 00000 n 0000731625 00000 n 0000731652 00000 n 0000731679 00000 n 0000731706 00000 n 0000731733 00000 n 0000731760 00000 n 0000731787 00000 n 0000731814 00000 n 0000731841 00000 n 0000732467 00000 n 0000732681 00000 n 0000738614 00000 n 0000738865 00000 n 0000739210 00000 n 0000739700 00000 n 0000741839 00000 n 0000742049 00000 n 0000742272 00000 n 0000742805 00000 n 0000744927 00000 n 0000745137 00000 n 0000745360 00000 n 0000745872 00000 n 0000749321 00000 n 0000749531 00000 n 0000749754 00000 n 0000750314 00000 n 0000752961 00000 n 0000753168 00000 n 0000753388 00000 n 0000753933 00000 n 0000758840 00000 n 0000759088 00000 n 0000759444 00000 n 0000759936 00000 n 0000765519 00000 n 0000765770 00000 n 0000766204 00000 n 0000766724 00000 n 0000768066 00000 n 0000768276 00000 n 0000768499 00000 n 0000768984 00000 n 0000772599 00000 n 0000772809 00000 n 0000773032 00000 n 0000773586 00000 n 0000779845 00000 n 0000780055 00000 n 0000780278 00000 n 0000780907 00000 n 0000791784 00000 n 0000792028 00000 n 0000792257 00000 n 0000792802 00000 n 0000796037 00000 n 0000796249 00000 n 0000796471 00000 n 0000797003 00000 n 0000799581 00000 n 0000799836 00000 n 0000800074 00000 n 0000800606 00000 n 0000804338 00000 n 0000804548 00000 n 0000804771 00000 n 0000805334 00000 n 0000811993 00000 n 0000812236 00000 n 0000812482 00000 n 0000812948 00000 n 0000818252 00000 n 0000818504 00000 n 0000818939 00000 n 0000819462 00000 n 0000827504 00000 n 0000827748 00000 n 0000827977 00000 n 0000828512 00000 n 0000830515 00000 n 0000830722 00000 n 0000830942 00000 n 0000831452 00000 n 0000832659 00000 n 0000832875 00000 n 0000833101 00000 n 0000833581 00000 n 0000841245 00000 n 0000841494 00000 n 0000841728 00000 n 0000842288 00000 n 0000849759 00000 n 0000850003 00000 n 0000850231 00000 n 0000850733 00000 n 0000861138 00000 n 0000861382 00000 n 0000861611 00000 n 0000862133 00000 n 0000871905 00000 n 0000872149 00000 n 0000872378 00000 n 0000872955 00000 n 0000882274 00000 n 0000882518 00000 n 0000882747 00000 n 0000883247 00000 n 0000894566 00000 n 0000894810 00000 n 0000895039 00000 n 0000895593 00000 n 0000901470 00000 n 0000901714 00000 n 0000901943 00000 n trailer <> startxref 902402 %%EOF flaky_tests.txt000066400000000000000000000010041524103652300141430ustar00rootroot00000000000000AllowedShapeTests/S2ClosestEdgeQueryShapeTest\.(CircleEdges|FractalEdges|PointCloudEdges|ConservativeCellDistanceIsUsed)/(-1|0) CompareEdgeDistance\.Consistency GetSignedArea\.ErrorAccumulation IntLatLngSnapFunction\.SnapPoint S2Cell\.GetDistanceToEdge S2CellId\.MaximumTile S2ClosestEdgeQuery\.IsConservativeDistanceLessOrEqual S2ConvexHullQuery\.PointsInsideHull S2FurthestEdgeQuery\.PointCloudEdges S2LatLngRect\.GetCentroid S2PaddedCell\.ShrinkToFit S2Polygon\.TestApproxContainsAndDisjoint SignTest\.StressTest pyproject.toml000066400000000000000000000041021524103652300137700ustar00rootroot00000000000000[project] name = "s2geometry" description = "Computational geometry and spatial indexing on the sphere" readme = "README.md" authors = [ { name = "Dan Larkin-York", email = "dan@arangodb.com" }, { name = "Eric Veach", email = "ericv@google.com" }, { name = "Jesse Rosenstock", email = "jmr@google.com" }, { name = "Julien Basch", email = "julienbasch@google.com" }, { name = "Mike Playle", email = "mike@mythik.co.uk" }, { name = "Phil Elson", email = "pelson.pub@gmail.com" }, { name = "Robert Coup", email = "robert.coup@koordinates.com" }, { name = "Tiago Brito", email = "tiago.brito@90poe.io" }, { name = "Zachary Burnett", email = "zachary.r.burnett@gmail.com" }, ] requires-python = ">=3.10" classifiers = [ "Programming Language :: Python :: 3", "Operating System :: POSIX", ] dynamic = [ "version", ] license = "Apache-2.0" license-files = ["LICENSE", "NOTICE", "AUTHORS"] [project.urls] Source = "https://github.com/google/s2geometry" [dependency-groups] test = [ "pytest", ] [build-system] requires = [ "cmake_build_extension", "setuptools", "setuptools_scm[toml]", "swig", ] build-backend = "setuptools.build_meta" [tool.setuptools] zip-safe = false include-package-data = false [tool.setuptools.packages.find] where = [ "src", ] namespaces = false [tool.setuptools.package-dir] "" = "src" [tool.setuptools_scm] # The same as the default. See #450. # https://setuptools-scm.readthedocs.io/en/latest/config/#setuptools_scm._config.DEFAULT_TAG_REGEX tag_regex = "^(?:[\\w-]+-)?(?P[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$" [tool.cibuildwheel] # we only need to build with CPython 3.10 (because of the limited API / stable ABI) build = "cp310-*" test-groups = ["test"] test-requires = ["abi3audit"] test-command = "pytest {project}/src/python/s2geometry_test.py && abi3audit --strict --report {project}/dist/*.whl" [tool.cibuildwheel.macos] # delocate is not needed because BUILD_SHARED_LIBS is OFF in setup.py, # so all dependencies are statically linked into the extension module. repair-wheel-command = "" setup.py000066400000000000000000000025301524103652300125710ustar00rootroot00000000000000from pathlib import Path import sys import cmake_build_extension import setuptools setuptools.setup( ext_modules=[ cmake_build_extension.CMakeExtension( # This could be anything you like, it is used to create build folders name="SwigBindings", # Name of the resulting package name (import s2geometry) install_prefix="s2geometry", # Selects the folder where the main CMakeLists.txt is stored # (it could be a subfolder) source_dir=str(Path(__file__).parent.absolute()), cmake_configure_options=[ # This option points CMake to the right Python interpreter, and helps # the logic of FindPython3.cmake to find the active version f"-DPython3_ROOT_DIR={Path(sys.prefix)}", "-DCALL_FROM_SETUP_PY:BOOL=ON", "-DBUILD_SHARED_LIBS:BOOL=OFF", "-DCMAKE_POSITION_INDEPENDENT_CODE=ON", "-DWITH_PYTHON=ON", "-DBUILD_TESTS=OFF", "-DFETCH_ABSEIL=ON", "-DWITH_PYTHON_LIMITED_API=ON", ], ), ], options={"bdist_wheel": {"py_limited_api": "cp310"}}, cmdclass=dict( # Enable the CMakeExtension entries defined above build_ext=cmake_build_extension.BuildExtension, ), ) src/000077500000000000000000000000001524103652300116465ustar00rootroot00000000000000src/.bazelrc000066400000000000000000000004311524103652300132670ustar00rootroot00000000000000# Enable Bzlmod for every Bazel command common --enable_bzlmod common --cxxopt=-std=c++20 common --announce_rc # Faster tests than fastbuild (-O0). build:dev --copt=-O1 # CI-specific flags common:ci --color=yes build:ci --show_progress_rate_limit=10 test:ci --test_output=errors src/BUILD.bazel000066400000000000000000001127731524103652300135370ustar00rootroot00000000000000load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") package(default_visibility = ["//visibility:public"]) bool_flag( name = "use_openssl", build_setting_default = False, ) config_setting( name = "use_openssl_setting", flag_values = {":use_openssl": "True"}, ) cc_library( name = "s2", srcs = [ ":s2/encoded_s2cell_id_vector.cc", ":s2/encoded_s2point_vector.cc", ":s2/encoded_s2shape_index.cc", ":s2/encoded_string_vector.cc", ":s2/id_set_lexicon.cc", ":s2/internal/s2incident_edge_tracker.cc", ":s2/internal/s2index_cell_data.cc", ":s2/mutable_s2shape_index.cc", ":s2/r2rect.cc", ":s2/s1angle.cc", ":s2/s1chord_angle.cc", ":s2/s1interval.cc", ":s2/s2boolean_operation.cc", ":s2/s2buffer_operation.cc", ":s2/s2builder.cc", ":s2/s2builder_graph.cc", ":s2/s2builderutil_closed_set_normalizer.cc", ":s2/s2builderutil_find_polygon_degeneracies.cc", ":s2/s2builderutil_get_snapped_winding_delta.cc", ":s2/s2builderutil_lax_polygon_layer.cc", ":s2/s2builderutil_lax_polyline_layer.cc", ":s2/s2builderutil_s2point_vector_layer.cc", ":s2/s2builderutil_s2polygon_layer.cc", ":s2/s2builderutil_s2polyline_layer.cc", ":s2/s2builderutil_s2polyline_vector_layer.cc", ":s2/s2builderutil_snap_functions.cc", ":s2/s2cap.cc", ":s2/s2cell.cc", ":s2/s2cell_id.cc", ":s2/s2cell_index.cc", ":s2/s2cell_union.cc", ":s2/s2centroids.cc", ":s2/s2closest_cell_query.cc", ":s2/s2closest_edge_query.cc", ":s2/s2closest_point_query.cc", ":s2/s2contains_vertex_query.cc", ":s2/s2convex_hull_query.cc", ":s2/s2coords.cc", ":s2/s2crossing_edge_query.cc", ":s2/s2debug.cc", ":s2/s2earth.cc", ":s2/s2edge_clipping.cc", ":s2/s2edge_crosser.cc", ":s2/s2edge_crossings.cc", ":s2/s2edge_distances.cc", ":s2/s2edge_tessellator.cc", ":s2/s2error.cc", ":s2/s2fractal.cc", ":s2/s2furthest_edge_query.cc", ":s2/s2hausdorff_distance_query.cc", ":s2/s2latlng.cc", ":s2/s2latlng_rect.cc", ":s2/s2latlng_rect_bounder.cc", ":s2/s2lax_loop_shape.cc", ":s2/s2lax_polygon_shape.cc", ":s2/s2lax_polyline_shape.cc", ":s2/s2loop.cc", ":s2/s2loop_measures.cc", ":s2/s2max_distance_targets.cc", ":s2/s2measures.cc", ":s2/s2memory_tracker.cc", ":s2/s2metrics.cc", ":s2/s2min_distance_targets.cc", ":s2/s2padded_cell.cc", ":s2/s2point_compression.cc", ":s2/s2point_region.cc", ":s2/s2pointutil.cc", ":s2/s2polygon.cc", ":s2/s2polyline.cc", ":s2/s2polyline_alignment.cc", ":s2/s2polyline_measures.cc", ":s2/s2polyline_simplifier.cc", ":s2/s2predicates.cc", ":s2/s2projections.cc", ":s2/s2r2rect.cc", ":s2/s2region_coverer.cc", ":s2/s2region_intersection.cc", ":s2/s2region_term_indexer.cc", ":s2/s2region_union.cc", ":s2/s2shape_index.cc", ":s2/s2shape_index_buffered_region.cc", ":s2/s2shape_index_measures.cc", ":s2/s2shape_measures.cc", ":s2/s2shape_nesting_query.cc", ":s2/s2shapeutil_build_polygon_boundaries.cc", ":s2/s2shapeutil_coding.cc", ":s2/s2shapeutil_contains_brute_force.cc", ":s2/s2shapeutil_conversion.cc", ":s2/s2shapeutil_edge_iterator.cc", ":s2/s2shapeutil_edge_wrap.cc", ":s2/s2shapeutil_get_reference_point.cc", ":s2/s2shapeutil_visit_crossing_edge_pairs.cc", ":s2/s2text_format.cc", ":s2/s2wedge_relations.cc", ":s2/s2winding_operation.cc", ], hdrs = [ ":s2/_fp_contract_off.h", ":s2/encoded_s2cell_id_vector.h", ":s2/encoded_s2point_vector.h", ":s2/encoded_s2shape_index.h", ":s2/encoded_string_vector.h", ":s2/encoded_uint_vector.h", ":s2/id_set_lexicon.h", ":s2/internal/s2disjoint_set.h", ":s2/internal/s2incident_edge_tracker.h", ":s2/internal/s2index_cell_data.h", ":s2/internal/s2meta.h", ":s2/mutable_s2shape_index.h", ":s2/r1interval.h", ":s2/r2.h", ":s2/r2rect.h", ":s2/s1angle.h", ":s2/s1chord_angle.h", ":s2/s1interval.h", ":s2/s2boolean_operation.h", ":s2/s2buffer_operation.h", ":s2/s2builder.h", ":s2/s2builder_graph.h", ":s2/s2builder_layer.h", ":s2/s2builderutil_closed_set_normalizer.h", ":s2/s2builderutil_find_polygon_degeneracies.h", ":s2/s2builderutil_get_snapped_winding_delta.h", ":s2/s2builderutil_graph_shape.h", ":s2/s2builderutil_lax_polygon_layer.h", ":s2/s2builderutil_lax_polyline_layer.h", ":s2/s2builderutil_s2point_vector_layer.h", ":s2/s2builderutil_s2polygon_layer.h", ":s2/s2builderutil_s2polyline_layer.h", ":s2/s2builderutil_s2polyline_vector_layer.h", ":s2/s2builderutil_snap_functions.h", ":s2/s2builderutil_testing.h", ":s2/s2cap.h", ":s2/s2cell.h", ":s2/s2cell_id.h", ":s2/s2cell_index.h", ":s2/s2cell_iterator.h", ":s2/s2cell_iterator_join.h", ":s2/s2cell_range_iterator.h", ":s2/s2cell_union.h", ":s2/s2centroids.h", ":s2/s2closest_cell_query.h", ":s2/s2closest_cell_query_base.h", ":s2/s2closest_edge_query.h", ":s2/s2closest_edge_query_base.h", ":s2/s2closest_point_query.h", ":s2/s2closest_point_query_base.h", ":s2/s2coder.h", ":s2/s2contains_point_query.h", ":s2/s2contains_vertex_query.h", ":s2/s2convex_hull_query.h", ":s2/s2coords.h", ":s2/s2coords_internal.h", ":s2/s2crossing_edge_query.h", ":s2/s2debug.h", ":s2/s2distance_target.h", ":s2/s2earth.h", ":s2/s2edge_clipping.h", ":s2/s2edge_crosser.h", ":s2/s2edge_crossings.h", ":s2/s2edge_crossings_internal.h", ":s2/s2edge_distances.h", ":s2/s2edge_tessellator.h", ":s2/s2edge_vector_shape.h", ":s2/s2error.h", ":s2/s2fractal.h", ":s2/s2furthest_edge_query.h", ":s2/s2hausdorff_distance_query.h", ":s2/s2latlng.h", ":s2/s2latlng_rect.h", ":s2/s2latlng_rect_bounder.h", ":s2/s2lax_loop_shape.h", ":s2/s2lax_polygon_shape.h", ":s2/s2lax_polyline_shape.h", ":s2/s2loop.h", ":s2/s2loop_measures.h", ":s2/s2max_distance_targets.h", ":s2/s2measures.h", ":s2/s2memory_tracker.h", ":s2/s2metrics.h", ":s2/s2min_distance_targets.h", ":s2/s2padded_cell.h", ":s2/s2point.h", ":s2/s2point_array.h", ":s2/s2point_compression.h", ":s2/s2point_index.h", ":s2/s2point_region.h", ":s2/s2point_span.h", ":s2/s2point_vector_shape.h", ":s2/s2pointutil.h", ":s2/s2polygon.h", ":s2/s2polyline.h", ":s2/s2polyline_alignment.h", ":s2/s2polyline_alignment_internal.h", ":s2/s2polyline_measures.h", ":s2/s2polyline_simplifier.h", ":s2/s2predicates.h", ":s2/s2predicates_internal.h", ":s2/s2projections.h", ":s2/s2r2rect.h", ":s2/s2region.h", ":s2/s2region_coverer.h", ":s2/s2region_intersection.h", ":s2/s2region_term_indexer.h", ":s2/s2region_union.h", ":s2/s2shape.h", ":s2/s2shape_index.h", ":s2/s2shape_index_buffered_region.h", ":s2/s2shape_index_measures.h", ":s2/s2shape_index_region.h", ":s2/s2shape_measures.h", ":s2/s2shape_nesting_query.h", ":s2/s2shapeutil_build_polygon_boundaries.h", ":s2/s2shapeutil_coding.h", ":s2/s2shapeutil_contains_brute_force.h", ":s2/s2shapeutil_conversion.h", ":s2/s2shapeutil_count_edges.h", ":s2/s2shapeutil_edge_iterator.h", ":s2/s2shapeutil_edge_wrap.h", ":s2/s2shapeutil_get_reference_point.h", ":s2/s2shapeutil_shape_edge.h", ":s2/s2shapeutil_shape_edge_id.h", ":s2/s2shapeutil_testing.h", ":s2/s2shapeutil_visit_crossing_edge_pairs.h", ":s2/s2text_format.h", ":s2/s2validation_query.h", ":s2/s2wedge_relations.h", ":s2/s2winding_operation.h", ":s2/s2wrapped_shape.h", ":s2/sequence_lexicon.h", ":s2/thread_testing.h", ":s2/value_lexicon.h", ], deps = [ "//s2/base:casts", "//s2/base:log_severity", "//s2/base:spinlock", "//s2/testing:gtest_prod", "//s2/util/bitmap", "//s2/util/bits", "//s2/util/coding", "//s2/util/endian", "//s2/util/gtl:compact_array", "//s2/util/gtl:container_logging", "//s2/util/gtl:dense_hash_set", "//s2/util/gtl:requires", "//s2/util/gtl:unaligned", "//s2/util/gtl:value_or_die", "//s2/util/hash:mix", "//s2/util/math:mathutil", "//s2/util/math:matrix3x3", "//s2/util/math:vector", "//s2/util/math/exactfloat", "//s2/util/random", "//s2/util/task:status_macros", "//s2/util/units", "@abseil-cpp//absl/base", "@abseil-cpp//absl/container:btree", "@abseil-cpp//absl/container:flat_hash_set", "@abseil-cpp//absl/flags:flag", "@abseil-cpp//absl/log:absl_log", "@abseil-cpp//absl/log:check", "@abseil-cpp//absl/random:bit_gen_ref", "@abseil-cpp//absl/status", "@abseil-cpp//absl/status:statusor", ], ) cc_binary( name = "s2shared", srcs = [ ":s2/encoded_s2cell_id_vector.cc", ":s2/encoded_s2point_vector.cc", ":s2/encoded_s2shape_index.cc", ":s2/encoded_string_vector.cc", ":s2/id_set_lexicon.cc", ":s2/mutable_s2shape_index.cc", ":s2/r2rect.cc", ":s2/s1angle.cc", ":s2/s1chord_angle.cc", ":s2/s1interval.cc", ":s2/s2boolean_operation.cc", ":s2/s2buffer_operation.cc", ":s2/s2builder.cc", ":s2/s2builder_graph.cc", ":s2/s2builderutil_closed_set_normalizer.cc", ":s2/s2builderutil_find_polygon_degeneracies.cc", ":s2/s2builderutil_get_snapped_winding_delta.cc", ":s2/s2builderutil_lax_polygon_layer.cc", ":s2/s2builderutil_lax_polyline_layer.cc", ":s2/s2builderutil_s2point_vector_layer.cc", ":s2/s2builderutil_s2polygon_layer.cc", ":s2/s2builderutil_s2polyline_layer.cc", ":s2/s2builderutil_s2polyline_vector_layer.cc", ":s2/s2builderutil_snap_functions.cc", ":s2/s2cap.cc", ":s2/s2cell.cc", ":s2/s2cell_id.cc", ":s2/s2cell_index.cc", ":s2/s2cell_union.cc", ":s2/s2centroids.cc", ":s2/s2closest_cell_query.cc", ":s2/s2closest_edge_query.cc", ":s2/s2closest_point_query.cc", ":s2/s2contains_vertex_query.cc", ":s2/s2convex_hull_query.cc", ":s2/s2coords.cc", ":s2/s2crossing_edge_query.cc", ":s2/s2debug.cc", ":s2/s2earth.cc", ":s2/s2edge_clipping.cc", ":s2/s2edge_crosser.cc", ":s2/s2edge_crossings.cc", ":s2/s2edge_distances.cc", ":s2/s2edge_tessellator.cc", ":s2/s2error.cc", ":s2/s2fractal.cc", ":s2/s2furthest_edge_query.cc", ":s2/s2hausdorff_distance_query.cc", ":s2/s2latlng.cc", ":s2/s2latlng_rect.cc", ":s2/s2latlng_rect_bounder.cc", ":s2/s2lax_loop_shape.cc", ":s2/s2lax_polygon_shape.cc", ":s2/s2lax_polyline_shape.cc", ":s2/s2loop.cc", ":s2/s2loop_measures.cc", ":s2/s2max_distance_targets.cc", ":s2/s2measures.cc", ":s2/s2memory_tracker.cc", ":s2/s2metrics.cc", ":s2/s2min_distance_targets.cc", ":s2/s2padded_cell.cc", ":s2/s2point_compression.cc", ":s2/s2point_region.cc", ":s2/s2pointutil.cc", ":s2/s2polygon.cc", ":s2/s2polyline.cc", ":s2/s2polyline_alignment.cc", ":s2/s2polyline_measures.cc", ":s2/s2polyline_simplifier.cc", ":s2/s2predicates.cc", ":s2/s2projections.cc", ":s2/s2r2rect.cc", ":s2/s2region_coverer.cc", ":s2/s2region_intersection.cc", ":s2/s2region_term_indexer.cc", ":s2/s2region_union.cc", ":s2/s2shape_index.cc", ":s2/s2shape_index_buffered_region.cc", ":s2/s2shape_index_measures.cc", ":s2/s2shape_measures.cc", ":s2/s2shape_nesting_query.cc", ":s2/s2shapeutil_build_polygon_boundaries.cc", ":s2/s2shapeutil_coding.cc", ":s2/s2shapeutil_contains_brute_force.cc", ":s2/s2shapeutil_conversion.cc", ":s2/s2shapeutil_edge_iterator.cc", ":s2/s2shapeutil_get_reference_point.cc", ":s2/s2shapeutil_visit_crossing_edge_pairs.cc", ":s2/s2text_format.cc", ":s2/s2wedge_relations.cc", ":s2/s2winding_operation.cc", ], linkshared = True, deps = [ ":s2", ], ) cc_library( name = "s2_testing_headers", testonly = True, srcs = [ ":s2/gmock_matchers.cc", ":s2/s2builderutil_testing.cc", ":s2/s2random.cc", ":s2/s2shapeutil_testing.cc", ":s2/s2testing.cc", ":s2/thread_testing.cc", ], hdrs = [ ":s2/gmock_matchers.h", ":s2/s2builderutil_testing.h", ":s2/s2cell_iterator_testing.h", ":s2/s2closest_edge_query_testing.h", ":s2/s2coder_testing.h", ":s2/s2random.h", ":s2/s2shapeutil_testing.h", ":s2/s2testing.h", ":s2/thread_testing.h", ], includes = ["src"], deps = [ ":s2", "//s2/base:timer", "@abseil-cpp//absl/base", "@abseil-cpp//absl/flags:flag", "@abseil-cpp//absl/hash:hash_testing", "@abseil-cpp//absl/log:absl_log", "@abseil-cpp//absl/log:check", "@abseil-cpp//absl/log:log_streamer", "@abseil-cpp//absl/status", "@abseil-cpp//absl/status:statusor", "@abseil-cpp//absl/strings:cord", "@googletest//:gtest", ], ) cc_test( name = "s2disjoint_set_test", srcs = [":s2/internal/s2disjoint_set_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2fractal_test", srcs = [":s2/s2fractal_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "encoded_s2cell_id_vector_test", srcs = [":s2/encoded_s2cell_id_vector_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "encoded_s2point_vector_test", srcs = [":s2/encoded_s2point_vector_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "encoded_s2shape_index_test", srcs = [":s2/encoded_s2shape_index_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "encoded_string_vector_test", srcs = [":s2/encoded_string_vector_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "encoded_uint_vector_test", srcs = [":s2/encoded_uint_vector_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "id_set_lexicon_test", srcs = [":s2/id_set_lexicon_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "mutable_s2shape_index_test", srcs = [":s2/mutable_s2shape_index_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "r1interval_test", srcs = [":s2/r1interval_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "r2rect_test", srcs = [":s2/r2rect_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s1angle_test", srcs = [":s2/s1angle_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s1chord_angle_test", srcs = [":s2/s1chord_angle_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s1interval_test", srcs = [":s2/s1interval_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2boolean_operation_test", srcs = [":s2/s2boolean_operation_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2buffer_operation_test", srcs = [":s2/s2buffer_operation_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builder_graph_test", srcs = [":s2/s2builder_graph_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builder_test", srcs = [":s2/s2builder_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_closed_set_normalizer_test", srcs = [":s2/s2builderutil_closed_set_normalizer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_find_polygon_degeneracies_test", srcs = [":s2/s2builderutil_find_polygon_degeneracies_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_get_snapped_winding_delta_test", srcs = [":s2/s2builderutil_get_snapped_winding_delta_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_lax_polygon_layer_test", srcs = [":s2/s2builderutil_lax_polygon_layer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_lax_polyline_layer_test", srcs = [":s2/s2builderutil_lax_polyline_layer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_s2point_vector_layer_test", srcs = [":s2/s2builderutil_s2point_vector_layer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_s2polygon_layer_test", srcs = [":s2/s2builderutil_s2polygon_layer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_s2polyline_layer_test", srcs = [":s2/s2builderutil_s2polyline_layer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_s2polyline_vector_layer_test", srcs = [":s2/s2builderutil_s2polyline_vector_layer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_snap_functions_test", srcs = [":s2/s2builderutil_snap_functions_test.cc"], # https://github.com/google/s2geometry/issues/596 flaky = True, shard_count = 3, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2builderutil_testing_test", srcs = [":s2/s2builderutil_testing_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cap_test", srcs = [":s2/s2cap_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cell_test", srcs = [":s2/s2cell_test.cc"], # https://github.com/google/s2geometry/issues/505 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cell_id_test", srcs = [":s2/s2cell_id_test.cc"], # https://github.com/google/s2geometry/issues/516 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cell_index_test", srcs = [":s2/s2cell_index_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cell_iterator_join_test", srcs = [":s2/s2cell_iterator_join_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cell_iterator_testing_test", srcs = [":s2/s2cell_iterator_testing_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cell_range_iterator_test", srcs = [":s2/s2cell_range_iterator_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2cell_union_test", srcs = [":s2/s2cell_union_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2centroids_test", srcs = [":s2/s2centroids_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2closest_cell_query_base_test", srcs = [":s2/s2closest_cell_query_base_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2closest_cell_query_test", srcs = [":s2/s2closest_cell_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2closest_edge_query_base_test", srcs = [":s2/s2closest_edge_query_base_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2closest_edge_query_test", srcs = [":s2/s2closest_edge_query_test.cc"], # https://github.com/google/s2geometry/issues/552 # https://github.com/google/s2geometry/issues/582 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2closest_point_query_base_test", srcs = [":s2/s2closest_point_query_base_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2closest_point_query_test", srcs = [":s2/s2closest_point_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2contains_point_query_test", srcs = [":s2/s2contains_point_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2contains_vertex_query_test", srcs = [":s2/s2contains_vertex_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2convex_hull_query_test", srcs = [":s2/s2convex_hull_query_test.cc"], # https://github.com/google/s2geometry/issues/515 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2coords_test", srcs = [":s2/s2coords_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2crossing_edge_query_test", srcs = [":s2/s2crossing_edge_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2earth_test", srcs = [":s2/s2earth_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2edge_clipping_test", srcs = [":s2/s2edge_clipping_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2edge_crosser_test", srcs = [":s2/s2edge_crosser_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2edge_crossings_test", srcs = [":s2/s2edge_crossings_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2edge_distances_test", srcs = [":s2/s2edge_distances_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2edge_tessellator_test", srcs = [":s2/s2edge_tessellator_test.cc"], shard_count = 2, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2edge_vector_shape_test", srcs = [":s2/s2edge_vector_shape_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2error_test", srcs = [":s2/s2error_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2furthest_edge_query_test", srcs = [":s2/s2furthest_edge_query_test.cc"], # https://github.com/google/s2geometry/issues/592 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2hausdorff_distance_query_test", srcs = [":s2/s2hausdorff_distance_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2index_cell_data_test", srcs = [":s2/internal/s2index_cell_data_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2latlng_test", srcs = [":s2/s2latlng_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2latlng_rect_bounder_test", srcs = [":s2/s2latlng_rect_bounder_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2latlng_rect_test", srcs = [":s2/s2latlng_rect_test.cc"], # https://github.com/google/s2geometry/issues/523 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2lax_loop_shape_test", srcs = [":s2/s2lax_loop_shape_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2lax_polygon_shape_test", srcs = [":s2/s2lax_polygon_shape_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2lax_polyline_shape_test", srcs = [":s2/s2lax_polyline_shape_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2loop_measures_test", srcs = [":s2/s2loop_measures_test.cc"], # https://github.com/google/s2geometry/issues/395 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2loop_test", srcs = [":s2/s2loop_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", "@abseil-cpp//absl/status:status_matchers", ], ) cc_test( name = "s2measures_test", srcs = [":s2/s2measures_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2memory_tracker_test", srcs = [":s2/s2memory_tracker_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2metrics_test", srcs = [":s2/s2metrics_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2max_distance_targets_test", srcs = [":s2/s2max_distance_targets_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2min_distance_targets_test", srcs = [":s2/s2min_distance_targets_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2padded_cell_test", srcs = [":s2/s2padded_cell_test.cc"], # https://github.com/google/s2geometry/issues/598 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2point_test", srcs = [":s2/s2point_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2point_vector_shape_test", srcs = [":s2/s2point_vector_shape_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2point_compression_test", srcs = [":s2/s2point_compression_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2point_index_test", srcs = [":s2/s2point_index_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2point_region_test", srcs = [":s2/s2point_region_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2pointutil_test", srcs = [":s2/s2pointutil_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2polygon_test", srcs = [":s2/s2polygon_test.cc"], flaky = True, shard_count = 5, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2polyline_alignment_test", srcs = [":s2/s2polyline_alignment_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2polyline_simplifier_test", srcs = [":s2/s2polyline_simplifier_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2polyline_measures_test", srcs = [":s2/s2polyline_measures_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2polyline_test", srcs = [":s2/s2polyline_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2predicates_test", srcs = [":s2/s2predicates_test.cc"], # https://github.com/google/s2geometry/issues/511 # https://github.com/google/s2geometry/issues/612 flaky = True, deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2projections_test", srcs = [":s2/s2projections_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2r2rect_test", srcs = [":s2/s2r2rect_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2region_test", srcs = [":s2/s2region_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2region_term_indexer_test", srcs = [":s2/s2region_term_indexer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2region_coverer_test", srcs = [":s2/s2region_coverer_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2region_union_test", srcs = [":s2/s2region_union_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shape_index_buffered_region_test", srcs = [":s2/s2shape_index_buffered_region_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shape_index_measures_test", srcs = [":s2/s2shape_index_measures_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shape_index_region_test", srcs = [":s2/s2shape_index_region_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shape_index_test", srcs = [":s2/s2shape_index_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shape_measures_test", srcs = [":s2/s2shape_measures_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shape_nesting_query_test", srcs = [":s2/s2shape_nesting_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_build_polygon_boundaries_test", srcs = [":s2/s2shapeutil_build_polygon_boundaries_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_coding_test", srcs = [":s2/s2shapeutil_coding_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_contains_brute_force_test", srcs = [":s2/s2shapeutil_contains_brute_force_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_conversion_test", srcs = [":s2/s2shapeutil_conversion_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_count_edges_test", srcs = [":s2/s2shapeutil_count_edges_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_edge_iterator_test", srcs = [":s2/s2shapeutil_edge_iterator_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_edge_wrap_test", srcs = [":s2/s2shapeutil_edge_wrap_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_get_reference_point_test", srcs = [":s2/s2shapeutil_get_reference_point_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2shapeutil_visit_crossing_edge_pairs_test", srcs = [":s2/s2shapeutil_visit_crossing_edge_pairs_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) #cc_test( # name = "s2testing_test", # srcs = [":s2/s2testing_test.cc"], # deps = [ # ":s2", # ":s2_testing_headers", # "//s2/testing:test_main", # ], #) cc_test( name = "s2text_format_test", srcs = [":s2/s2text_format_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2validation_query_test", srcs = [":s2/s2validation_query_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2wedge_relations_test", srcs = [":s2/s2wedge_relations_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2winding_operation_test", srcs = [":s2/s2winding_operation_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "s2wrapped_shape_test", srcs = [":s2/s2wrapped_shape_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "sequence_lexicon_test", srcs = [":s2/sequence_lexicon_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) cc_test( name = "value_lexicon_test", srcs = [":s2/value_lexicon_test.cc"], deps = [ ":s2", ":s2_testing_headers", "//s2/testing:test_main", ], ) src/MODULE.bazel000066400000000000000000000022241524103652300136520ustar00rootroot00000000000000module( name = "s2geometry", version = "head", bazel_compatibility = [ ">=8.0.0", ], compatibility_level = 1, ) # Production dependencies bazel_dep(name = "abseil-cpp", version = "20260526.0") bazel_dep(name = "bazel_skylib", version = "1.9.0") bazel_dep(name = "rules_cc", version = "0.2.22") # Development dependencies (only needed for tests) bazel_dep(name = "boringssl", version = "0.20260616.0", dev_dependency = True) bazel_dep(name = "openssl", version = "3.5.5.bcr.3", dev_dependency = True) bazel_dep(name = "google_benchmark", version = "1.9.5", dev_dependency = True) bazel_dep(name = "googletest", version = "1.17.0.bcr.2", dev_dependency = True) # Python configuration # The platforms dependency is needed for pybind_extension rules. See: # https://github.com/pybind/pybind11_bazel/blob/master/MODULE.bazel bazel_dep(name = "platforms", version = "1.1.0") bazel_dep(name = "pybind11_bazel", version = "3.0.1") bazel_dep(name = "rules_python", version = "2.3.1") # Extensions cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure_extension", dev_dependency = True) use_repo(cc_configure, "local_config_cc") src/python/000077500000000000000000000000001524103652300131675ustar00rootroot00000000000000src/python/BUILD.bazel000066400000000000000000000112001524103652300150370ustar00rootroot00000000000000load("@pybind11_bazel//:build_defs.bzl", "pybind_extension", "pybind_library") load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load("@rules_python//python:defs.bzl", "py_library", "py_test") package(default_visibility = ["//visibility:private"]) # ======================================== # Python Package # ======================================== py_library( name = "s2geometry_pybind", srcs = ["s2geometry_pybind/__init__.py"], data = [ ":s2geometry_bindings", ], imports = ["."], visibility = ["//visibility:public"], ) # ======================================== # C++ Bindings # ======================================== pybind_extension( name = "s2geometry_bindings", srcs = ["module.cc"], deps = [ ":r1interval_bindings", ":r2point_bindings", ":r2rect_bindings", ":s1angle_bindings", ":s1chord_angle_bindings", ":s1interval_bindings", ":s2cap_bindings", ":s2cell_bindings", ":s2cell_id_bindings", ":s2latlng_bindings", ":s2point_bindings", ], ) pybind_library( name = "r1interval_bindings", srcs = ["r1interval_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", ], ) pybind_library( name = "r2point_bindings", srcs = ["r2point_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", ], ) pybind_library( name = "r2rect_bindings", srcs = ["r2rect_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", ], ) pybind_library( name = "s1angle_bindings", srcs = ["s1angle_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", "@abseil-cpp//absl/strings", ], ) pybind_library( name = "s1chord_angle_bindings", srcs = ["s1chord_angle_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", "@abseil-cpp//absl/strings", ], ) pybind_library( name = "s1interval_bindings", srcs = ["s1interval_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", "@abseil-cpp//absl/strings", ], ) pybind_library( name = "s2point_bindings", srcs = ["s2point_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", ], ) pybind_library( name = "s2latlng_bindings", srcs = ["s2latlng_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", "@abseil-cpp//absl/strings", ], ) cc_library( name = "s2cell_id_range", srcs = ["s2cell_id_range.cc"], hdrs = ["s2cell_id_range.h"], deps = [ "//:s2", "@abseil-cpp//absl/log:absl_check", ], ) pybind_library( name = "s2cell_id_bindings", srcs = ["s2cell_id_bindings.cc"], deps = [ ":s2cell_id_range", "//:s2", "@abseil-cpp//absl/strings", ], ) cc_test( name = "s2cell_id_range_test", srcs = ["s2cell_id_range_test.cc"], deps = [ ":s2cell_id_range", "//:s2", "//s2/testing:test_main", ], ) pybind_library( name = "s2cap_bindings", srcs = ["s2cap_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", ], ) pybind_library( name = "s2cell_bindings", srcs = ["s2cell_bindings.cc"], deps = [ "//:s2", "@abseil-cpp//absl/hash", "@abseil-cpp//absl/strings", ], ) # ======================================== # Python Tests # ======================================== py_test( name = "r1interval_test", srcs = ["r1interval_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s1angle_test", srcs = ["s1angle_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s1chord_angle_test", srcs = ["s1chord_angle_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "r2point_test", srcs = ["r2point_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "r2rect_test", srcs = ["r2rect_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s1interval_test", srcs = ["s1interval_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s2point_test", srcs = ["s2point_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s2latlng_test", srcs = ["s2latlng_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s2cap_test", srcs = ["s2cap_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s2cell_id_test", srcs = ["s2cell_id_test.py"], deps = [":s2geometry_pybind"], ) py_test( name = "s2cell_test", srcs = ["s2cell_test.py"], deps = [":s2geometry_pybind"], ) src/python/CMakeLists.txt000066400000000000000000000047171524103652300157400ustar00rootroot00000000000000# Generate standard target names. cmake_policy(SET CMP0078 NEW) # Honor SWIG_MODULE_NAME via -module flag. cmake_policy(SET CMP0086 NEW) # Handle where to install the resulting Python package if (CALL_FROM_SETUP_PY) # The CMakeExtension will set CMAKE_INSTALL_PREFIX to the root # of the resulting wheel archive set(S2GEOMETRY_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) else() # The Python package is installed directly in the folder of the # detected interpreter (system, user, or virtualenv) set(S2GEOMETRY_INSTALL_PREFIX ${Python3_SITELIB}) endif() include(${SWIG_USE_FILE}) include_directories(${Python3_INCLUDE_DIRS}) # SWIG does not understand `uint64_t`. `SWIGWORDSIZE64` controls whether # it maps `uint64_t` to `unsigned long` or `unsigned long long`. # (See `stdint.i`.) `SWIGWORDSIZE64` should really be called # `INT64_IS_LONG_INT`. Unices other that macOS use `long`. Windows uses # `long long`. If you get error involving `vector` # and `vector` while compiling `s2PYTHON_wrap.cxx`, then # this is probably defined incorrectly. # https://github.com/swig/swig/issues/2923 if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND UNIX AND NOT APPLE) set(CMAKE_SWIG_FLAGS "-DSWIGWORDSIZE64") else() set(CMAKE_SWIG_FLAGS "") endif() set_property(SOURCE s2.i PROPERTY SWIG_FLAGS "-module" "s2geometry") set_property(SOURCE s2.i PROPERTY CPLUSPLUS ON) swig_add_library(s2geometry LANGUAGE python SOURCES s2.i) if (WITH_PYTHON_LIMITED_API) target_link_libraries(s2geometry Python3::SABIModule s2) # https://www.swig.org/Doc4.2/Python.html#Python_stable_abi target_compile_definitions(s2geometry PRIVATE Py_LIMITED_API=0x030a0000) else() target_link_libraries(s2geometry Python3::Module s2) endif() enable_testing() add_test(NAME s2geometry_test COMMAND ${Python3_EXECUTABLE} "${PROJECT_SOURCE_DIR}/src/python/s2geometry_test.py") set_property(TEST s2geometry_test PROPERTY ENVIRONMENT "PYTHONPATH=$ENV{PYTHONPATH}:${PROJECT_BINARY_DIR}/python") # Install the wrapper. install(TARGETS s2geometry DESTINATION ${S2GEOMETRY_INSTALL_PREFIX}) # Install swig-generated Python file (we rename it to __init__.py as it will # ultimately end up in a directory called s2geometry in site-packages, which will # serve as the module directory. install(FILES "${CMAKE_CURRENT_BINARY_DIR}/s2geometry.py" DESTINATION ${S2GEOMETRY_INSTALL_PREFIX} RENAME __init__.py COMPONENT s2geometry) src/python/README.md000066400000000000000000000214361524103652300144540ustar00rootroot00000000000000# S2 Geometry Pybind11 Bindings *UNDER DEVELOPMENT* This directory contains SWIG and pybind11-based Python SDK for S2 Geometry. ## Migration Strategy The S2 Geometry library is transitioning from SWIG-based bindings to pybind11-based bindings. During this migration: - **SWIG bindings** (`s2geometry`): The current production bindings, built with CMake. Use `import s2geometry` to access these. - **pybind11 bindings** (`s2geometry_pybind`): The new bindings under development, built with Bazel. Use `import s2geometry_pybind` to access these. Once the pybind11 bindings are feature-complete and stable, the SWIG bindings will be deprecated and the pybind11 package will be renamed to `s2geometry` to become the primary Python API. ## User Guide ### Usage Example ```python import s2geometry_pybind as s2 p1 = s2.S2Point(1.0, 0.0, 0.0) p2 = s2.S2Point(0.0, 1.0, 0.0) sum_point = p1 + p2 print(sum_point) ``` ### Interface Notes The Python bindings follow the C++ API closely but with Pythonic conventions: **Naming Conventions:** - Core classes exist within the top-level module; we may define submodules for utility classes. - Class names remain unchanged (e.g., `S2Point`, `S1Angle`, `R1Interval`) - Method names are converted to snake_case (converted from UpperCamelCase C++ function names) - The `Get` prefix is dropped: C++ `GetDistance` becomes Python `distance`, `GetBoundUV` becomes `bound_uv`, etc. **Properties vs. Methods:** - Simple accessors that return internal state (including trivial unit conversions) are properties: `point.x`, `point.y`, `interval.lo`, `interval.hi`, `angle.radians`, `angle.degrees` - Properties are always read-only. To create a modified object, use a constructor or factory method. - Other functions are methods: `interval.length()`, `angle.normalized()`, `angle.sin()` **Invalid Values:** - Invalid inputs to constructions or functions raises `ValueError`. - Example: `S1Interval(0.0, 4.0)` raises `ValueError` because `4.0 > Ï€`. - Some classes change the behavior of operations to guarantee validity. - Example: `S2LatLng` arithmetic operators automatically clamp the result to a valid range whereas in C++ these operators can produce invalid states. - Note: In C++, these conditions trigger `ABSL_DCHECK` assertions. The bindings prevent these assertions from firing by pre-validating inputs. - Note: Python bindings check for invalid inputs and throw C++ exceptions which are caught by pybind and converted to Python exceptions. Exceptions are normally prohibited by the C++ style guide, but this is the preferred approach for pybind. **Documentation:** - Python docstrings provide essential information about parameters, return values, and key behaviors - For comprehensive documentation including edge cases and algorithmic details, refer to the C++ header files - The C++ documentation is the authoritative source of truth **Operators:** - Standard Python operators work as expected: `+`, `-`, `*`, `==`, `!=`, `<`, `>` (for C++ classes that implement those operators) - Types that define `__eq__` also define `__hash__`, so they can be used as dictionary keys and in sets. - Binding types are intentionally immutable. In-place mutation operators are not supported. Augmented assignment (`+=`, `-=`, `*=`, `/=`) still works: Python falls back to the binary operator and rebinds the variable (e.g. `a += b` is equivalent to `a = a + b`). **Method Overloads:** - Instead of Python overloads, C++ overloaded methods are exposed under distinct names. For different argument types, the short name is used for the same-type argument and a longer name for other types (e.g., `R2Rect.contains(other: R2Rect)` and `R2Rect.contains_point(p: R2Point)`). For overloads with significantly different behavior, descriptive names are chosen (e.g., `R2Rect.vertex(k)` for CCW vertex index and `R2Rect.vertex_ij(i, j)` for axis-direction vertex access). **Default Values:** - Some methods have default parameter values (e.g., `approx_equals(other, max_error=1e-15)`). These defaults are re-defined in the Python bindings and are expected to match the C++ defaults. **String Representations:** - `repr()` prefixes the class name and delegates to C++ `operator<<` for the value - `str()` delegates to C++ `operator<<` for a cleaner output - Example: `repr(S1Interval(0.0, 2.0))` returns `'S1Interval([0, 2])'` while `str()` returns `'[0, 2]'` **Vector Inheritance:** - In C++, various geometry classes inherit from or expose vector types (e.g., `S2Point` inherits from `Vector3_d`, `R2Point` is a type alias for `Vector2_d`, `R1Interval` returns bounds as `Vector2_d`) - The Python bindings do **not** expose this inheritance hierarchy; it is treated as an implementation detail - Instead, classes that inherit from a vector expose key functions from the `BasicVector` interface (e.g., `norm()`, `dot_prod()`, `cross_prod()`) - C++ functions that accept or return a vector object use a Python tuple (of length matching the vector dimension) - Array indexing operators (e.g., `point[0]`) are not currently supported **Iterators:** - Some classes expose methods that return iterables (e.g., `S2CellId.children()`, `S2CellId.cells(level)`). - Iterables support forward iteration, `len()`, indexing, slicing, `in`, and `reversed()` unless otherwise noted. **Serialization:** - The C++ Encoder/Decoder serialization functions are not currently supported ## Development ### Directory Structure ``` python/ ├── module.cc # Binding module entry point ├── s2point_bindings.cc # Bindings for S2Point (add more *_bindings.cc as needed) ├── s2geometry_pybind/ # Dir for Python package │ └── __init__.py # Package initialization ├── s2point_test.py # Tests for S2Point (add more *_test.py as needed) └── BUILD.bazel # Build rules for bindings, library, and tests ``` ### Building with Bazel (pybind11 bindings) Bazel can be used for development and testing of the new pybind11-based bindings. To run all tests: ```bash cd src bazel test //python/... ``` ### Building with CMake (SWIG bindings) CMake currently builds **only the SWIG-based bindings** (the legacy `s2geometry` package). The pybind11 bindings are not yet integrated into the CMake build system. For detailed CMake build instructions, dependency installation, and Python wheel creation, see the [parent directory README](../README.md#build-and-install). Key points: - Install dependencies: `sudo apt-get install cmake libssl-dev swig python3-dev` - Enable Python bindings with `-DWITH_PYTHON=ON` when running cmake - This will build the SWIG-based `s2geometry` package only Example: ```bash mkdir build && cd build cmake -DBUILD_TESTS=yes -DWITH_PYTHON=ON -DCMAKE_PREFIX_PATH=/path/to/absl/install -DCMAKE_CXX_STANDARD=17 .. make -j $(nproc) make test ARGS="-j$(nproc)" sudo make install ``` To run the SWIG tests directly without cmake: ```bash cd build/python PYTHONPATH=. python3 ../../src/python/s2geometry_test.py ``` **Note:** Once the pybind11 bindings are complete, they will be integrated into the CMake build system as a replacement for the SWIG bindings. ## Extending the Bindings To add bindings for a new class: 1. Create `_bindings.cc` with pybind11 bindings 2. Update `BUILD.bazel` to add a new `pybind_library` target 3. Update `module.cc` to call your binding function 4. Create tests in `_test.py` ### Binding File Organization Use the following sections to organize functions within the bindings files and tests. Secondarily, follow the order in which functions are declared in the C++ headers. 1. **Constructors** - Default constructors and constructors with parameters 1. **Constants** - Class-level constants in upper snake case (e.g., `S2CellId.MAX_LEVEL`, `S2CellId.NUM_FACES`). Accessible as class attributes. 1. **Factory methods** - Static factory methods (e.g., `from_degrees`, `from_radians`, `zero`, `invalid`) 1. **Properties** - Mutable and read-only properties (e.g., coordinate accessors like `x`, `y`, `lo`, `hi`) 1. **Predicates** - Simple boolean state checks (e.g., `is_empty`, `is_valid`, `is_full`) 1. **Geometric operations** - All other methods including conversions, computations, containment checks, set operations, normalization, and distance calculations 1. **Traversal** - Methods for navigating a cell hierarchy (e.g., `parent`, `child`, neighbor methods) 1. **Vector operations** - Methods from the Vector base class (e.g., `norm`, `norm2`, `normalize`, `dot_prod`, `cross_prod`, `angle`). Only applicable to classes that inherit from `util/math/vector.h` 1. **Operators** - Operator overloads (e.g., `==`, `+`, `*`, comparison operators) 1. **String representation** - `__repr__` (which also provides `__str__`), and string conversion methods like `to_string_in_degrees` 1. **Module-level functions** - Standalone functions (e.g., trigonometric functions for S1Angle) src/python/coder.i000066400000000000000000000076101524103652300144410ustar00rootroot00000000000000// // Exposes Encoder and Decoder a subset of functionality plus the // ability to set and get internal buffer. This allows passing them // into other SWIG'd methods, such as those in the S2 SWIG library. // For example: // // class S2Polygon { // ... // void Encode(Encoder* const encoder) const override; // // bool Decode(Decoder* const decoder) override; // }; // // Usage: // # data is a bytes object. // dec = pywrapcoder.Decoder(data) // polygon = s2.S2Polygon() // polygon.Decode(dec) // // enc = pywrapcoder.Encoder() // polygon.Encode(enc) // data = enc.buffer() // %{ #include "s2/util/coding/coder.h" %} // For Decoder::reset to accept a bytes or bytearray object. %typemap(in) (const void* buf, size_t maxn) { if (PyBytes_Check($input)) { $1 = (void *) PyBytes_AsString($input); $2 = PyBytes_Size($input); } else if (PyByteArray_Check($input)) { $1 = (void *) PyByteArray_AsString($input); $2 = PyByteArray_Size($input); } else { // TODO: When Py_LIMITED_API is raised to 3.13+ (2028), replace // %S/(PyObject*)Py_TYPE() with %T in PyErr_Format calls for bare type // names (e.g. "int" vs ""). PyErr_Format(PyExc_TypeError, "bytes or bytearray needed, %S found", (PyObject*)Py_TYPE($input)); return nullptr; } }; // For Encoder::reset to accept a bytearray object. %typemap(in) (void* buf, size_t maxn) { if (PyByteArray_Check($input)) { $1 = (void *) PyByteArray_AsString($input); $2 = PyByteArray_Size($input); } else { PyErr_Format(PyExc_TypeError, "bytearray needed, %S found", (PyObject*)Py_TYPE($input)); return nullptr; } }; // Keep a reference to the object so that outside users don't // have to keep one, or else it could be released. // The auto-generated code passes *args to each of the methods, but the use // cases we support is only when a single arg is passed in. %pythonprepend Decoder::Decoder %{ if len(args) == 1: self._data_keepalive = args[0] %} %pythonprepend Decoder::reset %{ self._data_keepalive = args[0] %} %extend Decoder { // Allows direct construction with a bytes or bytearray objects. Decoder(PyObject *obj) { if (PyBytes_Check(obj)) { return new Decoder(PyBytes_AsString(obj), PyBytes_Size(obj)); } if (PyByteArray_Check(obj)) { return new Decoder(PyByteArray_AsString(obj), PyByteArray_Size(obj)); } PyErr_Format(PyExc_TypeError, "bytes or bytearray needed, %S found", (PyObject*)Py_TYPE(obj)); return nullptr; } } %extend Encoder { // Returns internal buffer as a bytearray. PyObject* buffer() { return PyByteArray_FromStringAndSize($self->base(), $self->length()); } } %ignoreall %unignore Decoder; %unignore Decoder::Decoder(); %unignore Decoder::Decoder(const void*, size_t); %unignore Decoder::~Decoder; %unignore Decoder::avail() const; %unignore Decoder::get8(); %unignore Decoder::get16(); %unignore Decoder::get32(); %unignore Decoder::get64(); %unignore Decoder::getfloat(); %unignore Decoder::getdouble(); %unignore Decoder::pos() const; %unignore Decoder::reset(const void*, size_t); %unignore Encoder; %unignore Encoder::Encoder(); %unignore Encoder::Encoder(void*, size_t); %unignore Encoder::~Encoder; %unignore Encoder::Ensure(size_t); %unignore Encoder::avail() const; %unignore Encoder::buffer(); %unignore Encoder::clear(); %unignore Encoder::length() const; %unignore Encoder::put8(unsigned char); %unignore Encoder::put16(uint16_t); %unignore Encoder::put32(uint32_t); %unignore Encoder::put64(uint64_t); %unignore Encoder::putdouble(double); %unignore Encoder::putfloat(float); %unignore Encoder::reset(void *, size_t); // Silence SWIG Warning 362: operator= can't be wrapped in Python. // %ignoreall is active but the warning fires at parse time regardless. %ignore Encoder::operator=; %include "s2/util/coding/coder.h" %unignoreall src/python/module.cc000066400000000000000000000024331524103652300147650ustar00rootroot00000000000000#include namespace py = pybind11; // Forward declarations for binding functions // keep-sorted start void bind_r1interval(py::module& m); void bind_r2point(py::module& m); void bind_r2rect(py::module& m); void bind_s1angle(py::module& m); void bind_s1chord_angle(py::module& m); void bind_s1interval(py::module& m); void bind_s2cap(py::module& m); void bind_s2cell(py::module& m); void bind_s2cell_id(py::module& m); void bind_s2latlng(py::module& m); void bind_s2point(py::module& m); // keep-sorted end PYBIND11_MODULE(s2geometry_bindings, m) { m.doc() = "S2 Geometry Python bindings using pybind11"; // Bind core geometry classes in dependency order. // Each class must be registered before classes that use it as a // parameter or return type. // No dependencies bind_r1interval(m); bind_r2point(m); bind_s1interval(m); bind_s2point(m); // Deps: r1interval, r2point bind_r2rect(m); // Deps: s2point bind_s1angle(m); // Deps: s1angle, s2point bind_s1chord_angle(m); // Deps: s1angle, s1chord_angle, s2point bind_s2cap(m); // Deps: s1angle, s2point bind_s2latlng(m); // Deps: s1angle, s2point, s2latlng, r2point, r2rect bind_s2cell_id(m); // Deps: r2rect, s1chord_angle, s2cap, s2cell_id, s2latlng, s2point bind_s2cell(m); } src/python/r1interval_bindings.cc000066400000000000000000000126271524103652300174520ustar00rootroot00000000000000#include #include #include #include "absl/hash/hash.h" #include "s2/r1interval.h" namespace py = pybind11; void bind_r1interval(py::module& m) { py::class_(m, "R1Interval") // Constructors .def(py::init<>(), "Default constructor creates an empty interval") .def(py::init(), py::arg("lo"), py::arg("hi"), "Constructor that accepts the endpoints of the interval.\n\n" "If lo > hi, the interval is empty.") // Static factory methods .def_static("empty", &R1Interval::Empty, "Returns the empty interval") .def_static("from_point", &R1Interval::FromPoint, py::arg("p"), "Constructs an interval containing a single point") .def_static("from_point_pair", &R1Interval::FromPointPair, py::arg("p1"), py::arg("p2"), "Constructs the minimal interval containing two points") // Properties .def_property_readonly("lo", &R1Interval::lo, "Lower bound") .def_property_readonly("hi", &R1Interval::hi, "Upper bound") .def("bounds", [](const R1Interval& self) { return py::make_tuple(self.lo(), self.hi()); }, "Return bounds as a tuple (lo, hi)") // Predicates .def("is_empty", &R1Interval::is_empty, "Return true if the interval is empty, i.e. it contains no points") // Geometric operations .def("center", &R1Interval::GetCenter, "Return the center of the interval.\n\n" "For empty intervals, the result is arbitrary.") .def("length", &R1Interval::GetLength, "Return the length of the interval.\n\n" "The length of an empty interval is negative.") .def("contains_point", py::overload_cast( &R1Interval::Contains, py::const_), py::arg("p"), "Return true if the interval contains the point 'p'") .def("interior_contains_point", py::overload_cast( &R1Interval::InteriorContains, py::const_), py::arg("p"), "Return true if the interior of the interval contains the point 'p'") .def("contains", py::overload_cast( &R1Interval::Contains, py::const_), py::arg("other"), "Return true if the interval contains the given interval") .def("interior_contains", py::overload_cast( &R1Interval::InteriorContains, py::const_), py::arg("other"), "Return true if the interior of this interval contains the entire " "interval 'other'") .def("intersects", &R1Interval::Intersects, py::arg("other"), "Return true if the two intervals contain any points in common") .def("interior_intersects", &R1Interval::InteriorIntersects, py::arg("other"), "Return true if the interior of this interval intersects any point " "of the given interval") .def("add_point", &R1Interval::AddPoint, py::arg("p"), "Expand the interval to include the given point 'p'") .def("add_interval", &R1Interval::AddInterval, py::arg("other"), "Expand the interval to include the given interval") .def("project", [](const R1Interval& self, double p) { if (self.is_empty()) { throw py::value_error("Cannot project onto an empty interval"); } return self.Project(p); }, py::arg("p"), "Return the closest point in the interval to 'p'.\n\n" "The interval must be non-empty.") .def("expanded", &R1Interval::Expanded, py::arg("margin"), "Return interval expanded on each side by 'margin'.\n\n" "If 'margin' is negative, shrink the interval instead. The " "resulting interval may be empty. Any expansion of an empty " "interval remains empty.") .def("union", &R1Interval::Union, py::arg("other"), "Return the smallest interval containing this interval and 'other'") .def("intersection", &R1Interval::Intersection, py::arg("other"), "Return the intersection of this interval with 'other'") .def("directed_hausdorff_distance", &R1Interval::GetDirectedHausdorffDistance, py::arg("other"), "Return the directed Hausdorff distance to 'other'") // Note: default value must match C++ signature in r1interval.h .def("approx_equals", &R1Interval::ApproxEquals, py::arg("other"), py::arg("max_error") = 1e-15, "Return true if approximately equal to 'other'.\n\n" "The empty interval is considered to be positioned arbitrarily, " "thus any interval with length <= 2*max_error matches the empty " "interval.") // Operators .def(py::self == py::self, "Return true if two intervals contain the same set of points") .def(py::self != py::self, "Return true if two intervals do not contain the same set of points") .def("__hash__", [](const R1Interval& self) { return absl::HashOf(self); }) // String representation .def("__repr__", [](const R1Interval& i) { std::ostringstream oss; oss << "R1Interval(" << i << ")"; return oss.str(); }) .def("__str__", [](const R1Interval& i) { std::ostringstream oss; oss << i; return oss.str(); }); } src/python/r1interval_test.py000066400000000000000000000223451524103652300166750ustar00rootroot00000000000000"""Tests for R1Interval pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestR1Interval(unittest.TestCase): """Test cases for R1Interval bindings.""" # Constructors def test_default_constructor(self): interval = s2.R1Interval() self.assertTrue(interval.is_empty()) def test_constructor_with_bounds(self): interval = s2.R1Interval(1.0, 3.0) self.assertEqual(interval.lo, 1.0) self.assertEqual(interval.hi, 3.0) self.assertFalse(interval.is_empty()) def test_constructor_lo_greater_than_hi_is_empty(self): interval = s2.R1Interval(3.0, 1.0) self.assertTrue(interval.is_empty()) def test_constructor_negative_values(self): interval = s2.R1Interval(-5.0, -2.0) self.assertEqual(interval.lo, -5.0) self.assertEqual(interval.hi, -2.0) self.assertFalse(interval.is_empty()) def test_constructor_large_values(self): interval = s2.R1Interval(-1e10, 1e10) self.assertEqual(interval.lo, -1e10) self.assertEqual(interval.hi, 1e10) # Static factory methods def test_empty(self): empty = s2.R1Interval.empty() self.assertTrue(empty.is_empty()) def test_from_point(self): interval = s2.R1Interval.from_point(5.0) self.assertEqual(interval.lo, 5.0) self.assertEqual(interval.hi, 5.0) self.assertFalse(interval.is_empty()) def test_from_point_pair(self): interval = s2.R1Interval.from_point_pair(5.0, 2.0) self.assertEqual(interval.lo, 2.0) self.assertEqual(interval.hi, 5.0) self.assertTrue(interval.contains_point(3.0)) def test_from_point_pair_ordered(self): interval = s2.R1Interval.from_point_pair(2.0, 5.0) self.assertEqual(interval.lo, 2.0) self.assertEqual(interval.hi, 5.0) # Properties def test_properties_lo_hi(self): interval = s2.R1Interval(1.0, 3.0) self.assertEqual(interval.lo, 1.0) self.assertEqual(interval.hi, 3.0) def test_lo_hi_are_readonly(self): interval = s2.R1Interval(1.0, 3.0) with self.assertRaises(AttributeError): interval.lo = 0.5 with self.assertRaises(AttributeError): interval.hi = 0.5 def test_bounds(self): interval = s2.R1Interval(1.0, 3.0) bounds = interval.bounds() self.assertEqual(bounds, (1.0, 3.0)) # Predicates def test_is_empty(self): self.assertTrue(s2.R1Interval().is_empty()) self.assertTrue(s2.R1Interval.empty().is_empty()) self.assertFalse(s2.R1Interval(1.0, 3.0).is_empty()) self.assertFalse(s2.R1Interval(1.0, 1.0).is_empty()) # single point # Geometric operations def test_center(self): interval = s2.R1Interval(1.0, 3.0) self.assertAlmostEqual(interval.center(), 2.0) def test_length(self): interval = s2.R1Interval(1.0, 3.0) self.assertAlmostEqual(interval.length(), 2.0) def test_length_empty_is_negative(self): empty = s2.R1Interval.empty() self.assertLess(empty.length(), 0) def test_contains_point(self): interval = s2.R1Interval(1.0, 3.0) self.assertTrue(interval.contains_point(1.0)) # lo boundary self.assertTrue(interval.contains_point(2.0)) # interior self.assertTrue(interval.contains_point(3.0)) # hi boundary self.assertFalse(interval.contains_point(0.5)) # below self.assertFalse(interval.contains_point(3.5)) # above def test_interior_contains_point(self): interval = s2.R1Interval(1.0, 3.0) self.assertFalse(interval.interior_contains_point(1.0)) # lo boundary self.assertTrue(interval.interior_contains_point(2.0)) # interior self.assertFalse(interval.interior_contains_point(3.0)) # hi boundary def test_contains_interval(self): outer = s2.R1Interval(1.0, 5.0) inner = s2.R1Interval(2.0, 4.0) disjoint = s2.R1Interval(6.0, 8.0) self.assertTrue(outer.contains(inner)) self.assertFalse(inner.contains(outer)) self.assertFalse(outer.contains(disjoint)) def test_contains_empty_interval(self): interval = s2.R1Interval(1.0, 3.0) empty = s2.R1Interval.empty() self.assertTrue(interval.contains(empty)) def test_interior_contains_interval(self): outer = s2.R1Interval(1.0, 5.0) inner = s2.R1Interval(2.0, 4.0) boundary = s2.R1Interval(1.0, 5.0) self.assertTrue(outer.interior_contains(inner)) self.assertFalse(outer.interior_contains(boundary)) def test_intersects(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(2.0, 4.0) i3 = s2.R1Interval(4.0, 6.0) self.assertTrue(i1.intersects(i2)) self.assertFalse(i1.intersects(i3)) def test_interior_intersects(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(2.0, 4.0) touching = s2.R1Interval(3.0, 5.0) self.assertTrue(i1.interior_intersects(i2)) self.assertFalse(i1.interior_intersects(touching)) def test_add_point(self): interval = s2.R1Interval(1.0, 3.0) interval.add_point(5.0) self.assertEqual(interval.hi, 5.0) interval.add_point(-1.0) self.assertEqual(interval.lo, -1.0) def test_add_point_to_empty(self): interval = s2.R1Interval() interval.add_point(2.0) self.assertEqual(interval.lo, 2.0) self.assertEqual(interval.hi, 2.0) def test_add_interval(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(2.0, 5.0) i1.add_interval(i2) self.assertEqual(i1.lo, 1.0) self.assertEqual(i1.hi, 5.0) def test_project(self): interval = s2.R1Interval(1.0, 3.0) self.assertAlmostEqual(interval.project(2.0), 2.0) # inside self.assertAlmostEqual(interval.project(0.0), 1.0) # below self.assertAlmostEqual(interval.project(5.0), 3.0) # above def test_project_on_empty_raises(self): with self.assertRaises(ValueError): s2.R1Interval.empty().project(1.0) def test_expanded(self): interval = s2.R1Interval(1.0, 3.0) expanded = interval.expanded(0.5) self.assertAlmostEqual(expanded.lo, 0.5) self.assertAlmostEqual(expanded.hi, 3.5) def test_expanded_shrink(self): interval = s2.R1Interval(1.0, 3.0) shrunk = interval.expanded(-0.5) self.assertAlmostEqual(shrunk.lo, 1.5) self.assertAlmostEqual(shrunk.hi, 2.5) def test_expanded_empty_stays_empty(self): empty = s2.R1Interval.empty() expanded = empty.expanded(1.0) self.assertTrue(expanded.is_empty()) def test_union(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(5.0, 7.0) union = i1.union(i2) self.assertEqual(union.lo, 1.0) self.assertEqual(union.hi, 7.0) def test_intersection(self): i1 = s2.R1Interval(1.0, 5.0) i2 = s2.R1Interval(3.0, 7.0) intersection = i1.intersection(i2) self.assertEqual(intersection.lo, 3.0) self.assertEqual(intersection.hi, 5.0) def test_intersection_disjoint(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(5.0, 7.0) intersection = i1.intersection(i2) self.assertTrue(intersection.is_empty()) def test_directed_hausdorff_distance(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(2.0, 5.0) dist = i1.directed_hausdorff_distance(i2) # max of (1-2, 3-5) clamped to 0 = max(0, 0) = 0 # Actually: max(0, max(hi-y.hi, y.lo-lo)) = max(0, max(3-5, 2-1)) = max(0, 1) = 1 self.assertAlmostEqual(dist, 1.0) def test_directed_hausdorff_distance_empty(self): empty = s2.R1Interval.empty() i = s2.R1Interval(1.0, 3.0) self.assertAlmostEqual(empty.directed_hausdorff_distance(i), 0.0) def test_approx_equals(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(1.0, 3.0) i3 = s2.R1Interval(1.0, 3.0 + 1e-16) i4 = s2.R1Interval(1.0, 3.1) self.assertTrue(i1.approx_equals(i2)) self.assertTrue(i1.approx_equals(i3)) self.assertFalse(i1.approx_equals(i4)) self.assertTrue(i1.approx_equals(i4, 0.2)) # Operators def test_equality(self): i1 = s2.R1Interval(1.0, 3.0) i2 = s2.R1Interval(1.0, 3.0) i3 = s2.R1Interval(1.0, 4.0) self.assertTrue(i1 == i2) self.assertTrue(i1 != i3) def test_empty_intervals_are_equal(self): e1 = s2.R1Interval.empty() e2 = s2.R1Interval() self.assertTrue(e1 == e2) def test_hash(self): a = s2.R1Interval(0.0, 1.0) b = s2.R1Interval(0.0, 1.0) self.assertEqual(hash(a), hash(b)) self.assertEqual(len({a, b}), 1) # String representation def test_string_representation(self): interval = s2.R1Interval(1.0, 3.0) self.assertEqual(repr(interval), "R1Interval([1, 3])") self.assertEqual(str(interval), "[1, 3]") def test_string_representation_empty(self): empty = s2.R1Interval.empty() self.assertEqual(repr(empty), "R1Interval([1, 0])") self.assertEqual(str(empty), "[1, 0]") if __name__ == "__main__": unittest.main() src/python/r2point_bindings.cc000066400000000000000000000065001524103652300167510ustar00rootroot00000000000000#include #include #include #include "absl/hash/hash.h" #include "s2/r2.h" namespace py = pybind11; void bind_r2point(py::module& m) { py::class_(m, "R2Point") // Constructors .def(py::init<>(), "Default constructor creates a zero vector") .def(py::init(), py::arg("x"), py::arg("y"), "Constructor that accepts x, y coordinates") .def(py::init([](py::tuple t) { if (t.size() != 2) { throw py::value_error("Tuple must have exactly 2 elements"); } return R2Point(t[0].cast(), t[1].cast()); }), py::arg("coords"), "Constructor that accepts a tuple of (x, y) coordinates") // Properties .def_property_readonly("x", py::overload_cast<>(&R2Point::x, py::const_), "The x coordinate") .def_property_readonly("y", py::overload_cast<>(&R2Point::y, py::const_), "The y coordinate") .def("data", [](const R2Point& self) { return py::make_tuple(self.x(), self.y()); }, "Return coordinates as a tuple (x, y)") // Vector operations .def("norm", &R2Point::Norm, "Return the Euclidean norm (length)") .def("norm2", &R2Point::Norm2, "Return the squared Euclidean norm") .def("normalize", &R2Point::Normalize, "Return a normalized copy of the vector.\n\n" "Returns a unit vector if the norm is nonzero.") .def("dot_prod", [](const R2Point& self, const R2Point& other) { return self.DotProd(other); }, py::arg("other"), "Return the dot product with another point") .def("cross_prod", [](const R2Point& self, const R2Point& other) { return self.CrossProd(other); }, py::arg("other"), "Return the cross product with another point (scalar for 2D)") .def("angle", [](const R2Point& self, const R2Point& other) { return self.Angle(other); }, py::arg("other"), "Return the angle between this and another point (radians).\n\n" "The result is in the range [-pi, pi].") .def("ortho", &R2Point::Ortho, "Return a perpendicular vector (rotated 90 degrees CCW)") .def("fabs", &R2Point::Fabs, "Return a vector with component-wise absolute values") // Operators .def(py::self + py::self, "Add two points (vector addition)") .def(py::self - py::self, "Subtract two points (vector subtraction)") .def(py::self * double(), "Multiply by scalar") .def("__rmul__", [](const R2Point& self, double v) -> R2Point { return self * v; }, "Multiply by scalar (reversed operands)") .def(py::self / double(), "Divide by scalar") .def(-py::self, "Negate point") .def(py::self == py::self, "Return true if points are exactly equal") .def(py::self != py::self, "Return true if points are not exactly equal") .def("__hash__", [](const R2Point& self) { return absl::HashOf(self); }) // String representation .def("__repr__", [](const R2Point& p) { std::ostringstream oss; oss << "R2Point(" << p << ")"; return oss.str(); }) .def("__str__", [](const R2Point& p) { std::ostringstream oss; oss << p; return oss.str(); }); } src/python/r2point_test.py000066400000000000000000000125261524103652300162030ustar00rootroot00000000000000"""Tests for R2Point pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestR2Point(unittest.TestCase): """Test cases for R2Point bindings.""" # Constructors def test_default_constructor(self): p = s2.R2Point() self.assertEqual(p.x, 0.0) self.assertEqual(p.y, 0.0) def test_constructor_with_coordinates(self): p = s2.R2Point(1.0, 2.0) self.assertEqual(p.x, 1.0) self.assertEqual(p.y, 2.0) def test_constructor_from_tuple(self): p = s2.R2Point((3.0, 4.0)) self.assertEqual(p.x, 3.0) self.assertEqual(p.y, 4.0) def test_constructor_from_tuple_wrong_length(self): with self.assertRaises(ValueError): s2.R2Point((1.0,)) with self.assertRaises(ValueError): s2.R2Point((1.0, 2.0, 3.0)) # Properties def test_properties_are_readonly(self): p = s2.R2Point(1.0, 2.0) with self.assertRaises(AttributeError): p.x = 5.0 with self.assertRaises(AttributeError): p.y = 5.0 def test_data(self): p = s2.R2Point(1.0, 2.0) coords = p.data() self.assertEqual(coords, (1.0, 2.0)) # Vector operations def test_norm(self): p = s2.R2Point(3.0, 4.0) self.assertAlmostEqual(p.norm(), 5.0) self.assertAlmostEqual(p.norm2(), 25.0) def test_normalize(self): p = s2.R2Point(3.0, 4.0) normalized = p.normalize() self.assertAlmostEqual(normalized.norm(), 1.0) self.assertAlmostEqual(normalized.x, 0.6) self.assertAlmostEqual(normalized.y, 0.8) def test_dot_product(self): p1 = s2.R2Point(1.0, 0.0) p2 = s2.R2Point(0.0, 1.0) p3 = s2.R2Point(2.0, 3.0) self.assertAlmostEqual(p1.dot_prod(p2), 0.0) self.assertAlmostEqual(p1.dot_prod(p3), 2.0) def test_cross_product(self): p1 = s2.R2Point(1.0, 0.0) p2 = s2.R2Point(0.0, 1.0) # 2D cross product returns scalar: x1*y2 - y1*x2 self.assertAlmostEqual(p1.cross_prod(p2), 1.0) def test_angle(self): p1 = s2.R2Point(1.0, 0.0) p2 = s2.R2Point(0.0, 1.0) self.assertAlmostEqual(p1.angle(p2), math.pi / 2) def test_ortho(self): p = s2.R2Point(1.0, 0.0) o = p.ortho() # Rotated 90 degrees CCW: (1, 0) -> (0, 1) self.assertAlmostEqual(o.x, 0.0) self.assertAlmostEqual(o.y, 1.0) def test_ortho_general(self): p = s2.R2Point(3.0, 4.0) o = p.ortho() # Should be perpendicular self.assertAlmostEqual(p.dot_prod(o), 0.0) # Same norm self.assertAlmostEqual(o.norm(), p.norm()) def test_fabs(self): p = s2.R2Point(-3.0, -4.0) a = p.fabs() self.assertAlmostEqual(a.x, 3.0) self.assertAlmostEqual(a.y, 4.0) def test_fabs_mixed(self): p = s2.R2Point(-1.0, 2.0) a = p.fabs() self.assertAlmostEqual(a.x, 1.0) self.assertAlmostEqual(a.y, 2.0) # Operators def test_addition(self): p1 = s2.R2Point(1.0, 2.0) p2 = s2.R2Point(3.0, 4.0) result = p1 + p2 self.assertAlmostEqual(result.x, 4.0) self.assertAlmostEqual(result.y, 6.0) def test_subtraction(self): p1 = s2.R2Point(3.0, 4.0) p2 = s2.R2Point(1.0, 2.0) result = p1 - p2 self.assertAlmostEqual(result.x, 2.0) self.assertAlmostEqual(result.y, 2.0) def test_scalar_multiplication(self): p = s2.R2Point(1.0, 2.0) result1 = p * 3.0 result2 = 3.0 * p for result in [result1, result2]: self.assertAlmostEqual(result.x, 3.0) self.assertAlmostEqual(result.y, 6.0) def test_scalar_division(self): p = s2.R2Point(4.0, 6.0) result = p / 2.0 self.assertAlmostEqual(result.x, 2.0) self.assertAlmostEqual(result.y, 3.0) def test_negation(self): p = s2.R2Point(1.0, -2.0) result = -p self.assertAlmostEqual(result.x, -1.0) self.assertAlmostEqual(result.y, 2.0) def test_equality(self): p1 = s2.R2Point(1.0, 2.0) p2 = s2.R2Point(1.0, 2.0) p3 = s2.R2Point(1.0, 3.0) self.assertEqual(p1, p2) self.assertNotEqual(p1, p3) def test_add_assign(self): p = s2.R2Point(1.0, 2.0) p += s2.R2Point(3.0, 4.0) self.assertAlmostEqual(p.x, 4.0) self.assertAlmostEqual(p.y, 6.0) def test_sub_assign(self): p = s2.R2Point(3.0, 4.0) p -= s2.R2Point(1.0, 2.0) self.assertAlmostEqual(p.x, 2.0) self.assertAlmostEqual(p.y, 2.0) def test_mul_assign(self): p = s2.R2Point(1.0, 2.0) p *= 3.0 self.assertAlmostEqual(p.x, 3.0) self.assertAlmostEqual(p.y, 6.0) def test_div_assign(self): p = s2.R2Point(4.0, 6.0) p /= 2.0 self.assertAlmostEqual(p.x, 2.0) self.assertAlmostEqual(p.y, 3.0) def test_hash(self): a = s2.R2Point(1.0, 2.0) b = s2.R2Point(1.0, 2.0) self.assertEqual(hash(a), hash(b)) self.assertEqual(len({a, b}), 1) # String representation def test_string_representation(self): p = s2.R2Point(1.0, 2.0) self.assertEqual(repr(p), "R2Point([1, 2])") self.assertEqual(str(p), "[1, 2]") if __name__ == "__main__": unittest.main() src/python/r2rect_bindings.cc000066400000000000000000000172711524103652300165640ustar00rootroot00000000000000#include #include #include #include "absl/hash/hash.h" #include "s2/r2rect.h" namespace py = pybind11; namespace { void MaybeThrowInvalidRect(const R2Point& lo, const R2Point& hi) { // Both x and y intervals must be either both empty or both non-empty. bool x_empty = lo.x() > hi.x(); bool y_empty = lo.y() > hi.y(); if (x_empty != y_empty) { std::ostringstream oss; oss << "Invalid R2Rect: x and y intervals must be both empty or both " << "non-empty, got lo=" << lo << " hi=" << hi; throw py::value_error(oss.str()); } } } // namespace void bind_r2rect(py::module& m) { py::class_(m, "R2Rect") // Constructors .def(py::init<>(), "Default constructor creates an empty rectangle") .def(py::init([](const R2Point& lo, const R2Point& hi) { MaybeThrowInvalidRect(lo, hi); return R2Rect(lo, hi); }), py::arg("lo"), py::arg("hi"), "Constructor from lower-left and upper-right points.\n\n" "Raises ValueError if one axis interval is empty and the other " "is not.") .def(py::init([](const R1Interval& x, const R1Interval& y) { if (x.is_empty() != y.is_empty()) { throw py::value_error( "Invalid R2Rect: x and y intervals must be both empty or " "both non-empty"); } return R2Rect(x, y); }), py::arg("x"), py::arg("y"), "Constructor from x and y intervals.\n\n" "Both intervals must be either both empty or both non-empty.\n" "Raises ValueError if one is empty and the other is not.") // Static factory methods .def_static("empty", &R2Rect::Empty, "Returns the canonical empty rectangle") .def_static("from_center_size", [](const R2Point& center, const R2Point& size) { if (size.x() < 0 || size.y() < 0) { throw py::value_error( "Both components of size must be non-negative"); } return R2Rect::FromCenterSize(center, size); }, py::arg("center"), py::arg("size"), "Construct a rectangle from a center point and size.\n\n" "Both components of size must be non-negative.\n" "Raises ValueError if any size component is negative.") .def_static("from_point", &R2Rect::FromPoint, py::arg("p"), "Constructs a rectangle containing a single point") .def_static("from_point_pair", &R2Rect::FromPointPair, py::arg("p1"), py::arg("p2"), "Constructs the minimal bounding rectangle containing two " "points") // Properties .def_property_readonly("lo", &R2Rect::lo, "Lower-left corner of the rectangle") .def_property_readonly("hi", &R2Rect::hi, "Upper-right corner of the rectangle") .def_property_readonly("x", &R2Rect::x, "The x-interval") .def_property_readonly("y", &R2Rect::y, "The y-interval") // Predicates .def("is_valid", &R2Rect::is_valid, "Return true if the rectangle is valid") .def("is_empty", &R2Rect::is_empty, "Return true if the rectangle is empty") // Geometric operations .def("vertex", py::overload_cast(&R2Rect::GetVertex, py::const_), py::arg("k"), "Return the k-th vertex of the rectangle (k = 0,1,2,3) in CCW " "order.\n\n" "Vertex 0 is in the lower-left corner. The argument is reduced " "modulo 4.") .def("vertex_ij", [](const R2Rect& self, int i, int j) { return self.GetVertex(i, j); }, py::arg("i"), py::arg("j"), "Return the vertex in direction i along x-axis (0=left, 1=right) " "and direction j along y-axis (0=down, 1=up)") .def("center", &R2Rect::GetCenter, "Return the center of the rectangle") .def("size", &R2Rect::GetSize, "Return the width and height of the rectangle.\n\n" "Empty rectangles have a negative width and height.") .def("contains_point", py::overload_cast( &R2Rect::Contains, py::const_), py::arg("p"), "Return true if the rectangle contains the given point") .def("interior_contains_point", py::overload_cast( &R2Rect::InteriorContains, py::const_), py::arg("p"), "Return true if the interior of the rectangle contains the given " "point") .def("contains", py::overload_cast( &R2Rect::Contains, py::const_), py::arg("other"), "Return true if the rectangle contains the given other rectangle") .def("interior_contains", py::overload_cast( &R2Rect::InteriorContains, py::const_), py::arg("other"), "Return true if the interior of this rectangle contains all points " "of 'other'") .def("intersects", &R2Rect::Intersects, py::arg("other"), "Return true if this rectangle and 'other' have any points in " "common") .def("interior_intersects", &R2Rect::InteriorIntersects, py::arg("other"), "Return true if the interior of this rectangle intersects any " "point of 'other'") .def("add_point", &R2Rect::AddPoint, py::arg("p"), "Expand the rectangle to include the given point") .def("add_rect", &R2Rect::AddRect, py::arg("other"), "Expand the rectangle to include the given other rectangle") .def("project", [](const R2Rect& self, const R2Point& p) { if (self.is_empty()) { throw py::value_error( "Cannot project onto an empty rectangle"); } return self.Project(p); }, py::arg("p"), "Return the closest point in the rectangle to 'p'.\n\n" "The rectangle must be non-empty.") .def("expanded", py::overload_cast(&R2Rect::Expanded, py::const_), py::arg("margin"), "Return a rectangle expanded on each side by margin.\n\n" "margin.x() is applied on each side in the x-direction and " "margin.y() in the y-direction. If a margin component is negative, " "shrink the corresponding sides instead.") .def("union", &R2Rect::Union, py::arg("other"), "Return the smallest rectangle containing this rectangle and " "'other'") .def("intersection", &R2Rect::Intersection, py::arg("other"), "Return the smallest rectangle containing the intersection of " "this rectangle and 'other'") // Note: default value must match C++ signature in r2rect.h .def("approx_equals", &R2Rect::ApproxEquals, py::arg("other"), py::arg("max_error") = 1e-15, "Return true if approximately equal to 'other'") // Operators .def(py::self == py::self, "Return true if two rectangles are equal") .def(py::self != py::self, "Return true if two rectangles are not equal") .def("__hash__", [](const R2Rect& self) { return absl::HashOf(self); }) // String representation .def("__repr__", [](const R2Rect& r) { std::ostringstream oss; oss << "R2Rect(" << r << ")"; return oss.str(); }) .def("__str__", [](const R2Rect& r) { std::ostringstream oss; oss << r; return oss.str(); }); } src/python/r2rect_test.py000066400000000000000000000267501524103652300160130ustar00rootroot00000000000000"""Tests for R2Rect pybind11 bindings.""" import unittest import s2geometry_pybind as s2 class TestR2Rect(unittest.TestCase): """Test cases for R2Rect bindings.""" # Constructors def test_default_constructor(self): rect = s2.R2Rect() self.assertTrue(rect.is_empty()) def test_constructor_from_points(self): lo = s2.R2Point(1.0, 2.0) hi = s2.R2Point(3.0, 4.0) rect = s2.R2Rect(lo, hi) self.assertEqual(rect.lo, lo) self.assertEqual(rect.hi, hi) self.assertFalse(rect.is_empty()) def test_constructor_from_intervals(self): x = s2.R1Interval(1.0, 3.0) y = s2.R1Interval(2.0, 4.0) rect = s2.R2Rect(x, y) self.assertEqual(rect.x, x) self.assertEqual(rect.y, y) def test_constructor_from_intervals_both_empty(self): x = s2.R1Interval.empty() y = s2.R1Interval.empty() rect = s2.R2Rect(x, y) self.assertTrue(rect.is_empty()) def test_constructor_from_intervals_mixed_empty_raises(self): x = s2.R1Interval(1.0, 3.0) y = s2.R1Interval.empty() with self.assertRaises(ValueError): s2.R2Rect(x, y) def test_constructor_from_points_mixed_empty_raises(self): # lo.x > hi.x but lo.y < hi.y -> one axis empty, other not lo = s2.R2Point(3.0, 1.0) hi = s2.R2Point(1.0, 4.0) with self.assertRaises(ValueError): s2.R2Rect(lo, hi) # Static factory methods def test_empty(self): rect = s2.R2Rect.empty() self.assertTrue(rect.is_empty()) def test_from_point(self): p = s2.R2Point(1.0, 2.0) rect = s2.R2Rect.from_point(p) self.assertEqual(rect.lo, p) self.assertEqual(rect.hi, p) self.assertFalse(rect.is_empty()) def test_from_point_pair(self): p1 = s2.R2Point(3.0, 4.0) p2 = s2.R2Point(1.0, 2.0) rect = s2.R2Rect.from_point_pair(p1, p2) self.assertAlmostEqual(rect.lo.x, 1.0) self.assertAlmostEqual(rect.lo.y, 2.0) self.assertAlmostEqual(rect.hi.x, 3.0) self.assertAlmostEqual(rect.hi.y, 4.0) def test_from_center_size(self): center = s2.R2Point(2.0, 3.0) size = s2.R2Point(4.0, 6.0) rect = s2.R2Rect.from_center_size(center, size) self.assertAlmostEqual(rect.lo.x, 0.0) self.assertAlmostEqual(rect.lo.y, 0.0) self.assertAlmostEqual(rect.hi.x, 4.0) self.assertAlmostEqual(rect.hi.y, 6.0) def test_from_center_size_negative_raises(self): center = s2.R2Point(0.0, 0.0) with self.assertRaises(ValueError): s2.R2Rect.from_center_size(center, s2.R2Point(-1.0, 2.0)) with self.assertRaises(ValueError): s2.R2Rect.from_center_size(center, s2.R2Point(1.0, -2.0)) # Properties def test_lo_hi(self): rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 4.0)) self.assertAlmostEqual(rect.lo.x, 1.0) self.assertAlmostEqual(rect.lo.y, 2.0) self.assertAlmostEqual(rect.hi.x, 3.0) self.assertAlmostEqual(rect.hi.y, 4.0) def test_x_y(self): rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 4.0)) self.assertEqual(rect.x, s2.R1Interval(1.0, 3.0)) self.assertEqual(rect.y, s2.R1Interval(2.0, 4.0)) def test_properties_are_readonly(self): rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 4.0)) with self.assertRaises(AttributeError): rect.lo = s2.R2Point(0.0, 0.0) with self.assertRaises(AttributeError): rect.hi = s2.R2Point(0.0, 0.0) with self.assertRaises(AttributeError): rect.x = s2.R1Interval(0.0, 1.0) with self.assertRaises(AttributeError): rect.y = s2.R1Interval(0.0, 1.0) # Predicates def test_is_valid(self): rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 4.0)) self.assertTrue(rect.is_valid()) self.assertTrue(s2.R2Rect.empty().is_valid()) def test_is_empty(self): self.assertTrue(s2.R2Rect().is_empty()) self.assertTrue(s2.R2Rect.empty().is_empty()) rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 4.0)) self.assertFalse(rect.is_empty()) # Geometric operations def test_vertex(self): rect = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) # CCW: lower-left, lower-right, upper-right, upper-left v0 = rect.vertex(0) v1 = rect.vertex(1) v2 = rect.vertex(2) v3 = rect.vertex(3) self.assertEqual(v0, s2.R2Point(0.0, 0.0)) self.assertEqual(v1, s2.R2Point(1.0, 0.0)) self.assertEqual(v2, s2.R2Point(1.0, 1.0)) self.assertEqual(v3, s2.R2Point(0.0, 1.0)) def test_vertex_ij(self): rect = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) self.assertEqual(rect.vertex_ij(0, 0), s2.R2Point(0.0, 0.0)) self.assertEqual(rect.vertex_ij(1, 0), s2.R2Point(1.0, 0.0)) self.assertEqual(rect.vertex_ij(0, 1), s2.R2Point(0.0, 1.0)) self.assertEqual(rect.vertex_ij(1, 1), s2.R2Point(1.0, 1.0)) def test_center(self): rect = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 4.0)) center = rect.center() self.assertAlmostEqual(center.x, 1.0) self.assertAlmostEqual(center.y, 2.0) def test_size(self): rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 6.0)) size = rect.size() self.assertAlmostEqual(size.x, 2.0) self.assertAlmostEqual(size.y, 4.0) def test_contains_point(self): rect = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 2.0)) self.assertTrue(rect.contains_point(s2.R2Point(1.0, 1.0))) # interior self.assertTrue(rect.contains_point(s2.R2Point(0.0, 0.0))) # corner self.assertTrue(rect.contains_point(s2.R2Point(2.0, 2.0))) # corner self.assertFalse(rect.contains_point(s2.R2Point(3.0, 1.0))) # outside def test_interior_contains_point(self): rect = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 2.0)) self.assertTrue(rect.interior_contains_point(s2.R2Point(1.0, 1.0))) self.assertFalse(rect.interior_contains_point(s2.R2Point(0.0, 0.0))) self.assertFalse(rect.interior_contains_point(s2.R2Point(2.0, 1.0))) def test_contains_rect(self): outer = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(4.0, 4.0)) inner = s2.R2Rect(s2.R2Point(1.0, 1.0), s2.R2Point(3.0, 3.0)) disjoint = s2.R2Rect(s2.R2Point(5.0, 5.0), s2.R2Point(6.0, 6.0)) self.assertTrue(outer.contains(inner)) self.assertFalse(inner.contains(outer)) self.assertFalse(outer.contains(disjoint)) def test_interior_contains_rect(self): outer = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(4.0, 4.0)) inner = s2.R2Rect(s2.R2Point(1.0, 1.0), s2.R2Point(3.0, 3.0)) same = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(4.0, 4.0)) self.assertTrue(outer.interior_contains(inner)) self.assertFalse(outer.interior_contains(same)) def test_intersects(self): r1 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 2.0)) r2 = s2.R2Rect(s2.R2Point(1.0, 1.0), s2.R2Point(3.0, 3.0)) r3 = s2.R2Rect(s2.R2Point(3.0, 3.0), s2.R2Point(4.0, 4.0)) self.assertTrue(r1.intersects(r2)) self.assertFalse(r1.intersects(r3)) def test_interior_intersects(self): r1 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 2.0)) r2 = s2.R2Rect(s2.R2Point(1.0, 1.0), s2.R2Point(3.0, 3.0)) touching = s2.R2Rect(s2.R2Point(2.0, 2.0), s2.R2Point(3.0, 3.0)) self.assertTrue(r1.interior_intersects(r2)) self.assertFalse(r1.interior_intersects(touching)) def test_add_point(self): rect = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) rect.add_point(s2.R2Point(3.0, 3.0)) self.assertAlmostEqual(rect.hi.x, 3.0) self.assertAlmostEqual(rect.hi.y, 3.0) def test_add_rect(self): r1 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) r2 = s2.R2Rect(s2.R2Point(2.0, 2.0), s2.R2Point(3.0, 3.0)) r1.add_rect(r2) self.assertAlmostEqual(r1.lo.x, 0.0) self.assertAlmostEqual(r1.lo.y, 0.0) self.assertAlmostEqual(r1.hi.x, 3.0) self.assertAlmostEqual(r1.hi.y, 3.0) def test_project(self): rect = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 2.0)) # Point inside p = rect.project(s2.R2Point(1.0, 1.0)) self.assertEqual(p, s2.R2Point(1.0, 1.0)) # Point outside p = rect.project(s2.R2Point(5.0, 5.0)) self.assertEqual(p, s2.R2Point(2.0, 2.0)) # Point below p = rect.project(s2.R2Point(-1.0, -1.0)) self.assertEqual(p, s2.R2Point(0.0, 0.0)) def test_project_on_empty_raises(self): with self.assertRaises(ValueError): s2.R2Rect.empty().project(s2.R2Point(1.0, 1.0)) def test_expanded(self): rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 4.0)) expanded = rect.expanded(s2.R2Point(0.5, 1.0)) self.assertAlmostEqual(expanded.lo.x, 0.5) self.assertAlmostEqual(expanded.lo.y, 1.0) self.assertAlmostEqual(expanded.hi.x, 3.5) self.assertAlmostEqual(expanded.hi.y, 5.0) def test_union(self): r1 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) r2 = s2.R2Rect(s2.R2Point(2.0, 2.0), s2.R2Point(3.0, 3.0)) union = r1.union(r2) self.assertAlmostEqual(union.lo.x, 0.0) self.assertAlmostEqual(union.lo.y, 0.0) self.assertAlmostEqual(union.hi.x, 3.0) self.assertAlmostEqual(union.hi.y, 3.0) def test_intersection(self): r1 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 2.0)) r2 = s2.R2Rect(s2.R2Point(1.0, 1.0), s2.R2Point(3.0, 3.0)) inter = r1.intersection(r2) self.assertAlmostEqual(inter.lo.x, 1.0) self.assertAlmostEqual(inter.lo.y, 1.0) self.assertAlmostEqual(inter.hi.x, 2.0) self.assertAlmostEqual(inter.hi.y, 2.0) def test_approx_equals(self): r1 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) r2 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) r3 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0 + 1e-16)) r4 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.1)) self.assertTrue(r1.approx_equals(r2)) self.assertTrue(r1.approx_equals(r3)) self.assertFalse(r1.approx_equals(r4)) self.assertTrue(r1.approx_equals(r4, 0.2)) # Operators def test_equality(self): r1 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) r2 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) r3 = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(2.0, 2.0)) self.assertTrue(r1 == r2) self.assertTrue(r1 != r3) def test_empty_rects_are_equal(self): e1 = s2.R2Rect.empty() e2 = s2.R2Rect() self.assertTrue(e1 == e2) def test_hash(self): a = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) b = s2.R2Rect(s2.R2Point(0.0, 0.0), s2.R2Point(1.0, 1.0)) self.assertEqual(hash(a), hash(b)) self.assertEqual(len({a, b}), 1) # String representation def test_string_representation(self): rect = s2.R2Rect(s2.R2Point(1.0, 2.0), s2.R2Point(3.0, 4.0)) repr_str = repr(rect) str_str = str(rect) self.assertTrue(repr_str.startswith("R2Rect(")) # str should not have the class name prefix self.assertFalse(str_str.startswith("R2Rect(")) if __name__ == "__main__": unittest.main() src/python/s1angle_bindings.cc000066400000000000000000000157131524103652300167140ustar00rootroot00000000000000#include #include #include #include #include "absl/hash/hash.h" #include "absl/strings/str_cat.h" #include "s2/s1angle.h" #include "s2/s2point.h" namespace py = pybind11; namespace { void MaybeThrowNotNormalized(const S1Angle& angle) { if (!angle.IsNormalized()) { throw py::value_error( absl::StrCat("Angle ", angle.degrees(), " degrees is not in the normalized range (-180, 180]")); } } } // namespace void bind_s1angle(py::module& m) { py::class_(m, "S1Angle", "Represents a one-dimensional angle.\n\n" "The internal representation is a double-precision value in radians,\n" "so conversion to and from radians is exact. Conversions between\n" "degrees and radians are not always exact due to floating-point\n" "arithmetic (e.g. from_degrees(60).degrees != 60). Use e5/e6/e7\n" "representations for exact discrete comparisons.\n\n" "See s2/s1angle.h for comprehensive documentation including exact\n" "conversion guarantees and edge cases.") // Constructors .def(py::init<>(), "Default constructor creates a zero angle") .def(py::init(), py::arg("x"), py::arg("y"), "Construct the angle between two points.\n\n" "This is also equal to the distance between the points on the\n" "unit sphere. The points do not need to be normalized.") // Factory methods .def_static("from_radians", &S1Angle::Radians, py::arg("radians"), "Construct an angle from its measure in radians.\n\n" "This conversion is exact.") .def_static("from_degrees", &S1Angle::Degrees, py::arg("degrees"), "Construct an angle from its measure in degrees.\n\n" "Note: the round-trip from_degrees(x).degrees is not\n" "always exact. For example, from_degrees(60).degrees != 60.") .def_static("from_e5", &S1Angle::E5, py::arg("e5"), "Construct an angle from its E5 representation.\n\n" "E5 is degrees multiplied by 1e5 and rounded to the\n" "nearest integer.\n\n" "Note: E5 does not share the exact conversion guarantees\n" "of E6/E7. Avoid testing E5 values for exact equality\n" "with other formats.") .def_static("from_e6", &S1Angle::E6, py::arg("e6"), "Construct an angle from its E6 representation.\n\n" "E6 is degrees multiplied by 1e6 and rounded to the\n" "nearest integer.\n\n" "For any integer n: from_degrees(n) == from_e6(1000000 * n).") .def_static("from_e7", &S1Angle::E7, py::arg("e7"), "Construct an angle from its E7 representation.\n\n" "E7 is degrees multiplied by 1e7 and rounded to the\n" "nearest integer.\n\n" "For any integer n: from_degrees(n) == from_e7(10000000 * n).") .def_static("zero", &S1Angle::Zero, "Return a zero angle") .def_static("infinity", &S1Angle::Infinity, "Return an angle larger than any finite angle") // Properties .def_property_readonly("radians", &S1Angle::radians, "The angle in radians.\n\n" "This is the internal representation, so the conversion is exact.") .def_property_readonly("degrees", &S1Angle::degrees, "The angle in degrees.\n\n" "Note: from_degrees(x).degrees is not always exactly x due to\n" "the intermediate conversion to radians.") .def_property_readonly("e5", [](const S1Angle& self) { MaybeThrowNotNormalized(self); return self.e5(); }, "The E5 representation (degrees * 1e5, rounded).\n\n" "The angle must be in the normalized range (-180, 180] degrees.\n" "Raises ValueError if out of range.") .def_property_readonly("e6", [](const S1Angle& self) { MaybeThrowNotNormalized(self); return self.e6(); }, "The E6 representation (degrees * 1e6, rounded).\n\n" "The angle must be in the normalized range (-180, 180] degrees.\n" "Raises ValueError if out of range.") .def_property_readonly("e7", [](const S1Angle& self) { MaybeThrowNotNormalized(self); return self.e7(); }, "The E7 representation (degrees * 1e7, rounded).\n\n" "The angle must be in the normalized range (-180, 180] degrees.\n" "Raises ValueError if out of range.") // Predicates .def("is_normalized", &S1Angle::IsNormalized, "Return true if the angle is in the normalized range (-180, 180]") // Geometric operations .def("__abs__", &S1Angle::abs, "Return the absolute value of the angle") .def("normalized", &S1Angle::Normalized, "Return the angle normalized to the range (-180, 180] degrees") .def("normalize", &S1Angle::Normalize, "Normalize this angle in-place to the range (-180, 180] degrees") .def("sin", [](const S1Angle& self) { return sin(self); }, "Return the sine of the angle") .def("cos", [](const S1Angle& self) { return cos(self); }, "Return the cosine of the angle") .def("tan", [](const S1Angle& self) { return tan(self); }, "Return the tangent of the angle") // Operators .def(py::self == py::self, "Return true if angles are exactly equal") .def(py::self != py::self, "Return true if angles are not exactly equal") .def(py::self < py::self, "Return true if this angle is less than other") .def(py::self > py::self, "Return true if this angle is greater than other") .def(py::self <= py::self, "Return true if this angle is less than or equal to other") .def(py::self >= py::self, "Return true if this angle is greater than or equal to other") .def(-py::self, "Negate angle") .def(py::self + py::self, "Add two angles") .def(py::self - py::self, "Subtract two angles") .def(py::self * double(), "Multiply angle by scalar") .def("__rmul__", [](const S1Angle& self, double m) { return m * self; }, "Multiply angle by scalar (reversed operands)") .def(py::self / double(), "Divide angle by scalar") .def("__truediv__", [](const S1Angle& a, const S1Angle& b) -> double { return a / b; }, py::arg("other"), "Divide two angles, returning a scalar ratio") .def("__hash__", [](S1Angle self) { return absl::HashOf(self); }) // String representation .def("__repr__", [](S1Angle a) { std::ostringstream oss; oss << "S1Angle(" << a << ")"; return oss.str(); }) .def("__str__", [](S1Angle a) { std::ostringstream oss; oss << a; return oss.str(); }); } src/python/s1angle_test.py000066400000000000000000000226341524103652300161410ustar00rootroot00000000000000"""Tests for S1Angle pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestS1Angle(unittest.TestCase): """Test cases for S1Angle bindings.""" # Constructors def test_default_constructor(self): a = s2.S1Angle() self.assertEqual(a.radians, 0.0) def test_constructor_from_two_points(self): x = s2.S2Point(1.0, 0.0, 0.0) y = s2.S2Point(0.0, 1.0, 0.0) a = s2.S1Angle(x, y) self.assertAlmostEqual(a.radians, math.pi / 2) def test_constructor_from_same_point(self): p = s2.S2Point(1.0, 0.0, 0.0) a = s2.S1Angle(p, p) self.assertEqual(a.radians, 0.0) def test_constructor_from_antipodal_points(self): x = s2.S2Point(1.0, 0.0, 0.0) y = s2.S2Point(-1.0, 0.0, 0.0) a = s2.S1Angle(x, y) self.assertAlmostEqual(a.radians, math.pi) # Factory methods def test_from_radians(self): a = s2.S1Angle.from_radians(math.pi / 4) self.assertAlmostEqual(a.radians, math.pi / 4) def test_from_degrees(self): a = s2.S1Angle.from_degrees(45.0) self.assertAlmostEqual(a.degrees, 45.0) def test_from_e5(self): a = s2.S1Angle.from_e5(4500000) self.assertAlmostEqual(a.degrees, 45.0) def test_from_e6(self): a = s2.S1Angle.from_e6(45000000) self.assertAlmostEqual(a.degrees, 45.0) def test_from_e7(self): a = s2.S1Angle.from_e7(450000000) self.assertAlmostEqual(a.degrees, 45.0) def test_zero(self): a = s2.S1Angle.zero() self.assertEqual(a.radians, 0.0) def test_infinity(self): a = s2.S1Angle.infinity() self.assertTrue(math.isinf(a.radians)) self.assertTrue(a.radians > 0) # Properties def test_radians(self): a = s2.S1Angle.from_radians(1.5) self.assertEqual(a.radians, 1.5) def test_degrees(self): a = s2.S1Angle.from_degrees(180.0) self.assertAlmostEqual(a.radians, math.pi) self.assertAlmostEqual(a.degrees, 180.0) def test_degrees_radians_conversion(self): # Exact conversions per the C++ header documentation. self.assertEqual(s2.S1Angle.from_degrees(180.0).radians, math.pi) for k in range(9): self.assertEqual( s2.S1Angle.from_degrees(45 * k).radians, k * math.pi / 4 ) def test_e5(self): a = s2.S1Angle.from_degrees(45.0) self.assertEqual(a.e5, 4500000) def test_e6(self): a = s2.S1Angle.from_degrees(45.0) self.assertEqual(a.e6, 45000000) def test_e7(self): a = s2.S1Angle.from_degrees(45.0) self.assertEqual(a.e7, 450000000) def test_e5_e6_e7_consistency(self): # Degrees(n) == E6(1000000 * n) == E7(10000000 * n) for integer n. for n in [0, 1, 45, 90, 180, -180, -90]: self.assertEqual( s2.S1Angle.from_degrees(n).radians, s2.S1Angle.from_e6(1000000 * n).radians, ) self.assertEqual( s2.S1Angle.from_degrees(n).radians, s2.S1Angle.from_e7(10000000 * n).radians, ) def test_properties_are_readonly(self): a = s2.S1Angle.from_degrees(45.0) with self.assertRaises(AttributeError): a.radians = 1.0 with self.assertRaises(AttributeError): a.degrees = 1.0 def test_e5_not_normalized_raises(self): a = s2.S1Angle.from_degrees(270.0) with self.assertRaises(ValueError): _ = a.e5 def test_e6_not_normalized_raises(self): a = s2.S1Angle.from_degrees(270.0) with self.assertRaises(ValueError): _ = a.e6 def test_e7_not_normalized_raises(self): a = s2.S1Angle.from_degrees(270.0) with self.assertRaises(ValueError): _ = a.e7 def test_e6_minus_180_not_normalized_raises(self): # -180 degrees is outside the normalized range (-180, 180]. a = s2.S1Angle.from_degrees(-180.0) with self.assertRaises(ValueError): _ = a.e6 def test_e6_plus_180_is_valid(self): # +180 degrees is inside the normalized range (-180, 180]. a = s2.S1Angle.from_degrees(180.0) self.assertEqual(a.e6, 180000000) # Predicates def test_is_normalized(self): self.assertTrue(s2.S1Angle.from_degrees(45.0).is_normalized()) self.assertTrue(s2.S1Angle.from_degrees(180.0).is_normalized()) self.assertFalse(s2.S1Angle.from_degrees(270.0).is_normalized()) self.assertFalse(s2.S1Angle.from_degrees(-180.0).is_normalized()) # Geometric operations def test_abs(self): pos = s2.S1Angle.from_degrees(45.0) neg = s2.S1Angle.from_degrees(-45.0) self.assertAlmostEqual(abs(pos).degrees, 45.0) self.assertAlmostEqual(abs(neg).degrees, 45.0) def test_abs_zero(self): a = s2.S1Angle.zero() self.assertEqual(abs(a).radians, 0.0) def test_normalized(self): a = s2.S1Angle.from_degrees(270.0) self.assertAlmostEqual(a.normalized().degrees, -90.0) def test_normalized_negative(self): a = s2.S1Angle.from_degrees(-270.0) self.assertAlmostEqual(a.normalized().degrees, 90.0) def test_normalized_minus_180_becomes_180(self): # Normalized range is (-180, 180]; -180 maps to 180. a = s2.S1Angle.from_degrees(-180.0) self.assertAlmostEqual(a.normalized().degrees, 180.0) def test_normalize_in_place(self): a = s2.S1Angle.from_degrees(270.0) a.normalize() self.assertAlmostEqual(a.degrees, -90.0) def test_sin(self): a = s2.S1Angle.from_degrees(90.0) self.assertAlmostEqual(a.sin(), 1.0) def test_cos(self): a = s2.S1Angle.from_degrees(0.0) self.assertAlmostEqual(a.cos(), 1.0) def test_tan(self): a = s2.S1Angle.from_degrees(45.0) self.assertAlmostEqual(a.tan(), 1.0) # Operators def test_equality(self): a = s2.S1Angle.from_degrees(45.0) b = s2.S1Angle.from_degrees(45.0) c = s2.S1Angle.from_degrees(90.0) self.assertTrue(a == b) self.assertTrue(a != c) self.assertFalse(a != b) self.assertFalse(a == c) def test_comparison(self): small = s2.S1Angle.from_degrees(10.0) large = s2.S1Angle.from_degrees(20.0) self.assertTrue(small < large) self.assertTrue(large > small) self.assertTrue(small <= large) self.assertTrue(large >= small) self.assertTrue(small <= small) self.assertTrue(small >= small) self.assertFalse(small > large) self.assertFalse(large < small) def test_negation(self): a = s2.S1Angle.from_degrees(45.0) neg = -a self.assertAlmostEqual(neg.degrees, -45.0) def test_addition(self): a = s2.S1Angle.from_degrees(30.0) b = s2.S1Angle.from_degrees(60.0) result = a + b self.assertAlmostEqual(result.degrees, 90.0) def test_subtraction(self): a = s2.S1Angle.from_degrees(90.0) b = s2.S1Angle.from_degrees(30.0) result = a - b self.assertAlmostEqual(result.degrees, 60.0) def test_scalar_multiplication(self): a = s2.S1Angle.from_degrees(45.0) result1 = a * 2.0 result2 = 2.0 * a self.assertAlmostEqual(result1.degrees, 90.0) self.assertAlmostEqual(result2.degrees, 90.0) def test_scalar_division(self): a = s2.S1Angle.from_degrees(90.0) result = a / 2.0 self.assertAlmostEqual(result.degrees, 45.0) def test_angle_division(self): a = s2.S1Angle.from_degrees(90.0) b = s2.S1Angle.from_degrees(45.0) ratio = a / b self.assertAlmostEqual(ratio, 2.0) def test_add_assign(self): a = s2.S1Angle.from_degrees(30.0) a += s2.S1Angle.from_degrees(60.0) self.assertAlmostEqual(a.degrees, 90.0) def test_sub_assign(self): a = s2.S1Angle.from_degrees(90.0) a -= s2.S1Angle.from_degrees(30.0) self.assertAlmostEqual(a.degrees, 60.0) def test_mul_assign(self): a = s2.S1Angle.from_degrees(45.0) a *= 2.0 self.assertAlmostEqual(a.degrees, 90.0) def test_div_assign(self): a = s2.S1Angle.from_degrees(90.0) a /= 2.0 self.assertAlmostEqual(a.degrees, 45.0) def test_hash(self): a = s2.S1Angle.from_degrees(45.0) b = s2.S1Angle.from_degrees(45.0) self.assertEqual(hash(a), hash(b)) self.assertEqual(len({a, b}), 1) # String representation def test_repr(self): # The repr format comes from C++ operator<< which uses %.7f on degrees. self.assertEqual( repr(s2.S1Angle.from_degrees(45.0)), "S1Angle(45.0000000)" ) self.assertEqual( repr(s2.S1Angle.from_degrees(45.00)), "S1Angle(45.0000000)" ) self.assertEqual( repr(s2.S1Angle.from_degrees(0.0)), "S1Angle(0.0000000)" ) self.assertEqual( repr(s2.S1Angle.from_degrees(-90.0)), "S1Angle(-90.0000000)" ) # Precision beyond 7 decimal places is truncated. self.assertEqual( repr(s2.S1Angle.from_degrees(45.0000000001)), "S1Angle(45.0000000)" ) def test_str(self): self.assertEqual(str(s2.S1Angle.from_degrees(45.0)), "45.0000000") self.assertEqual(str(s2.S1Angle.zero()), "0.0000000") if __name__ == "__main__": unittest.main() src/python/s1chord_angle_bindings.cc000066400000000000000000000207741524103652300200760ustar00rootroot00000000000000#include #include #include #include #include "absl/hash/hash.h" #include "absl/strings/str_cat.h" #include "s2/s1angle.h" #include "s2/s1chord_angle.h" #include "s2/s2point.h" #include "s2/s2pointutil.h" namespace py = pybind11; namespace { void MaybeThrowNotUnitLength(const S2Point& p, const char* name) { if (!S2::IsUnitLength(p)) { throw py::value_error( absl::StrCat(name, " must be a unit-length vector (norm=", p.Norm(), ")")); } } void MaybeThrowIfSpecial(const S1ChordAngle& a, const char* name) { if (a.is_special()) { throw py::value_error( absl::StrCat(name, " must not be a special value " "(negative() or infinity())")); } } } // namespace void bind_s1chord_angle(py::module& m) { py::class_(m, "S1ChordAngle", "Represents the angle subtended by a chord on the unit sphere.\n\n" "S1ChordAngle can represent angles between 0 and Pi radians. It is\n" "more efficient than S1Angle for computing and comparing distances,\n" "but loses some accuracy as the angle approaches Pi radians.\n\n" "See s2/s1chord_angle.h for comprehensive documentation, including\n" "accuracy analysis and guidance on when to prefer S1Angle.") // Constructors .def(py::init<>(), "Default constructor creates a zero chord angle") .def(py::init([](const S2Point& x, const S2Point& y) { MaybeThrowNotUnitLength(x, "x"); MaybeThrowNotUnitLength(y, "y"); return S1ChordAngle(x, y); }), py::arg("x"), py::arg("y"), "Construct the chord angle between two unit-length points.\n\n" "Raises ValueError if either point is not unit-length.") .def(py::init(), py::arg("angle"), "Construct from an S1Angle.\n\n" "Angles outside [0, Pi] are mapped as follows:\n" " Infinity() -> Infinity()\n" " negative -> Negative()\n" " > Pi -> Straight()\n" "This conversion is relatively expensive; prefer to convert at\n" "the boundaries of your algorithm.") // Factory methods .def_static("from_radians", &S1ChordAngle::Radians, py::arg("radians"), "Construct a chord angle from an angle in radians") .def_static("from_degrees", &S1ChordAngle::Degrees, py::arg("degrees"), "Construct a chord angle from an angle in degrees") .def_static("from_e5", &S1ChordAngle::E5, py::arg("e5"), "Construct a chord angle from the E5 representation") .def_static("from_e6", &S1ChordAngle::E6, py::arg("e6"), "Construct a chord angle from the E6 representation") .def_static("from_e7", &S1ChordAngle::E7, py::arg("e7"), "Construct a chord angle from the E7 representation") .def_static("zero", &S1ChordAngle::Zero, "Return the zero chord angle") .def_static("right", &S1ChordAngle::Right, "Return a 90-degree chord angle") .def_static("straight", &S1ChordAngle::Straight, "Return a 180-degree chord angle (the maximum finite value)") .def_static("infinity", &S1ChordAngle::Infinity, "Return a chord angle larger than any finite chord angle") .def_static("negative", &S1ChordAngle::Negative, "Return a chord angle smaller than Zero()") // Properties .def_property_readonly("radians", &S1ChordAngle::radians, "The angle in radians.\n\n" "Note: this performs a trigonometric conversion and should be\n" "avoided in inner loops.") .def_property_readonly("degrees", &S1ChordAngle::degrees, "The angle in degrees.\n\n" "Note: this performs a trigonometric conversion and should be\n" "avoided in inner loops.") .def_property_readonly("e5", [](const S1ChordAngle& self) { MaybeThrowIfSpecial(self, "self"); return self.e5(); }, "The E5 representation (degrees * 1e5, rounded).\n\n" "Raises ValueError if the angle is negative() or infinity().") .def_property_readonly("e6", [](const S1ChordAngle& self) { MaybeThrowIfSpecial(self, "self"); return self.e6(); }, "The E6 representation (degrees * 1e6, rounded).\n\n" "Raises ValueError if the angle is negative() or infinity().") .def_property_readonly("e7", [](const S1ChordAngle& self) { MaybeThrowIfSpecial(self, "self"); return self.e7(); }, "The E7 representation (degrees * 1e7, rounded).\n\n" "Raises ValueError if the angle is negative() or infinity().") // Predicates .def("is_zero", &S1ChordAngle::is_zero, "Return true if this is exactly zero") .def("is_negative", &S1ChordAngle::is_negative, "Return true if this is less than zero (e.g. Negative())") .def("is_infinity", &S1ChordAngle::is_infinity, "Return true if this is the Infinity() sentinel") .def("is_special", &S1ChordAngle::is_special, "Return true if this is Negative() or Infinity()") .def("is_valid", &S1ChordAngle::is_valid, "Return true if the internal representation is valid.\n\n" "Negative() and Infinity() are both considered valid.") // Geometric operations .def("to_angle", &S1ChordAngle::ToAngle, "Convert to an S1Angle.\n\n" "Infinity() converts to S1Angle::Infinity(); Negative() converts\n" "to an unspecified negative S1Angle. Uses trigonometric functions\n" "and should be avoided in inner loops.") .def("sin", [](const S1ChordAngle& self) { MaybeThrowIfSpecial(self, "self"); return sin(self); }, "Return the sine of the chord angle.\n\n" "More accurate and efficient than converting to S1Angle first.\n" "Raises ValueError if the angle is negative() or infinity().") .def("cos", [](const S1ChordAngle& self) { MaybeThrowIfSpecial(self, "self"); return cos(self); }, "Return the cosine of the chord angle.\n\n" "More accurate and efficient than converting to S1Angle first.\n" "Raises ValueError if the angle is negative() or infinity().") .def("tan", [](const S1ChordAngle& self) { MaybeThrowIfSpecial(self, "self"); return tan(self); }, "Return the tangent of the chord angle.\n\n" "More accurate and efficient than converting to S1Angle first.\n" "Raises ValueError if the angle is negative() or infinity().") // Operators .def(py::self == py::self, "Return true if chord angles are equal") .def(py::self != py::self, "Return true if chord angles are not equal") .def(py::self < py::self, "Return true if this is less than other (by length2)") .def(py::self > py::self, "Return true if this is greater than other (by length2)") .def(py::self <= py::self, "Return true if this is less than or equal to other") .def(py::self >= py::self, "Return true if this is greater than or equal to other") .def("__add__", [](const S1ChordAngle& a, const S1ChordAngle& b) { MaybeThrowIfSpecial(a, "left operand"); MaybeThrowIfSpecial(b, "right operand"); return a + b; }, py::is_operator(), "Add two chord angles, clamping the result to [0, Pi].\n\n" "Raises ValueError if either operand is Negative() or Infinity().") .def("__sub__", [](const S1ChordAngle& a, const S1ChordAngle& b) { MaybeThrowIfSpecial(a, "left operand"); MaybeThrowIfSpecial(b, "right operand"); return a - b; }, py::is_operator(), "Subtract two chord angles, clamping the result to [0, Pi].\n\n" "Raises ValueError if either operand is Negative() or Infinity().") .def("__hash__", [](const S1ChordAngle& self) { return absl::Hash()(self.length2()); }) // String representation .def("__repr__", [](const S1ChordAngle& a) { std::ostringstream oss; oss << "S1ChordAngle(" << a << ")"; return oss.str(); }) .def("__str__", [](const S1ChordAngle& a) { std::ostringstream oss; oss << a; return oss.str(); }); } src/python/s1chord_angle_test.py000066400000000000000000000224561524103652300173220ustar00rootroot00000000000000"""Tests for S1ChordAngle pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestS1ChordAngle(unittest.TestCase): """Test cases for S1ChordAngle bindings.""" # Constructors def test_default_constructor(self): a = s2.S1ChordAngle() self.assertTrue(a.is_zero()) def test_constructor_from_two_points(self): x = s2.S2Point(1.0, 0.0, 0.0) y = s2.S2Point(0.0, 1.0, 0.0) a = s2.S1ChordAngle(x, y) self.assertAlmostEqual(a.radians, math.pi / 2) def test_constructor_from_same_point(self): p = s2.S2Point(1.0, 0.0, 0.0) a = s2.S1ChordAngle(p, p) self.assertTrue(a.is_zero()) def test_constructor_from_antipodal_points(self): x = s2.S2Point(1.0, 0.0, 0.0) y = s2.S2Point(-1.0, 0.0, 0.0) a = s2.S1ChordAngle(x, y) self.assertEqual(a, s2.S1ChordAngle.straight()) def test_constructor_non_unit_length_raises(self): bad = s2.S2Point(2.0, 0.0, 0.0) ok = s2.S2Point(1.0, 0.0, 0.0) with self.assertRaises(ValueError): s2.S1ChordAngle(bad, ok) with self.assertRaises(ValueError): s2.S1ChordAngle(ok, bad) def test_constructor_from_s1_angle(self): angle = s2.S1Angle.from_degrees(90.0) a = s2.S1ChordAngle(angle) self.assertAlmostEqual(a.radians, math.pi / 2) def test_constructor_from_s1_angle_negative(self): a = s2.S1ChordAngle(s2.S1Angle.from_radians(-1.0)) self.assertTrue(a.is_negative()) def test_constructor_from_s1_angle_infinity(self): a = s2.S1ChordAngle(s2.S1Angle.infinity()) self.assertTrue(a.is_infinity()) def test_constructor_from_s1_angle_larger_than_pi_clamps(self): a = s2.S1ChordAngle(s2.S1Angle.from_radians(math.pi + 1.0)) self.assertEqual(a, s2.S1ChordAngle.straight()) # Factory methods def test_from_radians(self): a = s2.S1ChordAngle.from_radians(math.pi / 2) self.assertAlmostEqual(a.radians, math.pi / 2) def test_from_degrees(self): a = s2.S1ChordAngle.from_degrees(90.0) self.assertAlmostEqual(a.degrees, 90.0) def test_zero(self): a = s2.S1ChordAngle.zero() self.assertTrue(a.is_zero()) def test_right(self): a = s2.S1ChordAngle.right() self.assertAlmostEqual(a.radians, math.pi / 2) def test_straight(self): a = s2.S1ChordAngle.straight() self.assertAlmostEqual(a.radians, math.pi) def test_infinity(self): a = s2.S1ChordAngle.infinity() self.assertTrue(a.is_infinity()) self.assertTrue(a.is_special()) def test_negative(self): a = s2.S1ChordAngle.negative() self.assertTrue(a.is_negative()) self.assertTrue(a.is_special()) # Properties def test_radians(self): a = s2.S1ChordAngle.from_radians(1.0) self.assertAlmostEqual(a.radians, 1.0) def test_degrees(self): a = s2.S1ChordAngle.from_degrees(45.0) self.assertAlmostEqual(a.degrees, 45.0) def test_e5_e6_e7(self): a = s2.S1ChordAngle.from_degrees(45.0) self.assertEqual(a.e5, 4500000) self.assertEqual(a.e6, 45000000) self.assertEqual(a.e7, 450000000) def test_e5_e6_e7_special_raises(self): with self.assertRaises(ValueError): _ = s2.S1ChordAngle.negative().e5 with self.assertRaises(ValueError): _ = s2.S1ChordAngle.infinity().e5 with self.assertRaises(ValueError): _ = s2.S1ChordAngle.negative().e6 with self.assertRaises(ValueError): _ = s2.S1ChordAngle.infinity().e6 with self.assertRaises(ValueError): _ = s2.S1ChordAngle.negative().e7 with self.assertRaises(ValueError): _ = s2.S1ChordAngle.infinity().e7 # Predicates def test_is_zero(self): self.assertTrue(s2.S1ChordAngle.zero().is_zero()) self.assertFalse(s2.S1ChordAngle.right().is_zero()) def test_is_negative(self): self.assertTrue(s2.S1ChordAngle.negative().is_negative()) self.assertFalse(s2.S1ChordAngle.zero().is_negative()) def test_is_infinity(self): self.assertTrue(s2.S1ChordAngle.infinity().is_infinity()) self.assertFalse(s2.S1ChordAngle.straight().is_infinity()) def test_is_special(self): self.assertTrue(s2.S1ChordAngle.negative().is_special()) self.assertTrue(s2.S1ChordAngle.infinity().is_special()) self.assertFalse(s2.S1ChordAngle.zero().is_special()) self.assertFalse(s2.S1ChordAngle.straight().is_special()) def test_is_valid(self): self.assertTrue(s2.S1ChordAngle.zero().is_valid()) self.assertTrue(s2.S1ChordAngle.straight().is_valid()) self.assertTrue(s2.S1ChordAngle.negative().is_valid()) self.assertTrue(s2.S1ChordAngle.infinity().is_valid()) # Geometric operations def test_to_angle(self): a = s2.S1ChordAngle.from_degrees(90.0) angle = a.to_angle() self.assertAlmostEqual(angle.degrees, 90.0) def test_to_angle_special_values(self): self.assertEqual(s2.S1ChordAngle.infinity().to_angle(), s2.S1Angle.infinity()) self.assertTrue(s2.S1ChordAngle.negative().to_angle().radians < 0) def test_sin_cos_tan(self): a = s2.S1ChordAngle.from_degrees(30.0) self.assertAlmostEqual(a.sin(), 0.5, places=10) self.assertAlmostEqual(a.cos(), math.sqrt(3) / 2, places=10) self.assertAlmostEqual(a.tan(), 1.0 / math.sqrt(3), places=10) def test_sin_cos_tan_special_raises(self): with self.assertRaises(ValueError): s2.S1ChordAngle.negative().sin() with self.assertRaises(ValueError): s2.S1ChordAngle.infinity().sin() with self.assertRaises(ValueError): s2.S1ChordAngle.negative().cos() with self.assertRaises(ValueError): s2.S1ChordAngle.infinity().cos() with self.assertRaises(ValueError): s2.S1ChordAngle.negative().tan() with self.assertRaises(ValueError): s2.S1ChordAngle.infinity().tan() # Operators def test_equality(self): a = s2.S1ChordAngle.from_degrees(45.0) b = s2.S1ChordAngle.from_degrees(45.0) c = s2.S1ChordAngle.from_degrees(90.0) self.assertTrue(a == b) self.assertTrue(a != c) def test_comparison(self): a = s2.S1ChordAngle.from_degrees(30.0) b = s2.S1ChordAngle.from_degrees(60.0) self.assertTrue(a < b) self.assertTrue(b > a) self.assertTrue(a <= a) self.assertTrue(a >= a) def test_comparison_special_values(self): # Negative < Zero < finite < Infinity. neg = s2.S1ChordAngle.negative() zero = s2.S1ChordAngle.zero() finite = s2.S1ChordAngle.from_degrees(45.0) inf = s2.S1ChordAngle.infinity() self.assertLess(neg, zero) self.assertLess(zero, finite) self.assertLess(finite, inf) def test_add(self): a = s2.S1ChordAngle.from_degrees(30.0) b = s2.S1ChordAngle.from_degrees(60.0) total = a + b self.assertAlmostEqual(total.degrees, 90.0, places=5) def test_add_clamps_to_pi(self): a = s2.S1ChordAngle.from_degrees(120.0) b = s2.S1ChordAngle.from_degrees(120.0) total = a + b self.assertEqual(total, s2.S1ChordAngle.straight()) def test_add_special_raises(self): a = s2.S1ChordAngle.from_degrees(30.0) with self.assertRaises(ValueError): _ = a + s2.S1ChordAngle.negative() with self.assertRaises(ValueError): _ = s2.S1ChordAngle.infinity() + a def test_sub(self): a = s2.S1ChordAngle.from_degrees(60.0) b = s2.S1ChordAngle.from_degrees(30.0) diff = a - b self.assertAlmostEqual(diff.degrees, 30.0, places=5) def test_sub_clamps_at_zero(self): a = s2.S1ChordAngle.from_degrees(30.0) b = s2.S1ChordAngle.from_degrees(60.0) diff = a - b self.assertTrue(diff.is_zero()) def test_sub_special_raises(self): a = s2.S1ChordAngle.from_degrees(30.0) with self.assertRaises(ValueError): _ = a - s2.S1ChordAngle.negative() def test_add_assign(self): a = s2.S1ChordAngle.from_degrees(30.0) a += s2.S1ChordAngle.from_degrees(60.0) self.assertAlmostEqual(a.degrees, 90.0, places=5) def test_sub_assign(self): a = s2.S1ChordAngle.from_degrees(60.0) a -= s2.S1ChordAngle.from_degrees(30.0) self.assertAlmostEqual(a.degrees, 30.0, places=5) def test_hash(self): a = s2.S1ChordAngle.from_degrees(45.0) b = s2.S1ChordAngle.from_degrees(45.0) self.assertEqual(hash(a), hash(b)) s = {a, b} self.assertEqual(len(s), 1) # String representation def test_repr(self): a = s2.S1ChordAngle.from_degrees(90.0) self.assertEqual(repr(a), "S1ChordAngle(90.0000000)") def test_str(self): a = s2.S1ChordAngle.from_degrees(90.0) self.assertEqual(str(a), "90.0000000") def test_str_negative_sentinel(self): # negative() is a sentinel value; its string output is implementation- # defined but should represent a negative angle. self.assertIn("-", str(s2.S1ChordAngle.negative())) if __name__ == "__main__": unittest.main() src/python/s1interval_bindings.cc000066400000000000000000000157751524103652300174620ustar00rootroot00000000000000#include #include #include "absl/hash/hash.h" #include "absl/strings/str_cat.h" #include "s2/s1interval.h" namespace py = pybind11; namespace { void MaybeThrowInvalidPoint(double p) { if (!S1Interval::IsValidPoint(p)) { throw py::value_error(absl::StrCat("Invalid S1 point: ", p)); } } } // namespace void bind_s1interval(py::module& m) { py::class_(m, "S1Interval") // Constructors .def(py::init<>(), "Default constructor creates an empty interval") .def(py::init([](double lo, double hi) { MaybeThrowInvalidPoint(lo); MaybeThrowInvalidPoint(hi); return S1Interval(lo, hi); }), py::arg("lo"), py::arg("hi"), "Constructor that accepts the endpoints of the interval.\n\n" "Both endpoints must be in the range -Pi to Pi inclusive.\n" "Raises ValueError if either bound is outside that range.") // Static factory methods .def_static("empty", &S1Interval::Empty, "Returns the empty interval") .def_static("full", &S1Interval::Full, "Returns the full interval") .def_static("from_point", &S1Interval::FromPoint, py::arg("p"), "Constructs an interval containing a single point") .def_static("from_point_pair", [](double p1, double p2) { MaybeThrowInvalidPoint(p1); MaybeThrowInvalidPoint(p2); return S1Interval::FromPointPair(p1, p2); }, py::arg("p1"), py::arg("p2"), "Constructs the minimal interval containing two points") // Properties .def_property_readonly("lo", &S1Interval::lo, "Lower bound") .def_property_readonly("hi", &S1Interval::hi, "Upper bound") .def("bounds", [](const S1Interval& self) { return py::make_tuple(self.lo(), self.hi()); }, "Return bounds as a tuple (lo, hi)") // Predicates .def("is_full", &S1Interval::is_full, "Return true if the interval contains all points on the unit circle") .def("is_empty", &S1Interval::is_empty, "Return true if the interval is empty, i.e. it contains no points") .def("is_inverted", &S1Interval::is_inverted, "Return true if lo() > hi(). (This is true for empty intervals.)") // Geometric operations .def("center", &S1Interval::GetCenter, "Return the midpoint of the interval.\n\n" "For full and empty intervals, the result is arbitrary.") .def("length", &S1Interval::GetLength, "Return the length of the interval.\n\n" "The length of an empty interval is negative.") .def("complement_center", &S1Interval::GetComplementCenter, "Return the midpoint of the complement of the interval.\n\n" "For full and empty intervals, the result is arbitrary. For a\n" "singleton interval, the result is its antipodal point on S1.") .def("contains_point", [](const S1Interval& self, double p) { MaybeThrowInvalidPoint(p); return self.Contains(p); }, py::arg("p"), "Return true if the interval (which is closed) contains the point 'p'") .def("interior_contains_point", [](const S1Interval& self, double p) { MaybeThrowInvalidPoint(p); return self.InteriorContains(p); }, py::arg("p"), "Return true if the interior of the interval contains the point 'p'") .def("contains", py::overload_cast( &S1Interval::Contains, py::const_), py::arg("other"), "Return true if the interval contains the given interval 'y'") .def("interior_contains", py::overload_cast( &S1Interval::InteriorContains, py::const_), py::arg("other"), "Return true if the interior of this interval contains the entire interval 'y'") .def("intersects", &S1Interval::Intersects, py::arg("other"), "Return true if the two intervals contain any points in common") .def("interior_intersects", &S1Interval::InteriorIntersects, py::arg("other"), "Return true if the interior of this interval contains any point of 'y'") .def("add_point", [](S1Interval& self, double p) { MaybeThrowInvalidPoint(p); self.AddPoint(p); }, py::arg("p"), "Expand the interval to contain the given point 'p'.\n\n" "The point should be an angle in the range [-Pi, Pi].") .def("project", [](const S1Interval& self, double p) { if (self.is_empty()) throw py::value_error("Invalid S1Interval"); MaybeThrowInvalidPoint(p); return self.Project(p); }, py::arg("p"), "Return the closest point in the interval to 'p'.\n\n" "The interval must be non-empty.") .def("expanded", &S1Interval::Expanded, py::arg("margin"), "Return interval expanded on each side by 'margin' (radians).\n\n" "If 'margin' is negative, shrink the interval instead. The resulting\n" "interval may be empty or full. Any expansion of a full interval remains\n" "full, and any expansion of an empty interval remains empty.") .def("union", &S1Interval::Union, py::arg("other"), "Return the smallest interval containing this interval and 'y'") .def("intersection", &S1Interval::Intersection, py::arg("other"), "Return the smallest interval containing the intersection with 'y'.\n\n" "Note that the region of intersection may consist of two disjoint intervals.") .def("complement", &S1Interval::Complement, "Return the complement of the interior of the interval") .def("directed_hausdorff_distance", &S1Interval::GetDirectedHausdorffDistance, py::arg("other"), "Return the directed Hausdorff distance to 'y'") // Note: default value must match C++ signature in s1interval.h .def("approx_equals", &S1Interval::ApproxEquals, py::arg("other"), py::arg("max_error") = 1e-15, "Return true if approximately equal to 'y'.\n\n" "Two intervals are approximately equal if each endpoint can be moved\n" "by at most 'max_error' (radians) to match the other interval.") // Operators .def(py::self == py::self, "Return true if two intervals contain the same set of points") .def(py::self != py::self, "Return true if two intervals do not contain the same set of points") .def("__hash__", [](const S1Interval& self) { return absl::HashOf(self); }) // String representation .def("__repr__", [](const S1Interval& i) { std::ostringstream oss; oss << "S1Interval(" << i << ")"; return oss.str(); }) .def("__str__", [](const S1Interval& i) { std::ostringstream oss; oss << i; return oss.str(); }); } src/python/s1interval_test.py000066400000000000000000000242641524103652300167000ustar00rootroot00000000000000"""Tests for S1Interval pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestS1Interval(unittest.TestCase): """Test cases for S1Interval bindings.""" # Constructors def test_default_constructor(self): interval = s2.S1Interval() self.assertTrue(interval.is_empty()) def test_constructor_with_bounds(self): interval = s2.S1Interval(0.0, math.pi / 2) self.assertAlmostEqual(interval.lo, 0.0) self.assertAlmostEqual(interval.hi, math.pi / 2) self.assertFalse(interval.is_empty()) def test_constructor_converts_minus_pi_to_pi(self): # "The value -Ï€ is converted internally to Ï€ except for the Full() and Empty() intervals" # (from s1interval.h constructor documentation) interval = s2.S1Interval(-math.pi, 0.0) self.assertEqual(interval.lo, math.pi) # -Ï€ converted to Ï€ self.assertEqual(interval.hi, 0.0) self.assertTrue(interval.is_inverted()) # Static factory methods def test_empty_constructor(self): empty = s2.S1Interval.empty() self.assertTrue(empty.is_empty()) def test_full_constructor(self): full = s2.S1Interval.full() self.assertTrue(full.is_full()) def test_from_point(self): point_interval = s2.S1Interval.from_point(1.0) self.assertEqual(point_interval.lo, 1.0) self.assertEqual(point_interval.hi, 1.0) def test_from_point_pair(self): pair_interval = s2.S1Interval.from_point_pair(0.5, 2.0) self.assertTrue(pair_interval.contains_point(1.0)) def test_from_point_pair_invalid_raises(self): with self.assertRaises(ValueError): s2.S1Interval.from_point_pair(0.5, 4.0) # 4.0 > Ï€ with self.assertRaises(ValueError): s2.S1Interval.from_point_pair(-4.0, 0.5) # -4.0 < -Ï€ # Properties def test_properties_lo_hi(self): interval = s2.S1Interval(0.0, math.pi / 2) self.assertAlmostEqual(interval.lo, 0.0) self.assertAlmostEqual(interval.hi, math.pi / 2) def test_lo_hi_are_readonly(self): interval = s2.S1Interval(0.0, math.pi / 2) with self.assertRaises(AttributeError): interval.lo = 0.5 with self.assertRaises(AttributeError): interval.hi = 0.5 def test_bounds(self): interval = s2.S1Interval(0.5, 2.0) bounds = interval.bounds() self.assertEqual(bounds, (0.5, 2.0)) self.assertAlmostEqual(bounds[0], interval.lo) self.assertAlmostEqual(bounds[1], interval.hi) # Predicates def test_invalid_bounds_too_large(self): with self.assertRaises(ValueError): s2.S1Interval(0.0, 4.0) # 4.0 > Ï€ def test_invalid_bounds_too_small(self): with self.assertRaises(ValueError): s2.S1Interval(-4.0, 0.0) # -4.0 < -Ï€ def test_invalid_both_bounds_out_of_range(self): with self.assertRaises(ValueError): s2.S1Interval(-4.0, 4.0) def test_is_full_and_empty(self): empty = s2.S1Interval.empty() self.assertTrue(empty.is_empty()) self.assertFalse(empty.is_full()) full = s2.S1Interval.full() self.assertTrue(full.is_full()) self.assertFalse(full.is_empty()) normal = s2.S1Interval(0.0, math.pi) self.assertFalse(normal.is_empty()) self.assertFalse(normal.is_full()) def test_is_inverted(self): # Normal interval normal = s2.S1Interval(0.0, math.pi) self.assertFalse(normal.is_inverted()) # Inverted interval (wraps around) inverted = s2.S1Interval(math.pi, 0.0) self.assertTrue(inverted.is_inverted()) # Geometric operations def test_center(self): interval = s2.S1Interval(0.0, math.pi) self.assertAlmostEqual(interval.center(), math.pi / 2) def test_length(self): interval = s2.S1Interval(0.0, math.pi) self.assertAlmostEqual(interval.length(), math.pi) def test_complement_center(self): interval = s2.S1Interval(0.0, math.pi / 2) complement_center = interval.complement_center() self.assertIsNotNone(complement_center) def test_contains_point(self): interval = s2.S1Interval(0.0, math.pi) self.assertTrue(interval.contains_point(math.pi / 2)) self.assertTrue(interval.contains_point(0.0)) self.assertTrue(interval.contains_point(math.pi)) self.assertFalse(interval.contains_point(-math.pi / 2)) def test_contains_point_invalid_raises(self): interval = s2.S1Interval(0.0, math.pi) with self.assertRaises(ValueError): interval.contains_point(4.0) # 4.0 > Ï€ def test_interior_contains_point(self): interval = s2.S1Interval(0.0, math.pi) self.assertTrue(interval.interior_contains_point(math.pi / 2)) self.assertFalse(interval.interior_contains_point(0.0)) self.assertFalse(interval.interior_contains_point(math.pi)) def test_interior_contains_point_invalid_raises(self): interval = s2.S1Interval(0.0, math.pi) with self.assertRaises(ValueError): interval.interior_contains_point(4.0) # 4.0 > Ï€ def test_contains_interval(self): interval1 = s2.S1Interval(0.0, math.pi) interval2 = s2.S1Interval(0.5, 2.0) interval3 = s2.S1Interval(-math.pi, -2.0) self.assertTrue(interval1.contains(interval2)) self.assertFalse(interval1.contains(interval3)) def test_interior_contains_interval(self): interval1 = s2.S1Interval(0.0, math.pi) interval2 = s2.S1Interval(0.5, 2.0) self.assertTrue(interval1.interior_contains(interval2)) def test_intersects(self): interval1 = s2.S1Interval(0.0, 2.0) interval2 = s2.S1Interval(1.0, 3.0) interval3 = s2.S1Interval(-3.0, -2.5) self.assertTrue(interval1.intersects(interval2)) self.assertFalse(interval1.intersects(interval3)) def test_interior_intersects(self): interval1 = s2.S1Interval(0.0, 2.0) interval2 = s2.S1Interval(1.0, 3.0) interval3 = s2.S1Interval(-3.0, -2.5) self.assertTrue(interval1.interior_intersects(interval2)) self.assertFalse(interval1.interior_intersects(interval3)) def test_add_point(self): interval = s2.S1Interval(0.0, 1.0) interval.add_point(1.5) self.assertTrue(interval.contains_point(1.5)) def test_add_point_invalid_raises(self): interval = s2.S1Interval(0.0, 1.0) with self.assertRaises(ValueError): interval.add_point(4.0) # 4.0 > Ï€ def test_project(self): interval = s2.S1Interval(0.0, 1.5) # Point inside interval self.assertAlmostEqual(interval.project(1.0), 1.0) def test_project_on_empty_raises(self): with self.assertRaises(ValueError): s2.S1Interval.empty().project(1.0) def test_project_invalid_point_raises(self): interval = s2.S1Interval(0.0, 1.5) with self.assertRaises(ValueError): interval.project(4.0) # 4.0 > Ï€ def test_expanded(self): interval = s2.S1Interval(0.5, 1.5) expanded = interval.expanded(0.5) self.assertAlmostEqual(expanded.length(), interval.length() + 1.0) def test_union(self): interval1 = s2.S1Interval(0.0, 1.0) interval2 = s2.S1Interval(0.5, 1.5) union = interval1.union(interval2) self.assertTrue(union.contains_point(0.5)) self.assertTrue(union.contains_point(1.2)) def test_intersection(self): interval1 = s2.S1Interval(0.0, 2.0) interval2 = s2.S1Interval(1.0, 3.0) intersection = interval1.intersection(interval2) self.assertAlmostEqual(intersection.lo, 1.0) self.assertAlmostEqual(intersection.hi, 2.0) def test_complement(self): interval = s2.S1Interval(0.0, math.pi / 2) complement = interval.complement() self.assertTrue(complement.is_inverted()) self.assertFalse(complement.contains_point(math.pi / 4)) self.assertTrue(complement.contains_point(math.pi)) def test_directed_hausdorff_distance(self): interval1 = s2.S1Interval(0.0, 1.0) interval2 = s2.S1Interval(0.5, 1.5) distance = interval1.directed_hausdorff_distance(interval2) self.assertIsNotNone(distance) def test_approx_equals(self): interval1 = s2.S1Interval(0.0, 2.0) interval2 = s2.S1Interval(0.0, 2.0) interval3 = s2.S1Interval(0.0, 2.0 + 1e-16) # Very small difference interval4 = s2.S1Interval(0.0, 2.1) # Larger difference # Test with default max_error (1e-15) self.assertTrue(interval1.approx_equals(interval2)) # Within default tolerance self.assertTrue(interval1.approx_equals(interval3)) # Outside default tolerance self.assertFalse(interval1.approx_equals(interval4)) # Test with explicit max_error values self.assertTrue(interval1.approx_equals(interval3, 1e-15)) self.assertFalse(interval1.approx_equals(interval4, 0.05)) self.assertTrue(interval1.approx_equals(interval4, 0.2)) # Operators def test_equality(self): interval1 = s2.S1Interval(0.0, 2.0) interval2 = s2.S1Interval(0.0, 2.0) interval3 = s2.S1Interval(0.0, 3.0) self.assertTrue(interval1 == interval2) self.assertTrue(interval1 != interval3) def test_hash(self): a = s2.S1Interval(0.0, 1.0) b = s2.S1Interval(0.0, 1.0) self.assertEqual(hash(a), hash(b)) self.assertEqual(len({a, b}), 1) # String representation def test_string_representation(self): interval = s2.S1Interval(0.0, 2.0) self.assertEqual(repr(interval), "S1Interval([0, 2])") self.assertEqual(str(interval), "[0, 2]") empty = s2.S1Interval.empty() # Empty interval has lo=pi, hi=-pi self.assertEqual(repr(empty), "S1Interval([3.14159, -3.14159])") self.assertEqual(str(empty), "[3.14159, -3.14159]") full = s2.S1Interval.full() # Full interval spans from -pi to pi self.assertEqual(repr(full), "S1Interval([-3.14159, 3.14159])") self.assertEqual(str(full), "[-3.14159, 3.14159]") if __name__ == "__main__": unittest.main() src/python/s2.i000066400000000000000000000027511524103652300136720ustar00rootroot00000000000000%include "std_vector.i" %include "std_string.i" %include "stdint.i" %{ #include "absl/strings/string_view.h" %} %typemap(typecheck) absl::string_view = char *; %typemap(in) absl::string_view { if ($input != Py_None) { Py_ssize_t len; if (PyUnicode_Check($input)) { const char *buf; buf = PyUnicode_AsUTF8AndSize($input, &len); if (buf == nullptr) { SWIG_fail; } $1 = absl::string_view(buf, len); } else { char *buf; if (PyBytes_AsStringAndSize($input, &buf, &len) == -1) { // Python has raised an error (likely TypeError or UnicodeEncodeError). SWIG_fail; } $1 = absl::string_view(buf, len); } } } %template() std::vector; %template() std::vector; %template() std::vector; %template() std::vector; %template() std::vector; // Standard Google convention is to ignore all functions and methods, and // selectively add back those for which wrapping is both required and // functional. %define %ignoreall %ignore ""; %enddef %define %unignore %rename("%s") %enddef %define %unignoreall %rename("%s") ""; %enddef %define ABSL_ATTRIBUTE_ALWAYS_INLINE %enddef %define ABSL_DEPRECATE_AND_INLINE(msg) %enddef %define ABSL_DEPRECATED(msg) %enddef %define absl_nonnull %enddef %define absl_nullable %enddef // TODO: Remove when Ubuntu 22 is unsupported, ~2027-05-01. #if SWIG_VERSION < 0x042000 %define final %enddef #endif %include "coder.i" %include "s2_common.i" src/python/s2_common.i000077500000000000000000001017641524103652300152510ustar00rootroot00000000000000// Copyright 2006 Google Inc. All Rights Reserved. // These SWIG definitions are shared between the internal Google and external // open source releases of s2. %{ #include #include #include #include "s2/s2boolean_operation.h" #include "s2/s2buffer_operation.h" #include "s2/s2builder.h" #include "s2/s2builder_layer.h" #include "s2/s2builderutil_s2polygon_layer.h" #include "s2/s2cell_id.h" #include "s2/s2region.h" #include "s2/s2cap.h" #include "s2/s2edge_crossings.h" #include "s2/s2edge_distances.h" #include "s2/s2earth.h" #include "s2/s2latlng.h" #include "s2/s2latlng_rect.h" #include "s2/s2loop.h" #include "s2/s2measures.h" #include "s2/s2pointutil.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2predicates.h" #include "s2/s2region_coverer.h" #include "s2/s2region_term_indexer.h" #include "s2/s2cell.h" #include "s2/s2cell_union.h" #include "s2/s2shape_index.h" #include "s2/mutable_s2shape_index.h" // Wrapper for S2BufferOperation::Options to work around the inability // to handle nested classes in SWIG. class S2BufferOperationOptions { public: S2BufferOperation::Options opts; void set_buffer_radius(S1Angle buffer_radius) { opts.set_buffer_radius(buffer_radius); } void set_error_fraction(double error_fraction) { opts.set_error_fraction(error_fraction); } }; // Wrapper for S2PolygonLayer::Options to work around the inability to // handle nested classes in SWIG. class S2PolygonLayerOptions { public: s2builderutil::S2PolygonLayer::Options opts; void set_edge_type(S2Builder::EdgeType edge_type) { opts.set_edge_type(edge_type); } }; %} %inline %{ static PyObject *FromS2CellId(const S2CellId &cell_id) { return SWIG_NewPointerObj(new S2CellId(cell_id), SWIGTYPE_p_S2CellId, SWIG_POINTER_OWN); } %} %apply std::vector *OUTPUT {std::vector *covering}; %apply std::vector *OUTPUT {std::vector *interior}; %apply std::vector *OUTPUT {std::vector *output}; %typemap(in, numinputs=0) S2CellId *OUTPUT_ARRAY_4(S2CellId temp[4]) { $1 = temp; } // For S2Polygon::GetOverlapFractions %typemap(out) std::pair { $result = Py_BuildValue("dd", $1.first, $1.second); } %typemap(argout) S2CellId *OUTPUT_ARRAY_4 { $result = PyList_New(4); if ($result == nullptr) return nullptr; for (int i = 0; i < 4; i++) { PyObject *const o = FromS2CellId($1[i]); if (!o) { Py_DECREF($result); return nullptr; } PyList_SET_ITEM($result, i, o); } } %apply S2CellId *OUTPUT_ARRAY_4 {S2CellId neighbors[4]}; // Convert an S2Error into a Python exception. This requires two // typemaps: the first declares a local variable of type S2Error and // passes a pointer to it into the called function, and the second // inspects the S2Error variable after the call and throws an // exception if its ok() method returns false. %typemap(in, numinputs=0) S2Error * (S2Error err) { $1 = &err; } %typemap(argout) S2Error * { if(!$1->ok()) SWIG_exception(SWIG_ValueError, std::string($1->message()).c_str()); } // This overload shadows the one the takes vector&, and it // does not work anyway. %ignore S2CellUnion::Init(std::vector const& cell_ids); // The SWIG code which picks between overloaded methods doesn't work // when given a list parameter. SWIG_Python_ConvertPtrAndOwn calls // SWIG_Python_GetSwigThis, doesn't find the 'this' attribute and gives up. // To avoid this problem rename the Polyline::Init methods so they aren't // overloaded. We also need to reimplement them since SWIG doesn't // seem to understand absl::Span. %extend S2Polyline { public: void InitFromS2LatLngs(const std::vector& vertices) { $self->Init(absl::MakeConstSpan(vertices)); } void InitFromS2Points(const std::vector& vertices) { $self->Init(absl::MakeConstSpan(vertices)); } }; // And similarly for the overloaded S2CellUnion::Normalize method. %rename(NormalizeS2CellUnion) S2CellUnion::Normalize(); %apply int *OUTPUT {int *next_vertex}; %apply int *OUTPUT {int *psi}; %apply int *OUTPUT {int *pti}; %apply int *OUTPUT {int *pi}; %apply int *OUTPUT {int *pj}; %apply int *OUTPUT {int *orientation}; %apply SWIGTYPE *DISOWN {S2Loop *loop_disown}; %apply SWIGTYPE *DISOWN {S2Builder::Layer *layer_disown}; %apply SWIGTYPE *DISOWN {S2Polygon *polygon_disown}; %typemap(in) std::vector * (std::vector loops) { PyObject *iter = PyObject_GetIter($input); if (iter == nullptr) { %argument_fail(SWIG_TypeError, "iterable of S2Loop *", $symname, $argnum); } for (PyObject *elem; (elem = PyIter_Next(iter)); Py_DECREF(elem)) { S2Loop *loop = nullptr; int res = SWIG_ConvertPtr( elem, reinterpret_cast(&loop), $descriptor(S2Loop *), SWIG_POINTER_NO_NULL); if (!SWIG_IsOK(res)) { Py_DECREF(elem); Py_DECREF(iter); for (S2Loop *loop : loops) delete loop; %argument_fail(res, "$type", $symname, $argnum); } loops.push_back(new S2Loop(*loop)); } Py_DECREF(iter); $1 = &loops; } %typemap(in, numinputs=0) std::vector *out(std::vector temp) { $1 = &temp; } %typemap(argout) std::vector *out { $result = PyList_New($1->size()); if ($result == nullptr) return nullptr; for (int i = 0; i < $1->size(); i++) { PyObject *const o = SWIG_NewPointerObj((*$1)[i], $descriptor(S2Polyline *), SWIG_POINTER_OWN); if (!o) { Py_DECREF($result); return nullptr; } PyList_SET_ITEM($result, i, o); } } %inline %{ // This isn't a constructor because it clashes with the SWIG-redefinition // below and the actual S2Point (a Vector_3d). static PyObject *S2Point_FromRaw(double x, double y, double z) { // Creates an S2Point directly, mostly useful for testing. return SWIG_NewPointerObj(new S2Point(x, y, z), SWIGTYPE_p_S2Point, SWIG_POINTER_OWN); } static PyObject *S2Point_ToRaw(const S2Point& p) { return Py_BuildValue("ddd", p[0], p[1], p[2]); } %} // We provide our own definition of S2Point, because the real one is too // difficult to wrap correctly. class S2Point { public: double x(); double y(); double z(); double Norm(); S2Point Normalize(); ~S2Point(); }; // The extensions below exist because of the difficulty swigging S2Point. // This alternate method of S2Loop::vertex() returns a S2LatLng instead. %extend S2Loop { public: S2LatLng GetS2LatLngVertex(int i) { return S2LatLng($self->vertex(i)); } }; // This alternate method of S2Cell::GetVertex() returns a S2LatLng instead. %extend S2Cell { public: S2LatLng GetS2LatLngVertex(int k) { return S2LatLng($self->GetVertex(k)); } }; // This alternate method of S2Cell::GetEdge() returns a S2LatLng instead. %extend S2Cell { public: S2LatLng GetS2LatLngEdge(int k) { return S2LatLng($self->GetEdge(k)); } }; // The extensions below exist to work around the use of absl::Span. %extend S2Loop { public: explicit S2Loop(const std::vector& vertices) { return new S2Loop(absl::MakeConstSpan(vertices)); } void Init(const std::vector& vertices) { $self->Init(absl::MakeConstSpan(vertices)); } }; // Add raw pointer versions of these functions because SWIG doesn't // understand unique_ptr and when std::move() must be used. // TODO(user): Make swig understand unique_ptr and vector. %extend S2Polygon { public: // Takes ownership of the loop. The _disown suffix is used to tell SWIG // that S2Polygon takes ownership of the loop. explicit S2Polygon(S2Loop* loop_disown) { // SWIG recognizes this as a constructor, but implements this // as a free function, so write it that way. return new S2Polygon(std::unique_ptr(loop_disown)); } void InitNested(std::vector* loops) { std::vector> unique_loops(loops->size()); for (int i = 0; i < loops->size(); ++i) { unique_loops[i].reset((*loops)[i]); } loops->clear(); $self->InitNested(std::move(unique_loops)); } void IntersectWithPolyline(S2Polyline const* in, std::vector* out) const { std::vector> polylines = $self->IntersectWithPolyline(*in); ABSL_DCHECK(out->empty()); out->reserve(polylines.size()); for (auto& polyline : polylines) { out->push_back(polyline.release()); } } } %extend S2Builder { public: void StartLayer(S2Builder::Layer* layer_disown) { $self->StartLayer(std::unique_ptr(layer_disown)); } } class S2PolygonLayerOptions { public: s2builderutil::S2PolygonLayer::Options opts; void set_edge_type(S2Builder::EdgeType); }; // S2PolygonLayer's constructor takes a pointer to an S2Polygon. We // need to ensure that the S2Polygon is not destroyed while the // S2PolygonLayer still references it. To do this, save a reference to // the polygon in the Python wrapper object. %pythonprepend s2builderutil::S2PolygonLayer::S2PolygonLayer %{ self._incref = args[0] %} %extend s2builderutil::S2PolygonLayer { public: S2PolygonLayer(S2Polygon* layer, const S2PolygonLayerOptions& options) { return new s2builderutil::S2PolygonLayer(layer, options.opts); } } %extend MutableS2ShapeIndex { public: void Add(S2Polygon* polygon_disown) { auto polygon = std::unique_ptr(polygon_disown); $self->Add(std::unique_ptr(new S2Polygon::OwningShape(std::move(polygon)))); } } %extend S2BooleanOperation { public: S2BooleanOperation(OpType op_type, S2Builder::Layer* layer_disown) { S2BooleanOperation::Options options; auto layer = std::unique_ptr(layer_disown); return new S2BooleanOperation(op_type, std::move(layer), options); } } class S2BufferOperationOptions { public: S2BufferOperation::Options opts; void set_buffer_radius(S1Angle); void set_error_fraction(double); }; %extend S2BufferOperation { public: S2BufferOperation(S2Builder::Layer* layer_disown) { auto layer = std::unique_ptr(layer_disown); return new S2BufferOperation(std::move(layer)); } S2BufferOperation(S2Builder::Layer* layer_disown, const S2BufferOperationOptions& options) { auto layer = std::unique_ptr(layer_disown); return new S2BufferOperation(std::move(layer), options.opts); } void AddPolygon(S2Polygon* polygon_disown) { auto polygon = std::unique_ptr(polygon_disown); $self->AddShape(S2Polygon::OwningShape(std::move(polygon))); } void AddPoint(S2Point& point) { $self->AddPoint(point); } } // Expose Options functions on S2RegionCoverer until we figure out // nested classes in SWIG. %extend S2RegionCoverer { int max_cells() const { return $self->options().max_cells(); } void set_max_cells(int max_cells) { $self->mutable_options()->set_max_cells(max_cells); } int min_level() const { return $self->options().min_level(); } void set_min_level(int min_level) { $self->mutable_options()->set_min_level(min_level); } int max_level() const { return $self->options().max_level(); } void set_max_level(int max_level) { $self->mutable_options()->set_max_level(max_level); } void set_fixed_level(int fixed_level) { $self->mutable_options()->set_fixed_level(fixed_level); } int level_mod() const { return $self->options().level_mod(); } void set_level_mod(int level_mod) { $self->mutable_options()->set_level_mod(level_mod); } int true_max_level() const { return $self->options().true_max_level(); } } // Expose Options functions on S2RegionTermIndexer until we figure out // nested classes in SWIG. %extend S2RegionTermIndexer { int max_cells() const { return $self->options().max_cells(); } void set_max_cells(int max_cells) { $self->mutable_options()->set_max_cells(max_cells); } int min_level() const { return $self->options().min_level(); } void set_min_level(int min_level) { $self->mutable_options()->set_min_level(min_level); } int max_level() const { return $self->options().max_level(); } void set_max_level(int max_level) { $self->mutable_options()->set_max_level(max_level); } void set_fixed_level(int fixed_level) { $self->mutable_options()->set_fixed_level(fixed_level); } int level_mod() const { return $self->options().level_mod(); } void set_level_mod(int level_mod) { $self->mutable_options()->set_level_mod(level_mod); } int true_max_level() const { return $self->options().true_max_level(); } bool index_contains_points_only() const { return $self->options().index_contains_points_only(); } void set_index_contains_points_only(bool value) { $self->mutable_options()->set_index_contains_points_only(value); } bool optimize_for_space() const { return $self->options().optimize_for_space(); } void set_optimize_for_space(bool value) { $self->mutable_options()->set_optimize_for_space(value); } char marker_character() const { return $self->options().marker_character(); } void set_marker_character(char ch) { $self->mutable_options()->set_marker_character(ch); } } %copyctor S1ChordAngle; // Raise ValueError for any functions that would trigger a // ABSL_CHECK/ABSL_DCHECK. %pythonprepend S2CellId::child %{ if not self.is_valid(): raise ValueError("S2CellId must be valid.") if self.is_leaf(): raise ValueError("S2CellId must be non-leaf.") if not 0 <= position < 4: raise ValueError("Position must be 0-3.") %} // TODO(jrosenstock): child_begin() // TODO(jrosenstock): child_end() %pythonprepend S2CellId::child_position(int) const %{ if not self.is_valid(): raise ValueError("S2CellId must be valid.") if level < 1 or level > self.level(): raise ValueError("level must must be in range [1, S2 cell level]") %} %pythonprepend S2CellId::contains %{ if not self.is_valid() or not other.is_valid(): raise ValueError("Both S2CellIds must be valid.") %} %pythonprepend S2CellId::intersects %{ if not self.is_valid() or not other.is_valid(): raise ValueError("Both S2CellIds must be valid.") %} %pythonprepend S2CellId::level %{ # As in the C++ version: # We can't just check is_valid() because we want level() to be # defined for end-iterators, i.e. S2CellId.End(level). However there is # no good way to define S2CellId::None().level(), so we do prohibit that. if self.id() == 0: raise ValueError("None has no level.") %} %pythonprepend S2CellId::parent %{ if not self.is_valid(): raise ValueError("S2CellId must be valid.") if len(args) == 1: level, = args if level < 0: raise ValueError("Level must be non-negative.") if level > self.level(): raise ValueError("Level must be less than or equal to cell's level.") %} %ignoreall %unignore MutableS2ShapeIndex; %unignore MutableS2ShapeIndex::~MutableS2ShapeIndex; %unignore MutableS2ShapeIndex::Add(S2Shape*); %unignore R1Interval; %ignore R1Interval::operator[]; %unignore R1Interval::GetLength; %unignore S1Angle; %unignore S1Angle::S1Angle; %unignore S1Angle::~S1Angle; %unignore S1Angle::Degrees; %unignore S1Angle::E5; %unignore S1Angle::E6; %unignore S1Angle::E7; %unignore S1Angle::Normalize; %unignore S1Angle::Normalized; %unignore S1Angle::Radians; %unignore S1Angle::UnsignedE6; %unignore S1Angle::abs; %unignore S1Angle::degrees; %unignore S1Angle::e6; %unignore S1Angle::e7; %unignore S1Angle::radians; %unignore S1ChordAngle; %unignore S1ChordAngle::ToAngle; %unignore S1ChordAngle::degrees; %unignore S1ChordAngle::Infinity; %unignore S1Interval; %ignore S1Interval::operator[]; %unignore S1Interval::GetLength; %unignore S2; %unignore S2::CrossingSign; %unignore S2::GetIntersection; %unignore S2::Interpolate; %unignore S2::Rotate; %unignore S2::TurnAngle; %unignore S2::UpdateMinDistance; %unignore S2BooleanOperation; %unignore S2BooleanOperation::Build; %unignore S2BooleanOperation::OpType; %unignore S2BooleanOperation::OpType::UNION; %unignore S2BooleanOperation::OpType::INTERSECTION; %unignore S2BooleanOperation::OpType::DIFFERENCE; %unignore S2BooleanOperation::OpType::SYMMETRIC_DIFFERENCE; %unignore S2BooleanOperation::S2BooleanOperation(OpType, S2Builder::Layer*, const Options&); %ignore S2BooleanOperation::S2BooleanOperation(OpType, std::unique_ptr, const Options&); %ignore S2BooleanOperation::S2BooleanOperation(OpType, std::unique_ptr); // Silence SWIG Warning 362: operator= can't be wrapped in Python. %ignore S2BooleanOperation::operator=; %unignore S2BufferOperation; %unignore S2BufferOperation::Build; %unignore S2BufferOperation::Options; %unignore S2BufferOperation::S2BufferOperation(S2Builder::Layer*); %ignore S2BufferOperation::S2BufferOperation(std::unique_ptr); %ignore S2BufferOperation::S2BufferOperation(std::unique_ptr, const Options&); // Silence SWIG Warning 362: operator= can't be wrapped in Python. %ignore S2BufferOperation::operator=; // Silence SWIG Warning 325: nested class Options can't be wrapped directly. // S2BufferOperationOptions provides a workaround wrapper. %warnfilter(325) S2BufferOperation; %unignore S2BufferOperationOptions; %unignore S2BufferOperationOptions::set_buffer_radius; %unignore S2BufferOperationOptions::set_error_fraction; %unignore S2Builder; %unignore S2Builder::Layer; %unignore S2Builder::S2Builder; %unignore S2Builder::StartLayer(S2Builder::Layer*); %unignore S2Builder::AddEdge; %unignore S2Builder::Build; %unignore S2Builder::EdgeType; %unignore S2Builder::EdgeType::DIRECTED; %unignore S2Builder::EdgeType::UNDIRECTED; %unignore s2builderutil; %unignore s2builderutil::S2PolygonLayer; %unignore s2builderutil::S2PolygonLayer::S2PolygonLayer(S2Polygon*); %unignore S2Cap; %unignore S2Cap::S2Cap; %unignore S2Cap::~S2Cap; %unignore S2Cap::AddPoint; %unignore S2Cap::ApproxEquals; %unignore S2Cap::Clone; %unignore S2Cap::Contains; %unignore S2Cap::Decode; %unignore S2Cap::Empty; %unignore S2Cap::Encode; %unignore S2Cap::Expanded; %unignore S2Cap::FromCenterArea(const S2Point&, double); %unignore S2Cap::FromCenterHeight(const S2Point&, double); %unignore S2Cap::FromPoint; %unignore S2Cap::Full; %unignore S2Cap::GetCapBound() const; %unignore S2Cap::GetCentroid; %unignore S2Cap::GetRectBound; %unignore S2Cap::Intersects; %unignore S2Cap::MayIntersect(const S2Cell&) const; %unignore S2Cap::Union; %unignore S2Cap::center; %unignore S2Cap::height; %unignore S2Cap::is_empty; %unignore S2Cap::is_valid; %unignore S2Cell; %unignore S2Cell::S2Cell; %unignore S2Cell::~S2Cell; %unignore S2Cell::ApproxArea; %unignore S2Cell::AverageArea; %unignore S2Cell::Clone; %unignore S2Cell::Contains; %unignore S2Cell::Decode; %unignore S2Cell::Encode; %unignore S2Cell::ExactArea; %unignore S2Cell::GetBoundaryDistance; %unignore S2Cell::GetCapBound() const; %unignore S2Cell::GetCenter; %unignore S2Cell::GetDistance; %unignore S2Cell::GetRectBound; %unignore S2Cell::GetS2LatLngEdge; %unignore S2Cell::GetS2LatLngVertex; %unignore S2Cell::GetVertex; %unignore S2Cell::MayIntersect(const S2Cell&) const; %unignore S2Cell::face; %unignore S2Cell::id; %unignore S2Cell::level; %unignore S2CellId; %unignore S2CellId::S2CellId; %unignore S2CellId::~S2CellId; %unignore S2CellId::AppendAllNeighbors(int, std::vector*) const; %rename(GetAllNeighbors) S2CellId::AppendAllNeighbors(int, std::vector*) const; %unignore S2CellId::AppendVertexNeighbors(int, std::vector*) const; %rename(GetVertexNeighbors) S2CellId::AppendVertexNeighbors(int, std::vector*) const; %unignore S2CellId::Begin; %unignore S2CellId::End; %unignore S2CellId::FromDebugString(absl::string_view); %unignore S2CellId::FromFaceIJ(int, int, int); %unignore S2CellId::FromFacePosLevel(int, uint64_t, int); %unignore S2CellId::FromLatLng; %unignore S2CellId::FromPoint; %unignore S2CellId::FromToken(absl::string_view); %unignore S2CellId::GetCenterSiTi(int*, int*) const; %unignore S2CellId::GetEdgeNeighbors; %unignore S2CellId::ToFaceIJOrientation(int*, int*, int*) const; %unignore S2CellId::ToLatLng; %unignore S2CellId::ToPoint; %unignore S2CellId::ToString; %unignore S2CellId::ToToken; %unignore S2CellId::child; %unignore S2CellId::child_begin; %unignore S2CellId::child_end; %unignore S2CellId::child_position(int) const; %unignore S2CellId::contains; %unignore S2CellId::face; %unignore S2CellId::id; %unignore S2CellId::intersects; %unignore S2CellId::is_leaf; %unignore S2CellId::is_face; %unignore S2CellId::is_valid; %unignore S2CellId::kMaxLevel; %unignore S2CellId::level; %unignore S2CellId::next; %unignore S2CellId::parent; %unignore S2CellId::pos; %unignore S2CellId::prev; %unignore S2CellId::range_max; %unignore S2CellId::range_min; %unignore S2CellUnion; %ignore S2CellUnion::operator[]; // Silence the SWIG warning. %unignore S2CellUnion::S2CellUnion(const std::vector &); %unignore S2CellUnion::~S2CellUnion; %unignore S2CellUnion::ApproxArea; %unignore S2CellUnion::Clone; %unignore S2CellUnion::Contains; %unignore S2CellUnion::Decode; %unignore S2CellUnion::Denormalize(int, int, std::vector*) const; %unignore S2CellUnion::Encode; %unignore S2CellUnion::ExactArea; %unignore S2CellUnion::FromNormalized(std::vector); %unignore S2CellUnion::GetCapBound() const; %unignore S2CellUnion::GetDifference; %unignore S2CellUnion::GetRectBound; %unignore S2CellUnion::Init(std::vector const &); %unignore S2CellUnion::Intersection; %unignore S2CellUnion::Intersects; %unignore S2CellUnion::IsNormalized() const; %unignore S2CellUnion::MayIntersect(const S2Cell&) const; // SWIG doesn't handle disambiguation of the overloaded Normalize methods, so // the Normalize() instance method is renamed to NormalizeS2CellUnion. %unignore S2CellUnion::Normalize(std::vector*); %unignore S2CellUnion::cell_id; %unignore S2CellUnion::cell_ids; %unignore S2CellUnion::empty; %unignore S2CellUnion::num_cells; %unignore S2Earth; %unignore S2Earth::GetDistance(const S2LatLng&, const S2LatLng&); %unignore S2Earth::GetDistance(const S2Point&, const S2Point&); %unignore S2Earth::GetDistanceKm(const S2LatLng&, const S2LatLng&); %unignore S2Earth::GetDistanceKm(const S2Point&, const S2Point&); %unignore S2Earth::GetDistanceMeters(const S2LatLng&, const S2LatLng&); %unignore S2Earth::GetDistanceMeters(const S2Point&, const S2Point&); %unignore S2Earth::GetInitialBearing(const S2LatLng&, const S2LatLng&); %unignore S2Earth::HighestAltitude(); %unignore S2Earth::HighestAltitudeKm(); %unignore S2Earth::HighestAltitudeMeters(); %unignore S2Earth::KmToRadians(double); %unignore S2Earth::LowestAltitude(); %unignore S2Earth::LowestAltitudeKm(); %unignore S2Earth::LowestAltitudeMeters(); %unignore S2Earth::MetersToRadians(double); %unignore S2Earth::RadiansToKm(double); %unignore S2Earth::RadiansToMeters(double); %unignore S2Earth::Radius(); %unignore S2Earth::RadiusKm(); %unignore S2Earth::RadiusMeters(); %unignore S2Earth::SquareKmToSteradians(double); %unignore S2Earth::SquareMetersToSteradians(double); %unignore S2Earth::SteradiansToSquareKm(double); %unignore S2Earth::SteradiansToSquareMeters(double); %unignore S2Earth::ToAngle(const util::units::Meters&); %unignore S2Earth::ToChordAngle(const util::units::Meters&); %unignore S2Earth::ToDistance(const S1Angle&); %unignore S2Earth::ToDistance(const S1ChordAngle&); %unignore S2Earth::ToKm(const S1Angle&); %unignore S2Earth::ToKm(const S1ChordAngle&); %unignore S2Earth::ToLongitudeRadians(const util::units::Meters&, double); %unignore S2Earth::ToMeters(const S1Angle&); %unignore S2Earth::ToMeters(const S1ChordAngle&); %unignore S2Earth::ToRadians(const util::units::Meters&); %unignore S2LatLng; %unignore S2LatLng::S2LatLng; %unignore S2LatLng::~S2LatLng; %unignore S2LatLng::ApproxEquals; %unignore S2LatLng::FromDegrees; %unignore S2LatLng::FromE6; %unignore S2LatLng::FromE7; %unignore S2LatLng::FromRadians; %unignore S2LatLng::FromUnsignedE6; %unignore S2LatLng::FromUnsignedE7; %unignore S2LatLng::GetDistance; %unignore S2LatLng::Normalized; %unignore S2LatLng::ToPoint; %unignore S2LatLng::ToStringInDegrees; %unignore S2LatLng::coords; %unignore S2LatLng::is_valid; %unignore S2LatLng::lat; %unignore S2LatLng::lng; %unignore S2LatLngRect; %unignore S2LatLngRect::S2LatLngRect; %unignore S2LatLngRect::~S2LatLngRect; %unignore S2LatLngRect::AddPoint; %unignore S2LatLngRect::ApproxEquals; %unignore S2LatLngRect::Area; %unignore S2LatLngRect::Clone; %unignore S2LatLngRect::Contains; %unignore S2LatLngRect::Decode; %unignore S2LatLngRect::Empty; %unignore S2LatLngRect::Encode; %unignore S2LatLngRect::ExpandedByDistance; %unignore S2LatLngRect::FromCenterSize; %unignore S2LatLngRect::FromPoint; %unignore S2LatLngRect::FromPointPair; %unignore S2LatLngRect::Full; %unignore S2LatLngRect::GetCapBound() const; %unignore S2LatLngRect::GetCenter; %unignore S2LatLngRect::GetCentroid; %unignore S2LatLngRect::GetDistance; %unignore S2LatLngRect::GetRectBound; %unignore S2LatLngRect::GetSize; %unignore S2LatLngRect::GetVertex; %unignore S2LatLngRect::Intersection; %unignore S2LatLngRect::Intersects; %unignore S2LatLngRect::MayIntersect(const S2Cell&) const; %unignore S2LatLngRect::Union; %unignore S2LatLngRect::hi; %unignore S2LatLngRect::is_empty; %unignore S2LatLngRect::is_point; %unignore S2LatLngRect::is_valid; %unignore S2LatLngRect::lat; %unignore S2LatLngRect::lat_hi; %unignore S2LatLngRect::lat_lo; %unignore S2LatLngRect::lng; %unignore S2LatLngRect::lng_hi; %unignore S2LatLngRect::lng_lo; %unignore S2LatLngRect::lo; %unignore S2Loop; %unignore S2Loop::~S2Loop; %unignore S2Loop::Clone; %unignore S2Loop::Contains; %unignore S2Loop::Decode; %unignore S2Loop::Encode; %unignore S2Loop::Equals; %unignore S2Loop::GetArea; %unignore S2Loop::GetCapBound() const; %unignore S2Loop::GetCentroid; %unignore S2Loop::GetDistance; %unignore S2Loop::GetRectBound; %unignore S2Loop::GetS2LatLngVertex; %unignore S2Loop::Intersects; %unignore S2Loop::IsNormalized() const; %unignore S2Loop::IsValid; %unignore S2Loop::MayIntersect(const S2Cell&) const; %unignore S2Loop::Normalize; %unignore S2Loop::Project; %unignore S2Loop::depth; %unignore S2Loop::is_empty; %unignore S2Loop::is_hole; %unignore S2Loop::num_vertices; %unignore S2Loop::sign; %unignore S2Loop::vertex; %unignore S2Polygon; %unignore S2Polygon::S2Polygon; %ignore S2Polygon::S2Polygon(std::unique_ptr, S2Debug); %ignore S2Polygon::S2Polygon(std::unique_ptr); %ignore S2Polygon::S2Polygon(std::vector>, S2Debug); %ignore S2Polygon::S2Polygon(std::vector>); %unignore S2Polygon::~S2Polygon; %unignore S2Polygon::BoundaryNear; %unignore S2Polygon::Clone; %unignore S2Polygon::Contains; %unignore S2Polygon::Copy; %unignore S2Polygon::Decode; %unignore S2Polygon::Encode; %unignore S2Polygon::Equals; %unignore S2Polygon::GetArea; %unignore S2Polygon::GetCapBound() const; %unignore S2Polygon::GetCentroid; %unignore S2Polygon::GetDistance; %unignore S2Polygon::GetLastDescendant(int) const; %unignore S2Polygon::GetOverlapFractions(const S2Polygon&, const S2Polygon&); %unignore S2Polygon::GetRectBound; %unignore S2Polygon::Init; %ignore S2Polygon::Init(std::unique_ptr); %unignore S2Polygon::InitNested; %ignore S2Polygon::InitNested(std::vector>); %unignore S2Polygon::InitToUnion; %unignore S2Polygon::Intersects; %unignore S2Polygon::IsValid; %unignore S2Polygon::MayIntersect(const S2Cell&) const; %unignore S2Polygon::Project; %unignore S2Polygon::is_empty; %unignore S2Polygon::loop; %unignore S2Polygon::num_loops; %unignore S2Polygon::num_vertices; %unignore S2Polyline; %unignore S2Polyline::S2Polyline(); %unignore S2Polyline::S2Polyline(std::vector const &); %ignore S2Polyline::S2Polyline(std::vector const &); %ignore S2Polyline::S2Polyline(std::vector const &, S2Debug); %unignore S2Polyline::~S2Polyline; %unignore S2Polyline::ApproxEquals; %unignore S2Polyline::Clone; %unignore S2Polyline::Contains; %unignore S2Polyline::Decode; %unignore S2Polyline::Encode; %unignore S2Polyline::GetCapBound() const; %unignore S2Polyline::GetCentroid; %unignore S2Polyline::GetLength; %unignore S2Polyline::GetRectBound; %unignore S2Polyline::GetSuffix; %unignore S2Polyline::Interpolate; %unignore S2Polyline::Intersects; %unignore S2Polyline::IsOnRight; %unignore S2Polyline::IsValid; %unignore S2Polyline::MayIntersect(const S2Cell&) const; %unignore S2Polyline::Project; %unignore S2Polyline::Reverse; %unignore S2Polyline::UnInterpolate; %unignore S2Polyline::num_vertices; %unignore S2Polyline::vertex; %unignore s2pred; %unignore s2pred::OrderedCCW; %unignore S2RegionCoverer; %unignore S2RegionCoverer::S2RegionCoverer; %unignore S2RegionCoverer::~S2RegionCoverer; %unignore S2RegionCoverer::GetCovering(const S2Region&, std::vector*); %unignore S2RegionCoverer::GetInteriorCovering(const S2Region&, std::vector*); %unignore S2RegionTermIndexer; %unignore S2RegionTermIndexer::S2RegionTermIndexer; %unignore S2RegionTermIndexer::~S2RegionTermIndexer; %unignore S2RegionTermIndexer::GetIndexTerms(const S2Point&, absl::string_view); %unignore S2RegionTermIndexer::GetIndexTerms(const S2Region&, absl::string_view); %unignore S2RegionTermIndexer::GetIndexTermsForCanonicalCovering( const S2CellUnion&, absl::string_view); %unignore S2RegionTermIndexer::GetQueryTerms(const S2Point&, absl::string_view); %unignore S2RegionTermIndexer::GetQueryTerms(const S2Region&, absl::string_view); %unignore S2RegionTermIndexer::GetQueryTermsForCanonicalCovering( const S2CellUnion&, absl::string_view); %unignore S2ShapeIndex; %include "s2/r1interval.h" %include "s2/s1angle.h" %include "s2/s1chord_angle.h" %include "s2/s1interval.h" %include "s2/s2boolean_operation.h" %include "s2/s2buffer_operation.h" %include "s2/s2builder.h" %include "s2/s2builder_layer.h" %include "s2/s2builderutil_s2polygon_layer.h" %include "s2/s2cell_id.h" %include "s2/s2edge_crossings.h" %include "s2/s2edge_distances.h" %include "s2/s2earth.h" %include "s2/s2region.h" %include "s2/s2cap.h" %include "s2/s2latlng.h" %include "s2/s2latlng_rect.h" %include "s2/s2loop.h" %include "s2/s2measures.h" %include "s2/s2pointutil.h" %include "s2/s2polygon.h" %include "s2/s2polyline.h" %include "s2/s2predicates.h" %include "s2/s2region_coverer.h" %include "s2/s2region_term_indexer.h" %include "s2/s2cell.h" %include "s2/s2cell_union.h" %include "s2/s2shape_index.h" %include "s2/mutable_s2shape_index.h" %unignoreall %define USE_STREAM_INSERTOR_FOR_STR(type) %extend type { std::string __str__() { std::ostringstream output; output << *$self; return output.str(); } } %enddef %define USE_EQUALS_FN_FOR_EQ_AND_NE(type) %extend type { bool __eq__(const type& other) { return $self->Equals(other); } bool __ne__(const type& other) { return !$self->Equals(other); } } %enddef %define USE_EQUALS_FOR_EQ_AND_NE(type) %extend type { bool __eq__(const type& other) { return *$self == other; } bool __ne__(const type& other) { return *$self != other; } } %enddef %define USE_COMPARISON_FOR_LT_AND_GT(type) %extend type { bool __lt__(const type& other) { return *$self < other; } bool __gt__(const type& other) { return *$self > other; } } %enddef %define USE_ARITHMETIC_FOR_ADD_AND_SUB(type) %extend type { type __add__(const type& other) { return *$self + other; } type __sub__(const type& other) { return *$self - other; } } %enddef %define USE_HASH_FOR_TYPE(type, hash_type) %extend type { size_t __hash__() { return hash_type()(*$self); } } %enddef USE_STREAM_INSERTOR_FOR_STR(S1Angle) USE_STREAM_INSERTOR_FOR_STR(S1Interval) USE_STREAM_INSERTOR_FOR_STR(S2CellId) USE_STREAM_INSERTOR_FOR_STR(S2Cap) USE_STREAM_INSERTOR_FOR_STR(S2LatLng) USE_STREAM_INSERTOR_FOR_STR(S2LatLngRect) USE_EQUALS_FOR_EQ_AND_NE(S2CellId) USE_COMPARISON_FOR_LT_AND_GT(S2CellId) USE_HASH_FOR_TYPE(S2CellId, S2CellIdHash) USE_EQUALS_FOR_EQ_AND_NE(S1Angle) USE_COMPARISON_FOR_LT_AND_GT(S1Angle) USE_EQUALS_FOR_EQ_AND_NE(S1ChordAngle) USE_COMPARISON_FOR_LT_AND_GT(S1ChordAngle) USE_ARITHMETIC_FOR_ADD_AND_SUB(S1ChordAngle) USE_EQUALS_FN_FOR_EQ_AND_NE(S2Loop) USE_EQUALS_FN_FOR_EQ_AND_NE(S2Polygon) USE_EQUALS_FN_FOR_EQ_AND_NE(S2Polyline) // Simple implementation of key S2Testing methods %pythoncode %{ import random class S2Testing(object): """ Simple implementation of key S2Testing methods. """ _rnd = random.Random(1) @classmethod def RandomPoint(cls): """ Return a random unit-length vector. """ x = cls._rnd.uniform(-1, 1) y = cls._rnd.uniform(-1, 1) z = cls._rnd.uniform(-1, 1) return S2Point_FromRaw(x, y, z).Normalize() @classmethod def GetRandomCap(cls, min_area, max_area): """ Return a cap with a random axis such that the log of its area is uniformly distributed between the logs of the two given values. (The log of the cap angle is also approximately uniformly distributed.) """ cap_area = max_area * pow(min_area / max_area, cls._rnd.random()) assert cap_area >= min_area assert cap_area <= max_area # The surface area of a cap is 2*Pi times its height. return S2Cap.FromCenterArea(cls.RandomPoint(), cap_area) %} src/python/s2cap_bindings.cc000066400000000000000000000211101524103652300163560ustar00rootroot00000000000000#include #include #include #include #include #include "absl/hash/hash.h" #include "s2/s1angle.h" #include "s2/s1chord_angle.h" #include "s2/s2cap.h" #include "s2/s2cell.h" #include "s2/s2cell_id.h" #include "s2/s2point.h" namespace py = pybind11; void bind_s2cap(py::module& m) { py::class_(m, "S2Cap", "A disc-shaped region defined by a center and radius on the sphere.\n\n" "The cap represents a portion of the unit sphere cut off by a plane.\n" "The boundary is a circle; the cap is a closed set (contains its\n" "boundary). A cap of radius Pi/2 is a hemisphere; Pi covers the full\n" "sphere. See s2/s2cap.h for comprehensive documentation.") // Constructors .def(py::init<>(), "Construct an empty S2Cap.") .def(py::init([](const S2Point& center, S1Angle radius) { return S2Cap(center.Normalize(), radius); }), py::arg("center"), py::arg("radius"), "Construct a cap with the given center and radius.\n\n" "center is normalized if not already unit length. Negative radius\n" "produces the empty cap; radius >= 180 degrees produces the full cap.") .def(py::init([](const S2Point& center, S1ChordAngle radius) { return S2Cap(center.Normalize(), radius); }), py::arg("center"), py::arg("radius"), "Construct a cap with the given center and radius as S1ChordAngle.\n\n" "center is normalized if not already unit length.") // Factory methods .def_static("from_point", [](const S2Point& center) { return S2Cap::FromPoint(center.Normalize()); }, py::arg("center"), "Return a cap containing a single point.\n\n" "center is normalized if not already unit length.") .def_static("from_center_height", [](const S2Point& center, double height) { return S2Cap::FromCenterHeight(center.Normalize(), height); }, py::arg("center"), py::arg("height"), "Return a cap with the given center and height.\n\n" "Height is the distance from the center point to the cutoff plane.\n" "center is normalized if not already unit length.\n" "A negative height yields an empty cap; height >= 2 yields a full cap.") .def_static("from_center_area", [](const S2Point& center, double area) { return S2Cap::FromCenterArea(center.Normalize(), area); }, py::arg("center"), py::arg("area"), "Return a cap with the given center and surface area in steradians.\n\n" "The area also equals the solid angle subtended by the cap.\n" "center is normalized if not already unit length.\n" "A negative area yields an empty cap; area >= 4*Pi yields a full cap.") .def_static("empty", &S2Cap::Empty, "Return an empty cap (contains no points).") .def_static("full", &S2Cap::Full, "Return a full cap (contains all points).") .def_static("from_points", [](const std::vector& points) { if (points.empty()) return S2Cap::Empty(); S2Cap result = S2Cap::FromPoint(points[0].Normalize()); for (size_t i = 1; i < points.size(); ++i) result.AddPoint(points[i].Normalize()); return result; }, py::arg("points"), "Return the smallest cap containing all given points.\n\n" "Returns the empty cap if the list is empty.") .def_static("from_caps", [](const std::vector& caps) { if (caps.empty()) return S2Cap::Empty(); S2Cap result = caps[0]; for (size_t i = 1; i < caps.size(); ++i) result.AddCap(caps[i]); return result; }, py::arg("caps"), "Return the smallest cap containing all given caps.\n\n" "Returns the empty cap if the list is empty.") // Properties .def_property_readonly("center", &S2Cap::center, "The center of the cap as a unit-length S2Point.") .def_property_readonly("radius", &S2Cap::radius, "The radius as an S1ChordAngle.") .def_property_readonly("height", &S2Cap::height, "The height of the cap (distance from center point to cutoff plane).") // Geometric operations .def("radius_angle", &S2Cap::GetRadius, "Return the radius as an S1Angle.\n\n" "Requires a trigonometric operation; may differ slightly from the\n" "value passed to the S1Angle constructor.") .def("area", &S2Cap::GetArea, "Return the surface area of the cap in steradians.") .def("centroid", &S2Cap::GetCentroid, "Return the true centroid of the cap multiplied by its surface area.\n\n" "The result lies on the ray from the origin through the cap's center.\n" "For zero-radius caps, always returns the origin (0, 0, 0).") // Predicates .def("is_empty", &S2Cap::is_empty, "Return true if the cap contains no points.") .def("is_full", &S2Cap::is_full, "Return true if the cap contains all points.") .def("complement", &S2Cap::Complement, "Return the complement of the interior of the cap.\n\n" "Same boundary as this cap but no shared interior points.\n" "Note: complement of a singleton equals complement of an empty cap.") .def("expanded", &S2Cap::Expanded, py::arg("distance"), "Return a cap containing all points within distance of this cap.\n\n" "Any expansion of an empty cap is still empty.") .def("union", &S2Cap::Union, py::arg("other"), "Return the smallest cap enclosing this cap and other.") // Containment / intersection .def("contains", py::overload_cast( &S2Cap::Contains, py::const_), py::arg("other"), "Return true if this cap contains the given cap.") .def("contains_point", py::overload_cast( &S2Cap::Contains, py::const_), py::arg("point"), "Return true if this cap contains the given point.\n\n" "point should be unit length.") .def("contains_cell", py::overload_cast( &S2Cap::Contains, py::const_), py::arg("cell"), "Return true if this cap contains the given cell.") .def("intersects", py::overload_cast( &S2Cap::Intersects, py::const_), py::arg("other"), "Return true if this cap intersects the given cap.") .def("interior_intersects", &S2Cap::InteriorIntersects, py::arg("other"), "Return true if the interior of this cap intersects other.\n\n" "This relationship is not symmetric: only the interior of this cap\n" "is tested, not the interior of other.") .def("interior_contains_point", &S2Cap::InteriorContains, py::arg("point"), "Return true if the interior of this cap contains the given point.\n\n" "point should be unit length.") .def("may_intersect", &S2Cap::MayIntersect, py::arg("cell"), "Return true if this cap may intersect the given cell.") .def("cap_bound", &S2Cap::GetCapBound, "Return a bounding cap for this cap (returns self).") // get_rect_bound() is deferred until S2LatLngRect is bound. .def("cell_union_bound", [](const S2Cap& self) { std::vector cell_ids; self.GetCellUnionBound(&cell_ids); return cell_ids; }, "Return a list of S2CellIds whose union covers this cap.") // Operators .def(py::self == py::self, "Return true if caps are identical.") .def(py::self != py::self, "Return true if caps are not identical.") .def("approx_equals", &S2Cap::ApproxEquals, py::arg("other"), py::arg("max_error") = S1Angle::Radians(1e-14), "Return true if this cap is approximately equal to other.\n\n" "Checks that the angle between centers and the difference in chord\n" "radii are both within max_error radians.") .def("__hash__", [](const S2Cap& self) { return absl::HashOf(self); }) // String representation .def("__repr__", [](const S2Cap& self) { std::ostringstream oss; oss << "S2Cap(" << self << ")"; return oss.str(); }) .def("__str__", [](const S2Cap& self) { std::ostringstream oss; oss << self; return oss.str(); }); } src/python/s2cap_test.py000066400000000000000000000252441524103652300156170ustar00rootroot00000000000000"""Tests for S2Cap pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestS2Cap(unittest.TestCase): """Test cases for S2Cap bindings.""" # Constructors def test_default_constructor_is_empty(self): cap = s2.S2Cap() self.assertTrue(cap.is_empty()) self.assertFalse(cap.is_full()) def test_constructor_s1angle(self): center = s2.S2Point(1.0, 0.0, 0.0) radius = s2.S1Angle.from_radians(math.pi / 4) cap = s2.S2Cap(center, radius) self.assertFalse(cap.is_empty()) self.assertFalse(cap.is_full()) def test_constructor_s1chord_angle(self): center = s2.S2Point(1.0, 0.0, 0.0) radius = s2.S1ChordAngle(s2.S1Angle.from_radians(math.pi / 4)) cap = s2.S2Cap(center, radius) self.assertFalse(cap.is_empty()) def test_constructor_negative_radius_is_empty(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap(center, s2.S1Angle.from_radians(-1.0)) self.assertTrue(cap.is_empty()) def test_constructor_pi_radius_is_full(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap(center, s2.S1Angle.from_radians(math.pi)) self.assertTrue(cap.is_full()) def test_constructor_normalizes_center(self): p = s2.S2Point(2.0, 0.0, 0.0) # not unit length cap = s2.S2Cap(p, s2.S1Angle.from_degrees(10.0)) self.assertAlmostEqual(cap.center.norm(), 1.0, places=15) # Factory methods def test_from_point(self): p = s2.S2Point(0.0, 1.0, 0.0) cap = s2.S2Cap.from_point(p) self.assertTrue(cap.contains_point(p)) def test_from_center_height(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap.from_center_height(center, 0.5) self.assertAlmostEqual(cap.height, 0.5) def test_from_center_height_negative_is_empty(self): center = s2.S2Point(1.0, 0.0, 0.0) self.assertTrue(s2.S2Cap.from_center_height(center, -1.0).is_empty()) def test_from_center_height_two_is_full(self): center = s2.S2Point(1.0, 0.0, 0.0) self.assertTrue(s2.S2Cap.from_center_height(center, 2.0).is_full()) def test_from_center_area(self): center = s2.S2Point(1.0, 0.0, 0.0) area = 2 * math.pi # hemisphere cap = s2.S2Cap.from_center_area(center, area) self.assertAlmostEqual(cap.area(), area, places=10) def test_empty(self): cap = s2.S2Cap.empty() self.assertTrue(cap.is_empty()) self.assertFalse(cap.is_full()) def test_full(self): cap = s2.S2Cap.full() self.assertTrue(cap.is_full()) self.assertFalse(cap.is_empty()) def test_from_points_empty(self): cap = s2.S2Cap.from_points([]) self.assertTrue(cap.is_empty()) def test_from_points_single(self): p = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap.from_points([p]) self.assertTrue(cap.contains_point(p)) def test_from_points_multiple(self): p1 = s2.S2Point(1.0, 0.0, 0.0) p2 = s2.S2Point(0.0, 1.0, 0.0) p3 = s2.S2Point(0.0, 0.0, 1.0) cap = s2.S2Cap.from_points([p1, p2, p3]) self.assertTrue(cap.contains_point(p1)) self.assertTrue(cap.contains_point(p2)) self.assertTrue(cap.contains_point(p3)) def test_from_caps_empty(self): cap = s2.S2Cap.from_caps([]) self.assertTrue(cap.is_empty()) def test_from_caps_single(self): c = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_degrees(10.0)) result = s2.S2Cap.from_caps([c]) self.assertTrue(result.contains_point(c.center)) def test_from_caps_multiple(self): c1 = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_degrees(10.0)) c2 = s2.S2Cap(s2.S2Point(0.0, 1.0, 0.0), s2.S1Angle.from_degrees(10.0)) result = s2.S2Cap.from_caps([c1, c2]) self.assertTrue(result.contains_point(c1.center)) self.assertTrue(result.contains_point(c2.center)) # Properties def test_center(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap.from_point(center) self.assertEqual(cap.center, center) def test_radius(self): center = s2.S2Point(1.0, 0.0, 0.0) chord = s2.S1ChordAngle(s2.S1Angle.from_radians(1.0)) cap = s2.S2Cap(center, chord) self.assertEqual(cap.radius, chord) def test_height(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap.from_center_height(center, 0.5) self.assertAlmostEqual(cap.height, 0.5) # Predicates def test_is_empty(self): self.assertTrue(s2.S2Cap.empty().is_empty()) self.assertFalse(s2.S2Cap.full().is_empty()) def test_is_full(self): self.assertTrue(s2.S2Cap.full().is_full()) self.assertFalse(s2.S2Cap.empty().is_full()) # Geometric operations def test_radius_angle(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) self.assertAlmostEqual(cap.radius_angle().radians, 1.0, places=14) def test_area(self): self.assertAlmostEqual(s2.S2Cap.full().area(), 4 * math.pi) self.assertAlmostEqual(s2.S2Cap.empty().area(), 0.0) def test_centroid(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap.from_center_height(center, 0.5) centroid = cap.centroid() # Centroid lies along the same axis as center. self.assertGreater(centroid.x, 0.0) self.assertAlmostEqual(centroid.y, 0.0) self.assertAlmostEqual(centroid.z, 0.0) def test_complement_of_empty_is_full(self): self.assertTrue(s2.S2Cap.empty().complement().is_full()) def test_complement_of_full_is_empty(self): self.assertTrue(s2.S2Cap.full().complement().is_empty()) def test_complement_roundtrip(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) comp = cap.complement() self.assertFalse(comp.is_empty()) self.assertFalse(comp.is_full()) def test_expanded(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap.from_point(center) delta = s2.S1Angle.from_radians(0.1) expanded = cap.expanded(delta) self.assertGreater(expanded.radius_angle().radians, cap.radius_angle().radians) def test_expanded_empty_stays_empty(self): self.assertTrue( s2.S2Cap.empty().expanded(s2.S1Angle.from_radians(1.0)).is_empty()) def test_union_contains_both_centers(self): p1 = s2.S2Point(1.0, 0.0, 0.0) p2 = s2.S2Point(math.cos(0.1), math.sin(0.1), 0.0) cap1 = s2.S2Cap(p1, s2.S1Angle.from_radians(0.01)) cap2 = s2.S2Cap(p2, s2.S1Angle.from_radians(0.01)) u = cap1.union(cap2) # Centers lie strictly inside the union radius, so contains_point is reliable. self.assertTrue(u.contains_point(p1)) self.assertTrue(u.contains_point(p2)) def test_full_contains_any_cap(self): cap = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_radians(1.0)) self.assertTrue(s2.S2Cap.full().contains(cap)) def test_empty_contained_by_any_cap(self): cap = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_radians(1.0)) self.assertTrue(cap.contains(s2.S2Cap.empty())) def test_contains_point(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) self.assertTrue(cap.contains_point(center)) self.assertFalse(cap.contains_point(s2.S2Point(-1.0, 0.0, 0.0))) def test_contains_cell(self): cell = s2.S2Cell(s2.S2CellId(s2.S2Point(1.0, 0.0, 0.0))) self.assertTrue(s2.S2Cap.full().contains_cell(cell)) self.assertFalse(s2.S2Cap.empty().contains_cell(cell)) def test_intersects(self): cap = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_radians(1.0)) self.assertTrue(cap.intersects(cap)) self.assertFalse(cap.intersects(s2.S2Cap.empty())) def test_interior_intersects(self): cap = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_radians(1.0)) self.assertTrue(cap.interior_intersects(cap)) def test_interior_contains_point(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) self.assertTrue(cap.interior_contains_point(center)) def test_may_intersect(self): cell = s2.S2Cell(s2.S2CellId(s2.S2Point(1.0, 0.0, 0.0))) self.assertTrue(s2.S2Cap.full().may_intersect(cell)) def test_cap_bound(self): center = s2.S2Point(1.0, 0.0, 0.0) cap = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) bound = cap.cap_bound() self.assertTrue(bound.approx_equals(cap)) def test_cell_union_bound(self): cell_ids = s2.S2Cap.full().cell_union_bound() self.assertGreater(len(cell_ids), 0) # Operators def test_equality(self): center = s2.S2Point(1.0, 0.0, 0.0) cap1 = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) cap2 = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) self.assertTrue(cap1 == cap2) self.assertFalse(cap1 != cap2) def test_inequality(self): cap1 = s2.S2Cap.from_point(s2.S2Point(1.0, 0.0, 0.0)) cap2 = s2.S2Cap.from_point(s2.S2Point(0.0, 1.0, 0.0)) self.assertTrue(cap1 != cap2) self.assertFalse(cap1 == cap2) def test_approx_equals(self): cap = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_radians(1.0)) self.assertTrue(cap.approx_equals(cap)) def test_approx_equals_with_max_error(self): cap = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_radians(1.0)) self.assertTrue(cap.approx_equals(cap, s2.S1Angle.from_radians(1e-10))) def test_approx_equals_false(self): cap1 = s2.S2Cap(s2.S2Point(1.0, 0.0, 0.0), s2.S1Angle.from_radians(1.0)) cap2 = s2.S2Cap(s2.S2Point(0.0, 1.0, 0.0), s2.S1Angle.from_radians(1.0)) self.assertFalse(cap1.approx_equals(cap2)) def test_hash(self): center = s2.S2Point(1.0, 0.0, 0.0) cap1 = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) cap2 = s2.S2Cap(center, s2.S1Angle.from_radians(1.0)) self.assertEqual(hash(cap1), hash(cap2)) s = {cap1, cap2} self.assertEqual(len(s), 1) # String representation def test_repr(self): cap = s2.S2Cap.empty() r = repr(cap) self.assertTrue(r.startswith("S2Cap(")) self.assertIn("Center=", r) self.assertIn("Radius=", r) def test_str(self): cap = s2.S2Cap.empty() s = str(cap) self.assertIn("Center=", s) self.assertIn("Radius=", s) if __name__ == "__main__": unittest.main() src/python/s2cell_bindings.cc000066400000000000000000000263331524103652300165460ustar00rootroot00000000000000#include #include #include #include #include #include #include "absl/hash/hash.h" #include "absl/strings/str_cat.h" #include "s2/s1chord_angle.h" #include "s2/s2cell.h" #include "s2/s2cell_id.h" #include "s2/s2latlng.h" #include "s2/s2point.h" namespace py = pybind11; namespace { // These three helpers are duplicated from s2cell_id_bindings.cc. void MaybeThrowFaceOutOfRange(int face) { if (face < 0 || face >= S2CellId::kNumFaces) { throw py::value_error( absl::StrCat("Face ", face, " out of range [0, ", S2CellId::kNumFaces - 1, "]")); } } void MaybeThrowLevelOutOfRange(int level, int min, int max) { if (level < min || level > max) { throw py::value_error( absl::StrCat("Level ", level, " out of range [", min, ", ", max, "]")); } } void MaybeThrowPositionOutOfRange(uint64_t pos) { if (pos > S2CellId::kMaxPosition) { throw py::value_error( absl::StrCat("pos ", pos, " out of range [0, ", S2CellId::kMaxPosition, "]")); } } } // namespace void bind_s2cell(py::module& m) { auto cls = py::class_(m, "S2Cell", "An S2Region representing a single cell on the sphere.\n\n" "Unlike S2CellId (which is just a 64-bit identifier), S2Cell carries\n" "precomputed state that allows efficient containment and intersection\n" "tests. See s2/s2cell.h for comprehensive documentation.") // Constructors .def(py::init([](S2CellId id) { // No validity check needed: all S2CellId objects reachable from // Python are guaranteed valid by the S2CellId bindings. return S2Cell(id); }), py::arg("cell_id"), "Construct the cell corresponding to the given S2CellId.") .def(py::init([](const S2Point& p) { return S2Cell(p); }), py::arg("point"), "Construct a leaf cell containing the given point.\n\n" "The point does not need to be normalized.") .def(py::init([](const S2LatLng& ll) { // No validity check needed: all S2LatLng objects reachable from // Python are guaranteed valid by the S2LatLng bindings. return S2Cell(ll); }), py::arg("latlng"), "Construct a leaf cell containing the given S2LatLng.") // Factory methods .def_static("from_face", [](int face) { MaybeThrowFaceOutOfRange(face); return S2Cell::FromFace(face); }, py::arg("face"), "Return the cell corresponding to the given S2 cube face (0..5).\n\n" "Raises ValueError if face is out of range.") .def_static("from_face_pos_level", [](int face, uint64_t pos, int level) { MaybeThrowFaceOutOfRange(face); MaybeThrowPositionOutOfRange(pos); MaybeThrowLevelOutOfRange(level, 0, S2CellId::kMaxLevel); return S2Cell::FromFacePosLevel(face, pos, level); }, py::arg("face"), py::arg("pos"), py::arg("level"), "Return a cell given its face, Hilbert curve position, and level.\n\n" "Raises ValueError if face, pos, or level is out of range.") // Properties .def_property_readonly("id", &S2Cell::id, "The S2CellId this cell corresponds to") .def_property_readonly("face", &S2Cell::face, "Which cube face this cell belongs to (0..5)") .def_property_readonly("level", &S2Cell::level, "The subdivision level (0..kMaxLevel)") .def_property_readonly("orientation", &S2Cell::orientation, "The Hilbert curve orientation of this cell.\n\n" "A bitmask: bit 0 (kSwapMask) indicates swapped\n" "axes; bit 1 (kInvertMask) indicates 180-degree\n" "rotation. Values are in [0, 3].") // Predicates .def("is_leaf", &S2Cell::is_leaf, "Return true if this is a leaf cell (level == kMaxLevel)") // Geometric operations .def("size_ij", &S2Cell::GetSizeIJ, "Return the edge length of this cell in (i,j)-space") .def("size_st", &S2Cell::GetSizeST, "Return the edge length of this cell in (s,t)-space") .def("vertex", &S2Cell::GetVertex, py::arg("k"), "Return the k-th vertex of the cell (k = 0,1,2,3) in CCW order.\n\n" "Lower-left, lower-right, upper-right, upper-left in the UV plane.\n" "The argument is reduced modulo 4 to the range [0..3].\n" "The returned point is normalized.") .def("edge", &S2Cell::GetEdge, py::arg("k"), "Return the normalized inward-facing normal of the great circle\n" "passing through the edge from vertex k to vertex k+1 (mod 4).\n\n" "The argument is reduced modulo 4 to the range [0..3].") .def("uv_coord_of_edge", &S2Cell::GetUVCoordOfEdge, py::arg("k"), "Return either U or V for the given edge, whichever is constant\n" "along it.\n\n" "Boundaries 0 and 2 return V; boundaries 1 and 3 return U.\n" "The argument is reduced modulo 4 to the range [0..3].") .def("ij_coord_of_edge", &S2Cell::GetIJCoordOfEdge, py::arg("k"), "Return either I or J for the given edge, whichever is constant\n" "along it.\n\n" "Boundaries 0 and 2 return J; boundaries 1 and 3 return I.\n" "The argument is reduced modulo 4 to the range [0..3].") .def("center", &S2Cell::GetCenter, "Return the center of the cell as a normalized S2Point") .def_static("average_area_for_level", [](int level) { MaybeThrowLevelOutOfRange(level, 0, S2CellId::kMaxLevel); return S2Cell::AverageArea(level); }, py::arg("level"), "Return the average area of cells at the given level,\n" "in steradians.\n\n" "Raises ValueError if level is out of range.") .def("approx_area", &S2Cell::ApproxArea, "Return the approximate area of this cell in steradians.\n\n" "Accurate to within 3% for all cell sizes and within 0.1% for\n" "cells at level 5 or higher.") .def("exact_area", &S2Cell::ExactArea, "Return the area of this cell as accurately as possible,\n" "in steradians.\n\n" "More expensive than approx_area but accurate to 6 digits\n" "even for leaf cells.") .def("bound_uv", &S2Cell::GetBoundUV, "Return the bounds of this cell in (u,v)-space") .def("distance", py::overload_cast( &S2Cell::GetDistance, py::const_), py::arg("point"), "Return the distance from this cell to the given point.\n\n" "Returns zero if the point is inside the cell.") .def("boundary_distance", &S2Cell::GetBoundaryDistance, py::arg("point"), "Return the distance from the cell boundary to the given point.") .def("max_distance", py::overload_cast( &S2Cell::GetMaxDistance, py::const_), py::arg("point"), "Return the maximum distance from this cell to the given point.") .def("distance_to_edge", py::overload_cast( &S2Cell::GetDistance, py::const_), py::arg("a"), py::arg("b"), "Return the minimum distance from this cell to the edge AB.\n\n" "Returns zero if the edge intersects the cell interior.") .def("max_distance_to_edge", py::overload_cast( &S2Cell::GetMaxDistance, py::const_), py::arg("a"), py::arg("b"), "Return the maximum distance from this cell to the edge AB.") .def("distance_to_cell", py::overload_cast(&S2Cell::GetDistance, py::const_), py::arg("cell"), "Return the distance from this cell to the given cell.\n\n" "Returns zero if one cell contains the other.") .def("max_distance_to_cell", py::overload_cast(&S2Cell::GetMaxDistance, py::const_), py::arg("cell"), "Return the maximum distance from this cell to the given cell.") .def("cell_union_bound", [](const S2Cell& self) { std::vector cell_ids; self.GetCellUnionBound(&cell_ids); return cell_ids; }, "Return a list of S2CellIds whose union covers this cell.\n\n" "For a single S2Cell, this always returns a list containing\n" "just this cell's id.") .def("contains", py::overload_cast( &S2Cell::Contains, py::const_), py::arg("cell"), "Return true if this cell contains the given cell") .def("contains_point", py::overload_cast( &S2Cell::Contains, py::const_), py::arg("point"), "Return true if this cell contains the given point.\n\n" "S2Cells are closed sets: points along an edge or vertex\n" "belong to the adjacent cell(s) as well.\n" "The point does not need to be normalized.") .def("may_intersect", &S2Cell::MayIntersect, py::arg("cell"), "Return true if this cell may intersect the given cell") .def("subdivide", [](const S2Cell& self) { if (self.is_leaf()) { throw py::value_error("Leaf cell has no children"); } S2Cell children[4]; self.Subdivide(children); return py::make_tuple(children[0], children[1], children[2], children[3]); }, "Return the four children of this cell as a tuple.\n\n" "Raises ValueError if this is a leaf cell.") // Operators .def(py::self == py::self, "Return true if cells are equal") .def(py::self != py::self, "Return true if cells are not equal") .def(py::self < py::self, "Compare cells by their cell id") .def(py::self > py::self, "Compare cells by their cell id") .def(py::self <= py::self, "Compare cells by their cell id") .def(py::self >= py::self, "Compare cells by their cell id") .def("__hash__", [](const S2Cell& self) { return absl::HashOf(self.id()); }) // String representation .def("__repr__", [](const S2Cell& cell) { std::ostringstream oss; oss << "S2Cell(" << cell.id() << ")"; return oss.str(); }) .def("__str__", [](const S2Cell& cell) { std::ostringstream oss; oss << cell.id(); return oss.str(); }); py::enum_(cls, "Boundary", py::arithmetic()) .value("BOTTOM_EDGE", S2Cell::kBottomEdge) .value("RIGHT_EDGE", S2Cell::kRightEdge) .value("TOP_EDGE", S2Cell::kTopEdge) .value("LEFT_EDGE", S2Cell::kLeftEdge) .export_values(); // TODO: The following S2Cell methods are not yet bound because they depend // on types that have not been bound yet: // - get_cap_bound() -> S2Cap // - get_rect_bound() -> S2LatLngRect } src/python/s2cell_id_bindings.cc000066400000000000000000000443341524103652300172230ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "absl/strings/str_cat.h" #include "s2/s2cell_id.h" #include "python/s2cell_id_range.h" #include "s2/s2latlng.h" namespace py = pybind11; namespace { void MaybeThrowNotValid(S2CellId id) { if (!id.is_valid()) { throw py::value_error(absl::StrCat("Invalid S2CellId: ", id.ToString())); } } void MaybeThrowLevelOutOfRange(int level, int min, int max) { if (level < min || level > max) { throw py::value_error( absl::StrCat("Level ", level, " out of range [", min, ", ", max, "]")); } } void MaybeThrowFaceOutOfRange(int face) { if (face < 0 || face >= S2CellId::kNumFaces) { throw py::value_error( absl::StrCat("Face ", face, " out of range [0, ", S2CellId::kNumFaces - 1, "]")); } } void MaybeThrowIfLeaf(S2CellId id) { if (id.is_leaf()) { throw py::value_error("Function invalid for leaf cells"); } } void MaybeThrowIfFace(S2CellId id) { if (id.is_face()) { throw py::value_error("Function invalid for face cells"); } } void MaybeThrowCellIdOutOfRange(const char* name, int value, int min, int max) { if (value < min || value > max) { throw py::value_error( absl::StrCat(name, " ", value, " out of range [", min, ", ", max, "]")); } } void MaybeThrowChildPositionOutOfRange(int position) { if (position < 0 || position > 3) { throw py::value_error( absl::StrCat("Child position ", position, " out of range [0, 3]")); } } void MaybeThrowPositionOutOfRange(uint64_t pos) { if (pos > S2CellId::kMaxPosition) { throw py::value_error( absl::StrCat("pos ", pos, " out of range [0, ", S2CellId::kMaxPosition, "]")); } } // Raise OverflowError if n exceeds Py_ssize_t; otherwise return it cast. // On 32-bit Python, cells() ranges above level ~15 exceed ssize_t max. Py_ssize_t LenOrThrow(int64_t n) { if (n > std::numeric_limits::max()) { throw std::overflow_error(absl::StrCat( "S2CellIdRange size ", n, " exceeds Py_ssize_t max (", std::numeric_limits::max(), ") on this platform. On 32-bit Python, cells() ranges above " "level ~15 exceed ssize_t. Use .size() for the full int64 count.")); } return static_cast(n); } // Normalize a Python-style index (negative counts from end) against a range // of length n and return the 0-based index. Raises IndexError if the index // is still out of [0, n) after normalization. // https://docs.python.org/3/reference/datamodel.html#object.__getitem__ int64_t IndexOrThrow(int64_t i, int64_t n) { if (i < 0) i += n; if (i < 0 || i >= n) throw py::index_error("index out of range"); return i; } // Raise ValueError if the slice step is anything other than 1 (or None). // S2CellIdRange slices must be contiguous; reversed() covers step=-1. void ValidateStepIsOne(py::slice s) { py::object step_obj = s.attr("step"); if (step_obj.is_none()) return; int64_t step = step_obj.cast(); if (step != 1) { throw py::value_error(absl::StrCat( "S2CellIdRange only supports slices with step 1 (got step ", step, ")")); } } // Resolve a Python slice against a range of length n and return the clamped // [start, stop) bounds. Slice indices are silently clamped per: // https://docs.python.org/3/reference/datamodel.html#sequences // // py::slice::compute() is not used because it requires Py_ssize_t, which is // 32-bit on 32-bit platforms; S2CellIdRange can have up to 2^60 cells so // indices are handled as int64_t directly. std::pair ClampedSlice(int64_t n, py::slice s) { auto clamp = [n](int64_t i) -> int64_t { if (i < 0) i += n; if (i < 0) return int64_t{0}; if (i > n) return n; return i; }; py::object start_obj = s.attr("start"); py::object stop_obj = s.attr("stop"); int64_t start = start_obj.is_none() ? int64_t{0} : clamp(start_obj.cast()); int64_t stop = stop_obj.is_none() ? n : clamp(stop_obj.cast()); if (stop < start) stop = start; return {start, stop}; } // Dereference an optional S2CellId from an iterator's next(), or raise // StopIteration if the iterator is exhausted. S2CellId NextOrStop(std::optional result) { if (!result) throw py::stop_iteration(); return *result; } } // namespace void bind_s2cell_id(py::module& m) { auto cls = py::class_(m, "S2CellId", "A 64-bit unsigned integer that uniquely identifies a cell in the\n" "S2 cell decomposition.\n\n" "See s2/s2cell_id.h for comprehensive documentation.") // Constructors .def(py::init([](uint64_t id) { S2CellId cell(id); MaybeThrowNotValid(cell); return cell; }), py::arg("id"), "Construct from a 64-bit cell id.\n\n" "Raises ValueError if the id is not valid.") .def(py::init([](const S2Point& p) { return S2CellId(p); }), py::arg("point"), "Construct a leaf cell containing the given point.\n\n" "The point does not need to be normalized.") .def(py::init([](const S2LatLng& ll) { return S2CellId(ll); }), py::arg("latlng"), "Construct a leaf cell containing the given S2LatLng.") // Factory methods .def_static("from_face", [](int face) { MaybeThrowFaceOutOfRange(face); return S2CellId::FromFace(face); }, py::arg("face"), "Return the cell corresponding to a given S2 cube face (0..5).\n\n" "Raises ValueError if face is out of range.") .def_static("from_face_pos_level", [](int face, uint64_t pos, int level) { MaybeThrowFaceOutOfRange(face); MaybeThrowPositionOutOfRange(pos); MaybeThrowLevelOutOfRange(level, 0, S2CellId::kMaxLevel); return S2CellId::FromFacePosLevel(face, pos, level); }, py::arg("face"), py::arg("pos"), py::arg("level"), "Return a cell given its face, Hilbert curve position, and level.\n\n" "Raises ValueError if face, pos, or level is out of range.") .def_static("from_token", [](const std::string& token) { S2CellId cell = S2CellId::FromToken(token); if (cell == S2CellId::None()) { throw py::value_error( absl::StrCat("Invalid S2CellId token: '", token, "'")); } return cell; }, py::arg("token"), "Return a cell from its token string.\n\n" "Raises ValueError if the token is malformed.") .def_static("from_face_ij", [](int face, int i, int j) { MaybeThrowFaceOutOfRange(face); MaybeThrowCellIdOutOfRange("i", i, 0, S2CellId::kMaxSize - 1); MaybeThrowCellIdOutOfRange("j", j, 0, S2CellId::kMaxSize - 1); return S2CellId::FromFaceIJ(face, i, j); }, py::arg("face"), py::arg("i"), py::arg("j"), "Return a leaf cell given its cube face and (i, j) coordinates") // Properties .def_property_readonly("id", &S2CellId::id, "The 64-bit unique identifier for this cell") // Predicates .def("is_leaf", &S2CellId::is_leaf, "Return true if this is a leaf cell (level == kMaxLevel)") .def("is_face", &S2CellId::is_face, "Return true if this is a top-level face cell (level == 0)") // Geometric operations .def_property_readonly("face", &S2CellId::face, "Which cube face this cell belongs to (0..5)") .def_property_readonly("pos", &S2CellId::pos, "The position along the Hilbert curve over this face") .def_property_readonly("level", &S2CellId::level, "The subdivision level (0..kMaxLevel)") .def("size_ij", py::overload_cast<>(&S2CellId::GetSizeIJ, py::const_), "Return the edge length of this cell in (i,j)-space") .def_static("size_ij_for_level", [](int level) { MaybeThrowLevelOutOfRange(level, 0, S2CellId::kMaxLevel); return S2CellId::GetSizeIJ(level); }, py::arg("level"), "Return the edge length in (i,j)-space of cells at the given level") .def("size_st", py::overload_cast<>(&S2CellId::GetSizeST, py::const_), "Return the edge length of this cell in (s,t)-space") .def_static("size_st_for_level", [](int level) { MaybeThrowLevelOutOfRange(level, 0, S2CellId::kMaxLevel); return S2CellId::GetSizeST(level); }, py::arg("level"), "Return the edge length in (s,t)-space of cells at the given level") .def("to_point", &S2CellId::ToPoint, "Return the center of the cell as a normalized S2Point") .def("to_lat_lng", &S2CellId::ToLatLng, "Return the S2LatLng corresponding to the center of the cell") .def("center_st", &S2CellId::GetCenterST, "Return the center of the cell in (s,t)-space") .def("bound_st", &S2CellId::GetBoundST, "Return the bounds of this cell in (s,t)-space") .def("center_uv", &S2CellId::GetCenterUV, "Return the center of the cell in (u,v)-space") .def("bound_uv", &S2CellId::GetBoundUV, "Return the bounds of this cell in (u,v)-space") .def("child_position", [](S2CellId self) { MaybeThrowLevelOutOfRange(self.level(), 1, S2CellId::kMaxLevel); return self.child_position(); }, "Return the child position (0..3) within this cell's parent.\n\n" "Raises ValueError if level < 1.") .def("child_position_at_level", [](S2CellId self, int level) { MaybeThrowLevelOutOfRange(level, 1, self.level()); return self.child_position(level); }, py::arg("level"), "Return the child position (0..3) of this cell's ancestor at\n" "the given level within its parent.\n\n" "Raises ValueError if level is out of range [1, self.level()].") .def("to_token", &S2CellId::ToToken, "Return a compact token string for this cell.\n\n" "Tokens preserve ordering and the round-trip\n" "from_token(cell.to_token()) == cell is guaranteed.") .def("range_min", &S2CellId::range_min, "Return the minimum cell id contained within this cell") .def("range_max", &S2CellId::range_max, "Return the maximum cell id contained within this cell") .def("contains", &S2CellId::contains, py::arg("other"), "Return true if the given cell is contained within this one") .def("intersects", &S2CellId::intersects, py::arg("other"), "Return true if the given cell intersects this one") .def("common_ancestor_level", &S2CellId::GetCommonAncestorLevel, py::arg("other"), "Return the level of the lowest common ancestor.\n\n" "Returns -1 if the cells are from different faces.") // Traversal .def("parent", [](S2CellId self) { MaybeThrowIfFace(self); return self.parent(); }, "Return the cell at the previous level.\n\n" "Raises ValueError if this is already a face cell.") .def("parent_at_level", [](S2CellId self, int level) { MaybeThrowLevelOutOfRange(level, 0, self.level()); return self.parent(level); }, py::arg("level"), "Return the cell at the given level.\n\n" "Raises ValueError if level is out of range [0, self.level()].") .def("child", [](S2CellId self, int position) { MaybeThrowIfLeaf(self); MaybeThrowChildPositionOutOfRange(position); return self.child(position); }, py::arg("position"), "Return the immediate child at the given position (0..3).\n\n" "Raises ValueError if this is a leaf cell or position is out of range.") .def("children", [](S2CellId self, py::object level_obj) { MaybeThrowIfLeaf(self); S2CellId begin, end; if (level_obj.is_none()) { begin = self.child_begin(); end = self.child_end(); } else { int level = level_obj.cast(); MaybeThrowLevelOutOfRange(level, self.level() + 1, S2CellId::kMaxLevel); begin = self.child_begin(level); end = self.child_end(level); } return S2CellIdRange{begin, end}; }, py::arg("level") = py::none(), "Return a range over the children of this cell.\n\n" "With no argument, returns the 4 immediate children.\n" "With a level argument, returns all descendants at that level.\n" "Raises ValueError if this is a leaf cell or level is out of range.") .def_static("cells", [](int level) { MaybeThrowLevelOutOfRange(level, 0, S2CellId::kMaxLevel); return S2CellIdRange{S2CellId::Begin(level), S2CellId::End(level)}; }, py::arg("level"), "Return a range over all cells at the given level across all 6 faces.\n\n" "Warning: the number of cells grows as 6 * 4^level.") .def("edge_neighbors", [](S2CellId self) { S2CellId neighbors[4]; self.GetEdgeNeighbors(neighbors); return py::make_tuple(neighbors[0], neighbors[1], neighbors[2], neighbors[3]); }, "Return the four cells adjacent across this cell's edges") .def("vertex_neighbors", [](S2CellId self, int level) { MaybeThrowIfFace(self); MaybeThrowLevelOutOfRange(level, 0, self.level() - 1); std::vector output; self.AppendVertexNeighbors(level, &output); return output; }, py::arg("level"), "Return the neighbors of the closest vertex at the given level.\n\n" "Normally returns 4 neighbors, but may return 3 for cube vertices.\n" "Raises ValueError if level >= self.level().") .def("all_neighbors", [](S2CellId self, int level) { MaybeThrowLevelOutOfRange(level, self.level(), S2CellId::kMaxLevel); std::vector output; self.AppendAllNeighbors(level, &output); return output; }, py::arg("level"), "Return all neighbors of this cell at the given level.\n\n" "Raises ValueError if level < self.level().") // Operators .def(py::self == py::self, "Return true if cell ids are equal") .def(py::self != py::self, "Return true if cell ids are not equal") .def(py::self < py::self, "Compare cell ids by their numeric value") .def(py::self > py::self, "Compare cell ids by their numeric value") .def(py::self <= py::self, "Compare cell ids by their numeric value") .def(py::self >= py::self, "Compare cell ids by their numeric value") .def("__hash__", [](S2CellId self) { return absl::Hash()(self); }) // String representation .def("__repr__", [](S2CellId id) { std::ostringstream oss; oss << "S2CellId(" << id << ")"; return oss.str(); }) .def("__str__", [](S2CellId id) { std::ostringstream oss; oss << id; return oss.str(); }); cls.attr("MAX_LEVEL") = S2CellId::kMaxLevel; cls.attr("MAX_POSITION") = S2CellId::kMaxPosition; cls.attr("NUM_FACES") = S2CellId::kNumFaces; py::class_(m, "S2CellIdRange", "A range of S2CellIds at the same level along the Hilbert curve.\n\n" "Supports len(), indexing, slicing, iteration, reversed(), and 'in'.\n" "Returned from S2CellId.children() and S2CellId.cells().\n\n" "Slicing: only step=1 is supported. Use reversed() for step=-1.\n" "Other step values raise ValueError.") .def("__len__", [](const S2CellIdRange& self) { return LenOrThrow(self.size()); }) .def("size", &S2CellIdRange::size, "Return the number of cells in the range as a 64-bit integer.\n\n" "Equivalent to len() on 64-bit platforms; use this method when\n" "the range may exceed Py_ssize_t (e.g. very large cells() ranges\n" "on 32-bit Python).") .def("__getitem__", [](const S2CellIdRange& self, int64_t i) { return self.at(IndexOrThrow(i, self.size())); }, py::arg("index")) .def("__getitem__", [](const S2CellIdRange& self, py::slice s) { ValidateStepIsOne(s); auto [start, stop] = ClampedSlice(self.size(), s); return self.slice(start, stop); }, py::arg("slice")) .def("__contains__", &S2CellIdRange::contains, py::arg("cell")) .def("__eq__", [](const S2CellIdRange& self, const S2CellIdRange& other) { return self.begin == other.begin && self.end == other.end; }, py::arg("other")) .def("__repr__", [](const S2CellIdRange& self) { std::ostringstream oss; oss << "S2CellIdRange(begin=" << self.begin.id() << ", end=" << self.end.id() << ")"; return oss.str(); }) .def("__iter__", [](const S2CellIdRange& self) { return S2CellIdForwardIterator{self.begin, self.end}; }) .def("__reversed__", [](const S2CellIdRange& self) { return S2CellIdReverseIterator{self.end, self.begin}; }); py::class_(m, "_S2CellIdForwardIterator", py::module_local()) .def("__iter__", [](S2CellIdForwardIterator& self) -> S2CellIdForwardIterator& { return self; }) .def("__next__", [](S2CellIdForwardIterator& self) { return NextOrStop(self.next()); }); py::class_(m, "_S2CellIdReverseIterator", py::module_local()) .def("__iter__", [](S2CellIdReverseIterator& self) -> S2CellIdReverseIterator& { return self; }) .def("__next__", [](S2CellIdReverseIterator& self) { return NextOrStop(self.next()); }); } src/python/s2cell_id_range.cc000066400000000000000000000032161524103652300165140ustar00rootroot00000000000000// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "python/s2cell_id_range.h" #include "absl/log/absl_check.h" int64_t S2CellIdRange::size() const { ABSL_DCHECK(begin == end || begin.level() == end.level()) << "S2CellIdRange: begin and end must be at the same level"; return end.distance_from_begin() - begin.distance_from_begin(); } S2CellId S2CellIdRange::at(int64_t i) const { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, size()); return begin.advance(i); } S2CellIdRange S2CellIdRange::slice(int64_t start, int64_t stop) const { ABSL_DCHECK_GE(start, 0); ABSL_DCHECK_LE(start, stop); ABSL_DCHECK_LE(stop, size()); return S2CellIdRange{begin.advance(start), begin.advance(stop)}; } bool S2CellIdRange::contains(S2CellId cell) const { return cell >= begin && cell < end && cell.level() == begin.level(); } std::optional S2CellIdForwardIterator::next() { if (cur == end) return std::nullopt; S2CellId result = cur; cur = cur.next(); return result; } std::optional S2CellIdReverseIterator::next() { if (cur == begin) return std::nullopt; cur = cur.prev(); return cur; } src/python/s2cell_id_range.h000066400000000000000000000050371524103652300163610ustar00rootroot00000000000000// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Helpers for S2CellId sequence iteration used by Python bindings. // // S2CellIdRange represents a contiguous range of S2CellIds at a fixed level, // with forward and reverse iterators. These types are exposed to pybind11 to // support Python's sequence protocol (len, indexing, slicing, iteration, // reversed) on S2CellId ranges returned by methods such as children() and // cells(). #ifndef PYTHON_S2CELL_ID_RANGE_H_ #define PYTHON_S2CELL_ID_RANGE_H_ #include #include #include "s2/s2cell_id.h" // A contiguous half-open range [begin, end) of S2CellIds at the same level // along the Hilbert curve. All operations are O(1). The range may be empty // (begin == end). struct S2CellIdRange { S2CellId begin; S2CellId end; // Return the number of cells in the range. int64_t size() const; // Return the cell at 0-based offset i. i must be in [0, size()); behavior // is undefined otherwise. S2CellId at(int64_t i) const; // Return the sub-range [start, stop). start and stop must satisfy // 0 <= start <= stop <= size(); behavior is undefined otherwise. S2CellIdRange slice(int64_t start, int64_t stop) const; // Return true if cell is in the range and at the same level as begin. bool contains(S2CellId cell) const; }; // Forward iterator over an S2CellIdRange. struct S2CellIdForwardIterator { S2CellId cur; S2CellId end; // Return the next cell and advance, or std::nullopt if exhausted. std::optional next(); }; // Reverse iterator over an S2CellIdRange. Construct with cur = range.end; // next() decrements cur before yielding, so the empty-range case (begin == // end) is handled without a separate flag. struct S2CellIdReverseIterator { S2CellId cur; // one-past-current; starts at range.end S2CellId begin; // stop when cur reaches here // Return the next cell (in reverse order) and advance, or std::nullopt if // exhausted. std::optional next(); }; #endif // PYTHON_S2CELL_ID_RANGE_H_ src/python/s2cell_id_range_test.cc000066400000000000000000000173171524103652300175620ustar00rootroot00000000000000// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "python/s2cell_id_range.h" #include #include #include #include "s2/s2cell_id.h" namespace { // Convenience: range of all cells at a given level on a single face. S2CellIdRange FaceRange(int face, int level) { S2CellId f = S2CellId::FromFace(face); return S2CellIdRange{f.child_begin(level), f.child_end(level)}; } // Collect all cells produced by iterating a range forward. std::vector Collect(S2CellIdRange r) { std::vector result; S2CellIdForwardIterator it{r.begin, r.end}; while (std::optional cell = it.next()) { result.push_back(*cell); } return result; } // Collect all cells produced by iterating a range in reverse. std::vector CollectReverse(S2CellIdRange r) { std::vector result; S2CellIdReverseIterator rit{r.end, r.begin}; while (std::optional cell = rit.next()) { result.push_back(*cell); } return result; } // --------------------------------------------------------------------------- // S2CellIdRange::size // --------------------------------------------------------------------------- TEST(S2CellIdRangeTest, SizeEmptyRange) { S2CellId face = S2CellId::FromFace(0); S2CellIdRange r{face.child_begin(1), face.child_begin(1)}; EXPECT_EQ(r.size(), 0); } TEST(S2CellIdRangeTest, SizeFaceLevel1) { // Each face has 4 level-1 children. S2CellIdRange r = FaceRange(0, 1); EXPECT_EQ(r.size(), 4); } TEST(S2CellIdRangeTest, SizeFaceLevel2) { // Each face has 16 level-2 children. S2CellIdRange r = FaceRange(0, 2); EXPECT_EQ(r.size(), 16); } TEST(S2CellIdRangeTest, SizeAllFacesLevel0) { S2CellIdRange r{S2CellId::Begin(0), S2CellId::End(0)}; EXPECT_EQ(r.size(), 6); } // --------------------------------------------------------------------------- // S2CellIdRange::at // --------------------------------------------------------------------------- TEST(S2CellIdRangeTest, AtFirstCell) { S2CellIdRange r = FaceRange(0, 1); EXPECT_EQ(r.at(0), r.begin); } TEST(S2CellIdRangeTest, AtLastCell) { S2CellIdRange r = FaceRange(0, 1); EXPECT_EQ(r.at(3), r.begin.advance(3)); } TEST(S2CellIdRangeTest, AtMiddleCell) { S2CellIdRange r = FaceRange(0, 2); EXPECT_EQ(r.at(7), r.begin.advance(7)); } // --------------------------------------------------------------------------- // S2CellIdRange::slice // --------------------------------------------------------------------------- TEST(S2CellIdRangeTest, SliceFullRange) { S2CellIdRange r = FaceRange(0, 1); S2CellIdRange s = r.slice(0, 4); EXPECT_EQ(s.begin, r.begin); EXPECT_EQ(s.end, r.end); } TEST(S2CellIdRangeTest, SliceFirstTwo) { S2CellIdRange r = FaceRange(0, 1); S2CellIdRange s = r.slice(0, 2); EXPECT_EQ(s.size(), 2); EXPECT_EQ(s.begin, r.begin); EXPECT_EQ(s.end, r.begin.advance(2)); } TEST(S2CellIdRangeTest, SliceLastTwo) { S2CellIdRange r = FaceRange(0, 1); S2CellIdRange s = r.slice(2, 4); EXPECT_EQ(s.size(), 2); EXPECT_EQ(s.begin, r.begin.advance(2)); EXPECT_EQ(s.end, r.end); } TEST(S2CellIdRangeTest, SliceEmpty) { S2CellIdRange r = FaceRange(0, 1); S2CellIdRange s = r.slice(2, 2); EXPECT_EQ(s.size(), 0); EXPECT_EQ(s.begin, s.end); } TEST(S2CellIdRangeTest, SliceSingleCell) { S2CellIdRange r = FaceRange(0, 1); S2CellIdRange s = r.slice(1, 2); EXPECT_EQ(s.size(), 1); EXPECT_EQ(s.at(0), r.begin.advance(1)); } // --------------------------------------------------------------------------- // S2CellIdRange::contains // --------------------------------------------------------------------------- TEST(S2CellIdRangeTest, ContainsCellInRange) { S2CellIdRange r = FaceRange(0, 1); EXPECT_TRUE(r.contains(r.begin)); EXPECT_TRUE(r.contains(r.begin.advance(1))); EXPECT_TRUE(r.contains(r.begin.advance(3))); } TEST(S2CellIdRangeTest, ContainsExcludesEnd) { S2CellIdRange r = FaceRange(0, 1); EXPECT_FALSE(r.contains(r.end)); } TEST(S2CellIdRangeTest, ContainsCellFromDifferentFace) { S2CellIdRange r = FaceRange(0, 1); S2CellId other = S2CellId::FromFace(1).child_begin(1); EXPECT_FALSE(r.contains(other)); } TEST(S2CellIdRangeTest, ContainsCellAtWrongLevel) { S2CellIdRange r = FaceRange(0, 1); // A level-2 cell that falls within the level-1 range bounds should not match. S2CellId level2 = r.begin.child_begin(); EXPECT_FALSE(r.contains(level2)); } TEST(S2CellIdRangeTest, ContainsEmptyRange) { S2CellId face = S2CellId::FromFace(0); S2CellIdRange r{face.child_begin(1), face.child_begin(1)}; EXPECT_FALSE(r.contains(face.child_begin(1))); } // --------------------------------------------------------------------------- // S2CellIdForwardIterator // --------------------------------------------------------------------------- TEST(S2CellIdForwardIteratorTest, IteratesAllCells) { S2CellIdRange r = FaceRange(0, 1); std::vector cells = Collect(r); ASSERT_EQ(cells.size(), 4u); for (int i = 0; i < 4; ++i) { EXPECT_EQ(cells[i], r.begin.advance(i)); } } TEST(S2CellIdForwardIteratorTest, EmptyRangeProducesNoItems) { S2CellId face = S2CellId::FromFace(0); S2CellIdRange r{face.child_begin(1), face.child_begin(1)}; EXPECT_TRUE(Collect(r).empty()); } TEST(S2CellIdForwardIteratorTest, ReturnsNulloptWhenExhausted) { S2CellIdRange r = FaceRange(0, 1); S2CellIdForwardIterator it{r.begin, r.end}; for (int i = 0; i < 4; ++i) it.next(); EXPECT_EQ(it.next(), std::nullopt); // Calling next() again is safe. EXPECT_EQ(it.next(), std::nullopt); } // --------------------------------------------------------------------------- // S2CellIdReverseIterator // --------------------------------------------------------------------------- TEST(S2CellIdReverseIteratorTest, IteratesAllCellsInReverse) { S2CellIdRange r = FaceRange(0, 1); std::vector cells = CollectReverse(r); ASSERT_EQ(cells.size(), 4u); for (int i = 0; i < 4; ++i) { EXPECT_EQ(cells[i], r.begin.advance(3 - i)); } } TEST(S2CellIdReverseIteratorTest, EmptyRangeProducesNoItems) { S2CellId face = S2CellId::FromFace(0); S2CellIdRange r{face.child_begin(1), face.child_begin(1)}; EXPECT_TRUE(CollectReverse(r).empty()); } TEST(S2CellIdReverseIteratorTest, SingleCellRange) { S2CellIdRange r = FaceRange(0, 1); S2CellIdRange single = r.slice(2, 3); std::vector cells = CollectReverse(single); ASSERT_EQ(cells.size(), 1u); EXPECT_EQ(cells[0], single.at(0)); } TEST(S2CellIdReverseIteratorTest, ReturnsNulloptWhenExhausted) { S2CellIdRange r = FaceRange(0, 1); S2CellIdReverseIterator it{r.end, r.begin}; for (int i = 0; i < 4; ++i) it.next(); EXPECT_EQ(it.next(), std::nullopt); EXPECT_EQ(it.next(), std::nullopt); } // --------------------------------------------------------------------------- // Round-trip: forward then reverse produces symmetric sequences // --------------------------------------------------------------------------- TEST(S2CellIdRangeTest, ForwardAndReverseAreSymmetric) { S2CellIdRange r = FaceRange(2, 2); // 16 cells on face 2 std::vector fwd = Collect(r); std::vector rev = CollectReverse(r); ASSERT_EQ(fwd.size(), rev.size()); for (size_t i = 0; i < fwd.size(); ++i) { EXPECT_EQ(fwd[i], rev[fwd.size() - 1 - i]); } } } // namespace src/python/s2cell_id_test.py000066400000000000000000000447551524103652300164570ustar00rootroot00000000000000"""Tests for S2CellId pybind11 bindings.""" import unittest import s2geometry_pybind as s2 class TestS2CellId(unittest.TestCase): """Test cases for S2CellId bindings.""" # Constructors def test_constructor_from_point(self): p = s2.S2Point(1.0, 0.0, 0.0) cell = s2.S2CellId(p) self.assertTrue(cell.is_leaf()) def test_constructor_from_latlng(self): ll = s2.S2LatLng.from_degrees(0.0, 0.0) cell = s2.S2CellId(ll) self.assertTrue(cell.is_leaf()) def test_constructor_from_uint64(self): # Construct from a face cell, then use its id to reconstruct. face_cell = s2.S2CellId.from_face(0) cell = s2.S2CellId(face_cell.id) self.assertEqual(cell, face_cell) def test_constructor_from_invalid_uint64_raises(self): with self.assertRaises(ValueError): s2.S2CellId(0) # Constants def test_max_level(self): self.assertEqual(s2.S2CellId.MAX_LEVEL, 30) def test_num_faces(self): self.assertEqual(s2.S2CellId.NUM_FACES, 6) # Factory methods def test_from_face(self): for face in range(6): cell = s2.S2CellId.from_face(face) self.assertEqual(cell.face, face) self.assertTrue(cell.is_face()) def test_from_face_out_of_range_raises(self): with self.assertRaises(ValueError) as cm: s2.S2CellId.from_face(6) self.assertEqual(str(cm.exception), "Face 6 out of range [0, 5]") with self.assertRaises(ValueError): s2.S2CellId.from_face(-1) def test_from_face_pos_level(self): cell = s2.S2CellId.from_face_pos_level(0, 0, 0) self.assertEqual(cell.level, 0) self.assertEqual(cell.face, 0) def test_from_face_pos_level_pos_out_of_range_raises(self): with self.assertRaises(ValueError): s2.S2CellId.from_face_pos_level(0, s2.S2CellId.MAX_POSITION + 1, 0) def test_from_token_roundtrip(self): cell = s2.S2CellId.from_face(3) token = cell.to_token() self.assertEqual(token, "7") cell2 = s2.S2CellId.from_token(token) self.assertEqual(cell, cell2) def test_from_token_invalid_raises(self): with self.assertRaises(ValueError) as cm: s2.S2CellId.from_token("invalid_token") self.assertEqual(str(cm.exception), "Invalid S2CellId token: 'invalid_token'") def test_from_face_ij(self): cell = s2.S2CellId.from_face_ij(0, 0, 0) self.assertTrue(cell.is_leaf()) def test_from_face_ij_i_out_of_range_raises(self): with self.assertRaises(ValueError): s2.S2CellId.from_face_ij(0, -1, 0) with self.assertRaises(ValueError): s2.S2CellId.from_face_ij(0, 1 << s2.S2CellId.MAX_LEVEL, 0) def test_from_face_ij_j_out_of_range_raises(self): with self.assertRaises(ValueError): s2.S2CellId.from_face_ij(0, 0, -1) with self.assertRaises(ValueError): s2.S2CellId.from_face_ij(0, 0, 1 << s2.S2CellId.MAX_LEVEL) # Properties def test_id_property(self): cell = s2.S2CellId.from_face(0) self.assertIsInstance(cell.id, int) self.assertGreater(cell.id, 0) # Predicates def test_is_leaf(self): p = s2.S2Point(1.0, 0.0, 0.0) leaf = s2.S2CellId(p) self.assertTrue(leaf.is_leaf()) face = s2.S2CellId.from_face(0) self.assertFalse(face.is_leaf()) def test_is_face(self): face = s2.S2CellId.from_face(0) self.assertTrue(face.is_face()) child = face.child(0) self.assertFalse(child.is_face()) # Geometric operations def test_face(self): for f in range(6): self.assertEqual(s2.S2CellId.from_face(f).face, f) def test_level(self): face = s2.S2CellId.from_face(0) self.assertEqual(face.level, 0) child = face.child(0) self.assertEqual(child.level, 1) def test_to_point(self): cell = s2.S2CellId.from_face(0) p = cell.to_point() # Face 0 center is approximately (1, 0, 0). self.assertAlmostEqual(p.x, 1.0, places=1) self.assertAlmostEqual(p.y, 0.0, places=1) self.assertAlmostEqual(p.z, 0.0, places=1) def test_to_lat_lng(self): ll = s2.S2LatLng.from_degrees(45.0, 90.0) cell = s2.S2CellId(ll) ll2 = cell.to_lat_lng() # The cell center may not exactly match the original point due to # quantization to the cell center. self.assertAlmostEqual(ll.lat.degrees, ll2.lat.degrees, places=5) self.assertAlmostEqual(ll.lng.degrees, ll2.lng.degrees, places=5) def test_center_st(self): # (s,t)-space covers [0,1] x [0,1] per face; a face cell's center # is at (0.5, 0.5). st = s2.S2CellId.from_face(0).center_st() self.assertAlmostEqual(st.x, 0.5) self.assertAlmostEqual(st.y, 0.5) def test_bound_st(self): # A face cell in (s,t) spans the full [0,1] x [0,1] range. bound = s2.S2CellId.from_face(0).bound_st() self.assertAlmostEqual(bound.lo.x, 0.0) self.assertAlmostEqual(bound.lo.y, 0.0) self.assertAlmostEqual(bound.hi.x, 1.0) self.assertAlmostEqual(bound.hi.y, 1.0) def test_center_uv(self): # (u,v)-space covers [-1,1] x [-1,1] per face; a face cell's center # is at the origin. uv = s2.S2CellId.from_face(0).center_uv() self.assertAlmostEqual(uv.x, 0.0) self.assertAlmostEqual(uv.y, 0.0) def test_bound_uv(self): # A face cell in (u,v) spans the full [-1,1] x [-1,1] range. bound = s2.S2CellId.from_face(0).bound_uv() self.assertAlmostEqual(bound.lo.x, -1.0) self.assertAlmostEqual(bound.lo.y, -1.0) self.assertAlmostEqual(bound.hi.x, 1.0) self.assertAlmostEqual(bound.hi.y, 1.0) def test_size_ij(self): # In (i,j)-space a face spans 2^kMaxLevel = 2^30 units. face = s2.S2CellId.from_face(0) self.assertEqual(face.size_ij(), 1 << s2.S2CellId.MAX_LEVEL) def test_size_ij_for_level(self): # Level 0 cells span 2^kMaxLevel in (i,j); leaf cells span 1. self.assertEqual(s2.S2CellId.size_ij_for_level(0), 1 << s2.S2CellId.MAX_LEVEL) self.assertEqual(s2.S2CellId.size_ij_for_level(30), 1) def test_size_st(self): # In (s,t)-space a face spans the full unit interval, so size is 1.0. self.assertAlmostEqual(s2.S2CellId.from_face(0).size_st(), 1.0) def test_size_st_for_level(self): # Level-0 cells span the full unit interval; level-30 cells span 1/2^30. self.assertAlmostEqual(s2.S2CellId.size_st_for_level(0), 1.0) self.assertAlmostEqual(s2.S2CellId.size_st_for_level(30), 1.0 / (1 << 30)) def test_child_position(self): face = s2.S2CellId.from_face(0) for pos in range(4): child = face.child(pos) self.assertEqual(child.child_position(), pos) def test_child_position_face_cell_raises(self): face = s2.S2CellId.from_face(0) with self.assertRaises(ValueError) as cm: face.child_position() self.assertEqual(str(cm.exception), "Level 0 out of range [1, 30]") def test_child_position_at_level(self): cell = s2.S2CellId.from_face(0).child(0).child(1).child(2) self.assertEqual(cell.child_position_at_level(1), 0) self.assertEqual(cell.child_position_at_level(2), 1) self.assertEqual(cell.child_position_at_level(3), 2) def test_to_token(self): cell = s2.S2CellId.from_face(0) self.assertEqual(cell.to_token(), "1") def test_range_min_max_leaf(self): # A leaf cell's range is just itself. leaf = s2.S2CellId(s2.S2Point(1.0, 0.0, 0.0)) self.assertEqual(leaf.range_min(), leaf) self.assertEqual(leaf.range_max(), leaf) def test_range_min_max_covers_children(self): # range_min/range_max bound the leaf cells of this cell; every # direct child's range must sit within the parent's range. face = s2.S2CellId.from_face(0) self.assertLess(face.range_min(), face.range_max()) children = [face.child(i) for i in range(4)] for child in children: self.assertGreaterEqual(child.range_min(), face.range_min()) self.assertLessEqual(child.range_max(), face.range_max()) # The first child's range_min equals the parent's, and likewise # the last child's range_max equals the parent's. self.assertEqual(children[0].range_min(), face.range_min()) self.assertEqual(children[-1].range_max(), face.range_max()) def test_contains(self): face = s2.S2CellId.from_face(0) child = face.child(0) self.assertTrue(face.contains(child)) self.assertFalse(child.contains(face)) def test_intersects(self): face = s2.S2CellId.from_face(0) child = face.child(0) self.assertTrue(face.intersects(child)) self.assertTrue(child.intersects(face)) # Different faces don't intersect. face1 = s2.S2CellId.from_face(1) self.assertFalse(face.intersects(face1)) def test_common_ancestor_level(self): # Two cells sharing the first two Hilbert curve steps on face 0 # diverge at level 2, so their common ancestor is at level 2. base = s2.S2CellId.from_face(0).child(0).child(1) cell1 = base.child(2) cell2 = base.child(3) self.assertEqual(cell1.common_ancestor_level(cell2), 2) def test_common_ancestor_level_different_faces(self): cell1 = s2.S2CellId.from_face(0) cell2 = s2.S2CellId.from_face(1) self.assertEqual(cell1.common_ancestor_level(cell2), -1) # Traversal def test_parent(self): face = s2.S2CellId.from_face(0) child = face.child(0) self.assertEqual(child.parent(), face) def test_parent_of_face_raises(self): face = s2.S2CellId.from_face(0) with self.assertRaises(ValueError) as cm: face.parent() self.assertEqual(str(cm.exception), "Function invalid for face cells") def test_parent_at_level(self): cell = s2.S2CellId.from_face(0).child(0).child(1).child(2) self.assertEqual(cell.parent_at_level(0), s2.S2CellId.from_face(0)) self.assertEqual(cell.parent_at_level(3), cell) def test_child(self): face = s2.S2CellId.from_face(0) for pos in range(4): child = face.child(pos) self.assertEqual(child.level, 1) def test_child_of_leaf_raises(self): leaf = s2.S2CellId(s2.S2Point(1.0, 0.0, 0.0)) with self.assertRaises(ValueError) as cm: leaf.child(0) self.assertEqual(str(cm.exception), "Function invalid for leaf cells") def test_child_position_out_of_range_raises(self): face = s2.S2CellId.from_face(0) with self.assertRaises(ValueError) as cm: face.child(4) self.assertEqual(str(cm.exception), "Child position 4 out of range [0, 3]") def test_children(self): face = s2.S2CellId.from_face(0) children = list(face.children()) self.assertEqual(len(children), 4) for child in children: self.assertEqual(child.level, 1) def test_children_positions(self): face = s2.S2CellId.from_face(0) children = list(face.children()) for i, child in enumerate(children): self.assertEqual(child.child_position(), i) def test_children_at_level(self): face = s2.S2CellId.from_face(0) # Level 2 descendants = 4^2 = 16 cells. children = list(face.children(2)) self.assertEqual(len(children), 16) for child in children: self.assertEqual(child.level, 2) def test_children_of_leaf_raises(self): leaf = s2.S2CellId(s2.S2Point(1.0, 0.0, 0.0)) with self.assertRaises(ValueError) as cm: list(leaf.children()) self.assertEqual(str(cm.exception), "Function invalid for leaf cells") def test_children_at_own_level_raises(self): cell = s2.S2CellId.from_face(0) with self.assertRaises(ValueError): cell.children(0) def test_cells_level_0(self): cells = list(s2.S2CellId.cells(0)) self.assertEqual(len(cells), 6) for i, cell in enumerate(cells): self.assertEqual(cell.face, i) def test_cells_level_1(self): cells = list(s2.S2CellId.cells(1)) # 6 faces * 4 children = 24 cells. self.assertEqual(len(cells), 24) for cell in cells: self.assertEqual(cell.level, 1) def test_cells_level_out_of_range_raises(self): with self.assertRaises(ValueError) as cm: s2.S2CellId.cells(31) self.assertEqual(str(cm.exception), "Level 31 out of range [0, 30]") def test_edge_neighbors(self): cell = s2.S2CellId.from_face(0) neighbors = cell.edge_neighbors() self.assertEqual(len(neighbors), 4) def test_vertex_neighbors(self): cell = s2.S2CellId.from_face(0).child(0).child(1).child(2) neighbors = cell.vertex_neighbors(1) self.assertGreaterEqual(len(neighbors), 3) self.assertLessEqual(len(neighbors), 4) def test_vertex_neighbors_face_cell_raises(self): face = s2.S2CellId.from_face(0) with self.assertRaises(ValueError): face.vertex_neighbors(0) def test_vertex_neighbors_level_out_of_range_raises(self): cell = s2.S2CellId.from_face(0).child(0).child(1).child(2) with self.assertRaises(ValueError): cell.vertex_neighbors(3) # level must be < self.level() (3) def test_all_neighbors(self): cell = s2.S2CellId.from_face(0).child(0) neighbors = cell.all_neighbors(1) self.assertGreater(len(neighbors), 0) # Operators def test_equality(self): a = s2.S2CellId.from_face(0) b = s2.S2CellId.from_face(0) c = s2.S2CellId.from_face(1) self.assertTrue(a == b) self.assertTrue(a != c) def test_comparison(self): a = s2.S2CellId.from_face(0) b = s2.S2CellId.from_face(1) self.assertTrue(a < b) self.assertTrue(b > a) self.assertTrue(a <= a) self.assertTrue(a >= a) def test_hash(self): a = s2.S2CellId.from_face(0) b = s2.S2CellId.from_face(0) self.assertEqual(hash(a), hash(b)) # Can be used in sets/dicts. s = {a, b} self.assertEqual(len(s), 1) # String representation def test_repr(self): cell = s2.S2CellId.from_face(0) self.assertEqual(repr(cell), "S2CellId(0/)") def test_str(self): cell = s2.S2CellId.from_face(0) self.assertEqual(str(cell), "0/") def test_repr_child(self): cell = s2.S2CellId.from_face(3).child(0).child(2) self.assertEqual(repr(cell), "S2CellId(3/02)") class TestS2CellIdRange(unittest.TestCase): """Test cases for the S2CellIdRange class returned by children()/cells().""" def test_len(self): face = s2.S2CellId.from_face(0) self.assertEqual(len(face.children()), 4) self.assertEqual(len(face.children(2)), 16) def test_size_matches_len(self): face = s2.S2CellId.from_face(0) self.assertEqual(face.children().size(), 4) self.assertEqual(s2.S2CellId.cells(1).size(), 24) def test_size_large_range(self): # cells(20) = 6 * 4^20 ≈ 6.6e12; fits in int64 but iterating would # be prohibitive. size() returns it without materializing. self.assertEqual(s2.S2CellId.cells(20).size(), 6 * (4 ** 20)) def test_getitem(self): face = s2.S2CellId.from_face(0) children = face.children() self.assertEqual(children[0].child_position(), 0) self.assertEqual(children[3].child_position(), 3) # Negative indexing. self.assertEqual(children[-1].child_position(), 3) def test_getitem_out_of_range_raises(self): children = s2.S2CellId.from_face(0).children() with self.assertRaises(IndexError): children[4] with self.assertRaises(IndexError): children[-5] def test_slice_basic(self): face = s2.S2CellId.from_face(0) children = face.children() sliced = children[1:3] self.assertEqual(len(sliced), 2) self.assertEqual(list(sliced), [face.child(1), face.child(2)]) def test_slice_open_ended(self): face = s2.S2CellId.from_face(0) children = face.children() self.assertEqual(list(children[:2]), [face.child(0), face.child(1)]) self.assertEqual(list(children[2:]), [face.child(2), face.child(3)]) self.assertEqual(list(children[:]), list(children)) def test_slice_negative_indices(self): face = s2.S2CellId.from_face(0) children = face.children() self.assertEqual(list(children[-2:]), [face.child(2), face.child(3)]) def test_slice_clamps_out_of_range(self): children = s2.S2CellId.from_face(0).children() # Stop past the end is clamped. self.assertEqual(len(children[0:100]), 4) # Start past the end produces an empty range. self.assertEqual(len(children[100:]), 0) def test_slice_step_not_one_raises(self): children = s2.S2CellId.from_face(0).children() with self.assertRaises(ValueError) as cm: children[::2] self.assertIn("step 1", str(cm.exception)) with self.assertRaises(ValueError): children[::-1] def test_slice_returns_range(self): # Slicing returns another S2CellIdRange, not a list. children = s2.S2CellId.from_face(0).children() sliced = children[1:3] self.assertIsInstance(sliced, s2.S2CellIdRange) def test_contains(self): face = s2.S2CellId.from_face(0) children = face.children() child0 = face.child(0) self.assertIn(child0, children) # A cell from a different face is not in the range. other = s2.S2CellId.from_face(1).child(0) self.assertNotIn(other, children) # A cell at the wrong level is not in the range. self.assertNotIn(face, children) def test_reversed(self): face = s2.S2CellId.from_face(0) children = list(face.children()) rev_children = list(reversed(face.children())) self.assertEqual(rev_children, list(reversed(children))) if __name__ == "__main__": unittest.main() src/python/s2cell_test.py000066400000000000000000000306611524103652300157720ustar00rootroot00000000000000"""Tests for S2Cell pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestS2Cell(unittest.TestCase): """Test cases for S2Cell bindings.""" # Constructors def test_constructor_from_cell_id(self): cell_id = s2.S2CellId.from_face(0) cell = s2.S2Cell(cell_id) self.assertEqual(cell.id, cell_id) self.assertEqual(cell.face, 0) self.assertEqual(cell.level, 0) def test_constructor_from_point(self): p = s2.S2Point(1.0, 0.0, 0.0) cell = s2.S2Cell(p) self.assertTrue(cell.is_leaf()) def test_constructor_from_latlng(self): ll = s2.S2LatLng.from_degrees(0.0, 0.0) cell = s2.S2Cell(ll) self.assertTrue(cell.is_leaf()) # Factory methods def test_from_face(self): for face in range(6): cell = s2.S2Cell.from_face(face) self.assertEqual(cell.face, face) self.assertEqual(cell.level, 0) def test_from_face_out_of_range_raises(self): with self.assertRaises(ValueError) as cm: s2.S2Cell.from_face(6) self.assertEqual(str(cm.exception), "Face 6 out of range [0, 5]") with self.assertRaises(ValueError): s2.S2Cell.from_face(-1) def test_from_face_pos_level(self): cell = s2.S2Cell.from_face_pos_level(0, 0, 0) self.assertEqual(cell.level, 0) self.assertEqual(cell.face, 0) def test_from_face_pos_level_out_of_range_raises(self): with self.assertRaises(ValueError): s2.S2Cell.from_face_pos_level(6, 0, 0) with self.assertRaises(ValueError): s2.S2Cell.from_face_pos_level(0, s2.S2CellId.MAX_POSITION + 1, 0) with self.assertRaises(ValueError): s2.S2Cell.from_face_pos_level(0, 0, 31) # Constants def test_boundary_constants(self): self.assertEqual(int(s2.S2Cell.BOTTOM_EDGE), 0) self.assertEqual(int(s2.S2Cell.RIGHT_EDGE), 1) self.assertEqual(int(s2.S2Cell.TOP_EDGE), 2) self.assertEqual(int(s2.S2Cell.LEFT_EDGE), 3) # Properties def test_id(self): cell_id = s2.S2CellId.from_face(3) cell = s2.S2Cell(cell_id) self.assertEqual(cell.id, cell_id) def test_face(self): for f in range(6): self.assertEqual(s2.S2Cell.from_face(f).face, f) def test_level(self): face = s2.S2Cell.from_face(0) self.assertEqual(face.level, 0) child = s2.S2Cell(face.id.child(0)) self.assertEqual(child.level, 1) def test_orientation(self): # Orientation is a bitmask in [0, 3]. for f in range(6): self.assertIn(s2.S2Cell.from_face(f).orientation, range(4)) child = s2.S2Cell(s2.S2CellId.from_face(0).child(0)) self.assertIn(child.orientation, range(4)) # Predicates def test_is_leaf(self): face = s2.S2Cell.from_face(0) self.assertFalse(face.is_leaf()) leaf = s2.S2Cell(s2.S2Point(1.0, 0.0, 0.0)) self.assertTrue(leaf.is_leaf()) # Geometric operations def test_size_ij(self): # A face cell spans 2^kMaxLevel in (i,j). face = s2.S2Cell.from_face(0) self.assertEqual(face.size_ij(), 1 << s2.S2CellId.MAX_LEVEL) def test_size_st(self): # A face cell spans the full [0,1] range in (s,t). face = s2.S2Cell.from_face(0) self.assertAlmostEqual(face.size_st(), 1.0) def test_vertex_count_and_normalization(self): face = s2.S2Cell.from_face(0) for k in range(4): v = face.vertex(k) # Normalized vertices should have unit norm. self.assertAlmostEqual(v.norm(), 1.0) def test_vertex_mod_4(self): face = s2.S2Cell.from_face(0) # Argument is reduced modulo 4. v0 = face.vertex(0) v4 = face.vertex(4) self.assertAlmostEqual(v0.x, v4.x) self.assertAlmostEqual(v0.y, v4.y) self.assertAlmostEqual(v0.z, v4.z) def test_edge(self): face = s2.S2Cell.from_face(0) for k in range(4): e = face.edge(k) self.assertAlmostEqual(e.norm(), 1.0) def test_uv_coord_of_edge(self): face = s2.S2Cell.from_face(0) # Face cell UV bounds are [-1, 1] x [-1, 1]. Bottom/top edges are # constant in V; left/right constant in U. bottom = face.uv_coord_of_edge(s2.S2Cell.Boundary.BOTTOM_EDGE) top = face.uv_coord_of_edge(s2.S2Cell.Boundary.TOP_EDGE) self.assertAlmostEqual(bottom, -1.0) self.assertAlmostEqual(top, 1.0) right = face.uv_coord_of_edge(s2.S2Cell.Boundary.RIGHT_EDGE) left = face.uv_coord_of_edge(s2.S2Cell.Boundary.LEFT_EDGE) self.assertAlmostEqual(right, 1.0) self.assertAlmostEqual(left, -1.0) def test_ij_coord_of_edge(self): face = s2.S2Cell.from_face(0) # Face cell in (i,j): bottom/top edges are constant in J (0 and 2^30), # left/right edges are constant in I (0 and 2^30). self.assertEqual(face.ij_coord_of_edge(s2.S2Cell.Boundary.BOTTOM_EDGE), 0) self.assertEqual(face.ij_coord_of_edge(s2.S2Cell.Boundary.TOP_EDGE), 1 << 30) self.assertEqual(face.ij_coord_of_edge(s2.S2Cell.Boundary.LEFT_EDGE), 0) self.assertEqual(face.ij_coord_of_edge(s2.S2Cell.Boundary.RIGHT_EDGE), 1 << 30) def test_center(self): face = s2.S2Cell.from_face(0) c = face.center() # Face 0 center is (1, 0, 0). self.assertAlmostEqual(c.norm(), 1.0) self.assertAlmostEqual(c.x, 1.0, places=5) self.assertAlmostEqual(c.y, 0.0, places=5) self.assertAlmostEqual(c.z, 0.0, places=5) def test_average_area_for_level(self): # AverageArea halves (roughly) with each subdivision by 4: area at # level L is ~ (4*pi / 6) / 4^L. expected_0 = 4.0 * math.pi / 6.0 self.assertAlmostEqual( s2.S2Cell.average_area_for_level(0), expected_0, places=5) # Sum over all cells at level 5 should still be 4*pi. total = s2.S2Cell.average_area_for_level(5) * 6 * (4 ** 5) self.assertAlmostEqual(total, 4.0 * math.pi, places=5) def test_average_area_for_level_out_of_range_raises(self): with self.assertRaises(ValueError): s2.S2Cell.average_area_for_level(31) with self.assertRaises(ValueError): s2.S2Cell.average_area_for_level(-1) def test_approx_area(self): face = s2.S2Cell.from_face(0) expected = 4.0 * math.pi / 6.0 # approx_area is accurate to within 3%. self.assertAlmostEqual(face.approx_area(), expected, delta=expected * 0.03) def test_exact_area_sums_to_sphere(self): # Summing exact_area over all 6 face cells should give 4*pi. total = sum(s2.S2Cell.from_face(f).exact_area() for f in range(6)) self.assertAlmostEqual(total, 4.0 * math.pi, places=10) def test_bound_uv_face(self): face = s2.S2Cell.from_face(0) uv = face.bound_uv() self.assertAlmostEqual(uv.lo.x, -1.0) self.assertAlmostEqual(uv.lo.y, -1.0) self.assertAlmostEqual(uv.hi.x, 1.0) self.assertAlmostEqual(uv.hi.y, 1.0) def test_distance_to_point_outside(self): face = s2.S2Cell.from_face(0) # A point on the opposite face should be at a positive distance. far = s2.S2Point(-1.0, 0.0, 0.0) d = face.distance(far) self.assertGreater(d.radians, 0.0) def test_distance_to_point_inside(self): face = s2.S2Cell.from_face(0) # Center of face 0 is inside; distance should be zero. center = face.center() self.assertAlmostEqual(face.distance(center).radians, 0.0) def test_boundary_distance(self): face = s2.S2Cell.from_face(0) center = face.center() # Interior point has positive boundary distance. self.assertGreater(face.boundary_distance(center).radians, 0.0) # A far exterior point also has positive boundary distance. far = s2.S2Point(-1.0, 0.0, 0.0) self.assertGreater(face.boundary_distance(far).radians, 0.0) def test_max_distance_to_point(self): face = s2.S2Cell.from_face(0) center = face.center() # Max distance from a face cell to its own center should be positive # (distance to the farthest corner). self.assertGreater(face.max_distance(center).radians, 0.0) def test_distance_to_edge(self): face = s2.S2Cell.from_face(0) # An edge on the opposite face; use unit-length endpoints. a = s2.S2Point(-1.0, 1.0, 0.0).normalize() b = s2.S2Point(-1.0, -1.0, 0.0).normalize() self.assertGreater(face.distance_to_edge(a, b).radians, 0.0) def test_max_distance_to_edge(self): face = s2.S2Cell.from_face(0) a = s2.S2Point(-1.0, 1.0, 0.0).normalize() b = s2.S2Point(-1.0, -1.0, 0.0).normalize() self.assertGreater(face.max_distance_to_edge(a, b).radians, 0.0) def test_distance_to_cell(self): face0 = s2.S2Cell.from_face(0) # Distance from a cell to itself is zero. self.assertAlmostEqual(face0.distance_to_cell(face0).radians, 0.0) # Face 0 (pos X) and face 3 (neg X) are opposite and non-adjacent. face3 = s2.S2Cell.from_face(3) self.assertGreater(face0.distance_to_cell(face3).radians, 0.0) def test_max_distance_to_cell(self): face0 = s2.S2Cell.from_face(0) face3 = s2.S2Cell.from_face(3) self.assertGreater(face0.max_distance_to_cell(face3).radians, 0.0) def test_cell_union_bound(self): cell = s2.S2Cell.from_face(0) bound = cell.cell_union_bound() self.assertEqual(len(bound), 1) self.assertEqual(bound[0], cell.id) def test_contains_cell(self): face = s2.S2Cell.from_face(0) child = s2.S2Cell(face.id.child(0)) self.assertTrue(face.contains(child)) self.assertFalse(child.contains(face)) def test_contains_point(self): face = s2.S2Cell.from_face(0) # Face 0 center is (1, 0, 0), which is inside face 0. self.assertTrue(face.contains_point(s2.S2Point(1.0, 0.0, 0.0))) # A point on the opposite face is not in face 0. self.assertFalse(face.contains_point(s2.S2Point(-1.0, 0.0, 0.0))) def test_may_intersect(self): face0 = s2.S2Cell.from_face(0) face1 = s2.S2Cell.from_face(1) # A cell intersects itself. self.assertTrue(face0.may_intersect(face0)) # Distinct faces (disjoint cell id ranges) do not intersect. self.assertFalse(face0.may_intersect(face1)) # A cell contained within another may_intersect the outer cell. child = s2.S2Cell(face0.id.child(0)) self.assertTrue(face0.may_intersect(child)) self.assertTrue(child.may_intersect(face0)) # Traversal def test_subdivide(self): face = s2.S2Cell.from_face(0) children = face.subdivide() self.assertEqual(len(children), 4) for i, child in enumerate(children): self.assertEqual(child.level, 1) self.assertEqual(child.face, 0) # Subdivide should produce the same children as constructing # from the S2CellId children. self.assertEqual(child.id, face.id.child(i)) def test_subdivide_leaf_raises(self): leaf = s2.S2Cell(s2.S2Point(1.0, 0.0, 0.0)) with self.assertRaises(ValueError) as cm: leaf.subdivide() self.assertEqual(str(cm.exception), "Leaf cell has no children") # Operators def test_equality(self): a = s2.S2Cell.from_face(0) b = s2.S2Cell.from_face(0) c = s2.S2Cell.from_face(1) self.assertTrue(a == b) self.assertTrue(a != c) def test_comparison(self): a = s2.S2Cell.from_face(0) b = s2.S2Cell.from_face(1) self.assertTrue(a < b) self.assertTrue(b > a) self.assertTrue(a <= a) self.assertTrue(a >= a) def test_hash(self): a = s2.S2Cell.from_face(0) b = s2.S2Cell.from_face(0) self.assertEqual(hash(a), hash(b)) s = {a, b} self.assertEqual(len(s), 1) # String representation def test_repr(self): cell = s2.S2Cell.from_face(0) self.assertEqual(repr(cell), "S2Cell(0/)") def test_str(self): cell = s2.S2Cell.from_face(0) self.assertEqual(str(cell), "0/") def test_repr_child(self): cell = s2.S2Cell(s2.S2CellId.from_face(3).child(0).child(2)) self.assertEqual(repr(cell), "S2Cell(3/02)") if __name__ == "__main__": unittest.main() src/python/s2geometry_pybind/000077500000000000000000000000001524103652300166345ustar00rootroot00000000000000src/python/s2geometry_pybind/__init__.py000066400000000000000000000001351524103652300207440ustar00rootroot00000000000000"""S2 Geometry library Python bindings using pybind11.""" from s2geometry_bindings import * src/python/s2geometry_test.py000077500000000000000000002253361524103652300167160ustar00rootroot00000000000000# # Copyright 2006 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Tests for S2 Geometry SWIG bindings.""" from collections import defaultdict import math import unittest import s2geometry as s2 class PyWrapS2TestCase(unittest.TestCase): def testS2PointFromRawToNamedCorrectly(self): x = 1.0 y = 2.0 z = 3.0 point = s2.S2Point_FromRaw(x, y, z) self.assertEqual(x, point.x()) self.assertEqual(y, point.y()) self.assertEqual(z, point.z()) def testContainsIsWrappedCorrectly(self): london = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(51.3368602, 0.4931979), s2.S2LatLng.FromDegrees(51.7323965, 0.1495211), ) e14lj = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(51.5213527, -0.0476026), s2.S2LatLng.FromDegrees(51.5213527, -0.0476026), ) self.assertTrue(london.Contains(e14lj)) def testS2CellIdEqualsIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) cell = s2.S2CellId(london) same_cell = s2.S2CellId(london) self.assertEqual(cell, same_cell) def testS2CellIdComparsionIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) cell = s2.S2CellId(london) self.assertLess(cell, cell.next()) self.assertGreater(cell.next(), cell) def testS2CellIdFromToTokenIsWrappedCorrectly(self): cell = s2.S2CellId.FromToken("487604c489f841c3") self.assertEqual(cell.ToToken(), "487604c489f841c3") self.assertEqual(cell.id(), 0x487604C489F841C3) cell = s2.S2CellId.FromToken("487") self.assertEqual(cell.ToToken(), "487") self.assertEqual(cell.id(), 0x4870000000000000) cell = s2.S2CellId.FromToken("this is invalid") self.assertEqual(cell.ToToken(), "X") self.assertEqual(cell.id(), 0) def testS2CellIdGetEdgeNeighborsIsWrappedCorrectly(self): cell = s2.S2CellId(0x466D319000000000) expected_neighbors = [ s2.S2CellId(0x466D31B000000000), s2.S2CellId(0x466D317000000000), s2.S2CellId(0x466D323000000000), s2.S2CellId(0x466D31F000000000), ] neighbors = cell.GetEdgeNeighbors() self.assertCountEqual(neighbors, expected_neighbors) def testS2CellIdGetVertexNeighborsIsWrappedCorrectly(self): cell = s2.S2CellId(0x466D319000000000) expected_neighbors = [ s2.S2CellId(0x466D31C000000000), s2.S2CellId(0x466D314000000000), s2.S2CellId(0x466D324000000000), s2.S2CellId(0x466D33C000000000), ] self.assertEqual(cell.level(), 12) # Requires level < cell.level. neighbors = cell.GetVertexNeighbors(11) self.assertCountEqual(neighbors, expected_neighbors) def testS2CellIdGetAllNeighborsIsWrappedCorrectly(self): cell = s2.S2CellId(0x466D319000000000) expected_neighbors = [ s2.S2CellId(0x466D31D000000000), s2.S2CellId(0x466D311000000000), s2.S2CellId(0x466D31B000000000), s2.S2CellId(0x466D323000000000), s2.S2CellId(0x466D31F000000000), s2.S2CellId(0x466D317000000000), s2.S2CellId(0x466D321000000000), s2.S2CellId(0x466D33D000000000), ] self.assertEqual(cell.level(), 12) # Requires level >= cell.level. neighbors = cell.GetAllNeighbors(12) self.assertCountEqual(neighbors, expected_neighbors) def testS2CellIdChild(self): valid = s2.S2CellId(0x89C259C000000000) invalid = s2.S2CellId(0) self.assertTrue(valid.is_valid()) self.assertFalse(invalid.is_valid()) self.assertEqual(valid.child(0).parent().id(), valid.id()) with self.assertRaises(ValueError): valid.child(-1) with self.assertRaises(ValueError): valid.child(4) with self.assertRaises(ValueError): invalid.child(0) leaf = s2.S2CellId(s2.S2LatLng.FromDegrees(10.0, 20.0)) with self.assertRaises(ValueError): leaf.child(0) def testS2CellIdChildLevelIsWrappedCorrectly(self): cell = s2.S2CellId(0x876BEC2688E50000) self.assertEqual(cell.child_position(3), 2) with self.assertRaises(ValueError): cell.child_position(-1) with self.assertRaises(ValueError): cell.child_position(0) with self.assertRaises(ValueError): cell.child_position(40) def testS2CellIdContainsInvalidRaises(self): valid = s2.S2CellId(0x89C259C000000000) invalid = s2.S2CellId(0) self.assertTrue(valid.is_valid()) self.assertFalse(invalid.is_valid()) self.assertTrue(valid.contains(valid)) with self.assertRaises(ValueError): valid.contains(invalid) with self.assertRaises(ValueError): invalid.contains(valid) def testS2CellIdGetAllNeighborsIsWrappedCorrectly(self): cell = s2.S2CellId(0x6AA7590000000000) expected_neighbors = ( s2.S2CellId(0x2AB3530000000000), s2.S2CellId(0x2AB34B0000000000), s2.S2CellId(0x2AB34D0000000000), s2.S2CellId(0x6AA75B0000000000), s2.S2CellId(0x6AA7570000000000), s2.S2CellId(0x6AA75F0000000000), s2.S2CellId(0x6AA7510000000000), s2.S2CellId(0x6AA75D0000000000), ) neighbors = cell.GetAllNeighbors(cell.level()) self.assertEqual(neighbors, expected_neighbors) def testS2CellIdIntersectsIsTrueForOverlap(self): cell1 = s2.S2CellId(0x89C259C000000000) cell2 = s2.S2CellId(0x89C2590000000000) self.assertTrue(cell1.intersects(cell2)) def testS2CellIdIntersectsIsFalseForNonOverlap(self): cell1 = s2.S2CellId(0x89C259C000000000) cell2 = s2.S2CellId(0x89E83D0000000000) self.assertFalse(cell1.intersects(cell2)) def testS2CellIdIntersectsInvalidRaises(self): valid = s2.S2CellId(0x89C259C000000000) invalid = s2.S2CellId(0) self.assertTrue(valid.is_valid()) self.assertFalse(invalid.is_valid()) with self.assertRaises(ValueError): valid.intersects(invalid) with self.assertRaises(ValueError): invalid.intersects(valid) def testS2CellIdLevel(self): leaf = s2.S2CellId(s2.S2LatLng.FromDegrees(10.0, 20.0)) self.assertEqual(leaf.level(), 30) with self.assertRaises(ValueError): s2.S2CellId(0).level() def testS2CellIdParent(self): leaf = s2.S2CellId(s2.S2LatLng.FromDegrees(10.0, 20.0)) self.assertEqual(leaf.level(), 30) self.assertEqual(leaf.parent().level(), 29) level8 = leaf.parent(8) self.assertEqual(level8.level(), 8) self.assertEqual(level8.parent(0).level(), 0) # Error to have negative level. with self.assertRaises(ValueError): level8.parent(-1) # Same level is ok. self.assertEqual(level8.parent(8).level(), 8) # Error to ask for parent with lower level. with self.assertRaises(ValueError): level8.parent(9) # Parent of invalid is an error with self.assertRaises(ValueError): s2.S2CellId(0).parent() def testS2HashingIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) cell = s2.S2CellId(london) same_cell = s2.S2CellId(london) self.assertEqual(hash(cell), hash(same_cell)) def testCovererIsWrappedCorrectly(self): london = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(51.3368602, 0.4931979), s2.S2LatLng.FromDegrees(51.7323965, 0.1495211), ) e14lj = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(51.5213527, -0.0476026), s2.S2LatLng.FromDegrees(51.5213527, -0.0476026), ) coverer = s2.S2RegionCoverer() coverer.set_max_cells(6) self.assertEqual(6, coverer.max_cells()) covering = coverer.GetCovering(e14lj) self.assertLessEqual(len(covering), 6) for cellid in covering: self.assertTrue(london.Contains(s2.S2Cell(cellid))) interior = coverer.GetInteriorCovering(e14lj) for cellid in interior: self.assertTrue(london.Contains(s2.S2Cell(cellid))) def testS2CellUnionIsWrappedCorrectly(self): cell_union = s2.S2CellUnion() cell_union.Init([0x466D319000000000, 0x466D31B000000000]) self.assertEqual(cell_union.num_cells(), 2) trondheim = s2.S2LatLng.FromDegrees(63.431052, 10.395083) self.assertTrue(cell_union.Contains(s2.S2CellId(trondheim))) # Init() calls Normalized, so cell_ids() are normalized. cell_union2 = s2.S2CellUnion.FromNormalized(cell_union.cell_ids()) # There is no S2CellUnion::Equals, and cell_ids is a non-iterable # SWIG object, so just perform the same checks again. self.assertEqual(cell_union2.num_cells(), 2) self.assertTrue(cell_union2.Contains(s2.S2CellId(trondheim))) def testS2PolygonIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon = s2.S2Polygon(s2.S2Cell(s2.S2CellId(london))) self.assertEqual(polygon.num_loops(), 1) point = london.ToPoint() self.assertTrue(polygon.Contains(point)) def testS2LoopIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon = s2.S2Polygon(s2.S2Cell(s2.S2CellId(london))) loop = polygon.loop(0) self.assertTrue(loop.IsValid()) self.assertEqual(0, loop.depth()) self.assertFalse(loop.is_hole()) self.assertEqual(4, loop.num_vertices()) self.assertTrue(loop.IsNormalized()) point = london.ToPoint() self.assertTrue(loop.Contains(point)) def testS2LoopUsesValueEquality(self): self.assertEqual(s2.S2Loop(), s2.S2Loop()) def testS2PolygonCopiesLoopInConstructorBecauseItTakesOwnership(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) loop = s2.S2Loop(s2.S2Cell(s2.S2CellId(london))) s2.S2Polygon(loop) def testS2LoopAreaIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) loop = s2.S2Loop(s2.S2Cell(s2.S2CellId(london))) equivalent_polygon = s2.S2Polygon(loop) self.assertAlmostEqual(loop.GetArea(), equivalent_polygon.GetArea()) def testS2PolygonInitNestedIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) small_loop = s2.S2Loop(s2.S2Cell(s2.S2CellId(london))) big_loop = s2.S2Loop(s2.S2Cell(s2.S2CellId(london).parent(1))) polygon = s2.S2Polygon() polygon.InitNested([big_loop, small_loop]) def testS2PolygonInitNestedWithIncorrectTypeIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) loop = s2.S2Loop(s2.S2Cell(s2.S2CellId(london))) polygon = s2.S2Polygon() with self.assertRaises(TypeError): polygon.InitNested([loop, s2.S2CellId()]) def testS2PolygonGetAreaIsWrappedCorrectly(self): # Cell at level 10 containing central London. london_level_10 = s2.S2CellId( s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) ).parent(10) polygon = s2.S2Polygon(s2.S2Cell(london_level_10)) # Because S2Cell.ExactArea() isn't swigged, compare S2Polygon.GetArea() with # S2CellUnion.ExactArea(). cell_union = s2.S2CellUnion() cell_union.Init([london_level_10.id()]) self.assertAlmostEqual( cell_union.ExactArea(), polygon.GetArea(), places=10 ) def testS2PolygonGetOverlapFractions(self): # Matches S2Polygon, OverlapFractions test from cs/s2polygon_test.cc a = s2.S2Polygon() b = s2.S2Polygon() r1, r2 = s2.S2Polygon.GetOverlapFractions(a, b) self.assertAlmostEqual(1.0, r1) self.assertAlmostEqual(1.0, r2) def verts2loop(vs): loop = s2.S2Loop() loop.Init([s2.S2LatLng.FromDegrees(*v).ToPoint() for v in vs]) return loop loop1verts = [(-10, 10), (0, 10), (0, -10), (-10, -10), (-10, 0)] b = s2.S2Polygon(verts2loop(loop1verts)) r1, r2 = s2.S2Polygon.GetOverlapFractions(a, b) self.assertAlmostEqual(1.0, r1) self.assertAlmostEqual(0.0, r2) loop2verts = [(-10, 0), (10, 0), (10, -10), (-10, -10)] a = s2.S2Polygon(verts2loop(loop2verts)) r1, r2 = s2.S2Polygon.GetOverlapFractions(a, b) self.assertAlmostEqual(0.5, r1) self.assertAlmostEqual(0.5, r2) def testGetS2LatLngVertexIsWrappedCorrectly(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon = s2.S2Polygon(s2.S2Cell(s2.S2CellId(london))) loop = polygon.loop(0) first_vertex = loop.GetS2LatLngVertex(0) self.assertIsInstance(first_vertex, s2.S2LatLng) self.assertEqual( "51.500152,-0.126235", first_vertex.ToStringInDegrees() ) second_vertex = loop.GetS2LatLngVertex(1) self.assertIsInstance(second_vertex, s2.S2LatLng) self.assertEqual( "51.500153,-0.126235", second_vertex.ToStringInDegrees() ) def testGetLastDescendant(self): def verts2loop(vs): loop = s2.S2Loop() loop.Init([s2.S2LatLng.FromDegrees(*v).ToPoint() for v in vs]) return loop loop1 = verts2loop([(0, 0), (0, 10), (10, 10), (10, 0)]) # Shell loop2 = verts2loop([(2, 2), (2, 5), (5, 5), (5, 2)]) # Hole loop3 = verts2loop([(0, 20), (0, 30), (10, 30), (10, 20)]) # Shell polygon = s2.S2Polygon() polygon.InitNested([loop1, loop2, loop3]) self.assertEqual(1, polygon.GetLastDescendant(0)) self.assertEqual(1, polygon.GetLastDescendant(1)) self.assertEqual(2, polygon.GetLastDescendant(2)) def testS2PolylineInitFromS2LatLngs(self): e7_10deg = 0x5F5E100 list_ll = [] for lat, lng in [(0, 0), (0, e7_10deg), (e7_10deg, e7_10deg)]: list_ll.append(s2.S2LatLng.FromE7(lat, lng)) line = s2.S2Polyline() line.InitFromS2LatLngs(list_ll) self.assertAlmostEqual(20.0, line.GetLength().degrees()) def testS2PolylineInitFromS2Points(self): e7_10deg = 0x5F5E100 list_points = [] for lat, lng in [(0, 0), (0, e7_10deg), (e7_10deg, e7_10deg)]: list_points.append(s2.S2LatLng.FromE7(lat, lng).ToPoint()) line = s2.S2Polyline() line.InitFromS2Points(list_points) self.assertAlmostEqual(20.0, line.GetLength().degrees()) def testS2PolylineUsesValueEquality(self): self.assertEqual(s2.S2Polyline(), s2.S2Polyline()) def testS2PointsCanBeNormalized(self): line = s2.S2Polyline() line.InitFromS2LatLngs([ s2.S2LatLng.FromDegrees(37.794484, -122.394871), s2.S2LatLng.FromDegrees(37.762699, -122.435158), ]) self.assertNotAlmostEqual(line.GetCentroid().Norm(), 1.0) self.assertAlmostEqual(line.GetCentroid().Normalize().Norm(), 1.0) def testS1AngleComparsionIsWrappedCorrectly(self): ten_degrees = s2.S1Angle.Degrees(10) one_hundred_degrees = s2.S1Angle.Degrees(100) self.assertLess(ten_degrees, one_hundred_degrees) self.assertGreater(one_hundred_degrees, ten_degrees) def testS2PolygonIntersectsWithPolyline(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon = s2.S2Polygon(s2.S2Cell(s2.S2CellId(london).parent(15))) line = s2.S2Polyline() line.InitFromS2LatLngs([ s2.S2LatLng.FromDegrees(51.5, -0.128), s2.S2LatLng.FromDegrees(51.5, -0.125), ]) intersections = polygon.IntersectWithPolyline(line) self.assertEqual(1, len(intersections)) def testS2PolygonBoundaryNearIsSame(self): london_1 = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon_1 = s2.S2Polygon(s2.S2Loop(s2.S2Cell(s2.S2CellId(london_1)))) london_2 = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon_2 = s2.S2Polygon(s2.S2Loop(s2.S2Cell(s2.S2CellId(london_2)))) self.assertTrue(polygon_1.BoundaryNear(polygon_2)) def testS2PolygonBoundaryNearIsTotallyDifferent(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon_1 = s2.S2Polygon(s2.S2Loop(s2.S2Cell(s2.S2CellId(london)))) seattle = s2.S2LatLng.FromDegrees(47.6062, -122.3321) polygon_2 = s2.S2Polygon(s2.S2Loop(s2.S2Cell(s2.S2CellId(seattle)))) self.assertFalse(polygon_1.BoundaryNear(polygon_2)) def testS2PolygonBoundaryNearIsNear(self): def verts2loop(vs): loop = s2.S2Loop() loop.Init([s2.S2LatLng.FromDegrees(*v).ToPoint() for v in vs]) return loop vertices_1 = [(-10, 10), (0, 10), (0, -10), (-10, -10), (-10, 0)] polygon_1 = s2.S2Polygon(verts2loop(vertices_1)) vertices_2 = [(-10, 10), (0, 10), (0, -10.1), (-10, -10), (-10, 0)] polygon_2 = s2.S2Polygon(verts2loop(vertices_2)) self.assertTrue( polygon_1.BoundaryNear(polygon_2, s2.S1Angle.Degrees(1)) ) def testS2PolygonUsesValueEquality(self): self.assertEqual(s2.S2Polygon(), s2.S2Polygon()) def testCrossingSign(self): a = s2.S2LatLng.FromDegrees(-1, 0).ToPoint() b = s2.S2LatLng.FromDegrees(1, 0).ToPoint() c = s2.S2LatLng.FromDegrees(0, -1).ToPoint() d = s2.S2LatLng.FromDegrees(0, 1).ToPoint() # SWIG flattens namespaces, so this is just s2.CrossingSign, # not s2.S2.CrossingSign. self.assertEqual(1, s2.CrossingSign(a, b, c, d)) def testGetIntersection(self): a = s2.S2LatLng.FromDegrees(-1, 0).ToPoint() b = s2.S2LatLng.FromDegrees(1, 0).ToPoint() c = s2.S2LatLng.FromDegrees(0, -1).ToPoint() d = s2.S2LatLng.FromDegrees(0, 1).ToPoint() # SWIG namespace flattening as above. intersection = s2.GetIntersection(a, b, c, d) self.assertEqual( "0.000000,0.000000", s2.S2LatLng(intersection).ToStringInDegrees() ) def testS2CellDistance(self): # Level-0 cell (i.e. face) centered at (0, 0) cell = s2.S2Cell(s2.S2CellId(0x1000000000000000)) p1 = s2.S2LatLng.FromDegrees(0, 0).ToPoint() self.assertTrue(cell.Contains(p1)) d1 = cell.GetDistance(p1).ToAngle().degrees() # Inside, so distance is 0, but boundary distance is not. self.assertEqual(0.0, d1) bd1 = cell.GetBoundaryDistance(p1).ToAngle().degrees() self.assertEqual(45.0, bd1) p2 = s2.S2LatLng.FromDegrees(0, 90).ToPoint() self.assertFalse(cell.Contains(p2)) d2 = cell.GetDistance(p2).ToAngle().degrees() self.assertAlmostEqual(45.0, d2) bd2 = cell.GetBoundaryDistance(p2).ToAngle().degrees() # Outside, so distance and boundary distance are the same. self.assertAlmostEqual(45.0, bd2) def testS2Rotate(self): mtv_a = s2.S2LatLng.FromDegrees(37.4402777, -121.9638888).ToPoint() mtv_b = s2.S2LatLng.FromDegrees(37.3613888, -121.9283333).ToPoint() angle = s2.S1Angle.Radians(0.039678) point = s2.Rotate(mtv_a, mtv_b, angle) self.assertEqual( "37.439095,-121.967802", s2.S2LatLng(point).ToStringInDegrees() ) def testS2TurnAngle(self): mtv_a = s2.S2LatLng.FromDegrees(37.4402777, -121.9638888).ToPoint() mtv_b = s2.S2LatLng.FromDegrees(37.3613888, -121.9283333).ToPoint() mtv_c = s2.S2LatLng.FromDegrees(37.3447222, -122.0308333).ToPoint() angle = s2.TurnAngle(mtv_a, mtv_b, mtv_c) self.assertAlmostEqual(-1.7132025, angle) def testEncodeDecode(self): london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) polygon = s2.S2Polygon(s2.S2Cell(s2.S2CellId(london).parent(15))) self.assertEqual(polygon.num_loops(), 1) encoder = s2.Encoder() polygon.Encode(encoder) encoded = encoder.buffer() decoder = s2.Decoder(encoded) decoded_polygon = s2.S2Polygon() self.assertTrue(decoded_polygon.Decode(decoder)) self.assertEqual(decoded_polygon.num_loops(), 1) self.assertTrue(decoded_polygon.Equals(polygon)) def testS2CapRegion(self): center = s2.S2LatLng.FromDegrees(2.0, 3.0).ToPoint() cap = s2.S2Cap(center, s2.S1Angle.Degrees(1.0)) inside = s2.S2LatLng.FromDegrees(2.1, 2.9).ToPoint() outside = s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint() self.assertTrue(cap.Contains(inside)) self.assertFalse(cap.Contains(outside)) self.assertTrue(cap.Contains(s2.S2Cell(inside))) self.assertFalse(cap.Contains(s2.S2Cell(outside))) self.assertTrue(cap.MayIntersect(s2.S2Cell(inside))) self.assertFalse(cap.MayIntersect(s2.S2Cell(outside))) self.assertTrue(cap.ApproxEquals(cap.GetCapBound())) rect_bound = cap.GetRectBound() self.assertTrue(rect_bound.Contains(inside)) self.assertFalse(rect_bound.Contains(outside)) def testS2LatLngRectRegion(self): rect = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(1.0, 2.0), s2.S2LatLng.FromDegrees(3.0, 4.0) ) inside = s2.S2LatLng.FromDegrees(2.0, 3.0).ToPoint() outside = s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint() self.assertTrue(rect.Contains(inside)) self.assertFalse(rect.Contains(outside)) self.assertTrue(rect.Contains(s2.S2Cell(inside))) self.assertFalse(rect.Contains(s2.S2Cell(outside))) self.assertTrue(rect.MayIntersect(s2.S2Cell(inside))) self.assertFalse(rect.MayIntersect(s2.S2Cell(outside))) cap_bound = rect.GetCapBound() self.assertTrue(cap_bound.Contains(inside)) self.assertFalse(cap_bound.Contains(outside)) self.assertTrue(rect.ApproxEquals(rect.GetRectBound())) def testS2CellRegion(self): cell = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) inside = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() outside = s2.S2LatLng.FromDegrees(30.0, 40.0).ToPoint() self.assertTrue(cell.Contains(inside)) self.assertFalse(cell.Contains(outside)) self.assertTrue(cell.Contains(s2.S2Cell(inside))) self.assertFalse(cell.Contains(s2.S2Cell(outside))) self.assertTrue(cell.MayIntersect(s2.S2Cell(inside))) self.assertFalse(cell.MayIntersect(s2.S2Cell(outside))) cap_bound = cell.GetCapBound() self.assertTrue(cap_bound.Contains(inside)) self.assertFalse(cap_bound.Contains(outside)) rect_bound = cell.GetRectBound() self.assertTrue(rect_bound.Contains(inside)) self.assertFalse(rect_bound.Contains(outside)) def testS2CellUnionRegion(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) cell_union = s2.S2CellUnion() cell_union.Init([cell_id.id()]) inside = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() outside = s2.S2LatLng.FromDegrees(30.0, 40.0).ToPoint() self.assertTrue(cell_union.Contains(inside)) self.assertFalse(cell_union.Contains(outside)) self.assertTrue(cell_union.Contains(s2.S2Cell(inside))) self.assertFalse(cell_union.Contains(s2.S2Cell(outside))) self.assertTrue(cell_union.MayIntersect(s2.S2Cell(inside))) self.assertFalse(cell_union.MayIntersect(s2.S2Cell(outside))) cap_bound = cell_union.GetCapBound() self.assertTrue(cap_bound.Contains(inside)) self.assertFalse(cap_bound.Contains(outside)) rect_bound = cell_union.GetRectBound() self.assertTrue(rect_bound.Contains(inside)) self.assertFalse(rect_bound.Contains(outside)) def testS2CellUnionEmpty(self): empty_cell_union = s2.S2CellUnion() self.assertTrue(empty_cell_union.empty()) cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) cell_union = s2.S2CellUnion() cell_union.Init([cell_id.id()]) self.assertFalse(cell_union.empty()) def testS2CellUnionIntersectionWithS2CellUnion(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)) cell_union = s2.S2CellUnion() cell_union.Init([cell_id.id()]) # No intersection. outside_cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(5.0, 6.0)) outside_cell_union = s2.S2CellUnion() outside_cell_union.Init([outside_cell_id.id()]) empty_intersection = cell_union.Intersection(outside_cell_union) self.assertTrue(empty_intersection.empty()) # Complete overlap. self_intersection = cell_union.Intersection(cell_union) self.assertTrue(self_intersection.Contains(cell_union)) self.assertTrue(cell_union.Contains(self_intersection)) # Some intersection. joint_cell_union = s2.S2CellUnion() joint_cell_union.Init([cell_id.id(), outside_cell_id.id()]) outside_intersection = joint_cell_union.Intersection(outside_cell_union) self.assertTrue(outside_intersection.Contains(outside_cell_id)) self.assertFalse(outside_intersection.Contains(cell_id)) def testS2CellUnionIntersectionWithS2CellId(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)) cell_union = s2.S2CellUnion() cell_union.Init([cell_id.id()]) # No intersection. outside_cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(4.0, 5.0)) empty_intersection = cell_union.Intersection(outside_cell_id) self.assertTrue(empty_intersection.empty()) # Complete overlap. intersection = cell_union.Intersection(cell_id) self.assertTrue(intersection.Contains(cell_id)) # Some intersection. joint_cell_union = s2.S2CellUnion() joint_cell_union.Init([cell_id.id(), outside_cell_id.id()]) outside_intersection = joint_cell_union.Intersection(outside_cell_id) self.assertTrue(outside_intersection.Contains(outside_cell_id)) self.assertFalse(outside_intersection.Contains(cell_id)) def testS2CellUnionIsNormalized(self): empty_cell_union = s2.S2CellUnion() self.assertTrue(empty_cell_union.IsNormalized()) london = s2.S2LatLng.FromDegrees(51.5001525, -0.1262355) london_cell_id = s2.S2CellId(london) normalized_union = s2.S2CellUnion() normalized_union.Init([london_cell_id.id()]) self.assertTrue(normalized_union.IsNormalized()) def testS2CellUnionNormalizeS2CellUnion(self): empty_cell_union = s2.S2CellUnion() empty_cell_union.NormalizeS2CellUnion() self.assertTrue(empty_cell_union.IsNormalized()) cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) cell_union = s2.S2CellUnion() cell_union.Init([cell_id.id()]) cell_union.NormalizeS2CellUnion() self.assertTrue(cell_union.IsNormalized()) def testS2LoopRegion(self): cell = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) loop = s2.S2Loop(cell) inside = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() outside = s2.S2LatLng.FromDegrees(30.0, 40.0).ToPoint() self.assertTrue(loop.Contains(inside)) self.assertFalse(loop.Contains(outside)) self.assertTrue(loop.Contains(s2.S2Cell(inside))) self.assertFalse(loop.Contains(s2.S2Cell(outside))) self.assertTrue(loop.MayIntersect(s2.S2Cell(inside))) self.assertFalse(loop.MayIntersect(s2.S2Cell(outside))) cap_bound = loop.GetCapBound() self.assertTrue(cap_bound.Contains(inside)) self.assertFalse(cap_bound.Contains(outside)) rect_bound = loop.GetRectBound() self.assertTrue(rect_bound.Contains(inside)) self.assertFalse(rect_bound.Contains(outside)) def testS2PolygonRegion(self): cell = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) polygon = s2.S2Polygon(cell) inside = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() outside = s2.S2LatLng.FromDegrees(30.0, 40.0).ToPoint() self.assertTrue(polygon.Contains(inside)) self.assertFalse(polygon.Contains(outside)) self.assertTrue(polygon.Contains(s2.S2Cell(inside))) self.assertFalse(polygon.Contains(s2.S2Cell(outside))) self.assertTrue(polygon.MayIntersect(s2.S2Cell(inside))) self.assertFalse(polygon.MayIntersect(s2.S2Cell(outside))) cap_bound = polygon.GetCapBound() self.assertTrue(cap_bound.Contains(inside)) self.assertFalse(cap_bound.Contains(outside)) rect_bound = polygon.GetRectBound() self.assertTrue(rect_bound.Contains(inside)) self.assertFalse(rect_bound.Contains(outside)) def testS2PolylineRegion(self): polyline = s2.S2Polyline() polyline.InitFromS2LatLngs([ s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(1.0, 1.0), ]) # Contains(S2Point) always return false. self.assertFalse( polyline.Contains(s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint()) ) self.assertFalse( polyline.Contains(s2.S2Cell(s2.S2LatLng.FromDegrees(0.0, 0.0))) ) self.assertTrue( polyline.MayIntersect(s2.S2Cell(s2.S2LatLng.FromDegrees(0.0, 0.0))) ) self.assertFalse( polyline.MayIntersect(s2.S2Cell(s2.S2LatLng.FromDegrees(3.0, 4.0))) ) cap_bound = polyline.GetCapBound() self.assertTrue( cap_bound.Contains(s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint()) ) self.assertFalse( cap_bound.Contains(s2.S2LatLng.FromDegrees(2.0, 2.0).ToPoint()) ) rect_bound = polyline.GetRectBound() self.assertTrue( rect_bound.Contains(s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint()) ) self.assertFalse( rect_bound.Contains(s2.S2LatLng.FromDegrees(2.0, 2.0).ToPoint()) ) def testS2CellIdCenterSiTi(self): cell = s2.S2CellId.FromFacePosLevel( 3, 0x12345678, s2.S2CellId.kMaxLevel ) # Check that the (si, ti) coordinates of the center end in a # 1 followed by (30 - level) 0s. # Leaf level, 30. face, si, ti = cell.GetCenterSiTi() self.assertEqual(3, face) self.assertEqual(1 << 0, si & 1) self.assertEqual(1 << 0, ti & 1) # Level 29. face, si, ti = cell.parent(s2.S2CellId.kMaxLevel - 1).GetCenterSiTi() self.assertEqual(3, face) self.assertEqual(1 << 1, si & 3) self.assertEqual(1 << 1, ti & 3) # Level 28. face, si, ti = cell.parent(s2.S2CellId.kMaxLevel - 2).GetCenterSiTi() self.assertEqual(3, face) self.assertEqual(1 << 2, si & 7) self.assertEqual(1 << 2, ti & 7) # Level 20. face, si, ti = cell.parent(s2.S2CellId.kMaxLevel - 10).GetCenterSiTi() self.assertEqual(3, face) self.assertEqual(1 << 10, si & ((1 << 11) - 1)) self.assertEqual(1 << 10, ti & ((1 << 11) - 1)) # Level 10. face, si, ti = cell.parent(s2.S2CellId.kMaxLevel - 20).GetCenterSiTi() self.assertEqual(3, face) self.assertEqual(1 << 20, si & ((1 << 21) - 1)) self.assertEqual(1 << 20, ti & ((1 << 21) - 1)) # Level 0. face, si, ti = cell.parent(0).GetCenterSiTi() self.assertEqual(3, face) self.assertEqual(1 << 30, si & ((1 << 31) - 1)) self.assertEqual(1 << 30, ti & ((1 << 31) - 1)) def testS2CellIdToFromFaceIJ(self): cell = s2.S2CellId.FromFaceIJ(3, 1234, 5678) face, i, j, _ = cell.ToFaceIJOrientation() self.assertEqual(3, face) self.assertEqual(1234, i) self.assertEqual(5678, j) def testS2EarthMetricRadians(self): radius_rad = s2.S2Earth.KmToRadians(12.34) self.assertAlmostEqual(radius_rad, 0.0019368985451286374) angle = s2.S1Angle.Radians(radius_rad) radius_m = s2.S2Earth.RadiansToMeters(angle.radians()) self.assertEqual(radius_m, 12340.0) def testS2Point_ToFromRaw(self): p = s2.S2Point_FromRaw(1.0, 1.0, 1.0) p = p.Normalize() p_raw = s2.S2Point_ToRaw(p) self.assertAlmostEqual(p_raw[0], 0.57735027) self.assertAlmostEqual(p_raw[1], 0.57735027) self.assertAlmostEqual(p_raw[2], 0.57735027) def testS2Interpolate(self): p1 = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() p2 = s2.S2LatLng.FromDegrees(4.0, 5.0).ToPoint() p3 = s2.Interpolate(p1, p2, 0.5) self.assertEqual( "3.500133,4.499733", s2.S2LatLng(p3).ToStringInDegrees() ) def testS2predOrderedCCW(self): pC = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() p1 = s2.S2LatLng.FromDegrees(3.0, 5.0).ToPoint() p2 = s2.S2LatLng.FromDegrees(2.7, 3.0).ToPoint() p3 = s2.S2LatLng.FromDegrees(3.3, 3.0).ToPoint() self.assertFalse(s2.OrderedCCW(p1, p2, p3, pC)) self.assertTrue(s2.OrderedCCW(p2, p1, p3, pC)) self.assertTrue(s2.OrderedCCW(p1, p3, p2, pC)) self.assertTrue(s2.OrderedCCW(p3, p2, p1, pC)) def testS2UpdateMinDistance(self): pC = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() p1 = s2.S2LatLng.FromDegrees(3.0, 5.0).ToPoint() p2 = s2.S2LatLng.FromDegrees(2.7, 3.0).ToPoint() md = s2.S1ChordAngle.Infinity() self.assertTrue(s2.UpdateMinDistance(pC, p1, p2, md)) self.assertAlmostEqual(0.1478883, md.degrees()) pC = s2.S2LatLng.FromDegrees(3.0, 40.0).ToPoint() self.assertFalse(s2.UpdateMinDistance(pC, p1, p2, md)) self.assertAlmostEqual(0.1478883, md.degrees()) def testS1AngleToString(self): a = s2.S1Angle.Degrees(123) self.assertEqual("123.0000000", str(a)) def testS2CellIdToString(self): a = s2.S2CellId(12345) self.assertEqual("0/000000000000000000000001200130", str(a)) class S1AngleTest(unittest.TestCase): def testE5(self): a = s2.S1Angle.E5(1000000) self.assertAlmostEqual(10.0, a.degrees()) def testE6(self): a = s2.S1Angle.E6(10000000) self.assertAlmostEqual(10.0, a.degrees()) def testE7(self): a = s2.S1Angle.E7(100000000) self.assertAlmostEqual(10.0, a.degrees()) def testAccessors_e6_e7(self): a = s2.S1Angle.Degrees(45.0) self.assertEqual(45000000, a.e6()) self.assertEqual(450000000, a.e7()) def testUnsignedE6(self): a = s2.S1Angle.UnsignedE6(10000000) self.assertAlmostEqual(10.0, a.degrees()) def testNormalize(self): a = s2.S1Angle.Degrees(360 + 45) a.Normalize() self.assertAlmostEqual(45.0, a.degrees()) def testNormalized(self): a = s2.S1Angle.Degrees(360 + 45) b = a.Normalized() self.assertAlmostEqual(45.0, b.degrees()) def testAbs(self): a = s2.S1Angle.Degrees(-45.0) b = a.abs() self.assertAlmostEqual(45.0, b.degrees()) def testRadiansAccessor(self): a = s2.S1Angle.Degrees(180.0) self.assertAlmostEqual(3.14159265, a.radians(), places=5) class S2CapTest(unittest.TestCase): def testEmpty(self): cap = s2.S2Cap.Empty() self.assertTrue(cap.is_empty()) def testFull(self): cap = s2.S2Cap.Full() self.assertTrue(cap.is_valid()) self.assertFalse(cap.is_empty()) def testFromPoint(self): p = s2.S2LatLng.FromDegrees(1.0, 2.0).ToPoint() cap = s2.S2Cap.FromPoint(p) self.assertTrue(cap.is_valid()) self.assertTrue(cap.Contains(p)) def testFromCenterHeight(self): p = s2.S2LatLng.FromDegrees(1.0, 2.0).ToPoint() cap = s2.S2Cap.FromCenterHeight(p, 0.5) self.assertTrue(cap.is_valid()) self.assertAlmostEqual(0.5, cap.height()) def testCenterAndHeight(self): center = s2.S2LatLng.FromDegrees(2.0, 3.0).ToPoint() cap = s2.S2Cap(center, s2.S1Angle.Degrees(1.0)) c = cap.center() self.assertIsInstance(c, s2.S2Point) self.assertGreater(cap.height(), 0.0) def testGetCentroid(self): center = s2.S2LatLng.FromDegrees(2.0, 3.0).ToPoint() cap = s2.S2Cap(center, s2.S1Angle.Degrees(1.0)) centroid = cap.GetCentroid() self.assertIsInstance(centroid, s2.S2Point) def testExpanded(self): center = s2.S2LatLng.FromDegrees(2.0, 3.0).ToPoint() cap = s2.S2Cap(center, s2.S1Angle.Degrees(1.0)) expanded = cap.Expanded(s2.S1Angle.Degrees(1.0)) self.assertGreater(expanded.height(), cap.height()) def testUnion(self): p1 = s2.S2LatLng.FromDegrees(1.0, 1.0).ToPoint() p2 = s2.S2LatLng.FromDegrees(10.0, 10.0).ToPoint() cap1 = s2.S2Cap(p1, s2.S1Angle.Degrees(1.0)) cap2 = s2.S2Cap(p2, s2.S1Angle.Degrees(1.0)) union = cap1.Union(cap2) self.assertTrue(union.Contains(p1)) self.assertTrue(union.Contains(p2)) def testIntersects(self): p1 = s2.S2LatLng.FromDegrees(1.0, 1.0).ToPoint() cap1 = s2.S2Cap(p1, s2.S1Angle.Degrees(5.0)) cap2 = s2.S2Cap(p1, s2.S1Angle.Degrees(1.0)) self.assertTrue(cap1.Intersects(cap2)) def testEncodeDecode(self): center = s2.S2LatLng.FromDegrees(2.0, 3.0).ToPoint() cap = s2.S2Cap(center, s2.S1Angle.Degrees(1.0)) encoder = s2.Encoder() cap.Encode(encoder) decoder = s2.Decoder(encoder.buffer()) cap2 = s2.S2Cap() self.assertTrue(cap2.Decode(decoder)) # S2Cap.ApproxEquals is not exposed via SWIG, so compare heights. self.assertAlmostEqual(cap.height(), cap2.height()) def testAddPoint(self): cap = s2.S2Cap.Empty() p = s2.S2LatLng.FromDegrees(1.0, 2.0).ToPoint() cap.AddPoint(p) self.assertTrue(cap.Contains(p)) class S2CellTest(unittest.TestCase): def testApproxArea(self): cell = s2.S2Cell(s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10)) self.assertGreater(cell.ApproxArea(), 0.0) def testExactArea(self): cell = s2.S2Cell(s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10)) self.assertGreater(cell.ExactArea(), 0.0) def testAverageArea(self): area = s2.S2Cell.AverageArea(10) self.assertGreater(area, 0.0) def testGetCenter(self): cell = s2.S2Cell(s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10)) center = cell.GetCenter() self.assertIsInstance(center, s2.S2Point) def testGetVertex(self): cell = s2.S2Cell(s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10)) v = cell.GetVertex(0) self.assertIsInstance(v, s2.S2Point) def testGetS2LatLngEdge(self): cell = s2.S2Cell(s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10)) edge = cell.GetS2LatLngEdge(0) self.assertIsInstance(edge, s2.S2LatLng) def testFaceAndLevel(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10) cell = s2.S2Cell(cell_id) self.assertEqual(10, cell.level()) self.assertIn(cell.face(), range(6)) def testIdRoundTrip(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10) cell = s2.S2Cell(cell_id) self.assertEqual(cell_id, cell.id()) def testEncodeDecode(self): cell = s2.S2Cell(s2.S2CellId(s2.S2LatLng.FromDegrees(0, 0)).parent(10)) encoder = s2.Encoder() cell.Encode(encoder) decoder = s2.Decoder(encoder.buffer()) cell2 = s2.S2Cell() self.assertTrue(cell2.Decode(decoder)) self.assertEqual(cell.id(), cell2.id()) class S2CellIdTest(unittest.TestCase): def testBeginEnd(self): begin = s2.S2CellId.Begin(0) end = s2.S2CellId.End(0) self.assertTrue(begin.is_valid()) self.assertLess(begin, end) def testChildBeginEnd(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) begin = cell_id.child_begin() end = cell_id.child_end() self.assertLess(begin, end) def testIsLeaf(self): leaf = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)) self.assertTrue(leaf.is_leaf()) non_leaf = leaf.parent(10) self.assertFalse(non_leaf.is_leaf()) def testIsFace(self): face = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(0) self.assertTrue(face.is_face()) non_face = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) self.assertFalse(non_face.is_face()) def testPos(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)) pos = cell_id.pos() self.assertIsInstance(pos, int) def testRangeMinMax(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) rmin = cell_id.range_min() rmax = cell_id.range_max() self.assertLess(rmin, rmax) def testNextPrev(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) nxt = cell_id.next() prv = cell_id.prev() self.assertNotEqual(cell_id, nxt) self.assertNotEqual(cell_id, prv) self.assertEqual(cell_id, nxt.prev()) self.assertEqual(cell_id, prv.next()) def testKMaxLevel(self): self.assertEqual(30, s2.S2CellId.kMaxLevel) class S2CellUnionTest(unittest.TestCase): def testApproxArea(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) cu = s2.S2CellUnion() cu.Init([cell_id.id()]) self.assertGreater(cu.ApproxArea(), 0.0) def testDenormalize(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) cu = s2.S2CellUnion() cu.Init([cell_id.id()]) denormed = cu.Denormalize(0, 1) self.assertGreater(len(denormed), 0) def testCellId(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) cu = s2.S2CellUnion() cu.Init([cell_id.id()]) self.assertEqual(cell_id, cu.cell_id(0)) def testEncodeDecode(self): cell_id = s2.S2CellId(s2.S2LatLng.FromDegrees(1.0, 2.0)).parent(10) cu = s2.S2CellUnion() cu.Init([cell_id.id()]) encoder = s2.Encoder() cu.Encode(encoder) decoder = s2.Decoder(encoder.buffer()) cu2 = s2.S2CellUnion() self.assertTrue(cu2.Decode(decoder)) self.assertEqual(cu.num_cells(), cu2.num_cells()) class S2LoopTest(unittest.TestCase): def _makeLoop(self): cell = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) return s2.S2Loop(cell) def testClone(self): loop = self._makeLoop() clone = loop.Clone() self.assertTrue(loop.Equals(clone)) def testEncodeDecode(self): loop = self._makeLoop() encoder = s2.Encoder() loop.Encode(encoder) decoder = s2.Decoder(encoder.buffer()) loop2 = s2.S2Loop() self.assertTrue(loop2.Decode(decoder)) self.assertTrue(loop.Equals(loop2)) def testGetCentroid(self): loop = self._makeLoop() centroid = loop.GetCentroid() self.assertIsInstance(centroid, s2.S2Point) def testGetDistance(self): loop = self._makeLoop() p = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() d = loop.GetDistance(p) self.assertIsInstance(d, s2.S1Angle) def testIntersects(self): loop1 = self._makeLoop() loop2 = self._makeLoop() self.assertTrue(loop1.Intersects(loop2)) def testProject(self): loop = self._makeLoop() p = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() projected = loop.Project(p) self.assertIsInstance(projected, s2.S2Point) def testIsEmpty(self): loop = self._makeLoop() self.assertFalse(loop.is_empty()) def testSign(self): loop = self._makeLoop() sign = loop.sign() self.assertEqual(1, sign) def testVertex(self): loop = self._makeLoop() v = loop.vertex(0) self.assertIsInstance(v, s2.S2Point) class S2PolylineTest(unittest.TestCase): def _makePolyline(self): line = s2.S2Polyline() line.InitFromS2LatLngs([ s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(1.0, 1.0), ]) return line def testClone(self): line = self._makePolyline() clone = line.Clone() self.assertTrue(line.ApproxEquals(clone)) def testEncodeDecode(self): line = self._makePolyline() encoder = s2.Encoder() line.Encode(encoder) decoder = s2.Decoder(encoder.buffer()) line2 = s2.S2Polyline() self.assertTrue(line2.Decode(decoder)) self.assertTrue(line.ApproxEquals(line2)) def testApproxEquals(self): line1 = self._makePolyline() line2 = self._makePolyline() self.assertTrue(line1.ApproxEquals(line2)) def testGetSuffix(self): line = self._makePolyline() point, next_vertex = line.GetSuffix(0.5) self.assertIsInstance(point, s2.S2Point) self.assertIsInstance(next_vertex, int) def testInterpolateAndUnInterpolate(self): line = self._makePolyline() p = line.Interpolate(0.5) self.assertIsInstance(p, s2.S2Point) f = line.UnInterpolate(p, 1) self.assertAlmostEqual(0.5, f, places=5) def testIntersects(self): line1 = s2.S2Polyline() line1.InitFromS2LatLngs([ s2.S2LatLng.FromDegrees(-1.0, 0.0), s2.S2LatLng.FromDegrees(1.0, 0.0), ]) line2 = s2.S2Polyline() line2.InitFromS2LatLngs([ s2.S2LatLng.FromDegrees(0.0, -1.0), s2.S2LatLng.FromDegrees(0.0, 1.0), ]) self.assertTrue(line1.Intersects(line2)) def testIsOnRight(self): line = self._makePolyline() p = s2.S2LatLng.FromDegrees(0.0, 1.0).ToPoint() result = line.IsOnRight(p) self.assertIsInstance(result, bool) def testIsValid(self): line = self._makePolyline() self.assertTrue(line.IsValid()) def testProject(self): line = self._makePolyline() p = s2.S2LatLng.FromDegrees(0.5, 0.5).ToPoint() projected = line.Project(p) self.assertIsInstance(projected[0], s2.S2Point) def testReverse(self): line = self._makePolyline() v0_before = s2.S2LatLng(line.vertex(0)).ToStringInDegrees() line.Reverse() v_last = s2.S2LatLng(line.vertex(0)).ToStringInDegrees() self.assertNotEqual(v0_before, v_last) def testNumVertices(self): line = self._makePolyline() self.assertEqual(2, line.num_vertices()) def testVertex(self): line = self._makePolyline() v = line.vertex(0) self.assertIsInstance(v, s2.S2Point) class S2EarthTest(unittest.TestCase): def testGetDistanceLatLng(self): a = s2.S2LatLng.FromDegrees(0.0, 0.0) b = s2.S2LatLng.FromDegrees(1.0, 0.0) # GetDistance returns an opaque SWIG Meters* object. d = s2.S2Earth.GetDistance(a, b) self.assertTrue(d is not None) def testGetDistanceS2Point(self): a = s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint() b = s2.S2LatLng.FromDegrees(1.0, 0.0).ToPoint() # GetDistance returns an opaque SWIG Meters* object. d = s2.S2Earth.GetDistance(a, b) self.assertTrue(d is not None) def testGetDistanceKmLatLng(self): a = s2.S2LatLng.FromDegrees(0.0, 0.0) b = s2.S2LatLng.FromDegrees(1.0, 0.0) km = s2.S2Earth.GetDistanceKm(a, b) self.assertGreater(km, 100.0) def testGetDistanceKmS2Point(self): a = s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint() b = s2.S2LatLng.FromDegrees(1.0, 0.0).ToPoint() km = s2.S2Earth.GetDistanceKm(a, b) self.assertGreater(km, 100.0) def testGetDistanceMetersLatLng(self): a = s2.S2LatLng.FromDegrees(0.0, 0.0) b = s2.S2LatLng.FromDegrees(1.0, 0.0) m = s2.S2Earth.GetDistanceMeters(a, b) self.assertGreater(m, 100000.0) def testGetDistanceMetersS2Point(self): a = s2.S2LatLng.FromDegrees(0.0, 0.0).ToPoint() b = s2.S2LatLng.FromDegrees(1.0, 0.0).ToPoint() m = s2.S2Earth.GetDistanceMeters(a, b) self.assertGreater(m, 100000.0) def testGetInitialBearing(self): a = s2.S2LatLng.FromDegrees(0.0, 0.0) b = s2.S2LatLng.FromDegrees(1.0, 0.0) bearing = s2.S2Earth.GetInitialBearing(a, b) self.assertIsInstance(bearing, s2.S1Angle) def testRadiusMethods(self): km = s2.S2Earth.RadiusKm() self.assertAlmostEqual(6371.01, km, places=1) m = s2.S2Earth.RadiusMeters() self.assertAlmostEqual(6371010.0, m, places=-1) def testAltitudeMethods(self): hm = s2.S2Earth.HighestAltitudeMeters() self.assertGreater(hm, 0.0) lom = s2.S2Earth.LowestAltitudeMeters() self.assertLess(lom, 0.0) def testMetersToRadians(self): r = s2.S2Earth.MetersToRadians(1000.0) self.assertGreater(r, 0.0) def testRadiansToKm(self): km = s2.S2Earth.RadiansToKm(0.001) self.assertGreater(km, 0.0) def testSquareConversions(self): sr = s2.S2Earth.SquareKmToSteradians(1.0) self.assertGreater(sr, 0.0) sr2 = s2.S2Earth.SquareMetersToSteradians(1000000.0) self.assertGreater(sr2, 0.0) km2 = s2.S2Earth.SteradiansToSquareKm(sr) self.assertAlmostEqual(1.0, km2, places=5) m2 = s2.S2Earth.SteradiansToSquareMeters(sr2) self.assertAlmostEqual(1000000.0, m2, places=0) def testToDistance(self): a = s2.S1Angle.Degrees(1.0) # ToDistance returns an opaque SWIG Meters* object. d = s2.S2Earth.ToDistance(a) self.assertTrue(d is not None) def testToDistanceChordAngle(self): ca = s2.S1ChordAngle(s2.S1Angle.Degrees(1.0)) # ToDistance returns an opaque SWIG Meters* object. d = s2.S2Earth.ToDistance(ca) self.assertTrue(d is not None) def testToKm(self): a = s2.S1Angle.Degrees(1.0) km = s2.S2Earth.ToKm(a) self.assertGreater(km, 100.0) def testToKmChordAngle(self): ca = s2.S1ChordAngle(s2.S1Angle.Degrees(1.0)) km = s2.S2Earth.ToKm(ca) self.assertGreater(km, 100.0) def testToMeters(self): a = s2.S1Angle.Degrees(1.0) m = s2.S2Earth.ToMeters(a) self.assertGreater(m, 100000.0) def testToMetersChordAngle(self): ca = s2.S1ChordAngle(s2.S1Angle.Degrees(1.0)) m = s2.S2Earth.ToMeters(ca) self.assertGreater(m, 100000.0) class S2LatLngTest(unittest.TestCase): def testFromE6(self): ll = s2.S2LatLng.FromE6(10000000, 20000000) self.assertAlmostEqual(10.0, ll.lat().degrees()) self.assertAlmostEqual(20.0, ll.lng().degrees()) def testFromE7(self): ll = s2.S2LatLng.FromE7(100000000, 200000000) self.assertAlmostEqual(10.0, ll.lat().degrees()) self.assertAlmostEqual(20.0, ll.lng().degrees()) def testFromRadians(self): ll = s2.S2LatLng.FromRadians(0.0, math.pi / 2) self.assertAlmostEqual(0.0, ll.lat().degrees()) self.assertAlmostEqual(90.0, ll.lng().degrees()) def testFromUnsignedE6(self): ll = s2.S2LatLng.FromUnsignedE6(10000000, 20000000) self.assertAlmostEqual(10.0, ll.lat().degrees()) self.assertAlmostEqual(20.0, ll.lng().degrees()) def testFromUnsignedE7(self): ll = s2.S2LatLng.FromUnsignedE7(100000000, 200000000) self.assertAlmostEqual(10.0, ll.lat().degrees()) self.assertAlmostEqual(20.0, ll.lng().degrees()) def testCoords(self): ll = s2.S2LatLng.FromDegrees(10.0, 20.0) # coords() returns an opaque SWIG R2Point object. c = ll.coords() self.assertTrue(c is not None) class S2LatLngRectTest(unittest.TestCase): def testFromPoint(self): r = s2.S2LatLngRect.FromPoint(s2.S2LatLng.FromDegrees(1.0, 2.0)) self.assertTrue(r.is_point()) def testFromPointPair(self): r = s2.S2LatLngRect.FromPointPair( s2.S2LatLng.FromDegrees(1.0, 2.0), s2.S2LatLng.FromDegrees(3.0, 4.0) ) self.assertFalse(r.is_empty()) def testFromCenterSize(self): center = s2.S2LatLng.FromDegrees(1.0, 2.0) size = s2.S2LatLng.FromDegrees(2.0, 4.0) r = s2.S2LatLngRect.FromCenterSize(center, size) self.assertFalse(r.is_empty()) def testEmpty(self): r = s2.S2LatLngRect.Empty() self.assertTrue(r.is_empty()) def testFull(self): r = s2.S2LatLngRect.Full() self.assertFalse(r.is_empty()) def testExpandedByDistance(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(1.0, 2.0), s2.S2LatLng.FromDegrees(3.0, 4.0) ) expanded = r.ExpandedByDistance(s2.S1Angle.Degrees(1.0)) self.assertGreater(expanded.Area(), r.Area()) def testArea(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(1.0, 1.0) ) self.assertGreater(r.Area(), 0.0) def testGetCenter(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(2.0, 4.0) ) c = r.GetCenter() self.assertAlmostEqual(1.0, c.lat().degrees()) self.assertAlmostEqual(2.0, c.lng().degrees()) def testGetCentroid(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(2.0, 4.0) ) centroid = r.GetCentroid() self.assertIsInstance(centroid, s2.S2Point) def testGetDistance(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(1.0, 1.0) ) p = s2.S2LatLng.FromDegrees(5.0, 5.0) d = r.GetDistance(p) self.assertIsInstance(d, s2.S1Angle) def testGetSize(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(2.0, 4.0) ) size = r.GetSize() self.assertAlmostEqual(2.0, size.lat().degrees()) self.assertAlmostEqual(4.0, size.lng().degrees()) def testGetVertex(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(2.0, 4.0) ) for i in range(4): v = r.GetVertex(i) self.assertIsInstance(v, s2.S2LatLng) def testIntersectionAndUnion(self): r1 = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(0.0, 0.0), s2.S2LatLng.FromDegrees(2.0, 2.0) ) r2 = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(1.0, 1.0), s2.S2LatLng.FromDegrees(3.0, 3.0) ) inter = r1.Intersection(r2) self.assertFalse(inter.is_empty()) union = r1.Union(r2) self.assertGreater(union.Area(), r1.Area()) def testLatLngAccessors(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(1.0, 2.0), s2.S2LatLng.FromDegrees(3.0, 4.0) ) self.assertAlmostEqual(1.0, r.lat_lo().degrees()) self.assertAlmostEqual(3.0, r.lat_hi().degrees()) self.assertAlmostEqual(2.0, r.lng_lo().degrees()) self.assertAlmostEqual(4.0, r.lng_hi().degrees()) # lat()/lng() return opaque SWIG R1Interval/S1Interval objects. self.assertTrue(r.lat() is not None) self.assertTrue(r.lng() is not None) self.assertIsInstance(r.lo(), s2.S2LatLng) self.assertIsInstance(r.hi(), s2.S2LatLng) def testEncodeDecode(self): r = s2.S2LatLngRect( s2.S2LatLng.FromDegrees(1.0, 2.0), s2.S2LatLng.FromDegrees(3.0, 4.0) ) encoder = s2.Encoder() r.Encode(encoder) decoder = s2.Decoder(encoder.buffer()) r2 = s2.S2LatLngRect() self.assertTrue(r2.Decode(decoder)) self.assertTrue(r.ApproxEquals(r2)) def testAddPoint(self): r = s2.S2LatLngRect.Empty() r.AddPoint(s2.S2LatLng.FromDegrees(1.0, 2.0)) self.assertFalse(r.is_empty()) class EncoderDecoderTest(unittest.TestCase): def testPutGet8(self): enc = s2.Encoder() enc.Ensure(1) enc.put8(42) dec = s2.Decoder(enc.buffer()) self.assertEqual(42, dec.get8()) def testPutGet16(self): enc = s2.Encoder() enc.Ensure(2) enc.put16(1234) dec = s2.Decoder(enc.buffer()) self.assertEqual(1234, dec.get16()) def testPutGet32(self): enc = s2.Encoder() enc.Ensure(4) enc.put32(12345678) dec = s2.Decoder(enc.buffer()) self.assertEqual(12345678, dec.get32()) def testPutGet64(self): enc = s2.Encoder() enc.Ensure(8) enc.put64(123456789012345) dec = s2.Decoder(enc.buffer()) self.assertEqual(123456789012345, dec.get64()) def testPutGetFloat(self): enc = s2.Encoder() enc.Ensure(4) enc.putfloat(3.14) dec = s2.Decoder(enc.buffer()) self.assertAlmostEqual(3.14, dec.getfloat(), places=5) def testPutGetDouble(self): enc = s2.Encoder() enc.Ensure(8) enc.putdouble(3.141592653589793) dec = s2.Decoder(enc.buffer()) self.assertAlmostEqual(3.141592653589793, dec.getdouble()) def testEncoderLengthAndAvail(self): enc = s2.Encoder() self.assertEqual(0, enc.length()) enc.Ensure(1) enc.put8(1) self.assertEqual(1, enc.length()) self.assertGreaterEqual(enc.avail(), 0) def testEncoderClear(self): enc = s2.Encoder() enc.Ensure(1) enc.put8(1) enc.clear() self.assertEqual(0, enc.length()) def testEncoderEnsure(self): enc = s2.Encoder() enc.Ensure(100) self.assertGreaterEqual(enc.avail(), 100) def testDecoderPosAndAvail(self): enc = s2.Encoder() enc.Ensure(2) enc.put8(1) enc.put8(2) dec = s2.Decoder(enc.buffer()) self.assertEqual(0, dec.pos()) self.assertEqual(2, dec.avail()) dec.get8() self.assertEqual(1, dec.pos()) self.assertEqual(1, dec.avail()) class RegionTermIndexerTest(unittest.TestCase): def _randomCaps(self, query_type, **indexer_options): # This function creates an index consisting either of points (if # options.index_contains_points_only() is true) or S2Caps of random size. # It then executes queries consisting of points (if query_type == POINT) # or S2Caps of random size (if query_type == CAP). # # indexer_options are set on both the indexer & coverer (if relevant) # eg. _randomCaps('cap', min_level=0) calls indexer.set_min_level(0) ITERATIONS = 400 indexer = s2.S2RegionTermIndexer() coverer = s2.S2RegionCoverer() # set indexer options for opt_key, opt_value in indexer_options.items(): setter = "set_%s" % opt_key getattr(indexer, setter)(opt_value) if hasattr(coverer, setter): getattr(coverer, setter)(opt_value) caps = [] coverings = [] index = defaultdict(set) index_terms = 0 query_terms = 0 for i in range(ITERATIONS): # Choose the region to be indexed: either a single point or a cap # of random size (up to a full sphere). terms = [] if indexer.index_contains_points_only(): cap = s2.S2Cap.FromPoint(s2.S2Testing.RandomPoint()) terms = indexer.GetIndexTerms(cap.center(), "") else: cap = s2.S2Testing.GetRandomCap( 0.3 * s2.S2Cell.AverageArea(indexer.max_level()), 4.0 * s2.S2Cell.AverageArea(indexer.min_level()), ) terms = indexer.GetIndexTerms(cap, "") caps.append(cap) coverings.append(s2.S2CellUnion(coverer.GetCovering(cap))) for term in terms: index[term].add(i) index_terms += len(terms) for i in range(ITERATIONS): # Choose the region to be queried: either a random point or a cap of # random size. terms = [] if query_type == "cap": cap = s2.S2Cap.FromPoint(s2.S2Testing.RandomPoint()) terms = indexer.GetQueryTerms(cap.center(), "") else: cap = s2.S2Testing.GetRandomCap( 0.3 * s2.S2Cell.AverageArea(indexer.max_level()), 4.0 * s2.S2Cell.AverageArea(indexer.min_level()), ) terms = indexer.GetQueryTerms(cap, "") # Compute the expected results of the S2Cell query by brute force. covering = s2.S2CellUnion(coverer.GetCovering(cap)) expected, actual = set(), set() for j in range(len(caps)): if covering.Intersects(coverings[j]): expected.add(j) for term in terms: actual |= index[term] self.assertEqual(expected, actual) query_terms += len(terms) print( "Index terms/doc: %0.2f, Query terms/doc: %0.2f" % ( float(index_terms) / ITERATIONS, float(query_terms) / ITERATIONS, ) ) # We run one test case for each combination of space vs. time optimization, # and indexing regions vs. only points. def testIndexRegionsQueryRegionsOptimizeTime(self): self._randomCaps( "cap", optimize_for_space=False, min_level=0, max_level=16, max_cells=20, ) def testIndexRegionsQueryPointsOptimizeTime(self): self._randomCaps( "point", optimize_for_space=False, min_level=0, max_level=16, max_cells=20, ) def testIndexRegionsQueryRegionsOptimizeTimeWithLevelMod(self): self._randomCaps( "cap", optimize_for_space=False, min_level=6, max_level=12, level_mod=3, ) def testIndexRegionsQueryRegionsOptimizeSpace(self): self._randomCaps( "cap", optimize_for_space=True, min_level=4, max_level=s2.S2CellId.kMaxLevel, max_cells=8, ) def testIndexPointsQueryRegionsOptimizeTime(self): self._randomCaps( "cap", optimize_for_space=False, min_level=0, max_level=s2.S2CellId.kMaxLevel, level_mod=2, max_cells=20, index_contains_points_only=True, ) def testIndexPointsQueryRegionsOptimizeSpace(self): self._randomCaps( "cap", optimize_for_space=True, index_contains_points_only=True, ) def testMaxLevelSetLoosely(self): # Test that correct terms are generated even when (max_level - min_level) # is not a multiple of level_mod. indexer1 = s2.S2RegionTermIndexer() indexer1.set_min_level(1) indexer1.set_level_mod(2) indexer1.set_max_level(19) indexer2 = s2.S2RegionTermIndexer() indexer2.set_min_level(1) indexer2.set_level_mod(2) indexer2.set_max_level(19) indexer2.set_max_level(20) point = s2.S2Testing.RandomPoint() self.assertEqual( indexer1.GetIndexTerms(point, ""), indexer2.GetIndexTerms(point, "") ) self.assertEqual( indexer1.GetQueryTerms(point, ""), indexer2.GetQueryTerms(point, "") ) cap = s2.S2Testing.GetRandomCap(0.0, 1.0) self.assertEqual( indexer1.GetIndexTerms(cap, ""), indexer2.GetIndexTerms(cap, "") ) self.assertEqual( indexer1.GetQueryTerms(cap, ""), indexer2.GetQueryTerms(cap, "") ) def testS2CellIdFromDebugString(self): cell = s2.S2CellId.FromDebugString("5/31200") self.assertTrue(cell.is_valid()) self.assertEqual("5/31200", cell.ToString()) def testCovererSetFixedLevel(self): coverer = s2.S2RegionCoverer() coverer.set_fixed_level(10) self.assertEqual(10, coverer.min_level()) self.assertEqual(10, coverer.max_level()) def testCovererTrueMaxLevel(self): coverer = s2.S2RegionCoverer() coverer.set_max_level(20) self.assertEqual(20, coverer.true_max_level()) def testIndexerMarkerCharacter(self): indexer = s2.S2RegionTermIndexer() default_marker = indexer.marker_character() self.assertIsInstance(default_marker, str) def testIndexerTrueMaxLevel(self): indexer = s2.S2RegionTermIndexer() indexer.set_max_level(20) self.assertEqual(20, indexer.true_max_level()) def testIndexerSetFixedLevel(self): indexer = s2.S2RegionTermIndexer() indexer.set_fixed_level(10) self.assertEqual(10, indexer.min_level()) self.assertEqual(10, indexer.max_level()) class S2PolygonTestCase(unittest.TestCase): def _makePolygon(self): cell = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) return s2.S2Polygon(cell) def testInitToUnionSame(self): cell1 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) polygon1 = s2.S2Polygon(cell1) cell2 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) polygon2 = s2.S2Polygon(cell2) polygon3 = s2.S2Polygon() polygon3.InitToUnion(polygon1, polygon2) self.assertEqual(1, polygon3.num_loops()) loop = polygon3.loop(0) self.assertEqual(4, loop.num_vertices()) def testInitToUnionDistinct(self): cell1 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) polygon1 = s2.S2Polygon(cell1) cell2 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(13.0, 4.0)).parent(8) ) polygon2 = s2.S2Polygon(cell2) polygon3 = s2.S2Polygon() polygon3.InitToUnion(polygon1, polygon2) self.assertEqual(2, polygon3.num_loops()) loop = polygon3.loop(0) self.assertEqual(4, loop.num_vertices()) loop = polygon3.loop(1) self.assertEqual(4, loop.num_vertices()) def testClone(self): poly = self._makePolygon() clone = poly.Clone() self.assertTrue(poly.Equals(clone)) def testCopy(self): poly = self._makePolygon() copy = s2.S2Polygon() copy.Copy(poly) self.assertTrue(poly.Equals(copy)) def testGetCentroid(self): poly = self._makePolygon() centroid = poly.GetCentroid() self.assertIsInstance(centroid, s2.S2Point) def testGetDistance(self): poly = self._makePolygon() p = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() d = poly.GetDistance(p) self.assertIsInstance(d, s2.S1Angle) def testProject(self): poly = self._makePolygon() p = s2.S2LatLng.FromDegrees(3.0, 4.0).ToPoint() projected = poly.Project(p) self.assertIsInstance(projected, s2.S2Point) def testIsEmpty(self): empty = s2.S2Polygon() self.assertTrue(empty.is_empty()) poly = self._makePolygon() self.assertFalse(poly.is_empty()) def testNumVertices(self): poly = self._makePolygon() self.assertEqual(4, poly.num_vertices()) def testIntersects(self): poly1 = self._makePolygon() poly2 = self._makePolygon() self.assertTrue(poly1.Intersects(poly2)) def testIsValid(self): poly = self._makePolygon() self.assertTrue(poly.IsValid()) class S2ChordAngleTest(unittest.TestCase): def testBasic(self): ca = s2.S1ChordAngle(s2.S1Angle.Degrees(100)) self.assertAlmostEqual(100, ca.degrees()) def testArithmetic(self): ca1 = s2.S1ChordAngle(s2.S1Angle.Degrees(10)) ca2 = s2.S1ChordAngle(s2.S1Angle.Degrees(20)) ca3 = ca1 + ca2 self.assertAlmostEqual(30, ca3.degrees()) ca4 = ca2 - ca1 self.assertAlmostEqual(10, ca4.degrees()) def testComparison(self): ca1 = s2.S1ChordAngle(s2.S1Angle.Degrees(10)) ca2 = s2.S1ChordAngle(s2.S1Angle.Degrees(20)) self.assertTrue(ca1 < ca2) self.assertTrue(ca2 > ca1) self.assertFalse(ca1 > ca2) self.assertFalse(ca2 < ca1) ca3 = s2.S1ChordAngle(s2.S1Angle.Degrees(10)) self.assertTrue(ca1 == ca3) self.assertFalse(ca1 == ca2) self.assertFalse(ca1 != ca3) self.assertTrue(ca1 != ca2) def testInfinity(self): ca1 = s2.S1ChordAngle(s2.S1Angle.Degrees(179)) ca2 = s2.S1ChordAngle.Infinity() self.assertTrue(ca2 > ca1) def testCopy(self): ca1 = s2.S1ChordAngle(s2.S1Angle.Degrees(100)) ca2 = s2.S1ChordAngle(ca1) self.assertAlmostEqual(100, ca2.degrees()) def testToAngle(self): ca = s2.S1ChordAngle(s2.S1Angle.Degrees(90.0)) a = ca.ToAngle() self.assertAlmostEqual(90.0, a.degrees()) class S2BufferOperationTest(unittest.TestCase): def setUp(self): self.opts = s2.S2BufferOperationOptions() self.result = s2.S2Polygon() self.layer = s2.S2PolygonLayer(self.result) def testDefaults(self): op = s2.S2BufferOperation(self.layer, self.opts) cell1 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) op.AddPolygon(s2.S2Polygon(cell1)) op.Build() self.assertEqual(1, self.result.num_loops()) loop = self.result.loop(0) self.assertEqual(4, loop.num_vertices()) def testRadius(self): self.opts.set_buffer_radius(s2.S1Angle.Degrees(0.001)) op = s2.S2BufferOperation(self.layer, self.opts) cell1 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) op.AddPolygon(s2.S2Polygon(cell1)) op.Build() self.assertEqual(1, self.result.num_loops()) loop = self.result.loop(0) self.assertEqual(20, loop.num_vertices()) def testRadiusAndError(self): self.opts.set_buffer_radius(s2.S1Angle.Degrees(0.001)) self.opts.set_error_fraction(0.1) op = s2.S2BufferOperation(self.layer, self.opts) cell1 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) op.AddPolygon(s2.S2Polygon(cell1)) op.Build() self.assertEqual(1, self.result.num_loops()) loop = self.result.loop(0) self.assertEqual(12, loop.num_vertices()) def testPoint(self): self.opts.set_buffer_radius(s2.S1Angle.Degrees(0.001)) op = s2.S2BufferOperation(self.layer, self.opts) op.AddPoint(s2.S2LatLng.FromDegrees(14.0, 15.0).ToPoint()) op.Build() self.assertEqual(1, self.result.num_loops()) loop = self.result.loop(0) self.assertEqual(16, loop.num_vertices()) class S2BooleanOperationTest(unittest.TestCase): def setUp(self): self.index1 = s2.MutableS2ShapeIndex() self.index2 = s2.MutableS2ShapeIndex() def operate(self): poly = s2.S2Polygon() layer = s2.S2PolygonLayer(poly) op = s2.S2BooleanOperation(s2.S2BooleanOperation.OpType_UNION, layer) op.Build(self.index1, self.index2) return poly def testUnionSame(self): cell1 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) self.index1.Add(s2.S2Polygon(cell1)) cell2 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) self.index2.Add(s2.S2Polygon(cell2)) result = self.operate() self.assertEqual(1, result.num_loops()) loop = result.loop(0) self.assertEqual(4, loop.num_vertices()) def testUnionDistinct(self): cell1 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(3.0, 4.0)).parent(8) ) self.index1.Add(s2.S2Polygon(cell1)) cell2 = s2.S2Cell( s2.S2CellId(s2.S2LatLng.FromDegrees(13.0, 4.0)).parent(8) ) self.index2.Add(s2.S2Polygon(cell2)) result = self.operate() self.assertEqual(2, result.num_loops()) loop = result.loop(0) self.assertEqual(4, loop.num_vertices()) loop = result.loop(1) self.assertEqual(4, loop.num_vertices()) # See https://github.com/google/s2geometry/issues/376 @unittest.skip("CHECK-fails in debug mode.") class S2BuilderTest(unittest.TestCase): def setUp(self): self.p1 = s2.S2LatLng.FromDegrees(10.0, 10.0).ToPoint() self.p2 = s2.S2LatLng.FromDegrees(10.0, 11.0).ToPoint() self.p3 = s2.S2LatLng.FromDegrees(11.0, 10.0).ToPoint() self.p4 = s2.S2LatLng.FromDegrees(11.0, 11.0).ToPoint() def testSquareDirected(self): opts = s2.S2PolygonLayerOptions() opts.set_edge_type(s2.S2Builder.EdgeType_DIRECTED) result = s2.S2Polygon() b = s2.S2Builder() b.StartLayer(s2.S2PolygonLayer(result, opts)) b.AddEdge(self.p1, self.p2) b.AddEdge(self.p2, self.p4) b.AddEdge(self.p4, self.p3) b.AddEdge(self.p3, self.p1) b.Build() self.assertEqual(1, result.num_loops()) loop = result.loop(0) self.assertEqual(4, loop.num_vertices()) def testSquareUndirected(self): opts = s2.S2PolygonLayerOptions() opts.set_edge_type(s2.S2Builder.EdgeType_UNDIRECTED) result = s2.S2Polygon() b = s2.S2Builder() b.StartLayer(s2.S2PolygonLayer(result, opts)) b.AddEdge(self.p1, self.p2) b.AddEdge(self.p1, self.p3) b.AddEdge(self.p2, self.p4) b.AddEdge(self.p3, self.p4) b.Build() self.assertEqual(1, result.num_loops()) loop = result.loop(0) self.assertEqual(4, loop.num_vertices()) def testException(self): opts = s2.S2PolygonLayerOptions() opts.set_edge_type(s2.S2Builder.EdgeType_DIRECTED) result = s2.S2Polygon() b = s2.S2Builder() b.StartLayer(s2.S2PolygonLayer(result, opts)) b.AddEdge(self.p1, self.p2) b.AddEdge(self.p1, self.p3) b.AddEdge(self.p2, self.p4) b.AddEdge(self.p3, self.p4) with self.assertRaises(ValueError): b.Build() if __name__ == "__main__": unittest.main() src/python/s2latlng_bindings.cc000066400000000000000000000206541524103652300171100ustar00rootroot00000000000000#include #include #include #include #include "absl/hash/hash.h" #include "absl/strings/str_cat.h" #include "s2/s1angle.h" #include "s2/s2latlng.h" #include "s2/s2point.h" namespace py = pybind11; namespace { void MaybeThrowNotValid(const S2LatLng& ll) { if (!ll.is_valid()) { throw py::value_error(absl::StrCat( "Invalid S2LatLng: (", ll.lat().degrees(), ", ", ll.lng().degrees(), ") (latitude must be in [-90, 90], longitude in [-180, 180])")); } } void MaybeThrowNotFinite(double m) { if (!std::isfinite(m)) { throw py::value_error(absl::StrCat("Scalar must be finite, got ", m)); } } } // namespace void bind_s2latlng(py::module& m) { py::class_(m, "S2LatLng", "Represents a point on the unit sphere as a latitude-longitude pair.\n\n" "All S2LatLng values are guaranteed to be valid: latitude in [-90, 90]\n" "and longitude in [-180, 180] degrees. Constructors and factory methods\n" "raise ValueError for out-of-range inputs. Arithmetic operators\n" "automatically normalize the result.\n\n" "Note: the native C++ implementation does not normalize arithmetic\n" "results and allows invalid states.\n\n" "See s2/s2latlng.h for comprehensive documentation.") // Constructors .def(py::init<>(), "Default constructor sets latitude and longitude to zero") .def(py::init([](S1Angle lat, S1Angle lng) { S2LatLng ll(lat, lng); MaybeThrowNotValid(ll); return ll; }), py::arg("lat"), py::arg("lng"), "Construct from latitude and longitude angles.\n\n" "Raises ValueError if latitude is not in [-90, 90] or\n" "longitude is not in [-180, 180] degrees.") .def(py::init([](const S2Point& p) { S2LatLng ll(p); MaybeThrowNotValid(ll); return ll; }), py::arg("point"), "Convert a direction vector to an S2LatLng.\n\n" "The vector does not need to be unit length.\n" "Raises ValueError if the point has non-finite coordinates.") // Factory methods .def_static("from_radians", [](double lat_radians, double lng_radians) { S2LatLng ll = S2LatLng::FromRadians(lat_radians, lng_radians); MaybeThrowNotValid(ll); return ll; }, py::arg("lat_radians"), py::arg("lng_radians"), "Construct from latitude and longitude in radians.\n\n" "Raises ValueError if out of range.") .def_static("normalized_from_radians", [](double lat_radians, double lng_radians) { MaybeThrowNotFinite(lat_radians); MaybeThrowNotFinite(lng_radians); return S2LatLng::FromRadians(lat_radians, lng_radians) .Normalized(); }, py::arg("lat_radians"), py::arg("lng_radians"), "Construct from latitude and longitude in radians, accepting any\n" "finite values. Latitude is clamped to [-Pi/2, Pi/2] and longitude\n" "is wrapped to [-Pi, Pi].\n\n" "Raises ValueError if either value is non-finite.") .def_static("from_degrees", [](double lat_degrees, double lng_degrees) { S2LatLng ll = S2LatLng::FromDegrees(lat_degrees, lng_degrees); MaybeThrowNotValid(ll); return ll; }, py::arg("lat_degrees"), py::arg("lng_degrees"), "Construct from latitude and longitude in degrees.\n\n" "Raises ValueError if out of range.") .def_static("from_e5", [](int32_t lat_e5, int32_t lng_e5) { S2LatLng ll = S2LatLng::FromE5(lat_e5, lng_e5); MaybeThrowNotValid(ll); return ll; }, py::arg("lat_e5"), py::arg("lng_e5"), "Construct from latitude and longitude in E5 format.\n\n" "Raises ValueError if out of range.") .def_static("from_e6", [](int32_t lat_e6, int32_t lng_e6) { S2LatLng ll = S2LatLng::FromE6(lat_e6, lng_e6); MaybeThrowNotValid(ll); return ll; }, py::arg("lat_e6"), py::arg("lng_e6"), "Construct from latitude and longitude in E6 format.\n\n" "Raises ValueError if out of range.") .def_static("from_e7", [](int32_t lat_e7, int32_t lng_e7) { S2LatLng ll = S2LatLng::FromE7(lat_e7, lng_e7); MaybeThrowNotValid(ll); return ll; }, py::arg("lat_e7"), py::arg("lng_e7"), "Construct from latitude and longitude in E7 format.\n\n" "Raises ValueError if out of range.") .def_static("latitude", &S2LatLng::Latitude, py::arg("point"), "Return the latitude of a direction vector") .def_static("longitude", &S2LatLng::Longitude, py::arg("point"), "Return the longitude of a direction vector") // Properties .def_property_readonly("lat", &S2LatLng::lat, "The latitude as an S1Angle") .def_property_readonly("lng", &S2LatLng::lng, "The longitude as an S1Angle") .def_property_readonly("coords", &S2LatLng::coords, "The (lat, lng) coordinates in radians as an R2Point") // Geometric operations .def("to_point", &S2LatLng::ToPoint, "Convert to the equivalent unit-length S2Point") .def("distance", &S2LatLng::GetDistance, py::arg("other"), "Return the surface distance to another S2LatLng.\n\n" "Uses the Haversine formula.") // Note: default value must match C++ signature in s2latlng.h .def("approx_equals", [](const S2LatLng& self, const S2LatLng& o, S1Angle max_error) { return self.ApproxEquals(o, max_error); }, py::arg("other"), py::arg("max_error") = S1Angle::Radians(1e-15), "Return true if approximately equal to 'other'.\n\n" "Note: this compares coordinates in rectangular lat/lng space.\n" "For points near the poles, consider using distance() instead.") // Operators .def(py::self == py::self, "Return true if exactly equal") .def(py::self != py::self, "Return true if not exactly equal") .def(py::self < py::self, "Compare by latitude first, then longitude") .def(py::self > py::self, "Compare by latitude first, then longitude") .def(py::self <= py::self, "Compare by latitude first, then longitude") .def(py::self >= py::self, "Compare by latitude first, then longitude") .def("__add__", [](const S2LatLng& a, const S2LatLng& b) { return (a + b).Normalized(); }, py::arg("other"), "Add two S2LatLngs.\n\n" "The result is automatically normalized.\n" "Note: the native C++ implementation does not normalize.") .def("__sub__", [](const S2LatLng& a, const S2LatLng& b) { return (a - b).Normalized(); }, py::arg("other"), "Subtract two S2LatLngs.\n\n" "The result is automatically normalized.\n" "Note: the native C++ implementation does not normalize.") .def("__mul__", [](const S2LatLng& a, double m) { MaybeThrowNotFinite(m); return (a * m).Normalized(); }, py::arg("m"), "Multiply by scalar.\n\n" "The result is automatically normalized.\n" "Note: the native C++ implementation does not normalize.") .def("__rmul__", [](const S2LatLng& a, double m) { MaybeThrowNotFinite(m); return (m * a).Normalized(); }, py::arg("m"), "Multiply by scalar (reversed operands).\n\n" "The result is automatically normalized.\n" "Note: the native C++ implementation does not normalize.") .def("__hash__", [](const S2LatLng& self) { return absl::HashOf(self); }) // String representation .def("to_string_in_degrees", &S2LatLng::ToStringInDegrees, "Return \"lat,lng\" in degrees, e.g. \"37.794000,-122.395000\"") .def("__repr__", [](const S2LatLng& ll) { std::ostringstream oss; oss << "S2LatLng(" << ll << ")"; return oss.str(); }) .def("__str__", [](const S2LatLng& ll) { std::ostringstream oss; oss << ll; return oss.str(); }); } src/python/s2latlng_test.py000066400000000000000000000276641524103652300163450ustar00rootroot00000000000000"""Tests for S2LatLng pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestS2LatLng(unittest.TestCase): """Test cases for S2LatLng bindings.""" # Constructors def test_default_constructor(self): ll = s2.S2LatLng() self.assertEqual(ll.lat.radians, 0.0) self.assertEqual(ll.lng.radians, 0.0) def test_constructor_from_angles(self): lat = s2.S1Angle.from_degrees(37.0) lng = s2.S1Angle.from_degrees(-122.0) ll = s2.S2LatLng(lat, lng) self.assertAlmostEqual(ll.lat.degrees, 37.0) self.assertAlmostEqual(ll.lng.degrees, -122.0) def test_constructor_from_angles_at_bounds(self): ll = s2.S2LatLng( s2.S1Angle.from_degrees(90.0), s2.S1Angle.from_degrees(180.0) ) self.assertAlmostEqual(ll.lat.degrees, 90.0) self.assertAlmostEqual(ll.lng.degrees, 180.0) def test_constructor_from_angles_invalid_lat_raises(self): with self.assertRaises(ValueError) as cm: s2.S2LatLng( s2.S1Angle.from_degrees(91.0), s2.S1Angle.from_degrees(0.0) ) self.assertEqual( str(cm.exception), "Invalid S2LatLng: (91, 0) " "(latitude must be in [-90, 90], longitude in [-180, 180])", ) def test_constructor_from_angles_invalid_lng_raises(self): with self.assertRaises(ValueError): s2.S2LatLng( s2.S1Angle.from_degrees(0.0), s2.S1Angle.from_degrees(181.0) ) def test_constructor_from_point(self): p = s2.S2Point(1.0, 0.0, 0.0) ll = s2.S2LatLng(p) self.assertAlmostEqual(ll.lat.degrees, 0.0) self.assertAlmostEqual(ll.lng.degrees, 0.0) def test_constructor_from_nan_point_raises(self): p = s2.S2Point(float("nan"), 0.0, 0.0) with self.assertRaises(ValueError): s2.S2LatLng(p) def test_constructor_from_point_north_pole(self): p = s2.S2Point(0.0, 0.0, 1.0) ll = s2.S2LatLng(p) self.assertAlmostEqual(ll.lat.degrees, 90.0) # Factory methods def test_from_radians(self): ll = s2.S2LatLng.from_radians(math.pi / 4, -math.pi / 2) self.assertAlmostEqual(ll.lat.degrees, 45.0) self.assertAlmostEqual(ll.lng.degrees, -90.0) def test_from_radians_invalid_raises(self): with self.assertRaises(ValueError): s2.S2LatLng.from_radians(2.0, 0.0) # lat > pi/2 def test_normalized_from_radians_clamps_latitude(self): ll = s2.S2LatLng.normalized_from_radians(2.0, 0.0) # lat > pi/2 self.assertAlmostEqual(ll.lat.radians, math.pi / 2) self.assertAlmostEqual(ll.lng.radians, 0.0) def test_normalized_from_radians_wraps_longitude(self): # 3*pi/2 wraps to -pi/2 ll = s2.S2LatLng.normalized_from_radians(0.0, 3 * math.pi / 2) self.assertAlmostEqual(ll.lat.radians, 0.0) self.assertAlmostEqual(ll.lng.radians, -math.pi / 2) def test_normalized_from_radians_in_range_is_unchanged(self): ll = s2.S2LatLng.normalized_from_radians(0.5, -1.0) self.assertAlmostEqual(ll.lat.radians, 0.5) self.assertAlmostEqual(ll.lng.radians, -1.0) def test_normalized_from_radians_non_finite_raises(self): with self.assertRaises(ValueError): s2.S2LatLng.normalized_from_radians(float("nan"), 0.0) with self.assertRaises(ValueError): s2.S2LatLng.normalized_from_radians(0.0, float("inf")) def test_from_degrees(self): ll = s2.S2LatLng.from_degrees(45.0, -90.0) self.assertAlmostEqual(ll.lat.degrees, 45.0) self.assertAlmostEqual(ll.lng.degrees, -90.0) def test_from_degrees_invalid_raises(self): with self.assertRaises(ValueError): s2.S2LatLng.from_degrees(91.0, 0.0) with self.assertRaises(ValueError): s2.S2LatLng.from_degrees(0.0, 181.0) def test_from_e5(self): ll = s2.S2LatLng.from_e5(4500000, -9000000) self.assertAlmostEqual(ll.lat.degrees, 45.0) self.assertAlmostEqual(ll.lng.degrees, -90.0) def test_from_e5_invalid_raises(self): with self.assertRaises(ValueError): s2.S2LatLng.from_e5(9100000, 0) # 91 degrees def test_from_e6(self): ll = s2.S2LatLng.from_e6(45000000, -90000000) self.assertAlmostEqual(ll.lat.degrees, 45.0) self.assertAlmostEqual(ll.lng.degrees, -90.0) def test_from_e6_invalid_raises(self): with self.assertRaises(ValueError): s2.S2LatLng.from_e6(91000000, 0) # 91 degrees def test_from_e7(self): ll = s2.S2LatLng.from_e7(450000000, -900000000) self.assertAlmostEqual(ll.lat.degrees, 45.0) self.assertAlmostEqual(ll.lng.degrees, -90.0) def test_from_e7_invalid_raises(self): with self.assertRaises(ValueError): s2.S2LatLng.from_e7(910000000, 0) # 91 degrees def test_latitude_static(self): p = s2.S2Point(0.0, 0.0, 1.0) lat = s2.S2LatLng.latitude(p) self.assertAlmostEqual(lat.degrees, 90.0) def test_longitude_static(self): p = s2.S2Point(0.0, 1.0, 0.0) lng = s2.S2LatLng.longitude(p) self.assertAlmostEqual(lng.degrees, 90.0) # Properties def test_lat_lng_are_s1angles(self): ll = s2.S2LatLng.from_degrees(37.0, -122.0) self.assertIsInstance(ll.lat, s2.S1Angle) self.assertIsInstance(ll.lng, s2.S1Angle) def test_lat_lng_readonly(self): ll = s2.S2LatLng.from_degrees(37.0, -122.0) with self.assertRaises(AttributeError): ll.lat = s2.S1Angle.from_degrees(0.0) with self.assertRaises(AttributeError): ll.lng = s2.S1Angle.from_degrees(0.0) def test_coords(self): ll = s2.S2LatLng.from_radians(0.5, -1.0) coords = ll.coords self.assertIsInstance(coords, s2.R2Point) self.assertAlmostEqual(coords.x, 0.5) self.assertAlmostEqual(coords.y, -1.0) # Geometric operations def test_to_point(self): ll = s2.S2LatLng.from_degrees(0.0, 0.0) p = ll.to_point() self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 0.0) self.assertAlmostEqual(p.z, 0.0) def test_to_point_north_pole(self): ll = s2.S2LatLng.from_degrees(90.0, 0.0) p = ll.to_point() self.assertAlmostEqual(p.x, 0.0, places=15) self.assertAlmostEqual(p.y, 0.0, places=15) self.assertAlmostEqual(p.z, 1.0) def test_to_point_roundtrip(self): ll = s2.S2LatLng.from_degrees(37.7749, -122.4194) p = ll.to_point() ll2 = s2.S2LatLng(p) self.assertAlmostEqual(ll.lat.radians, ll2.lat.radians) self.assertAlmostEqual(ll.lng.radians, ll2.lng.radians) def test_distance(self): # Distance between two points on the equator, 90 degrees apart. a = s2.S2LatLng.from_degrees(0.0, 0.0) b = s2.S2LatLng.from_degrees(0.0, 90.0) self.assertAlmostEqual(a.distance(b).degrees, 90.0) def test_distance_same_point(self): ll = s2.S2LatLng.from_degrees(37.0, -122.0) self.assertAlmostEqual(ll.distance(ll).radians, 0.0) def test_to_string_in_degrees(self): ll = s2.S2LatLng.from_degrees(37.794, -122.395) self.assertEqual(ll.to_string_in_degrees(), "37.794000,-122.395000") def test_approx_equals(self): a = s2.S2LatLng.from_degrees(37.0, -122.0) b = s2.S2LatLng.from_degrees(37.0, -122.0) self.assertTrue(a.approx_equals(b)) def test_approx_equals_within_tolerance(self): a = s2.S2LatLng.from_degrees(37.0, -122.0) b = s2.S2LatLng.from_degrees(37.0 + 1e-16, -122.0) self.assertTrue(a.approx_equals(b)) def test_approx_equals_outside_default_tolerance(self): a = s2.S2LatLng.from_degrees(37.0, -122.0) b = s2.S2LatLng.from_degrees(37.1, -122.0) self.assertFalse(a.approx_equals(b)) def test_approx_equals_custom_tolerance(self): a = s2.S2LatLng.from_degrees(37.0, -122.0) b = s2.S2LatLng.from_degrees(37.1, -122.0) self.assertTrue(a.approx_equals(b, s2.S1Angle.from_degrees(0.2))) self.assertFalse(a.approx_equals(b, s2.S1Angle.from_degrees(0.05))) # Operators def test_equality(self): a = s2.S2LatLng.from_degrees(37.0, -122.0) b = s2.S2LatLng.from_degrees(37.0, -122.0) c = s2.S2LatLng.from_degrees(38.0, -122.0) self.assertTrue(a == b) self.assertTrue(a != c) self.assertFalse(a != b) self.assertFalse(a == c) def test_comparison(self): a = s2.S2LatLng.from_degrees(10.0, 20.0) b = s2.S2LatLng.from_degrees(20.0, 10.0) self.assertTrue(a < b) self.assertTrue(b > a) self.assertTrue(a <= b) self.assertTrue(b >= a) self.assertTrue(a <= a) self.assertTrue(a >= a) def test_addition(self): a = s2.S2LatLng.from_degrees(10.0, 20.0) b = s2.S2LatLng.from_degrees(30.0, 40.0) result = a + b self.assertAlmostEqual(result.lat.degrees, 40.0) self.assertAlmostEqual(result.lng.degrees, 60.0) def test_addition_normalizes(self): # 80 + 20 = 100 degrees latitude, should clamp to 90. a = s2.S2LatLng.from_degrees(80.0, 170.0) b = s2.S2LatLng.from_degrees(20.0, 30.0) result = a + b self.assertAlmostEqual(result.lat.degrees, 90.0) # 170 + 30 = 200 degrees longitude, should wrap to -160. self.assertAlmostEqual(result.lng.degrees, -160.0) def test_subtraction(self): a = s2.S2LatLng.from_degrees(30.0, 40.0) b = s2.S2LatLng.from_degrees(10.0, 20.0) result = a - b self.assertAlmostEqual(result.lat.degrees, 20.0) self.assertAlmostEqual(result.lng.degrees, 20.0) def test_subtraction_normalizes(self): # -80 - 20 = -100 degrees latitude, should clamp to -90. a = s2.S2LatLng.from_degrees(-80.0, -170.0) b = s2.S2LatLng.from_degrees(20.0, 30.0) result = a - b self.assertAlmostEqual(result.lat.degrees, -90.0) # -170 - 30 = -200 degrees longitude, should wrap to 160. self.assertAlmostEqual(result.lng.degrees, 160.0) def test_scalar_multiplication(self): ll = s2.S2LatLng.from_degrees(10.0, 20.0) result1 = ll * 2.0 result2 = 2.0 * ll for result in [result1, result2]: self.assertAlmostEqual(result.lat.degrees, 20.0) self.assertAlmostEqual(result.lng.degrees, 40.0) def test_scalar_multiplication_inf_raises(self): ll = s2.S2LatLng.from_degrees(10.0, 20.0) with self.assertRaises(ValueError): ll * float("inf") def test_scalar_multiplication_nan_raises(self): ll = s2.S2LatLng.from_degrees(10.0, 20.0) with self.assertRaises(ValueError): ll * float("nan") def test_rmul_inf_raises(self): ll = s2.S2LatLng.from_degrees(10.0, 20.0) with self.assertRaises(ValueError): float("inf") * ll def test_scalar_multiplication_normalizes(self): ll = s2.S2LatLng.from_degrees(60.0, 120.0) result = ll * 2.0 # 120 degrees latitude -> clamped to 90 self.assertAlmostEqual(result.lat.degrees, 90.0) # 240 degrees longitude -> wrapped to -120 self.assertAlmostEqual(result.lng.degrees, -120.0) def test_hash(self): a = s2.S2LatLng.from_degrees(45.0, 90.0) b = s2.S2LatLng.from_degrees(45.0, 90.0) self.assertEqual(hash(a), hash(b)) self.assertEqual(len({a, b}), 1) # String representation def test_repr(self): ll = s2.S2LatLng.from_degrees(45.0, -90.0) self.assertEqual(repr(ll), "S2LatLng([45.0000000, -90.0000000])") def test_str(self): ll = s2.S2LatLng.from_degrees(45.0, -90.0) self.assertEqual(str(ll), "[45.0000000, -90.0000000]") def test_repr_zero(self): ll = s2.S2LatLng() self.assertEqual(repr(ll), "S2LatLng([0.0000000, 0.0000000])") if __name__ == "__main__": unittest.main() src/python/s2point_bindings.cc000066400000000000000000000067501524103652300167610ustar00rootroot00000000000000#include #include #include #include "absl/hash/hash.h" #include "s2/s2point.h" namespace py = pybind11; void bind_s2point(py::module& m) { py::class_(m, "S2Point") // Constructors .def(py::init<>(), "Default constructor creates a zero vector") .def(py::init(), py::arg("x"), py::arg("y"), py::arg("z"), "Constructor that accepts x, y, z coordinates") .def(py::init([](py::tuple t) { if (t.size() != 3) { throw py::value_error("Tuple must have exactly 3 elements"); } return S2Point(t[0].cast(), t[1].cast(), t[2].cast()); }), py::arg("coords"), "Constructor that accepts a tuple of (x, y, z) coordinates") // Properties .def_property_readonly("x", py::overload_cast<>(&S2Point::x, py::const_), "The x coordinate") .def_property_readonly("y", py::overload_cast<>(&S2Point::y, py::const_), "The y coordinate") .def_property_readonly("z", py::overload_cast<>(&S2Point::z, py::const_), "The z coordinate") .def("data", [](const S2Point& self) { return py::make_tuple(self.x(), self.y(), self.z()); }, "Return coordinates as a tuple (x, y, z)") // Vector operations .def("norm", &S2Point::Norm, "Return the Euclidean norm (length)") .def("norm2", &S2Point::Norm2, "Return the squared Euclidean norm (dot product with itself)") .def("normalize", &S2Point::Normalize, "Return a normalized copy of the vector.\n\n" "Returns a unit vector if the norm is nonzero.") .def("dot_prod", [](const S2Point& self, const S2Point& other) { return self.DotProd(other); }, py::arg("other"), "Return the dot product with another point") .def("cross_prod", [](const S2Point& self, const S2Point& other) -> S2Point { return self.CrossProd(other); }, py::arg("other"), "Return the cross product with another point") .def("angle", [](const S2Point& self, const S2Point& other) { return self.Angle(other); }, py::arg("other"), "Return the angle between this and another point (radians).\n\n" "The result is in the range [0, pi]. If either vector is zero-length,\n" "or nearly zero-length, the result will be zero.") // Operators .def(py::self + py::self, "Add two points (vector addition)") .def(py::self - py::self, "Subtract two points (vector subtraction)") .def(py::self * double(), "Multiply by scalar") .def("__rmul__", [](const S2Point& self, double v) -> S2Point { return self * v; }, "Multiply by scalar (reversed operands)") .def(py::self / double(), "Divide by scalar") .def(-py::self, "Negate point") .def(py::self == py::self, "Return true if points are exactly equal") .def(py::self != py::self, "Return true if points are not exactly equal") .def("__hash__", [](const S2Point& self) { return absl::HashOf(self); }) // String representation // __repr__ prefixes class name, __str__ delegates to C++ operator<< .def("__repr__", [](const S2Point& p) { std::ostringstream oss; oss << "S2Point(" << p << ")"; return oss.str(); }) .def("__str__", [](const S2Point& p) { std::ostringstream oss; oss << p; return oss.str(); }); } src/python/s2point_test.py000066400000000000000000000113451524103652300162020ustar00rootroot00000000000000"""Tests for S2Point pybind11 bindings.""" import math import unittest import s2geometry_pybind as s2 class TestS2Point(unittest.TestCase): """Test cases for S2Point bindings.""" # Constructors def test_default_constructor(self): p = s2.S2Point() self.assertEqual(p.x, 0.0) self.assertEqual(p.y, 0.0) self.assertEqual(p.z, 0.0) def test_constructor_with_coordinates(self): p = s2.S2Point(1.0, 2.0, 3.0) self.assertEqual(p.x, 1.0) self.assertEqual(p.y, 2.0) self.assertEqual(p.z, 3.0) def test_unnormalized_point(self): # Unnormalized points are accepted by the constructor. p = s2.S2Point(3.0, 4.0, 0.0) self.assertAlmostEqual(p.x, 3.0) self.assertAlmostEqual(p.y, 4.0) self.assertAlmostEqual(p.z, 0.0) self.assertAlmostEqual(p.norm(), 5.0) # Not on unit sphere # User may call normalize() to obtain a unit vector. normalized = p.normalize() self.assertAlmostEqual(normalized.norm(), 1.0) def test_constructor_from_tuple(self): p = s2.S2Point((1.0, 2.0, 3.0)) self.assertEqual(p.x, 1.0) self.assertEqual(p.y, 2.0) self.assertEqual(p.z, 3.0) def test_constructor_from_tuple_wrong_length(self): with self.assertRaises(ValueError): s2.S2Point((1.0, 2.0)) with self.assertRaises(ValueError): s2.S2Point((1.0, 2.0, 3.0, 4.0)) # Properties def test_data(self): p = s2.S2Point(1.0, 2.0, 3.0) coords = p.data() self.assertEqual(coords, (1.0, 2.0, 3.0)) # Vector operations def test_norm(self): p = s2.S2Point(3.0, 4.0, 0.0) self.assertAlmostEqual(p.norm(), 5.0) self.assertAlmostEqual(p.norm2(), 25.0) def test_normalize(self): p = s2.S2Point(3.0, 4.0, 0.0) normalized = p.normalize() self.assertAlmostEqual(normalized.norm(), 1.0) self.assertAlmostEqual(normalized.x, 0.6) self.assertAlmostEqual(normalized.y, 0.8) self.assertAlmostEqual(normalized.z, 0.0) def test_dot_product(self): p1 = s2.S2Point(1.0, 0.0, 0.0) p2 = s2.S2Point(0.0, 1.0, 0.0) p3 = s2.S2Point(1.0, 0.0, 0.0) self.assertAlmostEqual(p1.dot_prod(p2), 0.0) self.assertAlmostEqual(p1.dot_prod(p3), 1.0) def test_cross_product(self): p1 = s2.S2Point(1.0, 0.0, 0.0) p2 = s2.S2Point(0.0, 1.0, 0.0) cross = p1.cross_prod(p2) self.assertAlmostEqual(cross.x, 0.0) self.assertAlmostEqual(cross.y, 0.0) self.assertAlmostEqual(cross.z, 1.0) def test_angle(self): p1 = s2.S2Point(1.0, 0.0, 0.0) p2 = s2.S2Point(0.0, 1.0, 0.0) self.assertAlmostEqual(p1.angle(p2), math.pi / 2) # Operators def test_addition(self): p1 = s2.S2Point(1.0, 2.0, 3.0) p2 = s2.S2Point(4.0, 5.0, 6.0) result = p1 + p2 self.assertAlmostEqual(result.x, 5.0) self.assertAlmostEqual(result.y, 7.0) self.assertAlmostEqual(result.z, 9.0) def test_subtraction(self): p1 = s2.S2Point(4.0, 5.0, 6.0) p2 = s2.S2Point(1.0, 2.0, 3.0) result = p1 - p2 self.assertAlmostEqual(result.x, 3.0) self.assertAlmostEqual(result.y, 3.0) self.assertAlmostEqual(result.z, 3.0) def test_scalar_multiplication(self): p = s2.S2Point(1.0, 2.0, 3.0) result1 = p * 2.0 result2 = 2.0 * p for result in [result1, result2]: self.assertAlmostEqual(result.x, 2.0) self.assertAlmostEqual(result.y, 4.0) self.assertAlmostEqual(result.z, 6.0) def test_scalar_division(self): p = s2.S2Point(2.0, 4.0, 6.0) result = p / 2.0 self.assertAlmostEqual(result.x, 1.0) self.assertAlmostEqual(result.y, 2.0) self.assertAlmostEqual(result.z, 3.0) def test_negation(self): p = s2.S2Point(1.0, -2.0, 3.0) result = -p self.assertAlmostEqual(result.x, -1.0) self.assertAlmostEqual(result.y, 2.0) self.assertAlmostEqual(result.z, -3.0) def test_equality(self): p1 = s2.S2Point(1.0, 2.0, 3.0) p2 = s2.S2Point(1.0, 2.0, 3.0) p3 = s2.S2Point(1.0, 2.0, 4.0) self.assertEqual(p1, p2) self.assertNotEqual(p1, p3) def test_hash(self): a = s2.S2Point(1.0, 0.0, 0.0) b = s2.S2Point(1.0, 0.0, 0.0) self.assertEqual(hash(a), hash(b)) self.assertEqual(len({a, b}), 1) # String representation def test_string_representation(self): p = s2.S2Point(1.0, 2.0, 3.0) self.assertEqual(repr(p), "S2Point([1, 2, 3])") self.assertEqual(str(p), "[1, 2, 3]") if __name__ == "__main__": unittest.main() src/s2/000077500000000000000000000000001524103652300121725ustar00rootroot00000000000000src/s2/_fp_contract_off.h000066400000000000000000000044351524103652300156440ustar00rootroot00000000000000// Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2__FP_CONTRACT_OFF_H_ #define S2__FP_CONTRACT_OFF_H_ // Turn off the fused multiply-add optimization ("fp-contract"). With // fp-contract on, any expression of the form "a * b + c" has two possible // results, and the compiler is free to choose either of them. Effectively // this makes it impossible to write deterministic functions that involve // floating-point math. // // S2 requires deterministic arithmetic for correctness. We need to turn off // fp-contract for the entire compilation unit, because S2 has public inline // functions, and the optimization is controlled by the setting in effect when // inline functions are instantiated (not when they are defined). // // Note that there is a standard C pragma to turn off FP contraction: // #pragma STDC FP_CONTRACT OFF // but it is not implemented in GCC because the standard pragma allows control // at the level of compound statements rather than entire functions. // // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=20785 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37845 // // This file may be included with other files in any order, as long as it // appears before the first non-inline function definition. It is // named with an underscore so that it is included first among the S2 headers. #if defined(__GNUC__) && !defined(__clang__) // GCC defines its own pragma that operates at the function level rather than // the statement level. #pragma GCC optimize("fp-contract=off") #else // Assume all other compilers support or ignore the standard pragma. // Avoid gcc `-Wunknown-pragmas` warnings by not using this for gcc. #pragma STDC FP_CONTRACT OFF #endif #endif // S2__FP_CONTRACT_OFF_H_ src/s2/base/000077500000000000000000000000001524103652300131045ustar00rootroot00000000000000src/s2/base/BUILD.bazel000066400000000000000000000013361524103652300147650ustar00rootroot00000000000000load("@rules_cc//cc:defs.bzl", "cc_library") package(default_visibility = ["//:__subpackages__"]) cc_library( name = "casts", hdrs = ["casts.h"], deps = [ "@abseil-cpp//absl/base:config", ], ) cc_library( name = "log_severity", hdrs = ["log_severity.h"], deps = [ "@abseil-cpp//absl/base:log_severity", ], ) cc_library( name = "malloc_extension", srcs = ["malloc_extension.cc"], hdrs = ["malloc_extension.h"], deps = [ "@abseil-cpp//absl/base:core_headers", ], ) cc_library( name = "spinlock", hdrs = ["spinlock.h"], deps = [ "@abseil-cpp//absl/base:core_headers", ], ) cc_library( name = "timer", hdrs = ["timer.h"], ) src/s2/base/casts.h000066400000000000000000000041331524103652300143730ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_BASE_CASTS_H_ #define S2_BASE_CASTS_H_ #include #include #include "absl/base/config.h" template inline To down_cast(From* f) { static_assert((std::is_base_of>::value), "target type not derived from source type"); // We depend on abseil-cpp internals, but if this doesn't get defined, // we will just not have the assert. #if ABSL_INTERNAL_HAS_RTTI assert(f == nullptr || dynamic_cast(f) != nullptr); #endif return static_cast(f); } // Overload of down_cast for references. Use like this: down_cast(foo). // The code is slightly convoluted because we're still using the pointer // form of dynamic cast. (The reference form throws an exception if it // fails.) // // There's no need for a special const overload either for the pointer // or the reference form. If you call down_cast with a const T&, the // compiler will just bind From to const T. template inline To down_cast(From& f) { static_assert(std::is_lvalue_reference::value, "target type not a reference"); static_assert((std::is_base_of>::value), "target type not derived from source type"); // We skip the assert and hence the dynamic_cast if RTTI is disabled. #if ABSL_INTERNAL_HAS_RTTI assert(dynamic_cast*>(&f) != nullptr); #endif return static_cast(f); } #endif // S2_BASE_CASTS_H_ src/s2/base/log_severity.h000066400000000000000000000015201524103652300157660ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_BASE_LOG_SEVERITY_H_ #define S2_BASE_LOG_SEVERITY_H_ #include "absl/base/log_severity.h" #ifdef NDEBUG constexpr bool S2_DEBUG_MODE = false; #else constexpr bool S2_DEBUG_MODE = true; #endif #endif // S2_BASE_LOG_SEVERITY_H_ src/s2/base/malloc_extension.cc000066400000000000000000000017711524103652300167640ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "s2/base/malloc_extension.h" #include #include #include "absl/base/attributes.h" ABSL_ATTRIBUTE_WEAK ABSL_ATTRIBUTE_NOINLINE size_t nallocx(size_t size, int) noexcept { return size; } ABSL_ATTRIBUTE_WEAK ABSL_ATTRIBUTE_NOINLINE __sized_ptr_t __size_returning_new(size_t size) { return {::operator new(size), size}; } src/s2/base/malloc_extension.h000066400000000000000000000032471524103652300166260ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_BASE_MALLOC_EXTENSION_H_ #define S2_BASE_MALLOC_EXTENSION_H_ // Some s2geometry functions use TCMalloc extensions. Here, we provide // default implementations so s2geometry can be used with other allocators. // // See // https://github.com/google/tcmalloc/blob/master/tcmalloc/malloc_extension.h #include extern "C" { // `nallocx` performs the same size computation that `malloc` would perform. // The default weak implementation just returns the `size` argument. // See https://jemalloc.net/jemalloc.3.html size_t nallocx(size_t size, int flags) noexcept; // `__size_returning_new` returns a pointer to the allocated memory along // with the (possibly rounded up) actual allocation size used. The default // weak implementation just returns the requested size. // This is a TCMalloc prototype of P0901R5 "Size feedback in operator new". // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0901r5.html struct __sized_ptr_t { void* p; size_t n; }; __sized_ptr_t __size_returning_new(size_t size); } // extern "C" #endif // S2_BASE_MALLOC_EXTENSION_H_ src/s2/base/spinlock.h000066400000000000000000000033611524103652300151020ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_BASE_SPINLOCK_H_ #define S2_BASE_SPINLOCK_H_ #include #include "absl/base/thread_annotations.h" class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { public: SpinLock() = default; ~SpinLock() = default; SpinLock(SpinLock const&) = delete; SpinLock& operator=(SpinLock const&) = delete; inline void lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { while (locked_.exchange(true, std::memory_order_acquire)) { // Spin. continue; } } inline void unlock() ABSL_UNLOCK_FUNCTION() { locked_.store(false, std::memory_order_release); } [[nodiscard]] inline bool IsHeld() const { return locked_.load(std::memory_order_relaxed); } private: std::atomic_bool locked_{false}; }; class [[nodiscard]] ABSL_SCOPED_LOCKABLE SpinLockHolder { public: inline explicit SpinLockHolder(SpinLock& l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l) : lock_(l) { l.lock(); } inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_.unlock(); } SpinLockHolder(const SpinLockHolder&) = delete; SpinLockHolder& operator=(const SpinLockHolder&) = delete; private: SpinLock& lock_; }; #endif // S2_BASE_SPINLOCK_H_ src/s2/base/timer.h000066400000000000000000000022571524103652300144030ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_BASE_TIMER_H_ #define S2_BASE_TIMER_H_ #include #include class CycleTimer { public: CycleTimer() = default; void Start() { start_ = Now(); } int64_t GetInMs() const { using msec = std::chrono::milliseconds; return std::chrono::duration_cast(GetDuration()).count(); } private: using Clock = std::chrono::high_resolution_clock; static Clock::time_point Now() { return Clock::now(); } Clock::duration GetDuration() const { return Now() - start_; } Clock::time_point start_; }; #endif // S2_BASE_TIMER_H_ src/s2/encoded_s2cell_id_vector.cc000066400000000000000000000157451524103652300174200ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_s2cell_id_vector.h" #include #include #include #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/encoded_uint_vector.h" #include "s2/s2cell_id.h" using absl::Span; using std::max; using std::min; using std::vector; namespace s2coding { void EncodeBaseShift(Encoder* encoder, int shift, uint64_t base, int base_len) { encoder->Ensure(2 + base_len); // "shift" and "base_len" are encoded in 1 or 2 bytes. // // "shift_code" is 5 bits: // values <= 28 represent even shifts in the range 0..56 // values 29, 30 represent odd shifts 1 and 3 // value 31 indicates that the shift is odd and encoded in the next byte int shift_code = shift >> 1; if (shift & 1) { shift_code = min(31, shift_code + 29); } encoder->put8((shift_code << 3) | base_len); if (shift_code == 31) { encoder->put8(shift >> 1); // Shift is always odd, so 3 bits unused. } // Encode the "base_len" most-significant bytes of "base". uint64_t base_bytes = base >> (64 - 8 * max(1, base_len)); EncodeUintWithLength(base_bytes, base_len, encoder); } void EncodeS2CellIdVector(Span v, Encoder* encoder) { // v[i] is encoded as (base + (deltas[i] << shift)). // // "base" consists of 0-7 bytes, and is always shifted so that its bytes are // the most-significant bytes of a uint64_t. // // "deltas" is an EncodedUintVector, which means that all deltas // have a fixed-length encoding determined by the largest delta. // // "shift" is in the range 0..56. The shift value is odd only if all // S2CellIds are at the same level, in which case the bit at position // (shift - 1) is automatically set to 1 in "base". // // "base" (3 bits) and "shift" (6 bits) are encoded in either one or two // bytes as follows: // // - if (shift <= 4 or shift is even), then 1 byte // - otherwise 2 bytes // // Note that (shift == 1) means that all S2CellIds are leaf cells, and // (shift == 2) means that all S2CellIds are at level 29. // // The full encoded format is as follows: // // Byte 0, bits 0-2: base length (0-7 bytes) // Byte 0, bits 3-7: encoded shift (see below) // Byte 1: extended shift code (only needed for odd shifts >= 5) // Followed by 0-7 bytes of "base" // Followed by an EncodedUintVector of deltas. uint64_t v_or = 0, v_and = ~0ULL, v_min = ~0ULL, v_max = 0; for (auto cellid : v) { v_or |= cellid.id(); v_and &= cellid.id(); v_min = min(v_min, cellid.id()); v_max = max(v_max, cellid.id()); } // These variables represent the values that will used during encoding. uint64_t e_base = 0; // Base value. int e_base_len = 0; // Number of bytes to represent "base". int e_shift = 0; // Delta shift. int e_max_delta_msb = 0; // Bit position of the MSB of the largest delta. if (v_or > 0) { // We only allow even shifts, unless all values have the same low bit (in // which case the shift is odd and the preceding bit is implicitly on). // There is no point in allowing shifts > 56 since deltas are encoded in // at least 1 byte each. e_shift = min(56, absl::countr_zero(v_or) & ~1); if (v_and & (1ULL << e_shift)) ++e_shift; // All S2CellIds same level. // "base" consists of the "base_len" most significant bytes of the minimum // S2CellId. We consider all possible values of "base_len" (0..7) and // choose the one that minimizes the total encoding size. uint64_t e_bytes = ~0ULL; // Best encoding size so far. for (int len = 0; len < 8; ++len) { // "t_base" is the base value being tested (first "len" bytes of v_min). // "t_max_delta_msb" is the most-significant bit position (i.e. bit-width // minus one) of the largest delta (or zero if there are no deltas, i.e. // if v.size() == 0). "t_bytes" is the total size of the variable // portion of the encoding. uint64_t t_base = v_min & ~(~0ULL >> (8 * len)); int t_max_delta_msb = max( 0, static_cast(absl::bit_width((v_max - t_base) >> e_shift)) - 1); uint64_t t_bytes = len + v.size() * ((t_max_delta_msb >> 3) + 1); if (t_bytes < e_bytes) { e_base = t_base; e_base_len = len; e_max_delta_msb = t_max_delta_msb; e_bytes = t_bytes; } } // It takes one extra byte to encode odd shifts (i.e., the case where all // S2CellIds are at the same level), so check whether we can get the same // encoding size per delta using an even shift. if ((e_shift & 1) && (e_max_delta_msb & 7) != 7) --e_shift; } ABSL_DCHECK_LE(e_base_len, 7); ABSL_DCHECK_LE(e_shift, 56); EncodeBaseShift(encoder, e_shift, e_base, e_base_len); // Finally, encode the vector of deltas. vector deltas; deltas.reserve(v.size()); for (auto cellid : v) { deltas.push_back((cellid.id() - e_base) >> e_shift); } EncodeUintVector(deltas, encoder); } bool EncodedS2CellIdVector::Init(Decoder* decoder) { // All encodings have at least 2 bytes (one for our header and one for the // EncodedUintVector header), so this is safe. if (decoder->avail() < 2) return false; // Invert the encoding of (shift_code, base_len) described above. int code_plus_len = decoder->get8(); int shift_code = code_plus_len >> 3; if (shift_code == 31) { shift_code = 29 + decoder->get8(); if (shift_code > 56) return false; // Valid range 0..56 } // Decode the "base_len" most-significant bytes of "base". base_len_ = code_plus_len & 7; if (!DecodeUintWithLength(base_len_, decoder, &base_)) return false; base_ <<= 64 - 8 * max(1, (int)base_len_); // Invert the encoding of "shift_code" described above. if (shift_code >= 29) { shift_ = 2 * (shift_code - 29) + 1; base_ |= 1ULL << (shift_ - 1); } else { shift_ = 2 * shift_code; } return deltas_.Init(decoder); } vector EncodedS2CellIdVector::Decode() const { vector result(size()); for (size_t i = 0; i < size(); ++i) { result[i] = (*this)[i]; } return result; } void EncodedS2CellIdVector::Encode(Encoder* encoder) const { // Re-encode the base and shift values. EncodeBaseShift(encoder, shift_, base_, base_len_); // And copy the encoded deltas. deltas_.Encode(encoder); } } // namespace s2coding src/s2/encoded_s2cell_id_vector.h000066400000000000000000000103621524103652300172500ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_ENCODED_S2CELL_ID_VECTOR_H_ #define S2_ENCODED_S2CELL_ID_VECTOR_H_ #include #include #include #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/encoded_uint_vector.h" #include "s2/s2cell_id.h" namespace s2coding { // Encodes a vector of S2CellIds in a format that can later be decoded as an // EncodedS2CellIdVector. The S2CellIds do not need to be valid. // // REQUIRES: "encoder" uses the default constructor, so that its buffer // can be enlarged as necessary by calling Ensure(int). void EncodeS2CellIdVector(absl::Span v, Encoder* encoder); // This class represents an encoded vector of S2CellIds. Values are decoded // only when they are accessed. This allows for very fast initialization and // no additional memory use beyond the encoded data. The encoded data is not // owned by this class; typically it points into a large contiguous buffer // that contains other encoded data as well. // // This is one of several helper classes that allow complex data structures to // be initialized from an encoded format in constant time and then decoded on // demand. This can be a big performance advantage when only a small part of // the data structure is actually used. // // The S2CellIds do not need to be sorted or at the same level. The // implementation is biased towards minimizing decoding times rather than // space usage. // // NOTE: If your S2CellIds represent S2Points that have been snapped to // S2CellId centers, then EncodedS2PointVector is both faster and smaller. class EncodedS2CellIdVector { public: // Constructs an uninitialized object; requires Init() to be called. EncodedS2CellIdVector() = default; // Initializes the EncodedS2CellIdVector. // // REQUIRES: The Decoder data buffer must outlive this object. bool Init(Decoder* decoder); // Returns the size of the original vector. size_t size() const; // Returns the element at the given index. S2CellId operator[](int i) const; // Returns the index of the first element x such that (x >= target), or // size() if no such element exists. // // REQUIRES: The vector elements are sorted in non-decreasing order. size_t lower_bound(S2CellId target) const; // Decodes and returns the entire original vector. std::vector Decode() const; // Copies the encoded byte stream to a new encoder. void Encode(Encoder* encoder) const; private: // Values are decoded as (base_ + (deltas_[i] << shift_)). EncodedUintVector deltas_; uint64_t base_; uint8_t shift_; uint8_t base_len_; }; ////////////////// Implementation details follow //////////////////// inline size_t EncodedS2CellIdVector::size() const { return deltas_.size(); } inline S2CellId EncodedS2CellIdVector::operator[](int i) const { return S2CellId((deltas_[i] << shift_) + base_); } inline size_t EncodedS2CellIdVector::lower_bound(S2CellId target) const { // We optimize the search by converting "target" to the corresponding delta // value and then searching directly in the deltas_ vector. // // To invert operator[], we essentially compute ((target - base_) >> shift_) // except that we also need to round up when shifting. The first two cases // ensure that "target" doesn't wrap around past zero when we do this. if (target.id() <= base_) return 0; if (target >= S2CellId::End(S2CellId::kMaxLevel)) return size(); return deltas_.lower_bound( (target.id() - base_ + (uint64_t{1} << shift_) - 1) >> shift_); } } // namespace s2coding #endif // S2_ENCODED_S2CELL_ID_VECTOR_H_ src/s2/encoded_s2cell_id_vector_test.cc000066400000000000000000000254571524103652300204600ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_s2cell_id_vector.h" #include #include #include #include #include #include "absl/log/log_streamer.h" #include "absl/random/random.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/mutable_s2shape_index.h" #include "s2/s1angle.h" #include "s2/s2cell_id.h" #include "s2/s2fractal.h" #include "s2/s2loop.h" #include "s2/s2point.h" #include "s2/s2pointutil.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2testing.h" #include "s2/s2text_format.h" using s2textformat::MakeCellIdOrDie; using std::make_unique; using std::vector; namespace s2coding { namespace { // Encodes the given vector and returns the corresponding // EncodedS2CellIdVector (which points into the Encoder's data buffer). EncodedS2CellIdVector MakeEncodedS2CellIdVector( absl::Span input, Encoder* encoder) { EncodeS2CellIdVector(input, encoder); Decoder decoder(encoder->base(), encoder->length()); EncodedS2CellIdVector cell_ids; EXPECT_TRUE(cell_ids.Init(&decoder)); return cell_ids; } // Encodes the given vector and checks that it has the expected size and // contents. void TestEncodedS2CellIdVector(const vector& expected, size_t expected_bytes) { Encoder encoder; EncodedS2CellIdVector actual = MakeEncodedS2CellIdVector(expected, &encoder); EXPECT_EQ(expected_bytes, encoder.length()); EXPECT_EQ(actual.Decode(), expected); } // Like the above, but accepts a vector rather than a // vector. void TestEncodedS2CellIdVector(absl::Span raw_expected, size_t expected_bytes) { vector expected; for (uint64_t raw_id : raw_expected) { expected.push_back(S2CellId(raw_id)); } TestEncodedS2CellIdVector(expected, expected_bytes); } TEST(EncodedS2CellIdVector, Empty) { TestEncodedS2CellIdVector(vector{}, 2); } TEST(EncodedS2CellIdVector, None) { TestEncodedS2CellIdVector({S2CellId::None()}, 3); } TEST(EncodedS2CellIdVector, NoneNone) { TestEncodedS2CellIdVector({S2CellId::None(), S2CellId::None()}, 4); } TEST(EncodedS2CellIdVector, Sentinel) { TestEncodedS2CellIdVector({S2CellId::Sentinel()}, 10); } TEST(EncodedS2CellIdVector, MaximumShiftCell) { // Tests the encoding of a single cell at level 2, which corresponds the // maximum encodable shift value (56). TestEncodedS2CellIdVector({MakeCellIdOrDie("0/00")}, 3); } TEST(EncodedS2CellIdVector, SentinelSentinel) { TestEncodedS2CellIdVector({S2CellId::Sentinel(), S2CellId::Sentinel()}, 11); } TEST(EncodedS2CellIdVector, NoneSentinelNone) { TestEncodedS2CellIdVector( {S2CellId::None(), S2CellId::Sentinel(), S2CellId::None()}, 26); } TEST(EncodedS2CellIdVector, InvalidCells) { // Tests that cells with an invalid LSB can be encoded. TestEncodedS2CellIdVector({0x6, 0xe, 0x7e}, 5); } TEST(EncodedS2CellIdVector, OneByteLeafCells) { // Tests that (1) if all cells are leaf cells, the low bit is not encoded, // and (2) this can be indicated using the standard 1-byte header. TestEncodedS2CellIdVector({0x3, 0x7, 0x177}, 5); } TEST(EncodedS2CellIdVector, OneByteLevel29Cells) { // Tests that (1) if all cells are at level 29, the low bit is not encoded, // and (2) this can be indicated using the standard 1-byte header. TestEncodedS2CellIdVector({0xc, 0x1c, 0x47c}, 5); } TEST(EncodedS2CellIdVector, OneByteLevel28Cells) { // Tests that (1) if all cells are at level 28, the low bit is not encoded, // and (2) this can be indicated using the extended 2-byte header. TestEncodedS2CellIdVector({0x30, 0x70, 0x1770}, 6); } TEST(EncodedS2CellIdVector, OneByteMixedCellLevels) { // Tests that cells at mixed levels can be encoded in one byte. TestEncodedS2CellIdVector({0x300, 0x1c00, 0x7000, 0xff00}, 6); } TEST(EncodedS2CellIdVector, OneByteMixedCellLevelsWithPrefix) { // Tests that cells at mixed levels can be encoded in one byte even when // they share a multi-byte prefix. TestEncodedS2CellIdVector({ 0x1234567800000300, 0x1234567800001c00, 0x1234567800007000, 0x123456780000ff00}, 10); } TEST(EncodedS2CellIdVector, OneByteRangeWithBaseValue) { // Tests that cells can be encoded in one byte by choosing a base value // whose bit range overlaps the delta values. // 1 byte header, 3 bytes base, 1 byte size, 4 bytes deltas TestEncodedS2CellIdVector({ 0x00ffff0000000000, 0x0100fc0000000000, 0x0100500000000000, 0x0100330000000000}, 9); } TEST(EncodedS2CellIdVector, MaxShiftRange) { const vector bytes = { (31 << 3) // 31 -> add 29 to bytes[1]. + 1, // Number of encoded cell IDs. 27, // 27+29 is the maximum supported shift. 1, 0 // Encoded cell ID. Not important. }; Decoder decoder(bytes.data(), bytes.size()); EncodedS2CellIdVector cell_ids; EXPECT_TRUE(cell_ids.Init(&decoder)); } TEST(EncodedS2CellIdVector, ShiftOutOfRange) { const vector bytes = { (31 << 3) // 31 -> add 29 to bytes[1]. + 1, // Number of encoded cell IDs. 28, // 28+29 is greater than the maximum supported shift of 56. 1, 0 // Encoded cell ID. Not important. }; Decoder decoder(bytes.data(), bytes.size()); EncodedS2CellIdVector cell_ids; EXPECT_FALSE(cell_ids.Init(&decoder)); } TEST(EncodedS2CellIdVector, SixFaceCells) { vector ids; for (int face = 0; face < 6; ++face) { ids.push_back(S2CellId::FromFace(face)); } TestEncodedS2CellIdVector(ids, 8); } TEST(EncodedS2CellIdVector, FourLevel10Children) { vector ids; S2CellId parent = MakeCellIdOrDie("3/012301230"); for (S2CellId id = parent.child_begin(); id != parent.child_end(); id = id.next()) { ids.push_back(id); } TestEncodedS2CellIdVector(ids, 8); } TEST(EncodedS2CellIdVector, FractalS2ShapeIndexCells) { absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "FRACTAL_S2_SHAPE_INDEX_CELLS", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); S2Fractal fractal(bitgen); fractal.SetLevelForApproxMaxEdges(3 * 1024); S2Point center = s2textformat::MakePointOrDie("47.677:-122.206"); MutableS2ShapeIndex index; index.Add(make_unique( fractal.MakeLoop(S2::GetFrame(center), S1Angle::Degrees(1)))); vector ids; for (MutableS2ShapeIndex::Iterator it(&index, S2ShapeIndex::BEGIN); !it.done(); it.Next()) { ids.push_back(it.id()); } EXPECT_EQ(966, ids.size()); TestEncodedS2CellIdVector(ids, 2902); } TEST(EncodedS2CellIdVector, CoveringCells) { vector ids{ 0x414a617f00000000, 0x414a61c000000000, 0x414a624000000000, 0x414a63c000000000, 0x414a647000000000, 0x414a64c000000000, 0x414a653000000000, 0x414a704000000000, 0x414a70c000000000, 0x414a714000000000, 0x414a71b000000000, 0x414a7a7c00000000, 0x414a7ac000000000, 0x414a8a4000000000, 0x414a8bc000000000, 0x414a8c4000000000, 0x414a8d7000000000, 0x414a8dc000000000, 0x414a914000000000, 0x414a91c000000000, 0x414a924000000000, 0x414a942c00000000, 0x414a95c000000000, 0x414a96c000000000, 0x414ab0c000000000, 0x414ab14000000000, 0x414ab34000000000, 0x414ab3c000000000, 0x414ab44000000000, 0x414ab4c000000000, 0x414ab6c000000000, 0x414ab74000000000, 0x414ab8c000000000, 0x414ab94000000000, 0x414aba1000000000, 0x414aba3000000000, 0x414abbc000000000, 0x414abe4000000000, 0x414abec000000000, 0x414abf4000000000, 0x46b5454000000000, 0x46b545c000000000, 0x46b5464000000000, 0x46b547c000000000, 0x46b5487000000000, 0x46b548c000000000, 0x46b5494000000000, 0x46b54a5400000000, 0x46b54ac000000000, 0x46b54b4000000000, 0x46b54bc000000000, 0x46b54c7000000000, 0x46b54c8004000000, 0x46b54ec000000000, 0x46b55ad400000000, 0x46b55b4000000000, 0x46b55bc000000000, 0x46b55c4000000000, 0x46b55c8100000000, 0x46b55dc000000000, 0x46b55e4000000000, 0x46b5604000000000, 0x46b560c000000000, 0x46b561c000000000, 0x46ca424000000000, 0x46ca42c000000000, 0x46ca43c000000000, 0x46ca444000000000, 0x46ca45c000000000, 0x46ca467000000000, 0x46ca469000000000, 0x46ca5fc000000000, 0x46ca604000000000, 0x46ca60c000000000, 0x46ca674000000000, 0x46ca679000000000, 0x46ca67f000000000, 0x46ca684000000000, 0x46ca855000000000, 0x46ca8c4000000000, 0x46ca8cc000000000, 0x46ca8e5400000000, 0x46ca8ec000000000, 0x46ca8f0100000000, 0x46ca8fc000000000, 0x46ca900400000000, 0x46ca98c000000000, 0x46ca994000000000, 0x46ca99c000000000, 0x46ca9a4000000000, 0x46ca9ac000000000, 0x46ca9bd500000000, 0x46ca9e4000000000, 0x46ca9ec000000000, 0x46caf34000000000, 0x46caf4c000000000, 0x46caf54000000000}; EXPECT_EQ(97, ids.size()); TestEncodedS2CellIdVector(ids, 488); } TEST(EncodedS2CellIdVector, LowerBoundLimits) { // Test seeking before the beginning and past the end of the vector. S2CellId first = S2CellId::Begin(S2CellId::kMaxLevel); S2CellId last = S2CellId::End(S2CellId::kMaxLevel).prev(); Encoder encoder; EncodedS2CellIdVector cell_ids = MakeEncodedS2CellIdVector( {first, last}, &encoder); EXPECT_EQ(0, cell_ids.lower_bound(S2CellId::None())); EXPECT_EQ(0, cell_ids.lower_bound(first)); EXPECT_EQ(1, cell_ids.lower_bound(first.next())); EXPECT_EQ(1, cell_ids.lower_bound(last.prev())); EXPECT_EQ(1, cell_ids.lower_bound(last)); EXPECT_EQ(2, cell_ids.lower_bound(last.next())); EXPECT_EQ(2, cell_ids.lower_bound(S2CellId::Sentinel())); } void EncodedS2CellIdVectorInitNeverCrashes(const vector& bytes, const uint64_t lower_bound) { Decoder decoder(bytes.data(), bytes.size()); EncodedS2CellIdVector cell_ids; if (!cell_ids.Init(&decoder)) { return; } const S2CellId cell_id(lower_bound); if (!cell_id.is_valid()) { return; } cell_ids.lower_bound(cell_id); } TEST(EncodedS2CellIdVector, EncodedS2CellIdVectorInitNeverCrashesRegression) { // This would overflow the size_ * len_ check in EncodedUintVector and let it // erroneously proceed to decoding, causing a segfault. EncodedS2CellIdVectorInitNeverCrashes( {32, 135, 128, 128, 128, 48, 39, 132, 143, 84}, 7059594055645134713 ); } } // namespace } // namespace s2coding src/s2/encoded_s2point_vector.cc000066400000000000000000001160271524103652300171510ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_s2point_vector.h" #include #include #include #include #include #include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/numeric/bits.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/util/coding/varint.h" #include "s2/encoded_string_vector.h" #include "s2/encoded_uint_vector.h" #include "s2/s2cell_id.h" #include "s2/s2coder.h" #include "s2/s2coords.h" #include "s2/s2error.h" #include "s2/s2point.h" using absl::MakeSpan; using absl::Span; using std::max; using std::min; using std::vector; namespace s2coding { // Like util_bits::InterleaveUint32, but interleaves bit pairs rather than // individual bits. This format is faster to decode than the fully interleaved // format, and produces the same results for our use case. inline uint64_t InterleaveUint32BitPairs(const uint32_t val0, const uint32_t val1) { uint64_t v0 = val0, v1 = val1; v0 = (v0 | (v0 << 16)) & 0x0000ffff0000ffff; v1 = (v1 | (v1 << 16)) & 0x0000ffff0000ffff; v0 = (v0 | (v0 << 8)) & 0x00ff00ff00ff00ff; v1 = (v1 | (v1 << 8)) & 0x00ff00ff00ff00ff; v0 = (v0 | (v0 << 4)) & 0x0f0f0f0f0f0f0f0f; v1 = (v1 | (v1 << 4)) & 0x0f0f0f0f0f0f0f0f; v0 = (v0 | (v0 << 2)) & 0x3333333333333333; v1 = (v1 | (v1 << 2)) & 0x3333333333333333; return v0 | (v1 << 2); } // This code is about 50% faster than util_bits::DeinterleaveUint32, which // uses a lookup table. The speed advantage is expected to be even larger in // code that mixes bit interleaving with other significant operations since it // doesn't require keeping a 256-byte lookup table in the L1 data cache. inline void DeinterleaveUint32BitPairs(uint64_t code, uint32_t* val0, uint32_t* val1) { uint64_t v0 = code, v1 = code >> 2; v0 &= 0x3333333333333333; v0 |= v0 >> 2; v1 &= 0x3333333333333333; v1 |= v1 >> 2; v0 &= 0x0f0f0f0f0f0f0f0f; v0 |= v0 >> 4; v1 &= 0x0f0f0f0f0f0f0f0f; v1 |= v1 >> 4; v0 &= 0x00ff00ff00ff00ff; v0 |= v0 >> 8; v1 &= 0x00ff00ff00ff00ff; v1 |= v1 >> 8; v0 &= 0x0000ffff0000ffff; v0 |= v0 >> 16; v1 &= 0x0000ffff0000ffff; v1 |= v1 >> 16; *val0 = v0; *val1 = v1; } // Forward declarations. void EncodeS2PointVectorFast(Span points, Encoder* encoder); void EncodeS2PointVectorCompact(Span points, Encoder* encoder); // To save space (especially for vectors of length 0, 1, and 2), the encoding // format is encoded in the low-order 3 bits of the vector size. Up to 7 // encoding formats are supported (only 2 are currently defined). Additional // formats could be supported by using "7" as an overflow indicator and // encoding the actual format separately, but it seems unlikely we will ever // need to do that. static const int kEncodingFormatBits = 3; static const uint8_t kEncodingFormatMask = (1 << kEncodingFormatBits) - 1; void EncodeS2PointVector(Span points, CodingHint hint, Encoder* encoder) { switch (hint) { case CodingHint::FAST: return EncodeS2PointVectorFast(points, encoder); case CodingHint::COMPACT: return EncodeS2PointVectorCompact(points, encoder); default: ABSL_LOG(DFATAL) << "Unknown CodingHint: " << static_cast(hint); } } bool EncodedS2PointVector::Init(Decoder* decoder) { if (decoder->avail() < 1) return false; // Peek at the format but don't advance the decoder; the format-specific // Init functions will do that. format_ = static_cast(*decoder->skip(0) & kEncodingFormatMask); switch (format_) { case UNCOMPRESSED: return InitUncompressedFormat(decoder); case CELL_IDS: return InitCellIdsFormat(decoder); default: return false; } } bool EncodedS2PointVector::Init(Decoder* decoder, S2Error& error) { if (!Init(decoder)) { error = S2Error::DataLoss("Error initializing EncodedS2PointVector"); return false; } return true; } vector EncodedS2PointVector::Decode() const { vector points; points.reserve(size_); for (size_t i = 0; i < size_; ++i) { points.push_back((*this)[i]); } return points; } bool EncodedS2PointVector::Decode(absl::Span points) const { ABSL_DCHECK_EQ(points.size(), size()); for (size_t i = 0; i < size_; ++i) { points[i] = (*this)[i]; } return true; } std::vector EncodedS2PointVector::Decode(S2Error& error) const { vector points; points.reserve(size_); for (size_t i = 0; i < size_ && error.ok(); ++i) { points.push_back(At(i, error)); } return points; } bool EncodedS2PointVector::Decode(absl::Span points, S2Error& error) const { ABSL_DCHECK_EQ(points.size(), size()); for (size_t i = 0; i < size_ && error.ok(); ++i) { points[i] = At(i, error); } return error.ok(); } // The encoding must be identical to EncodeS2PointVector(). void EncodedS2PointVector::Encode(Encoder* encoder) const { switch (format_) { case UNCOMPRESSED: EncodeS2PointVectorFast(MakeSpan(uncompressed_.points, size_), encoder); break; case CELL_IDS: { // This is a full decode/encode dance, and not at all efficient. EncodeS2PointVectorCompact(Decode(), encoder); break; } default: ABSL_LOG(FATAL) << "Unknown Format: " << static_cast(format_); } } ////////////////////////////////////////////////////////////////////////////// // UNCOMPRESSED Encoding Format ////////////////////////////////////////////////////////////////////////////// // Encodes a vector of points, optimizing for (encoding and decoding) speed. void EncodeS2PointVectorFast(Span points, Encoder* encoder) { if constexpr (absl::endian::native != absl::endian::little) { ABSL_LOG(FATAL) << "Not implemented on big-endian architectures"; } // This function always uses the UNCOMPRESSED encoding. The header consists // of a varint64 in the following format: // // bits 0-2: encoding format (UNCOMPRESSED) // bits 3-63: vector size // // This is followed by an array of S2Points in little-endian order. encoder->Ensure(Varint::kMax64 + points.size() * sizeof(S2Point)); uint64_t size_format = (points.size() << kEncodingFormatBits | EncodedS2PointVector::UNCOMPRESSED); encoder->put_varint64(size_format); encoder->putn(points.data(), points.size() * sizeof(S2Point)); } bool EncodedS2PointVector::InitUncompressedFormat(Decoder* decoder) { #ifdef __arm__ constexpr bool kIsArm32 = true; #else constexpr bool kIsArm32 = false; #endif if constexpr (absl::endian::native != absl::endian::little || kIsArm32) { // TODO(b/231674214): Make this work on platforms that don't support // unaligned 64-bit little-endian reads, e.g. by falling back to // // bit_cast(LittleEndian::Load64()). // // Maybe the compiler is smart enough that we can do this all the time, // but more likely we will need two cases using the #ifdef above. // (Note that even ARMv7 does not support unaligned 64-bit loads.) ABSL_LOG(DFATAL) << "Needs architecture with 64-bit little-endian unaligned loads"; return false; } uint64_t size; if (!decoder->get_varint64(&size)) return false; size >>= kEncodingFormatBits; // Note that the encoding format supports up to 2**59 vertices, but we // currently only support decoding up to 2**31 vertices, as // `EncodedS2PointVectorShape::num_points()` returns `int`. if (size > std::numeric_limits::max()) return false; size_ = size; size_t bytes = size_t{size_} * sizeof(S2Point); if (decoder->avail() < bytes) return false; uncompressed_.points = reinterpret_cast(decoder->skip(0)); decoder->skip(bytes); return true; } ////////////////////////////////////////////////////////////////////////////// // CELL_IDS Encoding Format ////////////////////////////////////////////////////////////////////////////// // Represents a point that can be encoded as an S2CellId center. // (If such an encoding is not possible then level < 0.) struct CellPoint { // Constructor necessary in order to narrow "int" arguments to "int8_t". CellPoint(int level, int face, uint32_t si, uint32_t ti) : level(level), face(face), si(si), ti(ti) {} int8_t level, face; uint32_t si, ti; }; // S2CellIds are represented in a special 64-bit format and are encoded in // fixed-size blocks. kBlockSize represents the number of values per block. // Block sizes of 4, 8, 16, and 32 were tested and kBlockSize == 16 seems to // offer the best compression. (Note that kBlockSize == 32 requires some code // modifications which have since been removed.) static constexpr int kBlockShift = 4; static constexpr size_t kBlockSize = 1 << kBlockShift; // Used to indicate that a point must be encoded as an exception (a 24-byte // S2Point) rather than as an S2CellId. static constexpr uint64_t kException = ~0ULL; // Represents the encoding parameters to be used for a given block (consisting // of kBlockSize encodable 64-bit values). See below. struct BlockCode { int delta_bits; // Delta length in bits (multiple of 4) int offset_bits; // Offset length in bits (multiple of 8) int overlap_bits; // {Delta, Offset} overlap in bits (0 or 4) }; // Returns a bit mask with "n" low-order 1 bits, for 0 <= n <= 64. inline uint64_t BitMask(int n) { return (n == 0) ? 0 : (~0ULL >> (64 - n)); } // Returns the maximum number of bits per value at the given S2CellId level. inline int MaxBitsForLevel(int level) { return 2 * level + 3; } // Returns the number of bits that "base" should be right-shifted in order to // encode only its leading "base_bits" bits, assuming that all points are // encoded at the given S2CellId level. inline int BaseShift(int level, int base_bits) { return max(0, MaxBitsForLevel(level) - base_bits); } // Forward declarations. int ChooseBestLevel(Span points, vector* cell_points); vector ConvertCellsToValues(absl::Span cell_points, int level, bool* have_exceptions); uint64_t ChooseBase(absl::Span values, int level, bool have_exceptions, int* base_bits); BlockCode GetBlockCode(Span values, uint64_t base, bool have_exceptions); // Encodes a vector of points, optimizing for space. void EncodeS2PointVectorCompact(Span points, Encoder* encoder) { // OVERVIEW // -------- // // We attempt to represent each S2Point as the center of an S2CellId. All // S2CellIds must be at the same level. Any points that cannot be encoded // exactly as S2CellId centers are stored as exceptions using 24 bytes each. // If there are so many exceptions that the CELL_IDS encoding does not save // significant space, we give up and use the uncompressed encoding. // // The first step is to choose the best S2CellId level. This requires // converting each point to (face, si, ti) coordinates and checking whether // the point can be represented exactly as an S2CellId center at some level. // We then build a histogram of S2CellId levels (just like the similar code // in S2Polygon::Encode) and choose the best level (or give up, if there are // not enough S2CellId-encodable points). // // The simplest approach would then be to take all the S2CellIds and // right-shift them to remove all the constant bits at the chosen level. // This would give the best spatial locality and hence the smallest deltas. // However instead we give up some spatial locality and use the similar but // faster transformation described below. // // Each encodable point is first converted to the (sj, tj) representation // defined below: // // sj = (((face & 3) << 30) | (si >> 1)) >> (30 - level); // tj = (((face & 4) << 29) | ti) >> (31 - level); // // These two values encode the (face, si, ti) tuple using (2 * level + 3) // bits. To see this, recall that "si" and "ti" are 31-bit values that all // share a common suffix consisting of a "1" bit followed by (30 - level) // "0" bits. The code above right-shifts these values to remove the // constant bits and then prepends the bits for "face", yielding a total of // (level + 2) bits for "sj" and (level + 1) bits for "tj". // // We then combine (sj, tj) into one 64-bit value by interleaving bit pairs: // // v = InterleaveBitPairs(sj, tj); // // (We could also interleave individual bits, but it is faster this way.) // The result is similar to right-shifting an S2CellId by (61 - 2 * level), // except that it is faster to decode and the spatial locality is not quite // as good. // // The 64-bit values are divided into blocks of size kBlockSize, and then // each value is encoded as the sum of a base value, a per-block offset, and // a per-value delta within that block: // // v[i,j] = base + offset[i] + delta[i, j] // // where "i" represents a block and "j" represents an entry in that block. // // The deltas for each block are encoded using a fixed number of 4-bit nibbles // (1-16 nibbles per delta). This allows any delta to be accessed in constant // time. // // The "offset" for each block is a 64-bit value encoded in 0-8 bytes. The // offset is left-shifted such that it overlaps the deltas by a configurable // number of bits (either 0 or 4), called the "overlap". The overlap and // offset length (0-8 bytes) are specified per block. The reason for the // overlap is that it allows fewer delta bits to be used in some cases. For // example if base == 0 and the range within a block is 0xf0 to 0x110, then // rather than using 12-bits deltas with an offset of 0, the overlap lets us // use 8-bits deltas with an offset of 0xf0 (saving 7 bytes per block). // // The global minimum value "base" is encoded using 0-7 bytes starting with // the most-significant non-zero bit possible for the chosen level. For // example, if (level == 7) then the encoded values have at most 17 bits, so // if "base" is encoded in 1 byte then it is shifted to occupy bits 9-16. // // Example: at level == 15, there are at most 33 non-zero value bits. The // following shows the bit positions covered by "base", "offset", and "delta" // assuming that "base" and "offset" are encoded in 2 bytes each, deltas are // encoded in 2 nibbles (1 byte) each, and "overlap" is 4 bits: // // Base: 1111111100000000----------------- // Offset: -------------1111111100000000---- // Delta: -------------------------00000000 // Overlap: ^^^^ // // The numbers (0 or 1) in this diagram denote the byte number of the encoded // value. Notice that "base" is shifted so that it starts at the leftmost // possible bit, "delta" always starts at the rightmost possible bit (bit 0), // and "offset" is shifted so that it overlaps "delta" by the chosen "overlap" // (either 0 or 4 bits). Also note that all of these values are summed, and // therefore each value can affect higher-order bits due to carries. // // NOTE(ericv): Encoding deltas in 4-bit rather than 8-bit length increments // reduces encoded sizes by about 7%. Allowing a 4-bit overlap between the // offset and deltas reduces encoded sizes by about 1%. Both optimizations // make the code more complex but don't affect running times significantly. // // ENCODING DETAILS // ---------------- // // Now we can move on to the actual encodings. First, there is a 2 byte // header encoded as follows: // // Byte 0, bits 0-2: encoding_format (CELL_IDS) // Byte 0, bit 3: have_exceptions // Byte 0, bits 4-7: (last_block_size - 1) // Byte 1, bits 0-2: base_bytes // Byte 1, bits 3-7: level (0-30) // // This is followed by an EncodedStringVector containing the encoded blocks. // Each block contains kBlockSize (8) values. The total size of the // EncodeS2PointVector is not stored explicitly, but instead is calculated as // // num_values == kBlockSize * (num_blocks - 1) + last_block_size . // // (An empty vector has num_blocks == 0 and last_block_size == kBlockSize.) // // Each block starts with a 1 byte header containing the following: // // Byte 0, bits 0-2: (offset_bytes - overlap_nibbles) // Byte 0, bit 3: overlap_nibbles // Byte 0, bits 4-7: (delta_nibbles - 1) // // "overlap_nibbles" is either 0 or 1 (indicating an overlap of 0 or 4 bits), // while "offset_bytes" is in the range 0-8 (indicating the number of bytes // used to encode the offset for this block). Note that some combinations // cannot be encoded: in particular, offset_bytes == 0 can only be encoded // with an overlap of 0 bits, and offset_bytes == 8 can only be encoded with // an overlap of 4 bits. This allows us to encode offset lengths of 0-8 // rather than just 0-7 without using an extra bit. (Note that the // combinations that can't be encoded are not useful anyway.) // // The header is followed by "offset_bytes" bytes for the offset, and then // (4 * delta_nibbles) bytes for the deltas. // // If there are any points that could not be represented as S2CellIds, then // "have_exceptions" in the header is true. In that case the delta values // within each block are encoded as (delta + kBlockSize), and values // 0...kBlockSize-1 are used to represent exceptions. If a block has // exceptions, they are encoded immediately following the array of deltas, // and are referenced by encoding the corresponding exception index // 0...kBlockSize-1 as the delta. // // TODO(ericv): A vector containing a single leaf cell is currently encoded as // 13 bytes (2 byte header, 7 byte base, 1 byte block count, 1 byte block // length, 1 byte block header, 1 byte delta). However if this case occurs // often, a better solution would be implement a separate format that encodes // the leading k bytes of an S2CellId. It would have a one-byte header // consisting of the encoding format (3 bits) and the number of bytes encoded // (3 bits), followed by the S2CellId bytes. The extra 2 header bits could be // used to store single points using other encodings, e.g. E7. // // If we had used 8-value blocks, we could have used the extra bit in the // first byte of the header to indicate that there is only one value, and // then skip the 2nd byte of header and the EncodedStringVector. But this // would be messy because it also requires special cases while decoding. // Essentially this would be a sub-format within the CELL_IDS format. // 1. Compute (level, face, si, ti) for each point, build a histogram of // levels, and determine the optimal level to use for encoding (if any). vector cell_points; int level = ChooseBestLevel(points, &cell_points); if (level < 0) { return EncodeS2PointVectorFast(points, encoder); } // 2. Convert the points into encodable 64-bit values. We don't use the // S2CellId itself because it requires a somewhat more complicated bit // interleaving operation. // // TODO(ericv): Benchmark using shifted S2CellIds instead. bool have_exceptions; vector values = ConvertCellsToValues(cell_points, level, &have_exceptions); // 3. Choose the global encoding parameter "base" (consisting of the bit // prefix shared by all values to be encoded). int base_bits; uint64_t base = ChooseBase(values, level, have_exceptions, &base_bits); // Now encode the output, starting with the 2-byte header (see above). int num_blocks = (values.size() + kBlockSize - 1) >> kBlockShift; int base_bytes = base_bits >> 3; encoder->Ensure(2 + base_bytes); int last_block_count = values.size() - kBlockSize * (num_blocks - 1); ABSL_DCHECK_GE(last_block_count, 0); ABSL_DCHECK_LE(last_block_count, kBlockSize); ABSL_DCHECK_LE(base_bytes, 7); ABSL_DCHECK_LE(level, 30); encoder->put8(EncodedS2PointVector::CELL_IDS | (have_exceptions << 3) | ((last_block_count - 1) << 4)); encoder->put8(base_bytes | (level << 3)); // Next we encode 0-7 bytes of "base". int base_shift = BaseShift(level, base_bits); EncodeUintWithLength(base >> base_shift, base_bytes, encoder); // Now we encode the contents of each block. StringVectorEncoder blocks; vector exceptions; for (size_t i = 0; i < values.size(); i += kBlockSize) { int block_size = min(kBlockSize, values.size() - i); BlockCode code = GetBlockCode(MakeSpan(&values[i], block_size), base, have_exceptions); // Encode the one-byte block header (see above). Encoder* block = blocks.AddViaEncoder(); int offset_bytes = code.offset_bits >> 3; int delta_nibbles = code.delta_bits >> 2; int overlap_nibbles = code.overlap_bits >> 2; block->Ensure(1 + offset_bytes + (kBlockSize / 2) * delta_nibbles); ABSL_DCHECK_LE(offset_bytes - overlap_nibbles, 7); ABSL_DCHECK_LE(overlap_nibbles, 1); ABSL_DCHECK_LE(delta_nibbles, 16); block->put8((offset_bytes - overlap_nibbles) | (overlap_nibbles << 3) | (delta_nibbles - 1) << 4); // Determine the offset for this block, and whether there are exceptions. uint64_t offset = ~0ULL; int num_exceptions = 0; for (int j = 0; j < block_size; ++j) { if (values[i + j] == kException) { num_exceptions += 1; } else { ABSL_DCHECK_GE(values[i + j], base); offset = min(offset, values[i + j] - base); } } if (num_exceptions == block_size) offset = 0; // Encode the offset. int offset_shift = code.delta_bits - code.overlap_bits; offset &= ~BitMask(offset_shift); ABSL_DCHECK_EQ(offset == 0, offset_bytes == 0); if (offset > 0) { EncodeUintWithLength(offset >> offset_shift, offset_bytes, block); } // Encode the deltas, and also gather any exceptions present. int delta_bytes = (delta_nibbles + 1) >> 1; exceptions.clear(); for (int j = 0; j < block_size; ++j) { uint64_t delta; if (values[i + j] == kException) { delta = exceptions.size(); exceptions.push_back(points[i + j]); } else { ABSL_DCHECK_GE(values[i + j], offset + base); delta = values[i + j] - (offset + base); if (have_exceptions) { ABSL_DCHECK_LE(delta, ~0ULL - kBlockSize); delta += kBlockSize; } } ABSL_DCHECK_LE(delta, BitMask(code.delta_bits)); if ((delta_nibbles & 1) && (j & 1)) { // Combine this delta with the high-order 4 bits of the previous delta. uint8_t last_byte = *(block->base() + block->length() - 1); block->RemoveLast(1); delta = (delta << 4) | (last_byte & 0xf); } EncodeUintWithLength(delta, delta_bytes, block); } // Append any exceptions to the end of the block. if (num_exceptions > 0) { int exceptions_bytes = exceptions.size() * sizeof(S2Point); block->Ensure(exceptions_bytes); block->putn(exceptions.data(), exceptions_bytes); } } blocks.Encode(encoder); } // Returns the S2CellId level for which the greatest number of the given points // can be represented as the center of an S2CellId. Initializes "cell_points" // to contain the S2CellId representation of each point (if any). Returns -1 // if there is no S2CellId that would result in significant space savings. int ChooseBestLevel(Span points, vector* cell_points) { cell_points->clear(); cell_points->reserve(points.size()); // Count the number of points at each level. int level_counts[S2CellId::kMaxLevel + 1] = { 0 }; for (const S2Point& point : points) { int face; uint32_t si, ti; int level = S2::XYZtoFaceSiTi(point, &face, &si, &ti); cell_points->push_back(CellPoint(level, face, si, ti)); if (level >= 0) ++level_counts[level]; } // Choose the level for which the most points can be encoded. int best_level = 0; for (int level = 1; level <= S2CellId::kMaxLevel; ++level) { if (level_counts[level] > level_counts[best_level]) { best_level = level; } } // The uncompressed encoding is smaller *and* faster when very few of the // points are encodable as S2CellIds. The CELL_IDS encoding uses about 1 // extra byte per point in this case, consisting of up to a 3 byte // EncodedStringVector offset for each block, a 1 byte block header, and 4 // bits per delta (encoding an exception number from 0-7), for a total of 8 // bytes per block. This represents a space overhead of about 4%, so we // require that at least 5% of the input points should be encodable as // S2CellIds in order for the CELL_IDS format to be worthwhile. constexpr double kMinEncodableFraction = 0.05; if (level_counts[best_level] <= kMinEncodableFraction * points.size()) { return -1; } return best_level; } // Given a vector of points in CellPoint format and an S2CellId level that has // been chosen for encoding, returns a vector of 64-bit values that should be // encoded in order to represent these points. Points that cannot be // represented losslessly as the center of an S2CellId at the chosen level are // indicated by the value "kException". "have_exceptions" is set to indicate // whether any exceptions were present. vector ConvertCellsToValues(absl::Span cell_points, int level, bool* have_exceptions) { vector values; values.reserve(cell_points.size()); *have_exceptions = false; int shift = S2CellId::kMaxLevel - level; for (CellPoint cp : cell_points) { if (cp.level != level) { values.push_back(kException); *have_exceptions = true; } else { // Note that bit 31 of tj is always zero, and that bits are interleaved in // such a way that bit 63 of the result is always zero. // // The S2CellId version of the following code is: // uint64_t v = S2CellId::FromFaceIJ(cp.face, cp.si >> 1, cp.ti >> 1). // parent(level).id() >> (2 * shift + 1); uint32_t sj = (((cp.face & 3) << 30) | (cp.si >> 1)) >> shift; uint32_t tj = (((cp.face & 4) << 29) | cp.ti) >> (shift + 1); uint64_t v = InterleaveUint32BitPairs(sj, tj); ABSL_DCHECK_LE(v, BitMask(MaxBitsForLevel(level))); values.push_back(v); } } return values; } uint64_t ChooseBase(absl::Span values, int level, bool have_exceptions, int* base_bits) { // Find the minimum and maximum non-exception values to be represented. uint64_t v_min = kException, v_max = 0; for (auto v : values) { if (v != kException) { v_min = min(v_min, v); v_max = max(v_max, v); } } if (v_min == kException) return 0; // Generally "base" is chosen as the bit prefix shared by v_min and v_max. // However there are a few adjustments we need to make. // // 1. Encodings are usually smaller if the bits represented by "base" and // "delta" do not overlap. Usually the shared prefix rule does this // automatically, but if v_min == v_max or there are special circumstances // that increase delta_bits (such as values.size() == 1) then we need to // make an adjustment. // // 2. The format only allows us to represent up to 7 bytes (56 bits) of // "base", so we need to ensure that "base" conforms to this requirement. int min_delta_bits = (have_exceptions || values.size() == 1) ? 8 : 4; int excluded_bits = max(absl::bit_width(v_min ^ v_max), max(min_delta_bits, BaseShift(level, 56))); uint64_t base = v_min & ~BitMask(excluded_bits); // Determine how many bytes are needed to represent this prefix. if (base == 0) { *base_bits = 0; } else { int low_bit = absl::countr_zero(base); *base_bits = (MaxBitsForLevel(level) - low_bit + 7) & ~7; } // Since base_bits has been rounded up to a multiple of 8, we may now be // able to represent additional bits of v_min. In general this reduces the // final encoded size. // // NOTE(ericv): A different strategy for choosing "base" is to encode all // blocks under the assumption that "base" equals v_min exactly, and then // set base equal to the minimum-length prefix of "v_min" that allows these // encodings to be used. This strategy reduces the encoded sizes by // about 0.2% relative to the strategy here, but is more complicated. return v_min & ~BitMask(BaseShift(level, *base_bits)); } // Returns true if the range of values [d_min, d_max] can be encoded using the // specified parameters (delta_bits, overlap_bits, and have_exceptions). bool CanEncode(uint64_t d_min, uint64_t d_max, int delta_bits, int overlap_bits, bool have_exceptions) { // "offset" can't represent the lowest (delta_bits - overlap_bits) of d_min. d_min &= ~BitMask(delta_bits - overlap_bits); // The maximum delta is reduced by kBlockSize if any exceptions exist, since // deltas 0..kBlockSize-1 are used to indicate exceptions. uint64_t max_delta = BitMask(delta_bits); if (have_exceptions) { if (max_delta < kBlockSize) return false; max_delta -= kBlockSize; } // The first test below is necessary to avoid 64-bit overflow. return (d_min > ~max_delta) || (d_min + max_delta >= d_max); } // Given a vector of 64-bit values to be encoded and an S2CellId level, returns // the optimal encoding parameters that should be used to encode each block. // Also returns the global minimum value "base" and the number of bits that // should be used to encode it ("base_bits"). BlockCode GetBlockCode(Span values, uint64_t base, bool have_exceptions) { // "b_min" and "b_max"n are the minimum and maximum values within this block. uint64_t b_min = kException, b_max = 0; for (uint64_t v : values) { if (v != kException) { b_min = min(b_min, v); b_max = max(b_max, v); } } if (b_min == kException) { // All values in this block are exceptions. return BlockCode{4, 0, 0}; } // Adjust the min/max values so that they are relative to "base". b_min -= base; b_max -= base; // Determine the minimum possible delta length and overlap that can be used // to encode this block. The block will usually be encodable using the // number of bits in (b_max - b_min) rounded up to a multiple of 4. If this // is not possible, the preferred solution is to shift "offset" so that the // delta and offset values overlap by 4 bits (since this only costs an // average of 4 extra bits per block). Otherwise we increase the delta size // by 4 bits. Certain cases require that both of these techniques are used. // // Example 1: b_min = 0x72, b_max = 0x7e. The range is 0x0c. This can be // encoded using delta_bits = 4 and overlap_bits = 0, which allows us to // represent an offset of 0x70 and a maximum delta of 0x0f, so that we can // encode values up to 0x7f. // // Example 2: b_min = 0x78, b_max = 0x84. The range is 0x0c, but in this // case it is not sufficient to use delta_bits = 4 and overlap_bits = 0 // because we can again only represent an offset of 0x70, so the maximum // delta of 0x0f only lets us encode values up to 0x7f. However if we // increase the overlap to 4 bits then we can represent an offset of 0x78, // which lets us encode values up to 0x78 + 0x0f = 0x87. // // Example 3: b_min = 0x08, b_max = 0x104. The range is 0xfc, so we should // be able to use 8-bit deltas. But even with a 4-bit overlap, we can still // only encode offset = 0 and a maximum value of 0xff. (We don't allow // bigger overlaps because statistically they are not worthwhile.) Instead // we increase the delta size to 12 bits, which handles this case easily. // // Example 4: b_min = 0xf08, b_max = 0x1004. The range is 0xfc, so we // should be able to use 8-bit deltas. With 8-bit deltas and no overlap, we // have offset = 0xf00 and a maximum encodable value of 0xfff. With 8-bit // deltas and a 4-bit overlap, we still have offset = 0xf00 and a maximum // encodable value of 0xfff. Even with 12-bit deltas, we have offset = 0 // and we can still only represent 0xfff. However with delta_bits = 12 and // overlap_bits = 4, we can represent offset = 0xf00 and a maximum encodable // value of 0xf00 + 0xfff = 0x1eff. // // It is possible to show that this last example is the worst case, i.e. we // do not need to consider increasing delta_bits or overlap_bits further. int delta_bits = (max(1, static_cast(absl::bit_width(b_max - b_min)) - 1) + 3) & ~3; int overlap_bits = 0; if (!CanEncode(b_min, b_max, delta_bits, 0, have_exceptions)) { if (CanEncode(b_min, b_max, delta_bits, 4, have_exceptions)) { overlap_bits = 4; } else { ABSL_DCHECK_LE(delta_bits, 60); delta_bits += 4; if (!CanEncode(b_min, b_max, delta_bits, 0, have_exceptions)) { ABSL_DCHECK(CanEncode(b_min, b_max, delta_bits, 4, have_exceptions)); overlap_bits = 4; } } } // When the block size is 1 and no exceptions exist, we have delta_bits == 4 // and overlap_bits == 0 which wastes 4 bits. We fix this below, which // among other things reduces the encoding size for single leaf cells by one // byte. (Note that when exceptions exist, delta_bits == 8 and overlap_bits // may be 0 or 4. These cases are covered by the unit tests.) if (values.size() == 1 && !have_exceptions) { ABSL_DCHECK(delta_bits == 4 && overlap_bits == 0); delta_bits = 8; } // Now determine the number of bytes needed to encode "offset", given the // chosen delta length. uint64_t max_delta = BitMask(delta_bits) - (have_exceptions ? kBlockSize : 0); int offset_bits = 0; if (b_max > max_delta) { // At least one byte of offset is required. Round up the minimum offset // to the next encodable value, and determine how many bits it has. int offset_shift = delta_bits - overlap_bits; uint64_t mask = BitMask(offset_shift); uint64_t min_offset = (b_max - max_delta + mask) & ~mask; ABSL_ASSUME(min_offset != 0); offset_bits = (absl::bit_width(min_offset) - offset_shift + 7) & ~7; // A 64-bit offset can only be encoded with an overlap of 4 bits. if (offset_bits == 64) overlap_bits = 4; } return BlockCode{delta_bits, offset_bits, overlap_bits}; } bool EncodedS2PointVector::InitCellIdsFormat(Decoder* decoder) { // This function inverts the encodings documented above. // First we decode the two-byte header. if (decoder->avail() < 2) return false; uint8_t header1 = decoder->get8(); uint8_t header2 = decoder->get8(); ABSL_DCHECK_EQ(header1 & 7, CELL_IDS); int last_block_count, base_bytes; cell_ids_.have_exceptions = (header1 & 8) != 0; last_block_count = (header1 >> 4) + 1; base_bytes = header2 & 7; cell_ids_.level = header2 >> 3; if (cell_ids_.level > S2CellId::kMaxLevel) return false; // Decode the base value (if any). uint64_t base; if (!DecodeUintWithLength(base_bytes, decoder, &base)) return false; cell_ids_.base = base << BaseShift(cell_ids_.level, base_bytes << 3); // Initialize the vector of encoded blocks. if (!cell_ids_.blocks.Init(decoder)) return false; size_ = kBlockSize * (cell_ids_.blocks.size() - 1) + last_block_count; // Note that the encoding format supports up to 2**59 vertices, but we // currently only support decoding up to 2**31 vertices, as // `EncodedS2PointVectorShape::num_points()` returns `int`. if (size_ > std::numeric_limits::max()) return false; return true; } S2Point EncodedS2PointVector::DecodeCellIdsFormat(int i, S2Error* error) const { // This function inverts the encodings documented above. const auto Error = [error](absl::string_view message) { if (error != nullptr) { *error = S2Error::DataLoss(message); } return S2Point(); }; // First we decode the block header. const absl::string_view block = cell_ids_.blocks[i >> kBlockShift]; if (block.empty()) { return Error("Invalid block header"); } const char* ptr = block.data(); const char* end = ptr + block.size(); uint8_t header = *ptr++; int overlap_nibbles = (header >> 3) & 1; int offset_bytes = (header & 7) + overlap_nibbles; int delta_nibbles = (header >> 4) + 1; // Decode the offset for this block. If offset_bytes is zero, we don't have // an offset so we can skip decoding it. It's possible to get an offset_shift // of 64 in this case, so skipping prevents us from shifting by that amount // and triggering undefined behavior. uint64_t offset = 0; if (offset_bytes > 0) { int offset_shift = (delta_nibbles - overlap_nibbles) << 2; // TODO(b/267575159): detect root cause for shift exponent overflow earlier? if (offset_shift >= 64) { return Error("Invalid offset_shift"); } if (ptr + offset_bytes > end) { return Error("Invalid offset outside of block size"); } offset = GetUintWithLength(ptr, offset_bytes) << offset_shift; ptr += offset_bytes; } // Decode the delta for the requested value. int delta_nibble_offset = (i & (kBlockSize - 1)) * delta_nibbles; int delta_bytes = (delta_nibbles + 1) >> 1; const char* delta_ptr = ptr + (delta_nibble_offset >> 1); if (delta_ptr + delta_bytes > end) { return Error("Invalid delta outside of block size"); } uint64_t delta = GetUintWithLength(delta_ptr, delta_bytes); delta >>= (delta_nibble_offset & 1) << 2; delta &= BitMask(delta_nibbles << 2); // Test whether this point is encoded as an exception. if (cell_ids_.have_exceptions) { if (delta < kBlockSize) { int block_size = min(kBlockSize, size_ - (i & ~(kBlockSize - 1))); ptr += (block_size * delta_nibbles + 1) >> 1; ptr += delta * sizeof(S2Point); if (ptr + sizeof(S2Point) > end) { return Error("Invalid exception delta outside of block size"); } return *reinterpret_cast(ptr); } delta -= kBlockSize; } // Otherwise convert the 64-bit value back to an S2Point. uint64_t value = cell_ids_.base + offset + delta; int shift = S2CellId::kMaxLevel - cell_ids_.level; // The S2CellId version of the following code is: // return S2CellId(((value << 1) | 1) << (2 * shift)).ToPoint(); uint32_t sj, tj; DeinterleaveUint32BitPairs(value, &sj, &tj); int si = (((sj << 1) | 1) << shift) & 0x7fffffff; int ti = (((tj << 1) | 1) << shift) & 0x7fffffff; int face = ((sj << shift) >> 30) | (((tj << (shift + 1)) >> 29) & 4); return S2::FaceUVtoXYZ(face, S2::STtoUV(S2::SiTitoST(si)), S2::STtoUV(S2::SiTitoST(ti))).Normalize(); } } // namespace s2coding src/s2/encoded_s2point_vector.h000066400000000000000000000157641524103652300170210ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_ENCODED_S2POINT_VECTOR_H_ #define S2_ENCODED_S2POINT_VECTOR_H_ #include #include #include #include #include "absl/base/optimization.h" #include "absl/log/absl_log.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/encoded_string_vector.h" #include "s2/encoded_uint_vector.h" #include "s2/s2coder.h" #include "s2/s2error.h" #include "s2/s2point.h" namespace s2coding { // Encodes a vector of S2Points in a format that can later be decoded as an // EncodedS2PointVector. // // REQUIRES: "encoder" uses the default constructor, so that its buffer // can be enlarged as necessary by calling Ensure(int). void EncodeS2PointVector(absl::Span points, CodingHint hint, Encoder* encoder); // This class represents an encoded vector of S2Points. Values are decoded // only when they are accessed. This allows for very fast initialization and // no additional memory use beyond the encoded data. The encoded data is not // owned by this class; typically it points into a large contiguous buffer // that contains other encoded data as well. // // This is one of several helper classes that allow complex data structures to // be initialized from an encoded format in constant time and then decoded on // demand. This can be a big performance advantage when only a small part of // the data structure is actually used. class EncodedS2PointVector { public: // Constructs an uninitialized object; requires Init() to be called. EncodedS2PointVector() {} // Initializes the EncodedS2PointVector. // // Encoded types do not necessarily read all of their data when calling // Init(), instead only data necessary to decode further is read, which means // that encoded types may in general log DFATAL errors when reading from an // untrusted byte stream using unchecked accessors (e.g. operator[]). // // Checked accessors such as Decode(S2Error&) will instead set an error // condition, at the cost of potentially more overhead when decoding. // // REQUIRES: The Decoder data buffer must outlive this object. [[nodiscard]] bool Init(Decoder* decoder); // Initializes the EncodedS2PointVector as above. Setting S2Error if // initialization fails. A true return status does -not- mean that the byte // stream is without errors. The individual points must still be checked with // a checked accessor such as Decode(S2Error&). [[nodiscard]] bool Init(Decoder* decoder, S2Error& error); // Returns the size of the original vector. size_t size() const; // Returns the element at the given index. S2Point operator[](int i) const; // Decodes and returns the entire original vector. std::vector Decode() const; // Decodes the entire original vector and stores it in the given span. bool Decode(absl::Span points) const; // Decodes and returns the entire original vector, checking for errors as it // goes. If an error occurs, a truncated vector is returned. std::vector Decode(S2Error& error) const; // Decodes the entire original vector and stores it in the given span. Checks // for errors as it goes. If an error occurs returns false and the span may // be incompletely written. bool Decode(absl::Span points, S2Error& error) const; // Copy the encoded data to the encoder. This allows for "reserialization" of // encoded shapes created through lazy decoding. void Encode(Encoder* encoder) const; // TODO(ericv): Consider adding a method that returns an adjacent pair of // points. This would save some decoding overhead. private: friend void EncodeS2PointVector(absl::Span, CodingHint, Encoder*); friend void EncodeS2PointVectorFast(absl::Span, Encoder*); friend void EncodeS2PointVectorCompact(absl::Span, Encoder*); // Decodes and returns the point at the given index. If any errors occur when // decoding, the error is set and a default constructed point returned. S2Point At(int i, S2Error& error) const; bool InitUncompressedFormat(Decoder* decoder); bool InitCellIdsFormat(Decoder* decoder); S2Point DecodeCellIdsFormat(int i, S2Error* error) const; // We use a tagged union to represent multiple formats, as opposed to an // abstract base class or templating. This represents the best compromise // between performance, space, and convenience. Note that the overhead of // checking the tag is trivial and will typically be branch-predicted // perfectly. // // TODO(ericv): Once additional formats have been implemented, consider // using std::variant<> instead. It's unclear whether this would have // better or worse performance than the current approach. enum Format : uint8_t { UNCOMPRESSED = 0, CELL_IDS = 1, }; Format format_; uint32_t size_; union { struct { const S2Point* points; } uncompressed_; struct { EncodedStringVector blocks; uint64_t base; uint8_t level; bool have_exceptions; // TODO(ericv): Use std::atomic_flag to cache the last point decoded in // a thread-safe way. This reduces benchmark times for actual polygon // operations (e.g. S2ClosestEdgeQuery) by about 15%. } cell_ids_; }; }; ////////////////// Implementation details follow //////////////////// inline size_t EncodedS2PointVector::size() const { return size_; } inline S2Point EncodedS2PointVector::At(int i, S2Error& error) const { switch (format_) { case Format::UNCOMPRESSED: return uncompressed_.points[i]; case Format::CELL_IDS: return DecodeCellIdsFormat(i, &error); default: error = S2Error::DataLoss("Unrecognized format"); return {}; } ABSL_UNREACHABLE(); } inline S2Point EncodedS2PointVector::operator[](int i) const { // Check error conditions in debug mode, elide them otherwise. #ifndef NDEBUG S2Error error; S2Point point = At(i, error); if (!error.ok()) { ABSL_LOG(DFATAL) << error.message(); } return point; #else switch (format_) { case Format::UNCOMPRESSED: return uncompressed_.points[i]; case Format::CELL_IDS: return DecodeCellIdsFormat(i, nullptr); default: return {}; } ABSL_UNREACHABLE(); #endif } } // namespace s2coding #endif // S2_ENCODED_S2POINT_VECTOR_H_ src/s2/encoded_s2point_vector_test.cc000066400000000000000000000555651524103652300202210ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_s2point_vector.h" #include #include #include #include #include #include #include "absl/log/absl_check.h" #include "absl/log/log_streamer.h" #include "absl/random/random.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "s2/base/log_severity.h" #include "s2/util/bits/bit-interleave.h" #include "s2/util/coding/coder.h" #include "s2/s2cell_id.h" #include "s2/s2coder.h" #include "s2/s2coords.h" #include "s2/s2fractal.h" #include "s2/s2loop.h" #include "s2/s2point.h" #include "s2/s2polygon.h" #include "s2/s2random.h" #include "s2/s2testing.h" #include "s2/s2text_format.h" #include "s2/util/math/matrix3x3.h" using s2textformat::MakeCellIdOrDie; using s2textformat::MakePointOrDie; using std::make_unique; using std::vector; namespace s2coding { static int kBlockSize = 16; // Number of deltas per block in implementation. size_t TestEncodedS2PointVector(const vector& expected, CodingHint hint, int64_t expected_bytes) { Encoder encoder; EncodeS2PointVector(expected, hint, &encoder); if (expected_bytes >= 0) { EXPECT_EQ(expected_bytes, encoder.length()); } // Allocate storage aligned to double. Since there is a varint at the // beginning of the encoding, the following S2Points will be unaligned, // so we test unaligned S2Point access for UNCOMPRESSED encodings. auto aligned = make_unique(encoder.length() / sizeof(double) + 1); std::memcpy(aligned.get(), encoder.base(), encoder.length()); { // Test un-checked decoding path. Decoder decoder(aligned.get(), encoder.length()); EncodedS2PointVector actual; EXPECT_TRUE(actual.Init(&decoder)); EXPECT_EQ(actual.Decode(), expected); } { // Test checked decoding path. Decoder decoder(aligned.get(), encoder.length()); EncodedS2PointVector actual; S2Error error; EXPECT_TRUE(actual.Init(&decoder, error)); EXPECT_TRUE(error.ok()) << error.message(); EXPECT_EQ(actual.Decode(error), expected); EXPECT_TRUE(error.ok()) << error.message(); } return encoder.length(); } // In order to make it easier to construct tests that encode particular // values, this function duplicates the part of EncodedS2PointVector that // converts an encoded 64-bit value back to an S2Point. S2Point EncodedValueToPoint(uint64_t value, int level) { uint32_t sj, tj; util_bits::DeinterleaveUint32(value, &sj, &tj); int shift = S2CellId::kMaxLevel - level; int si = (((sj << 1) | 1) << shift) & 0x7fffffff; int ti = (((tj << 1) | 1) << shift) & 0x7fffffff; int face = ((sj << shift) >> 30) | (((tj << (shift + 1)) >> 29) & 4); return S2::FaceUVtoXYZ(face, S2::STtoUV(S2::SiTitoST(si)), S2::STtoUV(S2::SiTitoST(ti))).Normalize(); } TEST(EncodedS2PointVectorTest, Empty) { TestEncodedS2PointVector({}, CodingHint::FAST, 1); // Test that an empty vector uses the UNCOMPRESSED encoding. TestEncodedS2PointVector({}, CodingHint::COMPACT, 1); } TEST(EncodedS2PointVectorTest, OnePoint) { TestEncodedS2PointVector({S2Point(1, 0, 0)}, CodingHint::FAST, 25); // Encoding: header (2 bytes), block count (1 byte), block offsets (1 byte), // block header (1 byte), delta (1 byte). TestEncodedS2PointVector({S2Point(1, 0, 0)}, CodingHint::COMPACT, 6); } TEST(EncodedS2PointVectorTest, OnePointWithExceptionsNoOverlap) { // Test encoding a block with one point when other blocks have exceptions // (which changes the encoding for all blocks). The case below yields // delta_bits == 8 and overlap_bits == 0. // // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes) // Block 0: block header (1 byte), 16 deltas (16 bytes), exception (24 bytes) // Block 1: block header (1 byte), delta (1 byte) S2Point a(1, 0, 0); vector points = { S2Point(1, 2, 3).Normalize(), a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a // Second block }; TestEncodedS2PointVector(points, CodingHint::COMPACT, 48); } TEST(EncodedS2PointVectorTest, OnePointWithExceptionsWithOverlap) { // Test encoding a block with one point when other blocks have exceptions // (which changes the encoding for all blocks). The case below yields // delta_bits == 8 and overlap_bits == 4. // // Encoding: header (2 bytes), base (2 bytes), block count (1 byte), // block offsets (2 bytes) // Block 0: header (1 byte), offset (2 bytes), 16 deltas (16 bytes), // exception (24 bytes) // Block 1: header (1 byte), offset (2 bytes), delta (1 byte) S2Point a = S2CellId(0x946df618d0000000).ToPoint(); S2Point b = S2CellId(0x947209e070000000).ToPoint(); vector points = { S2Point(1, 2, 3).Normalize(), a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, b // Second block }; TestEncodedS2PointVector(points, CodingHint::COMPACT, 54); } TEST(EncodedS2PointVectorTest, CellIdWithException) { // Test one point encoded as an S2CellId with one point encoded as an // exception. // // Encoding: header (2 bytes), block count (1 byte), block offsets (1 byte), // block header (1 byte), two deltas (2 bytes), exception (24 bytes). TestEncodedS2PointVector( {MakeCellIdOrDie("1/23").ToPoint(), S2Point(0.1, 0.2, 0.3).Normalize()}, CodingHint::COMPACT, 31); } TEST(EncodedS2PointVectorTest, PointsAtMultipleLevels) { // Test that when points at multiple levels are present, the level with the // most points is chosen (preferring the smallest level in case of ties). // (All other points are encoded as exceptions.) // In this example, the two points at level 5 (on face 1) should be encoded. // It is possible to tell which points are encoded by the length of the // encoding (since different numbers of "base" bytes are encoded). // // Encoding: header (2 bytes), base (1 byte), block count (1 byte), block // offsets (1 byte), block header (1 byte), 5 deltas (5 bytes), S2Point // exceptions (72 bytes). TestEncodedS2PointVector( {MakeCellIdOrDie("2/11001310230102").ToPoint(), MakeCellIdOrDie("1/23322").ToPoint(), MakeCellIdOrDie("3/3").ToPoint(), MakeCellIdOrDie("1/23323").ToPoint(), MakeCellIdOrDie("2/12101023022012").ToPoint()}, CodingHint::COMPACT, 83); } TEST(EncodedS2PointVectorTest, NoOverlapOrExtraDeltaBitsNeeded) { // This function tests the case in GetBlockCodes() where values can be // encoded using the minimum number delta bits and no overlap. From the // comments there: // // Example 1: b_min = 0x72, b_max = 0x7e. The range is 0x0c. This can be // encoded using delta_bits = 4 and overlap_bits = 0, which allows us to // represent an offset of 0x70 and a maximum delta of 0x0f, so that we can // encode values up to 0x7f. // // To set up this test, we need at least two blocks: one to set the global // minimum value, and the other to encode a specific range of deltas. To // make things easier, the first block has a minimum value of zero. // // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes) // Block 0: header (1 byte), 8 deltas (8 bytes) // Block 1: header (1 byte), offset (1 byte), 4 deltas (2 bytes) const int level = 3; vector points(kBlockSize, EncodedValueToPoint(0, level)); points.push_back(EncodedValueToPoint(0x72, level)); points.push_back(EncodedValueToPoint(0x74, level)); points.push_back(EncodedValueToPoint(0x75, level)); points.push_back(EncodedValueToPoint(0x7e, level)); TestEncodedS2PointVector(points, CodingHint::COMPACT, 10 + kBlockSize / 2); } TEST(EncodedS2PointVectorTest, OverlapNeeded) { // Like the above, but tests the following case: // // Example 2: b_min = 0x78, b_max = 0x84. The range is 0x0c, but in this // case it is not sufficient to use delta_bits = 4 and overlap_bits = 0 // because we can again only represent an offset of 0x70, so the maximum // delta of 0x0f only lets us encode values up to 0x7f. However if we // increase the overlap to 4 bits then we can represent an offset of 0x78, // which lets us encode values up to 0x78 + 0x0f = 0x87. // // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes) // Block 0: header (1 byte), 8 deltas (8 bytes) // Block 1: header (1 byte), offset (1 byte), 4 deltas (2 bytes) const int level = 3; vector points(kBlockSize, EncodedValueToPoint(0, level)); points.push_back(EncodedValueToPoint(0x78, level)); points.push_back(EncodedValueToPoint(0x7a, level)); points.push_back(EncodedValueToPoint(0x7c, level)); points.push_back(EncodedValueToPoint(0x84, level)); TestEncodedS2PointVector(points, CodingHint::COMPACT, 10 + kBlockSize / 2); } TEST(EncodedS2PointVectorTest, ExtraDeltaBitsNeeded) { // Like the above, but tests the following case: // // Example 3: b_min = 0x08, b_max = 0x104. The range is 0xfc, so we should // be able to use 8-bit deltas. But even with a 4-bit overlap, we can still // only encode offset = 0 and a maximum value of 0xff. (We don't allow // bigger overlaps because statistically they are not worthwhile.) Instead // we increase the delta size to 12 bits, which handles this case easily. // // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes) // Block 0: header (1 byte), 8 deltas (8 bytes) // Block 1: header (1 byte), 4 deltas (6 bytes) const int level = 3; vector points(kBlockSize, EncodedValueToPoint(0, level)); points.push_back(EncodedValueToPoint(0x08, level)); points.push_back(EncodedValueToPoint(0x4e, level)); points.push_back(EncodedValueToPoint(0x82, level)); points.push_back(EncodedValueToPoint(0x104, level)); TestEncodedS2PointVector(points, CodingHint::COMPACT, 13 + kBlockSize / 2); } TEST(EncodedS2PointVectorTest, ExtraDeltaBitsAndOverlapNeeded) { // Like the above, but tests the following case: // // Example 4: d_min = 0xf08, d_max = 0x1004. The range is 0xfc, so we // should be able to use 8-bit deltas. With 8-bit deltas and no overlap, we // have offset = 0xf00 and a maximum encodable value of 0xfff. With 8-bit // deltas and a 4-bit overlap, we still have offset = 0xf00 and a maximum // encodable value of 0xfff. Even with 12-bit deltas, we have offset = 0 // and we can still only represent 0xfff. However with delta_bits = 12 and // overlap_bits = 4, we can represent offset = 0xf00 and a maximum encodable // value of 0xf00 + 0xfff = 0x1eff. // // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes) // Block 0: header (1 byte), 8 deltas (8 bytes) // Block 1: header (1 byte), offset (1 byte), 4 deltas (6 bytes) const int level = 5; vector points(kBlockSize, EncodedValueToPoint(0, level)); points.push_back(EncodedValueToPoint(0xf08, level)); points.push_back(EncodedValueToPoint(0xf4e, level)); points.push_back(EncodedValueToPoint(0xf82, level)); points.push_back(EncodedValueToPoint(0x1004, level)); TestEncodedS2PointVector(points, CodingHint::COMPACT, 14 + kBlockSize / 2); } TEST(EncodedS2PointVectorTest, SixtyFourBitOffset) { // Tests a case where a 64-bit block offset is needed. // // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes) // Block 0: header (1 byte), 8 deltas (8 bytes) // Block 1: header (1 byte), offset (8 bytes), 2 deltas (1 byte) const int level = S2CellId::kMaxLevel; vector points(kBlockSize, S2CellId::Begin(level).ToPoint()); points.push_back(S2CellId::End(level).prev().ToPoint()); points.push_back(S2CellId::End(level).prev().prev().ToPoint()); TestEncodedS2PointVector(points, CodingHint::COMPACT, 16 + kBlockSize / 2); } TEST(EncodedS2PointVectorTest, AllExceptionsBlock) { // The encoding consists of two blocks; the first contains 16 encodable // values, while the second contains two exceptions. vector points(kBlockSize, EncodedValueToPoint(0, S2CellId::kMaxLevel)); points.push_back(S2Point(0.1, 0.2, 0.3).Normalize()); points.push_back(S2Point(0.3, 0.2, 0.1).Normalize()); // Encoding: header (2 bytes), block count (1 byte), block offsets (2 bytes). // 1st block header (1 byte), 16 deltas (16 bytes). // 2nd block header (1 byte), 2 deltas (1 byte), 2 exceptions (48 bytes). TestEncodedS2PointVector(points, CodingHint::COMPACT, 72); // Encoding: header (2 bytes), 18 S2Points (432 bytes). TestEncodedS2PointVector(points, CodingHint::FAST, 434); } TEST(EncodedS2PointVectorTest, FirstAtAllLevels) { // Test encoding the first S2CellId at each level (which also happens to have // the maximum face, si, and ti values). All such S2CellIds can be encoded in // 6 bytes because most of the bits are zero. for (int level = 0; level <= S2CellId::kMaxLevel; ++level) { SCOPED_TRACE(absl::StrCat("Level = ", level)); TestEncodedS2PointVector({S2CellId::Begin(level).ToPoint()}, CodingHint::COMPACT, 6); } } TEST(EncodedS2PointVectorTest, LastAtAllLevels) { // Test encoding the last S2CellId at each level. It turns out that such // S2CellIds have the largest possible face and ti values, and the minimum // possible si value at that level. Such S2CellIds can be encoded in 6 to 13 // bytes depending on the level. for (int level = 0; level <= S2CellId::kMaxLevel; ++level) { SCOPED_TRACE(absl::StrCat("Level = ", level)); // Note that 8 bit deltas are used to encode blocks of size 1, which // reduces the size of "base" from ((level + 2) / 4) to (level / 4) bytes. int expected_size = 6 + level / 4; TestEncodedS2PointVector({S2CellId::End(level).prev().ToPoint()}, CodingHint::COMPACT, expected_size); } } TEST(EncodedS2PointVectorTest, MaxFaceSiTiAtAllLevels) { // Similar to the test above, but tests encoding the S2CellId at each level // whose face, si, and ti values are all maximal. This turns out to be the // S2CellId whose human-readable form is 5/222...22 (0xb555555555555555), // however for clarity we construct it using S2CellId::FromFaceIJ. for (int level = 0; level <= S2CellId::kMaxLevel; ++level) { SCOPED_TRACE(absl::StrCat("Level = ", level)); S2CellId id = S2CellId::FromFaceIJ(5, S2::kLimitIJ - 1, S2::kLimitIJ - 1) .parent(level); // This encoding is one byte bigger than the previous test at levels 7, 11, // 15, 19, 23, and 27. This is because in the previous test, the // odd-numbered value bits are all zero (except for the face number), which // reduces the number of base bits needed by exactly 1. The encoding size // at level==3 is unaffected because for singleton blocks, the lowest 8 // value bits are encoded in the delta. int expected_size = (level < 4) ? 6 : 6 + (level + 1) / 4; TestEncodedS2PointVector({id.ToPoint()}, CodingHint::COMPACT, expected_size); } } TEST(EncodedS2PointVectorTest, LastTwoPointsAtAllLevels) { // Test encoding the last two S2CellIds at each level. for (int level = 0; level <= S2CellId::kMaxLevel; ++level) { SCOPED_TRACE(absl::StrCat("Level = ", level)); S2CellId id = S2CellId::End(level).prev(); // Notice that this costs only 4 bits more than encoding the last S2CellId // by itself (see LastAtAllLevels). This is because encoding a block of // size 1 uses 8-bit deltas (which reduces the size of "base" by 4 bits), // while this test uses two 4-bit deltas. int expected_size = 6 + (level + 2) / 4; TestEncodedS2PointVector({id.ToPoint(), id.prev().ToPoint()}, CodingHint::COMPACT, expected_size); } } TEST(EncodedS2PointVectorTest, ManyDuplicatePointsAtAllLevels) { // Test encoding 32 copies of the last S2CellId at each level. This uses // between 27 and 38 bytes depending on the level. (Note that the encoding // can use less than 1 byte per point in this situation.) for (int level = 0; level <= S2CellId::kMaxLevel; ++level) { SCOPED_TRACE(absl::StrCat("Level = ", level)); S2CellId id = S2CellId::End(level).prev(); // Encoding: header (2 bytes), base ((level + 2) / 4 bytes), block count // (1 byte), block offsets (2 bytes), block headers (2 bytes), 32 deltas // (16 bytes). At level 30 the encoding size goes up by 1 byte because // we can't encode an 8 byte "base" value, so instead this case uses a // base of 7 bytes plus a one-byte offset in each of the 2 blocks. int expected_size = 23 + (level + 2) / 4; if (level == 30) expected_size += 1; vector points(32, id.ToPoint()); TestEncodedS2PointVector(points, CodingHint::COMPACT, expected_size); } } TEST(EncodedS2PointVectorTest, SnappedFractalLoops) { absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "SNAPPED_FRACTAL_LOOPS", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); int kMaxPoints = 3 << 14; for (int num_points = 3; num_points <= kMaxPoints; num_points *= 4) { size_t s2polygon_size = 0, lax_polygon_size = 0; for (int i = 0; i < 10; ++i) { S2Fractal fractal(bitgen); fractal.SetLevelForApproxMaxEdges(num_points); Matrix3x3_d frame = s2random::Frame(bitgen); auto loop = fractal.MakeLoop(frame, S2Testing::KmToAngle(10)); vector points; for (int j = 0; j < loop->num_vertices(); ++j) { points.push_back(S2CellId(loop->vertex(j)).ToPoint()); } S2Polygon s2polygon(make_unique(points)); Encoder encoder; s2polygon.Encode(&encoder); s2polygon_size += encoder.length(); // S2LaxPolygonShape has 2 extra bytes of overhead to encode one loop. lax_polygon_size += TestEncodedS2PointVector(points, CodingHint::COMPACT, -1) + 2; } absl::PrintF("n=%5d s2=%9zu lax=%9zu\n", num_points, s2polygon_size, lax_polygon_size); } } void TestRoundtripEncoding(s2coding::CodingHint hint) { // Ensures that the EncodedS2PointVector can be encoded and decoded without // loss. const int level = 3; vector points(kBlockSize, EncodedValueToPoint(0, level)); points.push_back(EncodedValueToPoint(0x78, level)); points.push_back(EncodedValueToPoint(0x7a, level)); points.push_back(EncodedValueToPoint(0x7c, level)); points.push_back(EncodedValueToPoint(0x84, level)); EncodedS2PointVector a_vector; Encoder a_encoder; EncodedS2PointVector b_vector; Encoder b_encoder; // Encode and decode from a vector. { EncodeS2PointVector(points, hint, &a_encoder); Decoder decoder(a_encoder.base(), a_encoder.length()); ASSERT_TRUE(a_vector.Init(&decoder)); } ASSERT_EQ(points, a_vector.Decode()); // Encode and decode from an EncodedS2PointVector. { a_vector.Encode(&b_encoder); Decoder decoder(b_encoder.base(), b_encoder.length()); ASSERT_TRUE(b_vector.Init(&decoder)); } EXPECT_EQ(points, b_vector.Decode()); } TEST(EncodedS2PointVectorTest, RoundtripEncodingFast) { TestRoundtripEncoding(s2coding::CodingHint::FAST); } TEST(EncodedS2PointVectorTest, RoundtripEncodingCompact) { TestRoundtripEncoding(s2coding::CodingHint::COMPACT); } static void EncodePoints(int num_points, CodingHint hint, Encoder* encoder) { vector points = S2Testing::MakeRegularPoints( MakePointOrDie("23:16"), S2Testing::KmToAngle(10), num_points); for (S2Point& point : points) { point = S2CellId(point).ToPoint(); } EncodeS2PointVector(points, hint, encoder); } // Measures accessing points sequentially. This corresponds to the use case // where the vector is decoded upon initialization (e.g., S2LaxPolygonShape). static void BM_DecodePointSequentially(benchmark::State& state) { CodingHint hint = state.range(0) ? CodingHint::COMPACT : CodingHint::FAST; int num_points = state.range(1); Encoder encoder; EncodePoints(num_points, hint, &encoder); EncodedS2PointVector encoded_points; Decoder decoder(encoder.base(), encoder.length()); ABSL_CHECK(encoded_points.Init(&decoder)); std::vector points(num_points); while (state.KeepRunningBatch(num_points)) { for (int i = 0; i < num_points; ++i) { points[i] = encoded_points[i]; } } benchmark::DoNotOptimize(points); state.SetItemsProcessed(state.iterations()); } BENCHMARK(BM_DecodePointSequentially) ->ArgPair(0, 10)->ArgPair(0, 10000) ->ArgPair(1, 10)->ArgPair(1, 10000); // Measures accessing edges (adjacent point pairs) sequentially. This // corresponds to the common situation where the edges in an S2ShapeIndex cell // span a contiguous range of edge ids. The big difference compared to the // benchmark above is that each point is accessed twice in a row, since the // last vertex of one edge is typically the same as the first vertex of the // next edge. static void BM_GetEdgeSequentially(benchmark::State& state) { CodingHint hint = state.range(0) ? CodingHint::COMPACT : CodingHint::FAST; int num_points = state.range(1); Encoder encoder; EncodePoints(num_points, hint, &encoder); EncodedS2PointVector encoded_points; Decoder decoder(encoder.base(), encoder.length()); ABSL_CHECK(encoded_points.Init(&decoder)); std::vector points(num_points); while (state.KeepRunningBatch(num_points - 1)) { for (int i = 0; i < num_points - 1; ++i) { points[i] = encoded_points[i]; points[i + 1] = encoded_points[i + 1]; } } benchmark::DoNotOptimize(points); state.SetItemsProcessed(state.iterations() * 2); } BENCHMARK(BM_GetEdgeSequentially) ->ArgPair(0, 10)->ArgPair(0, 10000) ->ArgPair(1, 10)->ArgPair(1, 10000); // Fuzz testing of the decoder. void DecodePointVector(std::string data) { EncodedS2PointVector v; Decoder decoder(data.data(), data.size()); S2Error error; if (v.Init(&decoder, error)) { v.Decode(error); } } TEST(EncodedS2PointVectorTest, DecodeNeverCrashesRegression1) { DecodePointVector("i\370\305\201"); } TEST(EncodedS2PointVectorTest, DecodeNeverCrashesRegression2) { DecodePointVector( "\201\252\305+\010\023\304\n\274\3271^7\261\261iiY\261\261\261\261\261" "\253\313\220\254DDDDV\320"); } TEST(EncodedS2PointVectorTest, DecodeNeverCrashesRegression3) { DecodePointVector( "\351\010\010\010\010\010\0107\274\361\030fo[\210O\363\214]\010\021n" "\265W=(\014\014\014\014\203\034"); } TEST(EncodedS2PointVectorTest, DecodeNeverCrashesRegression4) { DecodePointVector( "\331\010\010\014\363+\214O\230\200\230{$$\314$\210b\222\034\210\210\232" "\210\210\212\214\034"); } } // namespace s2coding src/s2/encoded_s2shape_index.cc000066400000000000000000000175641524103652300167330ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_s2shape_index.h" #include #include #include #include #include #include "s2/base/casts.h" #include "absl/base/optimization.h" #include "absl/numeric/bits.h" #include "s2/util/coding/coder.h" #include "s2/util/coding/varint.h" #include "s2/encoded_s2cell_id_vector.h" #include "s2/encoded_string_vector.h" #include "s2/mutable_s2shape_index.h" #include "s2/s2cell_id.h" #include "s2/s2point.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" using std::make_unique; using std::unique_ptr; using std::vector; S2Shape* EncodedS2ShapeIndex::GetShape(int id) const { // This method is called when a shape has not been decoded yet. unique_ptr shape = (*shape_factory_)[id]; S2Shape* expected = kUndecodedShape(); if (shapes_[id].compare_exchange_strong(expected, shape.get(), std::memory_order_acq_rel)) { return shape.release(); // Ownership has been transferred to shapes_. } return expected; // Another thread updated shapes_[id] first. } const S2ShapeIndexCell* EncodedS2ShapeIndex::GetCell(int i) const { // memory_order_release ensures that no reads or writes in the current // thread can be reordered after this store, and all writes in the current // thread are visible to other threads that acquire the same atomic // variable. // // memory_order_acquire ensures that no reads or writes in the current // thread can be reordered before this load, and all writes in other threads // that release the same atomic variable are visible in this thread. // // We use this to implement lock-free synchronization on the read path as // follows: // // 1. cells_decoded(i) is updated using acquire/release semantics // 2. cells_[i] is written before cells_decoded(i) // 3. cells_[i] is read after cells_decoded(i) // // Note that we do still use a lock for the write path to ensure that // cells_[i] and cell_decoded(i) are updated together atomically. if (cell_decoded(i)) return cells_[i]; // Decode the cell before acquiring the spinlock in order to minimize the // time that the lock is held. auto cell = make_unique(); Decoder decoder = encoded_cells_.GetDecoder(i); if (!cell->Decode(num_shape_ids(), &decoder)) { return nullptr; } // Recheck cell_decoded(i) once we hold the lock in case another thread // has decoded this cell in the meantime. SpinLockHolder l(cells_lock_); if (cell_decoded(i)) return cells_[i]; // Update the cell, setting cells_[i] before cell_decoded(i). cells_[i] = cell.get(); set_cell_decoded(i); if (cell_cache_.size() < static_cast(max_cell_cache_size())) { cell_cache_.push_back(i); } return cell.release(); // Ownership has been transferred to cells_. } EncodedS2ShapeIndex::EncodedS2ShapeIndex() = default; EncodedS2ShapeIndex::~EncodedS2ShapeIndex() { // Although Minimize() does slightly more than required for destruction // (i.e., it resets vector elements to their default values), this does not // affect benchmark times. Minimize(); } bool EncodedS2ShapeIndex::Init(Decoder* decoder, const ShapeFactory& shape_factory) { Minimize(); uint64_t max_edges_version; if (!decoder->get_varint64(&max_edges_version)) return false; version_ = max_edges_version & 3; if (version_ != MutableS2ShapeIndex::kCurrentEncodingVersionNumber) { return false; } options_.set_max_edges_per_cell(max_edges_version >> 2); // AtomicShape is a subtype of std::atomic that changes the // default constructor value to kUndecodedShape(). This saves the effort of // initializing all the elements twice. shapes_ = vector(shape_factory.size()); shape_factory_ = shape_factory.Clone(); if (!cell_ids_.Init(decoder)) return false; // The cells_ elements are *uninitialized memory*. Instead we have bit // vector (cells_decoded_) to indicate which elements of cells_ are valid. // This reduces constructor times by more than a factor of 50, since rather // than needing to initialize one 64-bit pointer per cell to zero, we only // need to initialize one bit per cell to zero. // // For very large S2ShapeIndexes the internal memset() call to initialize // cells_decoded_ still takes about 1.3 microseconds per million cells // (assuming an optimized implementation that writes 32 bytes per cycle), // but this seems reasonable relative to other likely costs (I/O, etc). // // NOTE(ericv): DO NOT use make_unique<> here! make_unique<> allocates memory // using "new T[n]()", which initializes all elements of the array. This // slows down some benchmarks by over 100x. // // cells_ = make_unique[](cell_ids_.size()); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // NO NO NO cells_.reset(new S2ShapeIndexCell*[cell_ids_.size()]); cells_decoded_ = vector>((cell_ids_.size() + 63) >> 6); return encoded_cells_.Init(decoder); } void EncodedS2ShapeIndex::Encode(Encoder* encoder) const { // Re-encode the max edges and version number. encoder->Ensure(Varint::kMax64); uint64_t max_edges = options_.max_edges_per_cell(); encoder->put_varint64(max_edges << 2 | version_); // And copy the encoded cell ids and cells. cell_ids_.Encode(encoder); encoded_cells_.Encode(encoder); } void EncodedS2ShapeIndex::Minimize() { if (cells_ == nullptr) return; // Not initialized yet. for (auto& atomic_shape : shapes_) { S2Shape* shape = atomic_shape.load(std::memory_order_relaxed); if (shape != kUndecodedShape() && shape != nullptr) { atomic_shape.store(kUndecodedShape(), std::memory_order_relaxed); delete shape; } } if (cell_cache_.size() < static_cast(max_cell_cache_size())) { // When only a tiny fraction of the cells are decoded, we keep track of // those cells in cell_cache_ to avoid the cost of scanning the // cells_decoded_ vector. (The cost is only about 1 cycle per 64 cells, // but for a huge polygon with 1 million cells that's still 16000 cycles.) for (int pos : cell_cache_) { cells_decoded_[pos >> 6].store(0, std::memory_order_relaxed); delete cells_[pos]; } } else { // Scan the cells_decoded_ vector looking for cells that must be deleted. for (int i = cells_decoded_.size(); --i >= 0;) { uint64_t bits = cells_decoded_[i].load(std::memory_order_relaxed); if (bits == 0) continue; do { ABSL_ASSUME(bits != 0); int offset = absl::countr_zero(bits); delete cells_[(i << 6) + offset]; bits &= bits - 1; } while (bits != 0); cells_decoded_[i].store(0, std::memory_order_relaxed); } } cell_cache_.clear(); } size_t EncodedS2ShapeIndex::SpaceUsed() const { // TODO(ericv): Add SpaceUsed() method to S2Shape base class,and include // memory owned by the allocated S2Shapes (here and in S2ShapeIndex). size_t size = sizeof(*this); size += shapes_.capacity() * sizeof(std::atomic); size += cell_ids_.size() * sizeof(std::atomic); // cells_ size += cells_decoded_.capacity() * sizeof(std::atomic); size += cell_cache_.capacity() * sizeof(int); return size; } src/s2/encoded_s2shape_index.h000066400000000000000000000357221524103652300165710ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_ENCODED_S2SHAPE_INDEX_H_ #define S2_ENCODED_S2SHAPE_INDEX_H_ #include #include #include #include #include #include "absl/log/absl_check.h" #include "absl/strings/cord.h" #include "s2/util/coding/coder.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/encoded_s2cell_id_vector.h" #include "s2/encoded_string_vector.h" #include "s2/mutable_s2shape_index.h" #include "s2/s2cell_id.h" #include "s2/s2point.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" // EncodedS2ShapeIndex is an S2ShapeIndex implementation that works directly // with encoded data. Rather than decoding everything in advance, geometry is // decoded incrementally (down to individual edges) as needed. It can be // initialized from a single block of data in nearly constant time (about 1.3 // microseconds per million edges). This saves large amounts of memory and is // also much faster in the common situation where geometric data is loaded // from somewhere, decoded, and then only a single operation is performed on // it. It supports all S2ShapeIndex operations including boolean operations, // measuring distances, etc. // // The speedups can be over 1000x for large geometric objects. For example // vertices and 50,000 loops. If this geometry is represented as an // S2Polygon, then simply decoding it takes ~250ms and building its internal // S2ShapeIndex takes a further ~1500ms. These times are much longer than the // time needed for many operations, e.g. e.g. measuring the distance from the // polygon to one of its vertices takes only about 0.001ms. // // If the same geometry is represented using EncodedLaxPolygonShape and // EncodedS2ShapeIndex, initializing the index takes only 0.005ms. The // distance measuring operation itself takes slightly longer than before // (0.0013ms vs. the original 0.001ms) but the overall time is now much lower // (~0.007ms vs. 1750ms). This is possible because the new classes decode // data lazily (only when it is actually needed) and with fine granularity // (down to the level of individual edges). The overhead associated with this // incremental decoding is small; operations are typically 25% slower compared // to fully decoding the MutableS2ShapeIndex and its underlying shapes. // // EncodedS2ShapeIndex also uses less memory than MutableS2ShapeIndex. The // encoded data is contiguous block of memory that is typically between 4-20% // of the original index size (see MutableS2ShapeIndex::Encode for examples). // Constructing the EncodedS2ShapeIndex uses additional memory, but even so // the total memory usage immediately after construction is typically 25-35% // of the corresponding MutableS2ShapeIndex size. // // Note that MutableS2ShapeIndex will still be faster and use less memory if // you need to decode the entire index. Similarly MutableS2ShapeIndex will be // faster if you plan to execute a large number of operations on it. The main // advantage of EncodedS2ShapeIndex is that it is much faster and uses less // memory when only a small portion of the data needs to be decoded. // // Example code showing how to create an encoded index: // // Encoder encoder; // s2shapeutil::CompactEncodeTaggedShapes(index, encoder); // index.Encode(encoder); // string encoded(encoder.base(), encoder.length()); // Encoded data. // // Example code showing how to use an encoded index: // // Decoder decoder(encoded.data(), encoded.size()); // EncodedS2ShapeIndex index; // index.Init(&decoder, s2shapeutil::LazyDecodeShapeFactory(&decoder)); // S2ClosestEdgeQuery query(&index); // S2ClosestEdgeQuery::PointTarget target(test_point); // if (query.IsDistanceLessOrEqual(&target, limit)) { // ... // } // // Note that EncodedS2ShapeIndex does not make a copy of the encoded data, and // therefore the client must ensure that this data outlives the // EncodedS2ShapeIndex object. // // There are a number of built-in classes that work with S2ShapeIndex objects. // Generally these classes accept any collection of geometry that can be // represented by an S2ShapeIndex, i.e. any combination of points, polylines, // and polygons. Such classes include: // // - S2ContainsPointQuery: returns the shape(s) that contain a given point. // // - S2ClosestEdgeQuery: returns the closest edge(s) to a given point, edge, // S2CellId, or S2ShapeIndex. // // - S2CrossingEdgeQuery: returns the edge(s) that cross a given edge. // // - S2BooleanOperation: computes boolean operations such as union, // and boolean predicates such as containment. // // - S2ShapeIndexRegion: can be used together with S2RegionCoverer to // approximate geometry as a set of S2CellIds. // // - S2ShapeIndexBufferedRegion: computes approximations that have been // expanded by a given radius. // // EncodedS2ShapeIndex is thread-compatible, meaning that const methods are // thread safe, and non-const methods are not thread safe. The only non-const // method is Minimize(), so if you plan to call Minimize() while other threads // are actively using the index that you must use an external reader-writer // lock such as absl::Mutex to guard access to it. (There is no global state // and therefore each index can be guarded independently.) class EncodedS2ShapeIndex final : public S2ShapeIndex { public: using Options = MutableS2ShapeIndex::Options; using ShapeFactory = S2ShapeIndex::ShapeFactory; // Creates an index that must be initialized by calling Init(). EncodedS2ShapeIndex(); ~EncodedS2ShapeIndex() override; // Initializes the EncodedS2ShapeIndex, returning true on success. // // This method does not decode the S2Shape objects in the index; this is // the responsibility of the client-provided function "shape_factory" // (see s2shapeutil_coding.h). Example usage: // // index.Init(decoder, s2shapeutil::LazyDecodeShapeFactory(decoder)); // // Note that the encoded shape vector must *precede* the encoded S2ShapeIndex // in the Decoder's data buffer in this example. bool Init(Decoder* decoder, const ShapeFactory& shape_factory); // Copies the encoded byte stream into a new encoder. void Encode(Encoder* encoder) const override; const Options& options() const { return options_; } // The number of distinct shape ids in the index. This equals the number of // shapes in the index provided that no shapes have ever been removed. // (Shape ids are not reused.) int num_shape_ids() const override { return shapes_.size(); } // Return a pointer to the shape with the given id. // // REQUIRES: 0 <= id < num_shape_ids() const S2Shape* shape(int id) const override; // Minimizes memory usage by requesting that any data structures that can be // rebuilt should be discarded. This method invalidates all iterators. // // Like all non-const methods, this method is not thread-safe. void Minimize() override; class Iterator final : public IteratorBase { public: // Default constructor; must be followed by a call to Init(). Iterator(); // Constructs an iterator positioned as specified. By default iterators // are unpositioned, since this avoids an extra seek in this situation // where one of the seek methods (such as Locate) is immediately called. // // If you want to position the iterator at the beginning, e.g. in order to // loop through the entire index, do this instead: // // for (EncodedS2ShapeIndex::Iterator it(&index, S2ShapeIndex::BEGIN); // !it.done(); it.Next()) { ... } explicit Iterator(const EncodedS2ShapeIndex* index, InitialPosition pos = UNPOSITIONED); // Initializes an iterator for the given EncodedS2ShapeIndex. void Init(const EncodedS2ShapeIndex* index, InitialPosition pos = UNPOSITIONED); S2CellId id() const override; bool done() const override; const S2ShapeIndexCell& cell() const override; // S2CellIterator API: void Begin() override; void Finish() override; void Next() override; bool Prev() override; void Seek(S2CellId target) override; bool Locate(const S2Point& target) override { return LocateImpl(*this, target); } S2CellRelation Locate(S2CellId target) override { return LocateImpl(*this, target); } std::unique_ptr Clone() const override { return std::make_unique(*this); } private: const EncodedS2ShapeIndex* index_ = nullptr; int32_t cell_pos_; // Current position in the vector of index cells. int32_t num_cells_; }; // Returns the number of bytes currently occupied by the index (including any // unused space at the end of vectors, etc). It has the same thread safety // as the other "const" methods (see introduction). size_t SpaceUsed() const override; protected: std::unique_ptr NewIterator(InitialPosition pos) const override; private: friend class Iterator; // Returns a value indicating that a shape has not been decoded yet. inline static S2Shape* kUndecodedShape() { return reinterpret_cast(1); } // Like std::atomic, but defaults to kUndecodedShape(). class AtomicShape : public std::atomic { public: AtomicShape() : std::atomic(kUndecodedShape()) {} }; S2Shape* GetShape(int id) const; const S2ShapeIndexCell* GetCell(int i) const; bool cell_decoded(int i) const; void set_cell_decoded(int i) const; int max_cell_cache_size() const; std::unique_ptr shape_factory_; // The options specified for this index. Options options_; // The index encoding version. uint8_t version_; // A vector containing all shapes in the index. Initially all shapes are // set to kUndecodedShape(); as shapes are decoded, they are added to the // vector using std::atomic::compare_exchange_strong. mutable std::vector shapes_; // A vector containing the S2CellIds of each cell in the index. s2coding::EncodedS2CellIdVector cell_ids_; // A vector containing the encoded contents of each cell in the index. s2coding::EncodedStringVector encoded_cells_; // A raw array containing the decoded contents of each cell in the index. // Initially all values are *uninitialized memory*. The cells_decoded_ // field below keeps track of which elements are present. mutable std::unique_ptr cells_; // A bit vector indicating which elements of cells_ have been decoded. // All other elements of cells_ contain uninitialized (random) memory. mutable std::vector> cells_decoded_; // In order to minimize destructor time when very few cells of a large // S2ShapeIndex are needed, we keep track of the indices of the first few // cells to be decoded. This lets us avoid scanning the cells_decoded_ // vector when the number of cells decoded is very small. mutable std::vector cell_cache_; // Protects all updates to cells_ and cells_decoded_. mutable SpinLock cells_lock_; EncodedS2ShapeIndex(const EncodedS2ShapeIndex&) = delete; void operator=(const EncodedS2ShapeIndex&) = delete; }; ////////////////// Implementation details follow //////////////////// inline EncodedS2ShapeIndex::Iterator::Iterator( const EncodedS2ShapeIndex* index, InitialPosition pos) { Init(index, pos); } inline void EncodedS2ShapeIndex::Iterator::Init( const EncodedS2ShapeIndex* index, InitialPosition pos) { index_ = index; num_cells_ = index->cell_ids_.size(); cell_pos_ = (pos == BEGIN) ? 0 : num_cells_; } inline S2CellId EncodedS2ShapeIndex::Iterator::id() const { if (done()) { return S2CellId::Sentinel(); } return index_->cell_ids_[cell_pos_]; } inline bool EncodedS2ShapeIndex::Iterator::done() const { return cell_pos_ == num_cells_; } inline const S2ShapeIndexCell& EncodedS2ShapeIndex::Iterator::cell() const { ABSL_DCHECK(!done()); return *index_->GetCell(cell_pos_); } inline void EncodedS2ShapeIndex::Iterator::Begin() { cell_pos_ = 0; } inline void EncodedS2ShapeIndex::Iterator::Finish() { cell_pos_ = num_cells_; } inline void EncodedS2ShapeIndex::Iterator::Next() { ABSL_DCHECK(!done()); ++cell_pos_; } inline bool EncodedS2ShapeIndex::Iterator::Prev() { if (cell_pos_ == 0) { return false; } --cell_pos_; return true; } inline void EncodedS2ShapeIndex::Iterator::Seek(S2CellId target) { cell_pos_ = index_->cell_ids_.lower_bound(target); } inline std::unique_ptr EncodedS2ShapeIndex::NewIterator(InitialPosition pos) const { return std::make_unique(this, pos); } inline const S2Shape* EncodedS2ShapeIndex::shape(int id) const { const S2Shape* shape = shapes_[id].load(std::memory_order_acquire); if (shape != kUndecodedShape()) return shape; return GetShape(id); } // Returns true if the given cell has already been decoded. inline bool EncodedS2ShapeIndex::cell_decoded(int i) const { // cell_decoded(i) uses acquire/release synchronization (see .cc file). uint64_t group_bits = cells_decoded_[i >> 6].load(std::memory_order_acquire); return (group_bits & (1ULL << (i & 63))) != 0; } // Marks the given cell as having been decoded. // REQUIRES: cells_lock_ is held inline void EncodedS2ShapeIndex::set_cell_decoded(int i) const { ABSL_DCHECK(cells_lock_.IsHeld()); // We use memory_order_release for the store operation below to ensure that // cells_decoded(i) sees the most recent value, however we can use // memory_order_relaxed for the load because cells_lock_ is held. std::atomic* group = &cells_decoded_[i >> 6]; uint64_t bits = group->load(std::memory_order_relaxed); group->store(bits | 1ULL << (i & 63), std::memory_order_release); } inline int EncodedS2ShapeIndex::max_cell_cache_size() const { // The cell cache is sized so that scanning decoded_cells_ in the destructor // costs about 30 cycles per decoded cell in the worst case. (This overhead // is acceptable relative to the other costs of decoding each cell.) // // For example, if there are 65,536 cells then we won't need to scan // encoded_cells_ unless we decode at least (65536/2048) == 32 cells. It // takes about 1 cycle per 64 cells to scan encoded_cells_, so that works // out to (65536/64) == 1024 cycles. However this cost is amortized over // the 32 cells decoded, which works out to 32 cycles per cell. return cell_ids_.size() >> 11; } #endif // S2_ENCODED_S2SHAPE_INDEX_H_ src/s2/encoded_s2shape_index_test.cc000066400000000000000000000726111524103652300177640ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_s2shape_index.h" #include #include #include #include #include #include #include #include #include #include "absl/base/call_once.h" #include "absl/flags/flag.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/log/log_streamer.h" #include "absl/random/random.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "s2/util/coding/coder.h" #include "s2/mutable_s2shape_index.h" #include "s2/s1angle.h" #include "s2/s2builder.h" #include "s2/s2builder_layer.h" #include "s2/s2builderutil_s2polyline_layer.h" #include "s2/s2builderutil_snap_functions.h" #include "s2/s2cap.h" #include "s2/s2cell_id.h" #include "s2/s2closest_edge_query.h" #include "s2/s2coder.h" #include "s2/s2contains_point_query.h" #include "s2/s2edge_distances.h" #include "s2/s2error.h" #include "s2/s2fractal.h" #include "s2/s2latlng.h" #include "s2/s2lax_polygon_shape.h" #include "s2/s2lax_polyline_shape.h" #include "s2/s2loop.h" #include "s2/s2point.h" #include "s2/s2point_vector_shape.h" #include "s2/s2pointutil.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2random.h" #include "s2/s2shape.h" #include "s2/s2shapeutil_coding.h" #include "s2/s2shapeutil_testing.h" #include "s2/s2testing.h" #include "s2/s2text_format.h" #include "s2/thread_testing.h" #include "s2/util/math/matrix3x3.h" #include "s2/util/random/shared_bit_gen.h" using absl::StrCat; using s2builderutil::S2CellIdSnapFunction; using s2builderutil::S2PolylineLayer; using std::make_unique; using std::max; using std::string; using std::unique_ptr; using std::vector; template bool DecodeHomegeneousShapeIndex(EncodedS2ShapeIndex* index, Decoder* decoder) { return index->Init(decoder, s2shapeutil::HomogeneousShapeFactory(decoder)); } template void TestEncodedS2ShapeIndex(const MutableS2ShapeIndex& expected, size_t expected_bytes) { Encoder encoder; s2shapeutil::EncodeHomogeneousShapes(expected, &encoder); size_t shapes_bytes = encoder.length(); expected.Encode(&encoder); EXPECT_EQ(expected_bytes, encoder.length() - shapes_bytes); Decoder decoder(encoder.base(), encoder.length()); EncodedS2ShapeIndex actual; ASSERT_TRUE(DecodeHomegeneousShapeIndex(&actual, &decoder)); EXPECT_EQ(expected.options().max_edges_per_cell(), actual.options().max_edges_per_cell()); s2testing::ExpectEqual(expected, actual); // Make sure that re-encoding the index gives us back the original bytes. Encoder new_encoder; actual.Encode(&new_encoder); EXPECT_EQ(encoder.length() - shapes_bytes, new_encoder.length()); const char* index_base = encoder.base() + shapes_bytes; EXPECT_EQ(memcmp(index_base, new_encoder.base(), new_encoder.length()), 0); } TEST(EncodedS2ShapeIndex, Empty) { MutableS2ShapeIndex index; TestEncodedS2ShapeIndex(index, 4); } TEST(EncodedS2ShapeIndex, OneEdge) { MutableS2ShapeIndex index; index.Add(s2textformat::MakeLaxPolylineOrDie("1:1, 2:2")); TestEncodedS2ShapeIndex(index, 8); } TEST(EncodedS2ShapeIndex, RegularLoops) { struct TestCase { int num_edges; size_t expected_bytes; }; vector test_cases = { {4, 8}, {8, 8}, {16, 16}, {64, 77}, {256, 327}, {4096, 8813}, {65536, 168291}, }; for (const auto& test_case : test_cases) { MutableS2ShapeIndex index; SCOPED_TRACE(StrCat("num_edges = ", test_case.num_edges)); S2Polygon polygon(S2Loop::MakeRegularLoop(S2Point(3, 2, 1).Normalize(), S1Angle::Degrees(0.1), test_case.num_edges)); index.Add(make_unique(polygon)); TestEncodedS2ShapeIndex( index, test_case.expected_bytes); } } #if !defined( __EMSCRIPTEN__) && !(defined(__ANDROID__) && defined(__i386__)) // TODO(b/232496949): This test relies on `mt19937_64` return values because // it tests an exact encoded byte size. Either change it to accept a range // of sizes, or decode and check either the number of shapes, or possibly // the points themselves by resetting the RNG state. TEST(EncodedS2ShapeIndex, OverlappingPointClouds) { std::mt19937_64 bitgen; struct TestCase { int num_shapes, num_points_per_shape; size_t expected_bytes; }; vector test_cases = { {1, 50, 85}, {2, 100, 600}, {4, 100, 1426}, }; S2Cap cap(S2Point(0.1, -0.4, 0.3).Normalize(), S1Angle::Degrees(1)); for (const auto& test_case : test_cases) { MutableS2ShapeIndex index; SCOPED_TRACE(StrCat("num_shapes = ", test_case.num_shapes)); for (int i = 0; i < test_case.num_shapes; ++i) { vector points; for (int j = 0; j < test_case.num_points_per_shape; ++j) { points.push_back(s2random::SamplePoint(bitgen, cap)); } index.Add(make_unique(points)); } TestEncodedS2ShapeIndex( index, test_case.expected_bytes); } } // TODO(b/232496949): This test relies on `mt19937_64` return values. TEST(EncodedS2ShapeIndex, OverlappingPolylines) { std::mt19937_64 bitgen; struct TestCase { int num_shapes, num_shape_edges; size_t expected_bytes; }; vector test_cases = { {2, 50, 128}, {10, 50, 808}, {20, 50, 2499}, }; S2Cap cap(S2Point(-0.2, -0.3, 0.4).Normalize(), S1Angle::Degrees(0.1)); for (const auto& test_case : test_cases) { S1Angle edge_len = 2 * cap.GetRadius() / test_case.num_shape_edges; MutableS2ShapeIndex index; SCOPED_TRACE(StrCat("num_shapes = ", test_case.num_shapes)); for (int i = 0; i < test_case.num_shapes; ++i) { S2Point a = s2random::SamplePoint(bitgen, cap); S2Point b = s2random::Point(bitgen); vector vertices; int n = test_case.num_shape_edges; for (int j = 0; j <= n; ++j) { vertices.push_back(S2::GetPointOnLine(a, b, j * edge_len)); } index.Add(make_unique(vertices)); } TestEncodedS2ShapeIndex( index, test_case.expected_bytes); } } // TODO(b/232496949): This test relies on `mt19937_64` return values. TEST(EncodedS2ShapeIndex, OverlappingLoops) { std::mt19937_64 bitgen; struct TestCase { int num_shapes, max_edges_per_loop; size_t expected_bytes; }; vector test_cases = { {2, 250, 412}, {5, 250, 1208}, {25, 50, 3162}, }; S2Cap cap(S2Point(-0.1, 0.25, 0.2).Normalize(), S1Angle::Degrees(3)); for (const auto& test_case : test_cases) { MutableS2ShapeIndex index; SCOPED_TRACE(StrCat("num_shapes = ", test_case.num_shapes)); for (int i = 0; i < test_case.num_shapes; ++i) { S2Point center = s2random::SamplePoint(bitgen, cap); double radius_fraction = absl::Uniform(bitgen, 0.0, 1.0); // Scale the number of edges so that they are all about the same length // (similar to modeling all geometry at a similar resolution). int num_edges = max(3.0, test_case.max_edges_per_loop * radius_fraction); S2Polygon polygon(S2Loop::MakeRegularLoop( center, cap.GetRadius() * radius_fraction, num_edges)); index.Add(make_unique(polygon)); } TestEncodedS2ShapeIndex( index, test_case.expected_bytes); } } #endif // defined(__EMSCRIPTEN__) // Like S2PolylineLayer, but converts the polyline to an S2LaxPolylineShape // and adds it to an S2ShapeIndex (if the polyline is non-empty). class IndexedLaxPolylineLayer : public S2Builder::Layer { public: using Options = S2PolylineLayer::Options; explicit IndexedLaxPolylineLayer(MutableS2ShapeIndex* index, const Options& options = Options()) : index_(index), polyline_(make_unique()), layer_(polyline_.get(), options) {} GraphOptions graph_options() const override { return layer_.graph_options(); } void Build(const Graph& g, S2Error* error) override { layer_.Build(g, error); if (error->ok() && polyline_->num_vertices() > 0) { index_->Add(make_unique(*polyline_)); } } private: MutableS2ShapeIndex* index_; unique_ptr polyline_; S2PolylineLayer layer_; }; TEST(EncodedS2ShapeIndex, SnappedFractalPolylines) { absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "SNAPPED_FRACTAL_POLYLINES", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); MutableS2ShapeIndex index; S2Builder builder{S2Builder::Options{S2CellIdSnapFunction()}}; for (int i = 0; i < 5; ++i) { builder.StartLayer(make_unique(&index)); S2Fractal fractal(bitgen); fractal.SetLevelForApproxMaxEdges(3 * 256); auto frame = S2::GetFrame(S2LatLng::FromDegrees(10, i).ToPoint()); auto loop = fractal.MakeLoop(frame, S1Angle::Degrees(0.1)); vector vertices; S2Testing::AppendLoopVertices(*loop, &vertices); S2Polyline polyline(vertices); builder.AddPolyline(polyline); } S2Error error; ASSERT_TRUE(builder.Build(&error)) << error.message(); TestEncodedS2ShapeIndex( index, 8698); } // A test that repeatedly minimizes "index_" in one thread and then reads the // index_ concurrently from several other threads. When all threads have // finished reading, the first thread minimizes the index again. // // Note that Minimize() is non-const and therefore does not need to be tested // concurrently with the const methods. class LazyDecodeTest : public s2testing::ReaderWriterTest { public: LazyDecodeTest() { // We generate one shape per dimension. Each shape has vertices uniformly // distributed across the sphere, and the vertices for each dimension are // different. Having fewer cells in the index is more likely to trigger // race conditions, and so shape 0 has 384 points, shape 1 is a polyline // with 96 vertices, and shape 2 is a polygon with 24 vertices. MutableS2ShapeIndex input; for (int dim = 0; dim < 3; ++dim) { int level = 3 - dim; // See comments above. vector vertices; for (auto id = S2CellId::Begin(level); id != S2CellId::End(level); id = id.next()) { vertices.push_back(id.ToPoint()); } switch (dim) { case 0: input.Add(make_unique(vertices)); break; case 1: input.Add(make_unique(vertices)); break; default: input.Add(make_unique( vector>{std::move(vertices)})); break; } } Encoder encoder; ABSL_CHECK(s2shapeutil::CompactEncodeTaggedShapes(input, &encoder)); input.Encode(&encoder); encoded_.assign(encoder.base(), encoder.length()); Decoder decoder(encoded_.data(), encoded_.size()); ABSL_CHECK( index_.Init(&decoder, s2shapeutil::LazyDecodeShapeFactory(&decoder))); } void WriteOp() override { index_.Minimize(); } void ReadOp() override { util_random::SharedBitGen bitgen; S2ClosestEdgeQuery query(&index_); for (int iter = 0; iter < 10; ++iter) { S2ClosestEdgeQuery::PointTarget target(s2random::Point(bitgen)); query.FindClosestEdge(&target); } } protected: string encoded_; EncodedS2ShapeIndex index_; }; TEST(EncodedS2ShapeIndex, LazyDecode) { // Ensure that lazy decoding is thread-safe. In other words, make sure that // nothing bad happens when multiple threads call "const" methods that cause // index and/or shape data to be decoded. LazyDecodeTest test; // The number of readers should be large enough so that it is likely that // several readers will be running at once (with a multiple-core CPU). constexpr int kNumReaders = 8; constexpr int kIters = 1000; test.Run(kNumReaders, kIters); } TEST(EncodedS2ShapeIndex, JavaByteCompatibility) { MutableS2ShapeIndex expected; expected.Add(make_unique( s2textformat::MakePolylineOrDie("0:0, 1:1"))); expected.Add(make_unique( s2textformat::MakePolylineOrDie("1:1, 2:2"))); expected.Release(0); // bytes is the encoded data of an S2ShapeIndex with a null shape and a // polyline with one edge. It was derived by base-16 encoding the buffer of // an encoder to which expected was encoded. string bytes = absl::HexStringToBytes( "100036020102000000B4825F3C81FDEF3F27DCF7C958DE913F1EDD892B0BDF913FFC7FB8" "B805F6EF3F28516A6D8FDBA13F27DCF7C958DEA13F28C809010408020010"); Decoder decoder(bytes.data(), bytes.length()); MutableS2ShapeIndex actual; ASSERT_TRUE( actual.Init(&decoder, s2shapeutil::FullDecodeShapeFactory(&decoder))); s2testing::ExpectEqual(expected, actual); } // The number of different polygons used for benchmarking purposes. static constexpr int kNumBenchmarkPolygons = 3; // Returns a pointer to a cached polygon of the given type and snap state. // // REQUIRES: type < kNumBenchmarkPolygons const S2Polygon* GetBenchmarkPolygon(int type, bool snapped) { // Store an array of pointers to cache test polygons. We'll never call // destructors so this doesn't violate the trivial destruction rule. struct CachedPolygon { absl::once_flag once; const S2Polygon* polygon; const S2Polygon* snapped; }; static CachedPolygon cache[kNumBenchmarkPolygons] = {}; ABSL_CHECK_GE(type, 0); ABSL_CHECK_LT(type, kNumBenchmarkPolygons); // Initialize cache entry if it hasn't been done yet. absl::call_once(cache[type].once, [type]() { const string seed_str = StrCat("BENCHMARK_POLYGON", absl::GetFlag(FLAGS_s2_random_seed), type); std::seed_seq seed(seed_str.begin(), seed_str.end()); std::mt19937_64 bitgen(seed); S2Polygon* polygon; switch (type) { case 0: { // A small regular loop. polygon = new S2Polygon(S2Loop::MakeRegularLoop( s2random::Point(bitgen), S2Testing::KmToAngle(10), 8)); break; } case 1: { // A medium-sized fractal loop, e.g. a small natural feature. S2Fractal fractal(bitgen); fractal.SetLevelForApproxMaxEdges(3 * 256); Matrix3x3_d frame = s2random::Frame(bitgen); auto loop = fractal.MakeLoop(frame, S2Testing::KmToAngle(10)); polygon = new S2Polygon(std::move(loop)); break; } case 2: { // A large number of small loops. polygon = new S2Polygon(); S2Testing::ConcentricLoopsPolygon(S2Point(1, 0, 0), 100, 10, polygon); break; } default: ABSL_LOG(FATAL) << "Unsupported benchmark polygon index: " << type; } // Build snapped variant of polygon S2Polygon* snapped = new S2Polygon(); snapped->InitToSnapped(*polygon, S2CellId::kMaxLevel); cache[type].polygon = polygon; cache[type].snapped = snapped; }); // Cache will always be initialized at this point, safe to read values. return snapped ? cache[type].snapped : cache[type].polygon; } // Returns a pointer to a cached polygon specified by the benchmark state. // // REQUIRES: state.range(0) < kNumBenchmarkPolygons const S2Polygon* GetBenchmarkPolygon(const benchmark::State& state) { return GetBenchmarkPolygon(state.range(0), state.range(1)); } // Returns an owning pointer to a polygon specified by the benchmark state. // Since the returned pointer is mutable, polygons are cloned from the cached // values returned by `GetBenchmarkPolygon` // // REQUIRES: state.range(0) < kNumBenchmarkPolygons unique_ptr GetMutableBenchmarkPolygon( const benchmark::State& state) { return unique_ptr(GetBenchmarkPolygon(state)->Clone()); } // Returns a pointer to a lax polygon specified by the benchmark state. // // REQUIRES: state.range(0) < kNumBenchmarkPolygons const S2LaxPolygonShape* GetLaxBenchmarkPolygon(const benchmark::State& state) { // Store an array of pointers to cache test polygons. We'll never call // destructors so this doesn't violate the trivial destruction rule. static absl::once_flag once; static const S2LaxPolygonShape* cache[kNumBenchmarkPolygons][2] = {}; // Construct the lax polygon cache once. absl::call_once(once, []() { for (int type = 0; type < kNumBenchmarkPolygons; type++) { for (int snapped = 0; snapped <= 1; snapped++) { const S2Polygon* polygon = GetBenchmarkPolygon(type, snapped); cache[type][snapped] = new S2LaxPolygonShape(*polygon); } } }); int type = state.range(0); bool snapped = state.range(1); ABSL_CHECK_GE(type, 0); ABSL_CHECK_LT(type, kNumBenchmarkPolygons); // Cache will always be initialized at this point, safe to read values. return cache[type][snapped]; } // Runs the given benchmark for all benchmark polygons using the given value // of the "snapped" parameter. template void BenchmarkArgsSnapped(benchmark::internal::Benchmark* benchmark) { for (int i = 0; i < kNumBenchmarkPolygons; ++i) { benchmark->ArgPair(i, snap); } } // Runs the given benchmark for all benchmark polygons, with and without // snapping (which controls whether the FAST or COMPACT encoding is used). void BenchmarkArgs(benchmark::internal::Benchmark* benchmark) { BenchmarkArgsSnapped(benchmark); BenchmarkArgsSnapped(benchmark); } // Measure the time to build and destruct a MutableS2ShapeIndex. static void BM_MutableIndexBuildDestruct(benchmark::State& state) { auto polygon = GetBenchmarkPolygon(state); state.SetLabel(StrCat("vertices = ", polygon->num_vertices(), ", loops = ", polygon->num_loops())); for (auto _ : state) { MutableS2ShapeIndex index; index.Add(make_unique(polygon)); index.ForceBuild(); } } BENCHMARK(BM_MutableIndexBuildDestruct)->Apply(BenchmarkArgsSnapped); // Measure the time to decode and destruct a MutableS2ShapeIndex. static void BM_MutableIndexDecodeDestruct(benchmark::State& state) { Encoder encoder; { MutableS2ShapeIndex index; index.Add(make_unique(*GetBenchmarkPolygon(state))); ABSL_CHECK(s2shapeutil::FastEncodeTaggedShapes(index, &encoder)); index.Encode(&encoder); } for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); MutableS2ShapeIndex index; ABSL_CHECK( index.Init(&decoder, s2shapeutil::LazyDecodeShapeFactory(&decoder))); } } BENCHMARK(BM_MutableIndexDecodeDestruct)->Apply(BenchmarkArgsSnapped); // Measure the time to initialize and destruct an EncodedS2ShapeIndex. static void BM_EncodedIndexInitDestruct(benchmark::State& state) { Encoder encoder; { MutableS2ShapeIndex index; index.Add(make_unique(*GetBenchmarkPolygon(state))); ABSL_CHECK(s2shapeutil::FastEncodeTaggedShapes(index, &encoder)); int index_start = encoder.length(); index.Encode(&encoder); Decoder decoder(encoder.base(), encoder.length()); state.SetLabel(StrCat("index_bytes = ", encoder.length() - index_start)); } for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); EncodedS2ShapeIndex index; ABSL_CHECK( index.Init(&decoder, s2shapeutil::LazyDecodeShapeFactory(&decoder))); } } BENCHMARK(BM_EncodedIndexInitDestruct)->Apply(BenchmarkArgsSnapped); // Measure the time to decode and destruct a snapped/unsnapped S2Polygon. static void BM_S2PolygonDecodeDestructSnapped(benchmark::State& state) { Encoder encoder; GetBenchmarkPolygon(state)->Encode(&encoder); state.SetLabel(StrCat("bytes = ", encoder.length())); for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); S2Polygon polygon; ABSL_CHECK(polygon.Decode(&decoder)); } } BENCHMARK(BM_S2PolygonDecodeDestructSnapped)->Apply(BenchmarkArgs); // Measure the time to fully decode and destruct a snapped/unsnapped // S2LaxPolygonShape. static void BM_LaxPolygonDecodeDestructSnapped( benchmark::State& state) { Encoder encoder; GetLaxBenchmarkPolygon(state)->Encode(&encoder, s2coding::CodingHint::COMPACT); state.SetLabel(StrCat("bytes = ", encoder.length())); for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); S2LaxPolygonShape polygon; ABSL_CHECK(polygon.Init(&decoder)); } } BENCHMARK(BM_LaxPolygonDecodeDestructSnapped)->Apply(BenchmarkArgs); // Measure the time to initialize and destruct a snapped/unsnapped // EncodedS2LaxPolygonShape. static void BM_EncodedPolygonInitDestructSnapped( benchmark::State& state) { Encoder encoder; GetLaxBenchmarkPolygon(state)->Encode(&encoder, s2coding::CodingHint::COMPACT); state.SetLabel(StrCat("bytes = ", encoder.length())); for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); EncodedS2LaxPolygonShape polygon; ABSL_CHECK(polygon.Init(&decoder)); } } BENCHMARK(BM_EncodedPolygonInitDestructSnapped)->Apply(BenchmarkArgs); // Measure the time to access an edge of an S2Polygon::Shape. static void BM_S2PolygonGetEdge(benchmark::State& state) { S2Polygon::OwningShape shape(GetMutableBenchmarkPolygon(state)); int i = 0, num_edges = shape.num_edges(); for (auto _ : state) { (void) shape.edge(i); if (++i == num_edges) i = 0; } } BENCHMARK(BM_S2PolygonGetEdge)->Apply(BenchmarkArgsSnapped); static void BM_LaxPolygonGetEdge(benchmark::State& state) { const S2LaxPolygonShape& shape = *GetLaxBenchmarkPolygon(state); int i = 0, num_edges = shape.num_edges(); for (auto _ : state) { benchmark::DoNotOptimize(shape.edge(i)); if (++i == num_edges) i = 0; } } BENCHMARK(BM_LaxPolygonGetEdge)->Apply(BenchmarkArgsSnapped); // Measure the time to access an edge of a snapped/unsnapped // EncodedS2LaxPolygonShape. static void BM_EncodedPolygonGetEdge(benchmark::State& state) { Encoder encoder; GetLaxBenchmarkPolygon(state)->Encode(&encoder, s2coding::CodingHint::COMPACT); state.SetLabel(StrCat("bytes = ", encoder.length())); Decoder decoder(encoder.base(), encoder.length()); EncodedS2LaxPolygonShape shape; ABSL_CHECK(shape.Init(&decoder)); int i = 0, num_edges = shape.num_edges(); for (auto _ : state) { (void) shape.edge(i); if (++i == num_edges) i = 0; } } BENCHMARK(BM_EncodedPolygonGetEdge)->Apply(BenchmarkArgs); // Measure the time to check whether the polygon contains one of its vertices, // using a MutableS2ShapeIndex containing an S2Polygon::Shape. static void BM_ContainsPointMutableIndexS2Polygon(benchmark::State& state) { auto polygon = GetBenchmarkPolygon(state); MutableS2ShapeIndex index; index.Add(make_unique(polygon)); index.ForceBuild(); int i = 0, num_edges = index.shape(0)->num_edges(); for (auto _ : state) { S2Point test_point = index.shape(0)->edge(i).v0; if (S2ContainsPointQuery(&index).Contains(test_point)) ++i; if ((i += 10) >= num_edges) i = 0; } } BENCHMARK(BM_ContainsPointMutableIndexS2Polygon) ->Apply(BenchmarkArgsSnapped); // Measure the time to check whether the polygon contains one of its vertices, // using an EncodedS2ShapeIndex containing a snapped/unsnapped // EncodedS2LaxPolygonShape. static void BM_ContainsPointEncodedIndexPolygon(benchmark::State& state) { Encoder encoder; { MutableS2ShapeIndex index; index.Add(make_unique(*GetBenchmarkPolygon(state))); ABSL_CHECK(s2shapeutil::CompactEncodeTaggedShapes(index, &encoder)); index.Encode(&encoder); } Decoder decoder(encoder.base(), encoder.length()); EncodedS2ShapeIndex index; ABSL_CHECK( index.Init(&decoder, s2shapeutil::LazyDecodeShapeFactory(&decoder))); int i = 0, num_edges = index.shape(0)->num_edges(); for (auto _ : state) { S2Point test_point = index.shape(0)->edge(i).v0; if (S2ContainsPointQuery(&index).Contains(test_point)) ++i; if ((i += 10) >= num_edges) { // In theory we should stop benchmark timing for this, but ironically // that throws off the benchmark results. i = 0; index.Minimize(); } } } BENCHMARK(BM_ContainsPointEncodedIndexPolygon)->Apply(BenchmarkArgs); // Measure the time to compute distance from the polygon to one of its // vertices, using a MutableS2ShapeIndex containing an S2Polygon::Shape. static void BM_VertexDistanceMutableIndexS2Polygon(benchmark::State& state) { auto polygon = GetBenchmarkPolygon(state); MutableS2ShapeIndex index; index.Add(make_unique(polygon)); index.ForceBuild(); int i = 0, num_edges = index.shape(0)->num_edges(); for (auto _ : state) { S2ClosestEdgeQuery query(&index); S2Point v0 = index.shape(0)->edge(i).v0; S2Point test_point = (v0 + 1e-4 * S2::Ortho(v0)).Normalize(); S2ClosestEdgeQuery::PointTarget target(test_point); query.GetDistance(&target); if ((i += 10) >= num_edges) i = 0; } } BENCHMARK(BM_VertexDistanceMutableIndexS2Polygon) ->Apply(BenchmarkArgsSnapped); // Measure the time to compute the distance from the polygon to one of its // vertices, using an EncodedS2ShapeIndex containing a snapped/unsnapped // EncodedS2LaxPolygonShape. static void BM_VertexDistanceEncodedIndexPolygon(benchmark::State& state) { Encoder encoder; { MutableS2ShapeIndex index; index.Add(make_unique(*GetBenchmarkPolygon(state))); ABSL_CHECK(s2shapeutil::CompactEncodeTaggedShapes(index, &encoder)); index.Encode(&encoder); } Decoder decoder(encoder.base(), encoder.length()); EncodedS2ShapeIndex index; ABSL_CHECK( index.Init(&decoder, s2shapeutil::LazyDecodeShapeFactory(&decoder))); int i = 0, num_edges = index.shape(0)->num_edges(); for (auto _ : state) { S2ClosestEdgeQuery query(&index); S2Point v0 = index.shape(0)->edge(i).v0; S2Point test_point = (v0 + 1e-4 * S2::Ortho(v0)).Normalize(); S2ClosestEdgeQuery::PointTarget target(test_point); query.GetDistance(&target); if ((i += 10) >= num_edges) { // In theory we should stop benchmark timing for this, but ironically // that throws off the benchmark results. i = 0; index.Minimize(); } } } BENCHMARK(BM_VertexDistanceEncodedIndexPolygon)->Apply(BenchmarkArgs); // Measure the combined time to decode the snapped/unsnapped polygon, build an // S2ShapeIndex for it, and check whether the polygon contains one of its // vertices. static void BM_DecodePolygonBuildIndexContainsPointSnapped( benchmark::State& state) { Encoder encoder; GetBenchmarkPolygon(state)->Encode(&encoder); for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); S2Polygon polygon; ABSL_CHECK(polygon.Decode(&decoder)); MutableS2ShapeIndex index; index.Add(make_unique(&polygon)); S2ContainsPointQuery query(&index); benchmark::DoNotOptimize(query.Contains(polygon.loop(0)->vertex(0))); } } BENCHMARK(BM_DecodePolygonBuildIndexContainsPointSnapped)->Apply(BenchmarkArgs); // Measure the combined time to decode the snapped/unsnapped polygon and its // S2ShapeIndex, and check whether the polygon contains one of its vertices. static void BM_DecodeIndexAndPolygonContainsPointSnapped( benchmark::State& state) { Encoder encoder; { auto polygon = GetBenchmarkPolygon(state); MutableS2ShapeIndex index; index.Add(make_unique(polygon)); ABSL_CHECK(s2shapeutil::CompactEncodeTaggedShapes(index, &encoder)); index.Encode(&encoder); } for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); MutableS2ShapeIndex index; ABSL_CHECK( index.Init(&decoder, s2shapeutil::FullDecodeShapeFactory(&decoder))); S2ContainsPointQuery query(&index); benchmark::DoNotOptimize(query.Contains(index.shape(0)->edge(0).v0)); } } BENCHMARK(BM_DecodeIndexAndPolygonContainsPointSnapped)->Apply(BenchmarkArgs); // Measure the combined time to initialize encoded versions of the // snapped/unsnapped polygon and its index, and check whether the polygon // contains one of its vertices. static void BM_EncodedIndexAndPolygonContainsPointSnapped( benchmark::State& state) { Encoder encoder; { MutableS2ShapeIndex index; index.Add(make_unique(*GetBenchmarkPolygon(state))); ABSL_CHECK(s2shapeutil::CompactEncodeTaggedShapes(index, &encoder)); index.Encode(&encoder); } for (auto _ : state) { Decoder decoder(encoder.base(), encoder.length()); EncodedS2ShapeIndex index; ABSL_CHECK( index.Init(&decoder, s2shapeutil::LazyDecodeShapeFactory(&decoder))); S2ContainsPointQuery query(&index); benchmark::DoNotOptimize(query.Contains(index.shape(0)->edge(0).v0)); } } BENCHMARK(BM_EncodedIndexAndPolygonContainsPointSnapped)->Apply(BenchmarkArgs); src/s2/encoded_string_vector.cc000066400000000000000000000055441524103652300170620ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_string_vector.h" #include #include #include #include #include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/encoded_uint_vector.h" using absl::MakeSpan; using absl::Span; using absl::string_view; using std::string; using std::vector; namespace s2coding { StringVectorEncoder::StringVectorEncoder() = default; void StringVectorEncoder::Encode(Encoder* encoder) { offsets_.push_back(data_.length()); // We don't encode the first element of "offsets_", which is always zero. EncodeUintVector( MakeSpan(offsets_.data() + 1, offsets_.data() + offsets_.size()), encoder); encoder->Ensure(data_.length()); encoder->putn(data_.base(), data_.length()); } void StringVectorEncoder::Encode(Span v, Encoder* encoder) { StringVectorEncoder string_vector; for (const auto& str : v) string_vector.Add(str); string_vector.Encode(encoder); } bool EncodedStringVector::Init(Decoder* decoder) { if (!offsets_.Init(decoder)) return false; if (offsets_.size() > 0) { uint64_t length = offsets_[offsets_.size() - 1]; if (decoder->avail() < length) return false; data_ = absl::string_view(decoder->skip(0), length); decoder->skip(length); } else { data_ = absl::string_view(); } return true; } vector EncodedStringVector::Decode() const { size_t n = size(); vector result(n); uint64_t start = 0; for (size_t i = 0; i < n; ++i) { uint64_t limit = offsets_[i]; // Check bounds, skip invalid values, but continue decoding to provide // consistency between Decode() and operator[]. if (start <= limit && limit <= data_.size()) { result[i] = data_.substr(start, limit - start); } start = limit; } return result; } // The encoding must be identical to StringVectorEncoder::Encode(). void EncodedStringVector::Encode(Encoder* encoder) const { offsets_.Encode(encoder); if (offsets_.size() > 0) { ABSL_DCHECK_EQ(data_.size(), offsets_[offsets_.size() - 1]); encoder->Ensure(data_.size()); encoder->putn(data_.data(), data_.size()); } } } // namespace s2coding src/s2/encoded_string_vector.h000066400000000000000000000130001524103652300167060ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_ENCODED_STRING_VECTOR_H_ #define S2_ENCODED_STRING_VECTOR_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/encoded_uint_vector.h" namespace s2coding { // This class allows an EncodedStringVector to be created by adding strings // incrementally. It also supports adding strings that are the output of // another Encoder. For example, to create a vector of encoded S2Polygons, // you can do this: // // void EncodePolygons(const vector& polygons, Encoder* encoder) { // StringVectorEncoder encoded_polygons; // for (auto polygon : polygons) { // polygon->Encode(encoded_polygons.AddViaEncoder()); // } // encoded_polygons.Encode(encoder); // } class StringVectorEncoder { public: StringVectorEncoder(); // Adds a string to the encoded vector. void Add(absl::string_view str); // Adds a string to the encoded vector by means of the given Encoder. The // string consists of all output added to the encoder before the next call // to any method of this class (after which the encoder is no longer valid). Encoder* AddViaEncoder(); // Appends the EncodedStringVector representation to the given Encoder. // // REQUIRES: "encoder" uses the default constructor, so that its buffer // can be enlarged as necessary by calling Ensure(int). void Encode(Encoder* encoder); // Encodes a vector of strings in a format that can later be decoded as an // EncodedStringVector. // // REQUIRES: "encoder" uses the default constructor, so that its buffer // can be enlarged as necessary by calling Ensure(int). static void Encode(absl::Span v, Encoder* encoder); private: // A vector consisting of the starting offset of each string in the // encoder's data buffer, plus a final entry pointing just past the end of // the last string. std::vector offsets_; Encoder data_; }; // This class represents an encoded vector of strings. Values are decoded // only when they are accessed. This allows for very fast initialization and // no additional memory use beyond the encoded data. The encoded data is not // owned by this class; typically it points into a large contiguous buffer // that contains other encoded data as well. // // This is one of several helper classes that allow complex data structures to // be initialized from an encoded format in constant time and then decoded on // demand. This can be a big performance advantage when only a small part of // the data structure is actually used. class EncodedStringVector { public: // Constructs an uninitialized object; requires Init() to be called. EncodedStringVector() = default; // Initializes the EncodedStringVector. Returns false on errors, leaving // the vector in an unspecified state. // // REQUIRES: The Decoder data buffer must outlive this object. bool Init(Decoder* decoder); // Resets the vector to be empty. void Clear(); // Returns the size of the original vector. size_t size() const; // Returns the string at the given index. absl::string_view operator[](size_t i) const; // Returns a Decoder initialized with the string at the given index. Decoder GetDecoder(size_t i) const; // Returns the entire vector of original strings. Requires that the // data buffer passed to the constructor persists until the result vector is // no longer needed. std::vector Decode() const; // Copies the encoded byte stream to a new encoder. void Encode(Encoder* encoder) const; private: EncodedUintVector offsets_; absl::string_view data_; }; ////////////////// Implementation details follow //////////////////// inline void StringVectorEncoder::Add(absl::string_view str) { offsets_.push_back(data_.length()); data_.Ensure(str.size()); data_.putn(str.data(), str.size()); } inline Encoder* StringVectorEncoder::AddViaEncoder() { offsets_.push_back(data_.length()); return &data_; } inline void EncodedStringVector::Clear() { offsets_.Clear(); data_ = absl::string_view(); } inline size_t EncodedStringVector::size() const { return offsets_.size(); } inline absl::string_view EncodedStringVector::operator[](size_t i) const { // Return an empty decoder if we don't have enough data. if (i >= offsets_.size()) { return absl::string_view(); } uint64_t start = (i == 0) ? 0 : offsets_[i - 1]; uint64_t limit = offsets_[i]; if (start <= limit && limit <= data_.size()) { return data_.substr(start, limit - start); } else { return absl::string_view(); // Corrupt data, return empty string. } } inline Decoder EncodedStringVector::GetDecoder(size_t i) const { return Decoder((*this)[i]); } } // namespace s2coding #endif // S2_ENCODED_STRING_VECTOR_H_ src/s2/encoded_string_vector_test.cc000066400000000000000000000107411524103652300201140ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_string_vector.h" #include #include #include #include #include #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" using absl::string_view; using std::string; using std::vector; namespace s2coding { void TestEncodedStringVector(absl::Span input, size_t expected_bytes) { Encoder encoder; StringVectorEncoder::Encode(input, &encoder); EXPECT_EQ(expected_bytes, encoder.length()); Decoder decoder(encoder.base(), encoder.length()); EncodedStringVector actual; ASSERT_TRUE(actual.Init(&decoder)); vector expected; for (const auto& str : input) { expected.push_back(string_view(str)); } EXPECT_EQ(actual.Decode(), expected); // Check that `EncodedStringVector::Encode` produces the same result as // `StringVectorEncoder::Encode`, as documented. Encoder reencoder; actual.Encode(&reencoder); EXPECT_EQ(string_view(encoder.base(), encoder.length()), string_view(reencoder.base(), reencoder.length())); } TEST(EncodedStringVectorTest, Empty) { TestEncodedStringVector({}, 1); } TEST(EncodedStringVectorTest, EmptyString) { TestEncodedStringVector({""}, 2); } TEST(EncodedStringVectorTest, RepeatedEmptyStrings) { TestEncodedStringVector({"", "", ""}, 4); } TEST(EncodedStringVectorTest, OneString) { TestEncodedStringVector({"apples"}, 8); } TEST(EncodedStringVectorTest, TwoStrings) { TestEncodedStringVector({"fuji", "mutsu"}, 12); } TEST(EncodedStringVectorTest, TwoBigStrings) { TestEncodedStringVector({string(10000, 'x'), string(100000, 'y')}, 110007); } TEST(EncodedStringVectorTest, SubscriptOperator) { const string kInput[] = {"pink lady", "gala"}; Encoder encoder; StringVectorEncoder::Encode(kInput, &encoder); Decoder decoder(encoder.base(), encoder.length()); EncodedStringVector v; ASSERT_TRUE(v.Init(&decoder)); ASSERT_EQ(v.size(), 2); EXPECT_EQ(v[0], "pink lady"); EXPECT_EQ(v[1], "gala"); } TEST(EncodedStringVectorTest, ReInitialize) { const string kInput1[] = {"abcd", "edfg"}; const string kInput2[] = {"hij", "klm", "nop", "qrs"}; const string kInput3[] = {"tu"}; Encoder encoder; Encoder reencoder; EncodedStringVector v; StringVectorEncoder::Encode(kInput1, &encoder); Decoder decoder(encoder.base(), encoder.length()); ASSERT_TRUE(v.Init(&decoder)); ASSERT_EQ(v.size(), 2); EXPECT_EQ(v[0], "abcd"); // Reinitialize with a larger input. encoder.clear(); StringVectorEncoder::Encode(kInput2, &encoder); decoder = Decoder(encoder.base(), encoder.length()); ASSERT_TRUE(v.Init(&decoder)); ASSERT_EQ(v.size(), 4); EXPECT_EQ(v[0], "hij"); v.Encode(&reencoder); EXPECT_EQ(string_view(encoder.base(), encoder.length()), string_view(reencoder.base(), reencoder.length())); // Reinitialize with a smaller input. encoder.clear(); StringVectorEncoder::Encode(kInput3, &encoder); decoder = Decoder(encoder.base(), encoder.length()); ASSERT_TRUE(v.Init(&decoder)); ASSERT_EQ(v.size(), 1); EXPECT_EQ(v[0], "tu"); reencoder.clear(); v.Encode(&reencoder); EXPECT_EQ(string_view(encoder.base(), encoder.length()), string_view(reencoder.base(), reencoder.length())); // Reinitialize with an empty input. encoder.clear(); StringVectorEncoder::Encode({}, &encoder); decoder = Decoder(encoder.base(), encoder.length()); ASSERT_TRUE(v.Init(&decoder)); ASSERT_EQ(v.size(), 0); reencoder.clear(); v.Encode(&reencoder); EXPECT_EQ(string_view(encoder.base(), encoder.length()), string_view(reencoder.base(), reencoder.length())); // Reinitialize with an invalid input. encoder.clear(); decoder = Decoder(encoder.base(), encoder.length()); ASSERT_FALSE(v.Init(&decoder)); } } // namespace s2coding src/s2/encoded_uint_vector.h000066400000000000000000000245401524103652300163720ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_ENCODED_UINT_VECTOR_H_ #define S2_ENCODED_UINT_VECTOR_H_ #include #include #include #include #include #include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" #include "absl/types/span.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/util/coding/coder.h" #include "s2/util/coding/varint.h" #include "s2/util/endian/endian.h" namespace s2coding { // Encodes a vector of unsigned integers in a format that can later be // decoded as an EncodedUintVector. // // REQUIRES: T is an unsigned integer type. // REQUIRES: 2 <= sizeof(T) <= 8 // REQUIRES: "encoder" uses the default constructor, so that its buffer // can be enlarged as necessary by calling Ensure(int). template void EncodeUintVector(absl::Span v, Encoder* encoder); // This class represents an encoded vector of unsigned integers of type T. // Values are decoded only when they are accessed. This allows for very fast // initialization and no additional memory use beyond the encoded data. // The encoded data is not owned by this class; typically it points into a // large contiguous buffer that contains other encoded data as well. // // This is one of several helper classes that allow complex data structures to // be initialized from an encoded format in constant time and then decoded on // demand. This can be a big performance advantage when only a small part of // the data structure is actually used. // // Values are encoded using a fixed number of bytes per value, where the // number of bytes depends on the largest value present. // // REQUIRES: T is an unsigned integer type. // REQUIRES: 2 <= sizeof(T) <= 8 template class EncodedUintVector { public: static_assert(std::is_unsigned::value, "Unsupported signed integer"); static_assert(sizeof(T) & 0xe, "Unsupported integer length"); // Constructs an uninitialized object; requires Init() to be called. EncodedUintVector() = default; // Initializes the EncodedUintVector. Returns false on errors, leaving the // vector in an unspecified state. // // REQUIRES: The Decoder data buffer must outlive this object. bool Init(Decoder* decoder); // Resets the vector to be empty. void Clear(); // Returns the size of the original vector. size_t size() const; // Returns the element at the given index. T operator[](int i) const; // Returns the index of the first element x such that (x >= target), or // size() if no such element exists. // // REQUIRES: The vector elements are sorted in non-decreasing order. size_t lower_bound(T target) const; // Decodes and returns the entire original vector. std::vector Decode() const; void Encode(Encoder* encoder) const; private: template size_t lower_bound(T target) const; const char* data_; uint32_t size_; uint8_t len_; }; // Encodes an unsigned integer in little-endian format using "length" bytes. // (The client must ensure that the encoder's buffer is large enough.) // // REQUIRES: T is an unsigned integer type. // REQUIRES: 2 <= sizeof(T) <= 8 // REQUIRES: 0 <= length <= sizeof(T) // REQUIRES: value < 256 ** length // REQUIRES: encoder->avail() >= length template void EncodeUintWithLength(T value, int length, Encoder* encoder); // Decodes a variable-length integer consisting of "length" bytes starting at // "ptr" in little-endian format. // // REQUIRES: T is an unsigned integer type. // REQUIRES: 2 <= sizeof(T) <= 8 // REQUIRES: 0 <= length <= sizeof(T) template T GetUintWithLength(const char* ptr, int length); // Decodes and consumes a variable-length integer consisting of "length" bytes // in little-endian format. Returns false if not enough bytes are available. // // REQUIRES: T is an unsigned integer type. // REQUIRES: 2 <= sizeof(T) <= 8 // REQUIRES: 0 <= length <= sizeof(T) template bool DecodeUintWithLength(int length, Decoder* decoder, T* result); ////////////////// Implementation details follow //////////////////// template inline void EncodeUintWithLength(T value, int length, Encoder* encoder) { static_assert(std::is_unsigned::value, "Unsupported signed integer"); static_assert(sizeof(T) & 0xe, "Unsupported integer length"); ABSL_DCHECK(length >= 0 && length <= sizeof(T)); ABSL_DCHECK_GE(encoder->avail(), length); while (--length >= 0) { encoder->put8(value); value >>= 8; } ABSL_DCHECK_EQ(value, 0); } template inline T GetUintWithLength(const char* ptr, int length) { static_assert(std::is_unsigned::value, "Unsupported signed integer"); static_assert(sizeof(T) & 0xe, "Unsupported integer length"); ABSL_DCHECK(length >= 0 && length <= sizeof(T)); // Note that the following code is faster than any of the following: // // - A loop that repeatedly loads and shifts one byte. // - memcpying "length" bytes to a local variable of type T. // - A switch statement that handles each length optimally. // // The following code is slightly faster: // // T mask = (length == 0) ? 0 : ~T{0} >> 8 * (sizeof(T) - length); // return *reinterpret_cast(ptr) & mask; // // However this technique is unsafe because in extremely rare cases it might // access out-of-bounds heap memory. (This can only happen if "ptr" is // within (sizeof(T) - length) bytes of the end of a memory page and the // following page in the address space is unmapped.) if (length & sizeof(T)) { return LittleEndian::Load(ptr); } T x = 0; ptr += length; if (sizeof(T) > 4 && (length & 4)) { x = LittleEndian::Load(ptr -= sizeof(uint32_t)); } if (sizeof(T) > 2 && (length & 2)) { x = (x << 16) + LittleEndian::Load(ptr -= sizeof(uint16_t)); } if (sizeof(T) > 1 && (length & 1)) { x = (x << 8) + static_cast(*--ptr); } return x; } template bool DecodeUintWithLength(int length, Decoder* decoder, T* result) { if (decoder->avail() < static_cast(length)) return false; const char* ptr = decoder->skip(0); *result = GetUintWithLength(ptr, length); decoder->skip(length); return true; } template void EncodeUintVector(absl::Span v, Encoder* encoder) { // The encoding is as follows: // // varint64: (v.size() * sizeof(T)) | (len - 1) // array of v.size() elements ["len" bytes each] // // Note that we don't allow (len == 0) since this would require an extra bit // to encode the length. T one_bits = 1; // Ensures len >= 1. for (auto x : v) one_bits |= x; ABSL_ASSUME(one_bits != 0); int len = ((absl::bit_width(one_bits) - 1) >> 3) + 1; ABSL_DCHECK(len >= 1 && len <= 8); // Note that the multiplication is optimized into a bit shift. encoder->Ensure(Varint::kMax64 + v.size() * len); uint64_t size_len = (uint64_t{v.size()} * sizeof(T)) | (len - 1); encoder->put_varint64(size_len); for (auto x : v) { EncodeUintWithLength(x, len, encoder); } } template bool EncodedUintVector::Init(Decoder* decoder) { uint64_t size_len; if (!decoder->get_varint64(&size_len)) return false; size_ = size_len / sizeof(T); // Optimized into bit shift. len_ = (size_len & (sizeof(T) - 1)) + 1; if (size_ > std::numeric_limits::max() / sizeof(T)) return false; size_t bytes = static_cast(size_) * static_cast(len_); if (decoder->avail() < bytes) return false; data_ = decoder->skip(0); decoder->skip(bytes); return true; } template void EncodedUintVector::Clear() { size_ = 0; data_ = nullptr; } template inline size_t EncodedUintVector::size() const { return size_; } template inline T EncodedUintVector::operator[](int i) const { ABSL_DCHECK(i >= 0 && i < size_); return GetUintWithLength(data_ + i * len_, len_); } template size_t EncodedUintVector::lower_bound(T target) const { static_assert(sizeof(T) & 0xe, "Unsupported integer length"); ABSL_DCHECK(len_ >= 1 && len_ <= sizeof(T)); // TODO(ericv): Consider using the unused 28 bits of "len_" to store the // last result of lower_bound() to be used as a hint. This should help in // common situation where the same element is looked up repeatedly. This // would require declaring the new field (length_lower_bound_hint_) as // mutable std::atomic (accessed using std::memory_order_relaxed) // with a custom copy constructor that resets the hint component to zero. switch (len_) { case 1: return lower_bound<1>(target); case 2: return lower_bound<2>(target); case 3: return lower_bound<3>(target); case 4: return lower_bound<4>(target); case 5: return lower_bound<5>(target); case 6: return lower_bound<6>(target); case 7: return lower_bound<7>(target); case 8: return lower_bound<8>(target); } ABSL_UNREACHABLE(); } template template inline size_t EncodedUintVector::lower_bound(T target) const { size_t lo = 0, hi = size_; while (lo < hi) { size_t mid = (lo + hi) >> 1; T value = GetUintWithLength(data_ + mid * length, length); if (value < target) { lo = mid + 1; } else { hi = mid; } } return lo; } template std::vector EncodedUintVector::Decode() const { std::vector result(size_); for (int i = 0; i < size_; ++i) { result[i] = (*this)[i]; } return result; } template // The encoding must be identical to StringVectorEncoder::Encode(). void EncodedUintVector::Encode(Encoder* encoder) const { uint64_t size_len = (uint64_t{size_} * sizeof(T)) | (len_ - 1); encoder->Ensure(Varint::kMax64 + size_len); encoder->put_varint64(size_len); encoder->putn(data_, size_ * len_); } } // namespace s2coding #endif // S2_ENCODED_UINT_VECTOR_H_ src/s2/encoded_uint_vector_test.cc000066400000000000000000000147001524103652300175640ustar00rootroot00000000000000// Copyright 2018 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/encoded_uint_vector.h" #include #include #include #include #include #include #include #include "absl/log/absl_check.h" #include "s2/util/coding/coder.h" using std::vector; namespace s2coding { // Make sure that this class is compact since it is extensively used. // 16 for 64-bit, 12 for 32-bit. static_assert(sizeof(EncodedUintVector) <= 16, "too big"); template void TestEncodedUintVector(const vector& expected, size_t expected_bytes) { Encoder encoder; EncodeUintVector(expected, &encoder); EXPECT_EQ(expected_bytes, encoder.length()); Decoder decoder(encoder.base(), encoder.length()); EncodedUintVector actual; ASSERT_TRUE(actual.Init(&decoder)); EXPECT_EQ(actual.Decode(), expected); } TEST(EncodedUintVectorTest, Empty) { TestEncodedUintVector(vector{}, 1); } TEST(EncodedUintVectorTest, Zero) { TestEncodedUintVector(vector{0}, 2); } TEST(EncodedUintVectorTest, RepeatedZeros) { TestEncodedUintVector(vector{0, 0, 0}, 4); } TEST(EncodedUintVectorTest, MaxInt) { TestEncodedUintVector(vector{~0ULL}, 9); } TEST(EncodedUintVectorTest, OneByte) { TestEncodedUintVector(vector{0, 255, 1, 254}, 5); } TEST(EncodedUintVectorTest, TwoBytes) { TestEncodedUintVector(vector{0, 255, 256, 254}, 9); } TEST(EncodedUintVectorTest, ThreeBytes) { TestEncodedUintVector(vector{0xffffff, 0x0102, 0, 0x050403}, 13); } TEST(EncodedUintVectorTest, EightBytes) { TestEncodedUintVector(vector{~0ULL, 0, 0x0102030405060708}, 25); } template vector MakeSortedTestVector(int bytes_per_value, int num_values) { ABSL_DCHECK_LE(bytes_per_value, sizeof(T)); T limit_value = ~T{0} >> (8 * (sizeof(T) - bytes_per_value)); vector values; for (int i = 0; i + 1 < num_values; ++i) { values.push_back(limit_value * (static_cast(i) / (num_values - 1))); } // The last value needs special handling since casting it to "double" loses // precision when T == uint64_t. values.push_back(limit_value); ABSL_CHECK(std::is_sorted(values.begin(), values.end())); return values; } template EncodedUintVector MakeEncodedVector(const vector& values, Encoder* encoder) { EncodeUintVector(values, encoder); Decoder decoder(encoder->base(), encoder->length()); EncodedUintVector actual; ABSL_CHECK(actual.Init(&decoder)); return actual; } template void TestLowerBound(int bytes_per_value, int num_values) { auto v = MakeSortedTestVector(bytes_per_value, num_values); Encoder encoder; auto actual = MakeEncodedVector(v, &encoder); for (T x : v) { EXPECT_EQ(std::lower_bound(v.begin(), v.end(), x) - v.begin(), actual.lower_bound(x)); if (x > 0) { EXPECT_EQ(std::lower_bound(v.begin(), v.end(), x - 1) - v.begin(), actual.lower_bound(x - 1)); } } } TEST(EncodedUintVector, LowerBound) { for (int bytes_per_value = 8; bytes_per_value <= 8; ++bytes_per_value) { TestLowerBound(bytes_per_value, 10); if (bytes_per_value <= 4) { TestLowerBound(bytes_per_value, 500); if (bytes_per_value <= 2) { TestLowerBound(bytes_per_value, 100); } } } } TEST(EncodedUintVectorTest, RoundtripEncoding) { vector values{10, 20, 30, 40}; Encoder a_encoder; auto a = MakeEncodedVector(values, &a_encoder); ASSERT_EQ(a.Decode(), values); Encoder b_encoder; a.Encode(&b_encoder); Decoder decoder(b_encoder.base(), b_encoder.length()); EncodedUintVector v2; ASSERT_TRUE(v2.Init(&decoder)); EXPECT_EQ(v2.Decode(), values); } template static void BM_DecodeValue(benchmark::State& state) { const int bytes_per_value = state.range(0); constexpr int kNumValues = 1 << 10; // Must be power of 2. ABSL_DCHECK_EQ(kNumValues & (kNumValues - 1), 0); vector values(kNumValues); for (T& x : values) { for (int i = 0; i < bytes_per_value; ++i) { x = (x << 8) | 0xa5; // Immaterial. } } Encoder encoder; EncodeUintVector(values, &encoder); Decoder decoder(encoder.base(), encoder.length()); EncodedUintVector actual; ABSL_CHECK(actual.Init(&decoder)); int i = 0; for (auto _ : state) { benchmark::DoNotOptimize(actual[i]); i = (i + 1) & (kNumValues - 1); } } BENCHMARK_TEMPLATE(BM_DecodeValue, uint32_t) ->Arg(0) ->Arg(1) ->Arg(2) ->Arg(3) ->Arg(4); BENCHMARK_TEMPLATE(BM_DecodeValue, uint64_t) ->Arg(0) ->Arg(1) ->Arg(2) ->Arg(3) ->Arg(4) ->Arg(5) ->Arg(6) ->Arg(7) ->Arg(8); template static void BM_LowerBound(benchmark::State& state) { const int num_values = state.range(0); const int bytes_per_value = state.range(1); auto values = MakeSortedTestVector(bytes_per_value, num_values); T limit_value = values.back(); Encoder encoder; auto actual = MakeEncodedVector(values, &encoder); T value = 0, delta = 3 * (limit_value / num_values); for (auto _ : state) { benchmark::DoNotOptimize(actual.lower_bound(value)); if ((value += delta) > limit_value) value -= limit_value; } } // Use case: S2LaxPolygonShape::cumulative_vertices. // Stores one cumulative vertex count per loop. BENCHMARK_TEMPLATE(BM_LowerBound, uint32_t) ->ArgPair(10, 2) ->ArgPair(1000, 2) ->ArgPair(1000000, 3) ->ArgPair(1000000, 4); // Use case: EncodedS2ShapeIndex::cell_ids_. // Stores one S2CellId value per cell. BENCHMARK_TEMPLATE(BM_LowerBound, uint64_t) ->ArgPair(10, 1) ->ArgPair(1000, 2) ->ArgPair(100000, 3) ->ArgPair(1000000, 4) ->ArgPair(1000000, 5) ->ArgPair(1000000, 6) ->ArgPair(1000000, 7) ->ArgPair(1000000, 8); } // namespace s2coding src/s2/gmock_matchers.cc000066400000000000000000000634531524103652300155020ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "s2/gmock_matchers.h" #include #include #include #include #include #include #include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "s2/s1angle.h" #include "s2/s2debug.h" #include "s2/s2latlng.h" #include "s2/s2latlng_rect.h" #include "s2/s2loop.h" #include "s2/s2point.h" #include "s2/s2pointutil.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2text_format.h" using absl::string_view; using std::string; using std::unique_ptr; using ::testing::MakePolymorphicMatcher; using ::testing::MatchResultListener; using ::testing::PolymorphicMatcher; // Printing methods need to be in the global namespace. void PrintTo(const S2Point& p, std::ostream* os) { *os << s2textformat::ToString(p); } void PrintTo(const S2Polyline& l, std::ostream* os) { *os << s2textformat::ToString(l); } void PrintTo(const S2Polygon& p, std::ostream* os) { *os << s2textformat::ToString(p); } void PrintTo(const S2LatLngRect& r, std::ostream* os) { *os << s2textformat::ToString(r); } void PrintTo(const S2Loop& l, std::ostream* os) { *os << s2textformat::ToString(l); } namespace S2 { namespace { // Returns whether the point is approximately the zero-length vector. bool IsAlmostZeroLength(const S2Point& p) { // Implementation is similar to S2::IsUnitLength. See comments there. // TODO(ericv): Verify if this is actually a reasonable value. return fabs(p.Norm2()) <= 5 * DBL_EPSILON; } } // namespace // S2PointMatcher methods. S2PointMatcher::S2PointMatcher(const S2Point& expected, S1Angle tolerance) : expected_(expected), tolerance_(tolerance) { ABSL_CHECK(!IsAlmostZeroLength(expected)); } bool S2PointMatcher::MatchAndExplain(string_view s, MatchResultListener* listener) const { return MatchAndExplain(s2textformat::MakePointOrDie(s), listener); } bool S2PointMatcher::MatchAndExplain(const S2Point& g, MatchResultListener* listener) const { // S2::ApproxEquals will either check fail (debug mode) to unconditionally // return true if either point is the zero-length vector (default S2Point), so // handle that explicitly. if (IsAlmostZeroLength(g)) { *listener << "point is uninitialized or almost zero"; return false; } if ((tolerance_ == S1Angle::Zero() && expected_ != g) || !S2::ApproxEquals(g, expected_, tolerance_)) { *listener << "angle in degrees: " << S1Angle(g, expected_); return false; } return true; } // S2PolylineMatcher methods. bool S2PolylineMatcher::MatchAndExplain(string_view s, MatchResultListener* listener) const { unique_ptr line = s2textformat::MakePolylineOrDie(s); return MatchAndExplain(*line, listener); } bool S2PolylineMatcher::MatchAndExplain(const S2Polyline& g, MatchResultListener* listener) const { switch (options_.type) { case Options::EQUALS: { if (!expected_->Equals(g)) { *listener << "S2Polylines don't match"; return false; } break; } case Options::APPROX_EQUALS: if (!expected_->ApproxEquals(g, options_.tolerance)) { *listener << "S2Polylines don't match with tolerance in degrees " << options_.tolerance; return false; } break; } return true; } // S2PolylineIdenticalToMatcher methods. S2PolylineIdenticalToMatcher::S2PolylineIdenticalToMatcher( const S2Polyline& expected) : expected_(&expected) {} bool S2PolylineIdenticalToMatcher::MatchAndExplain( const S2Polyline& g, MatchResultListener* listener) const { if (expected_->num_vertices() != g.num_vertices()) { *listener << "whose num_vertices " << g.num_vertices() << " doesn't match " << expected_->num_vertices(); return false; } for (int i = 0; i < expected_->num_vertices(); ++i) { if (expected_->vertex(i) != g.vertex(i)) { *listener << "whose vertex(" << i << ") " << s2textformat::ToString(g.vertex(i)) << " doesn't match " << s2textformat::ToString(expected_->vertex(i)); return false; } } if (expected_->GetRectBound() != g.GetRectBound()) { *listener << "whose GetRectBound() " << s2textformat::ToString(g.GetRectBound()) << " doesn't match " << s2textformat::ToString(expected_->GetRectBound()); return false; } if (expected_->s2debug_override() != g.s2debug_override()) { *listener << "whose s2debug_override() " << (g.s2debug_override() == S2Debug::ALLOW ? "ALLOW" : "DISABLE") << " doesn't match " << (expected_->s2debug_override() == S2Debug::ALLOW ? "ALLOW" : "DISABLE"); return false; } return true; } void S2PolylineIdenticalToMatcher::DescribeTo(::std::ostream* os) const { *os << "is identical to polyline " << s2textformat::ToString(*expected_); } void S2PolylineIdenticalToMatcher::DescribeNegationTo(std::ostream* os) const { *os << "is not identical to polyline " << s2textformat::ToString(*expected_); } // S2PolygonMatcher methods. bool S2PolygonMatcher::MatchAndExplain(string_view s, MatchResultListener* listener) const { unique_ptr polygon = s2textformat::MakePolygonOrDie(s, S2Debug::ALLOW); return MatchAndExplain(*polygon, listener); } bool S2PolygonMatcher::MatchAndExplain(const S2Polygon& g, MatchResultListener* listener) const { switch (options_.type) { case Options::EQUALS: { if (!expected_->Equals(g)) { *listener << "S2Polygons don't match"; return false; } break; } case Options::APPROX_EQUALS: { if (!expected_->ApproxEquals(g, options_.tolerance)) { *listener << "S2Polygons don't match with tolerance in degrees " << options_.tolerance; return false; } break; } case Options::BOUNDARY_EQUALS: { if (!expected_->BoundaryEquals(g)) { *listener << "S2Polygons don't match"; return false; } break; } case Options::BOUNDARY_APPROX_EQUALS: { if (!expected_->BoundaryApproxEquals(g, options_.tolerance)) { *listener << "S2Polygons don't match with tolerance in degrees " << options_.tolerance; return false; } break; } case Options::BOUNDARY_NEAR: { if (!expected_->BoundaryNear(g, options_.tolerance)) { *listener << "S2Polygons don't match with tolerance in degrees " << options_.tolerance; return false; } break; } } return true; } // S2LoopMatcher methods. bool S2LoopMatcher::MatchAndExplain(string_view s, MatchResultListener* listener) const { unique_ptr loop = s2textformat::MakeLoopOrDie(s); return MatchAndExplain(*loop, listener); } bool S2LoopMatcher::MatchAndExplain(const S2Loop& g, MatchResultListener* listener) const { switch (options_.type) { case Options::EQUALS: { if (!expected_->Equals(g)) { *listener << "S2Loops don't match"; return false; } break; } case Options::BOUNDARY_EQUALS: { if (!expected_->BoundaryEquals(g)) { *listener << "S2Loops don't match"; return false; } break; } case Options::BOUNDARY_APPROX_EQUALS: { if (!expected_->BoundaryApproxEquals(g, options_.tolerance)) { *listener << "S2Loops don't match with tolerance in degrees " << options_.tolerance; return false; } break; } case Options::BOUNDARY_NEAR: { if (!expected_->BoundaryNear(g, options_.tolerance)) { *listener << "S2Loops don't match with tolerance in degrees " << options_.tolerance; return false; } break; } } return true; } // S2LoopIdenticalToMatcher methods. S2LoopIdenticalToMatcher::S2LoopIdenticalToMatcher(const S2Loop& expected) : expected_(&expected) {} bool S2LoopIdenticalToMatcher::MatchAndExplain( const S2Loop& g, MatchResultListener* listener) const { if (expected_->depth() != g.depth()) { *listener << "whose depth " << g.depth() << " doesn't match " << expected_->depth(); return false; } if (expected_->num_vertices() != g.num_vertices()) { *listener << "whose num_vertices " << g.num_vertices() << " doesn't match " << expected_->num_vertices(); return false; } for (int i = 0; i < expected_->num_vertices(); ++i) { if (expected_->vertex(i) != g.vertex(i)) { *listener << "whose vertex(" << i << ") " << s2textformat::ToString(g.vertex(i)) << " doesn't match " << s2textformat::ToString(expected_->vertex(i)); return false; } } if (expected_->is_empty() != g.is_empty()) { *listener << "whose is_empty() " << g.is_empty() << " doesn't match " << expected_->is_empty(); return false; } if (expected_->is_full() != g.is_full()) { *listener << "whose is_full() " << g.is_full() << " doesn't match " << expected_->is_full(); return false; } if (expected_->IsNormalized() != g.IsNormalized()) { *listener << "whose IsNormalized() " << g.IsNormalized() << " doesn't match " << expected_->IsNormalized(); return false; } if (expected_->Contains(S2::Origin()) != g.Contains(S2::Origin())) { *listener << "whose Contains(S2::Origin()) " << g.Contains(S2::Origin()) << " doesn't match " << expected_->Contains(S2::Origin()); return false; } if (expected_->GetRectBound() != g.GetRectBound()) { *listener << "whose GetRectBound() " << s2textformat::ToString(g.GetRectBound()) << " doesn't match " << s2textformat::ToString(expected_->GetRectBound()); return false; } if (expected_->s2debug_override() != g.s2debug_override()) { *listener << "whose s2debug_override() " << (g.s2debug_override() == S2Debug::ALLOW ? "ALLOW" : "DISABLE") << " doesn't match " << (expected_->s2debug_override() == S2Debug::ALLOW ? "ALLOW" : "DISABLE"); return false; } return true; } void S2LoopIdenticalToMatcher::DescribeTo(::std::ostream* os) const { *os << "is identical to loop " << s2textformat::ToString(*expected_); } void S2LoopIdenticalToMatcher::DescribeNegationTo(std::ostream* os) const { *os << "is not identical to loop " << s2textformat::ToString(*expected_); } // S2PolygonIdenticalToMatcher methods. S2PolygonIdenticalToMatcher::S2PolygonIdenticalToMatcher( const S2Polygon& expected) : expected_(&expected) {} bool S2PolygonIdenticalToMatcher::MatchAndExplain( const S2Polygon& g, MatchResultListener* listener) const { if (expected_->num_loops() != g.num_loops()) { *listener << "whose num_loops() " << g.num_loops() << " doesn't match " << expected_->num_loops(); return false; } for (int i = 0; i < expected_->num_loops(); ++i) { S2LoopIdenticalToMatcher loop_matcher(*expected_->loop(i)); if (!loop_matcher.MatchAndExplain(*g.loop(i), listener)) { *listener << " in loop " << i; return false; } } if (expected_->GetRectBound() != g.GetRectBound()) { *listener << "whose GetRectBound() " << s2textformat::ToString(g.GetRectBound()) << " doesn't match " << s2textformat::ToString(expected_->GetRectBound()); return false; } if (expected_->s2debug_override() != g.s2debug_override()) { *listener << "whose s2debug_override() " << (g.s2debug_override() == S2Debug::ALLOW ? "ALLOW" : "DISABLE") << " doesn't match " << (expected_->s2debug_override() == S2Debug::ALLOW ? "ALLOW" : "DISABLE"); return false; } return true; } void S2PolygonIdenticalToMatcher::DescribeTo(::std::ostream* os) const { *os << "is identical to polygon " << s2textformat::ToString(*expected_); } void S2PolygonIdenticalToMatcher::DescribeNegationTo(std::ostream* os) const { *os << "is not identical to polygon " << s2textformat::ToString(*expected_); } // S2LatLngRectMatcher methods. bool S2LatLngRectMatcher::MatchAndExplain(string_view s, MatchResultListener* listener) const { S2LatLngRect rect = s2textformat::MakeLatLngRectOrDie(s); return MatchAndExplain(rect, listener); } bool S2LatLngRectMatcher::MatchAndExplain(const S2LatLngRect& g, MatchResultListener* listener) const { switch (options_.type) { case Options::EQUALS: { if (!(expected_ == g)) { *listener << "S2LatLngRects don't match"; return false; } break; } case Options::APPROX_EQUALS: { if (!expected_.ApproxEquals(g, options_.tolerance)) { *listener << "S2LatLngRects don't match with tolerance in degrees " << options_.tolerance; return false; } break; } case Options::APPROX_EQUALS_2: { if (!expected_.ApproxEquals(g, options_.tolerance_lat_lng)) { *listener << "S2LatLngRects don't match with tolerance in degrees " << options_.tolerance_lat_lng; return false; } break; } } return true; } // S2LatLngMatcher methods. bool S2LatLngMatcher::MatchAndExplain(string_view s, MatchResultListener* listener) const { S2LatLng latlng = s2textformat::MakeLatLngOrDie(s); return MatchAndExplain(latlng, listener); } bool S2LatLngMatcher::MatchAndExplain(const S2LatLng& latlng, MatchResultListener* listener) const { switch (options_.type) { case Options::EQUALS: { if (!(expected_ == latlng)) { *listener << "S2LatLngs don't match"; return false; } break; } case Options::APPROX_EQUALS: { if (!expected_.ApproxEquals(latlng, options_.tolerance)) { *listener << "S2LatLngs don't match with tolerance in degrees " << options_.tolerance; return false; } break; } } return true; } // Predefined matchers. // Matchers for S2Points provided as objects. PolymorphicMatcher PointEquals(const S2Point& expected) { return MakePolymorphicMatcher(S2PointMatcher(expected, S1Angle::Zero())); } PolymorphicMatcher PointApproxEquals(const S2Point& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PointMatcher(expected, tolerance)); } // Matchers for S2Points provided as strings. PolymorphicMatcher PointEquals(string_view expected) { return MakePolymorphicMatcher(S2PointMatcher(expected, S1Angle::Zero())); } PolymorphicMatcher PointApproxEquals(string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PointMatcher(expected, tolerance)); } // Matchers for S2Polylines provided as objects. PolymorphicMatcher PolylineEquals( const S2Polyline& expected) { return MakePolymorphicMatcher(S2PolylineMatcher( expected, S2PolylineMatcher::Options(S2PolylineMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher PolylineApproxEquals( const S2Polyline& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolylineMatcher( expected, S2PolylineMatcher::Options( S2PolylineMatcher::Options::APPROX_EQUALS, tolerance))); } // Matchers for S2Polylines provided as strings. PolymorphicMatcher PolylineEquals(string_view expected) { return MakePolymorphicMatcher(S2PolylineMatcher( expected, S2PolylineMatcher::Options(S2PolylineMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher PolylineApproxEquals(string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolylineMatcher( expected, S2PolylineMatcher::Options( S2PolylineMatcher::Options::APPROX_EQUALS, tolerance))); } PolymorphicMatcher PolylineIdenticalTo( const S2Polyline& expected) { return MakePolymorphicMatcher(S2PolylineIdenticalToMatcher(expected)); } // Matchers for S2Polygons provided as objects. PolymorphicMatcher PolygonEquals(const S2Polygon& expected) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options(S2PolygonMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher PolygonApproxEquals( const S2Polygon& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options( S2PolygonMatcher::Options::APPROX_EQUALS, tolerance))); } PolymorphicMatcher PolygonBoundaryEquals( const S2Polygon& expected) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options(S2PolygonMatcher::Options::BOUNDARY_EQUALS, S1Angle::Zero()))); } PolymorphicMatcher PolygonBoundaryApproxEquals( const S2Polygon& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options( S2PolygonMatcher::Options::BOUNDARY_APPROX_EQUALS, tolerance))); } PolymorphicMatcher PolygonBoundaryNear( const S2Polygon& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options( S2PolygonMatcher::Options::BOUNDARY_NEAR, tolerance))); } // Matchers for S2Polygons provided as string. PolymorphicMatcher PolygonEquals(string_view expected) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options(S2PolygonMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher PolygonApproxEquals(string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options( S2PolygonMatcher::Options::APPROX_EQUALS, tolerance))); } PolymorphicMatcher PolygonBoundaryEquals( string_view expected) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options(S2PolygonMatcher::Options::BOUNDARY_EQUALS, S1Angle::Zero()))); } PolymorphicMatcher PolygonBoundaryApproxEquals( string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options( S2PolygonMatcher::Options::BOUNDARY_APPROX_EQUALS, tolerance))); } PolymorphicMatcher PolygonBoundaryNear(string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2PolygonMatcher( expected, S2PolygonMatcher::Options( S2PolygonMatcher::Options::BOUNDARY_NEAR, tolerance))); } PolymorphicMatcher PolygonIdenticalTo( const S2Polygon& expected) { return MakePolymorphicMatcher(S2PolygonIdenticalToMatcher(expected)); } // Matchers for S2Loops provided as objects. PolymorphicMatcher LoopEquals(const S2Loop& expected) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LoopBoundaryEquals(const S2Loop& expected) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LoopBoundaryApproxEquals( const S2Loop& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_APPROX_EQUALS, tolerance))); } PolymorphicMatcher LoopBoundaryNear(const S2Loop& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_NEAR, tolerance))); } PolymorphicMatcher LoopIdenticalTo( const S2Loop& expected) { return MakePolymorphicMatcher(S2LoopIdenticalToMatcher(expected)); } // Matchers for S2Loops provided as string. PolymorphicMatcher LoopEquals(string_view expected) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LoopBoundaryEquals(string_view expected) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LoopBoundaryApproxEquals(string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_APPROX_EQUALS, tolerance))); } PolymorphicMatcher LoopBoundaryNear(string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LoopMatcher( expected, S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_NEAR, tolerance))); } // Matchers for S2LatLngRect provided as objects. PolymorphicMatcher LatLngRectEquals( const S2LatLngRect& expected) { return MakePolymorphicMatcher(S2LatLngRectMatcher( expected, S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LatLngRectApproxEquals( const S2LatLngRect& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LatLngRectMatcher( expected, S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::APPROX_EQUALS, tolerance))); } PolymorphicMatcher LatLngRectApproxEquals( const S2LatLngRect& expected, S2LatLng tolerance) { return MakePolymorphicMatcher(S2LatLngRectMatcher( expected, S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::APPROX_EQUALS_2, tolerance))); } // Matchers for S2LatLngRect provided as string. PolymorphicMatcher LatLngRectEquals(string_view expected) { return MakePolymorphicMatcher(S2LatLngRectMatcher( expected, S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LatLngRectApproxEquals( string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LatLngRectMatcher( expected, S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::APPROX_EQUALS, tolerance))); } PolymorphicMatcher LatLngRectApproxEquals( string_view expected, S2LatLng tolerance) { return MakePolymorphicMatcher(S2LatLngRectMatcher( expected, S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::APPROX_EQUALS_2, tolerance))); } // Matchers for S2LatLng provided as objects. PolymorphicMatcher LatLngEquals(const S2LatLng& expected) { return MakePolymorphicMatcher(S2LatLngMatcher( expected, S2LatLngMatcher::Options(S2LatLngMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LatLngApproxEquals(const S2LatLng& expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LatLngMatcher( expected, S2LatLngMatcher::Options( S2LatLngMatcher::Options::APPROX_EQUALS, tolerance))); } // Matchers for S2LatLng provided as string. PolymorphicMatcher LatLngEquals(string_view expected) { return MakePolymorphicMatcher(S2LatLngMatcher( expected, S2LatLngMatcher::Options(S2LatLngMatcher::Options::EQUALS, S1Angle::Zero()))); } PolymorphicMatcher LatLngApproxEquals(string_view expected, S1Angle tolerance) { return MakePolymorphicMatcher(S2LatLngMatcher( expected, S2LatLngMatcher::Options( S2LatLngMatcher::Options::APPROX_EQUALS, tolerance))); } } // namespace S2 src/s2/gmock_matchers.h000066400000000000000000000537311524103652300153420ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_GMOCK_MATCHERS_H_ #define S2_GMOCK_MATCHERS_H_ #include #include #include #include #include #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/s1angle.h" #include "s2/s2latlng.h" #include "s2/s2latlng_rect.h" #include "s2/s2loop.h" #include "s2/s2point.h" #include "s2/s2pointutil.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2text_format.h" // GMock matchers for S2LatLng, S2LatLngRect, S2Point, S2Polygon, S2Polyline, // S2Loop. // // Defines polymorphic matchers that can accept a string representation // of each object or a const reference to the object. See gmock_matchers_test.cc // for additional usage examples. // // ==================== // = S2LatLng = // ==================== // // Matchers: // * LatLngEquals: defined as S2LatLng::operator== // * LatLngApproxEquals: defined as S2LatLng::ApproxEquals // // Examples: // EXPECT_THAT(latlng, S2::LatLngEquals("10:10")); // EXPECT_THAT(latlng, S2::LatLngApproxEquals(expected, // S1Angle::Degrees(0.1))); // // ======================== // = S2LatLngRect = // ======================== // // Matchers: // * LatLngRectEquals: defined as S2LatLngRect::operator== // * LatLngRectApproxEquals: defined as S2LatLngRect::ApproxEquals. Accepts // a single tolerance or individual tolerances for lat and lng. // // Examples: // EXPECT_THAT(rect, S2::LatLngRectEquals(expected)); // EXPECT_THAT(rect, S2::LatLngRectApproxEquals( // "0:0,10:10", S1Angle::Radians(1e-10))); // EXPECT_THAT(rect, S2::LatLngRectApproxEquals( // expected, S2LatLng::FromDegrees(0.1, 0.2))); // // =================== // = S2Point = // =================== // // Matchers: // * PointEquals: exact equality check. // * PointApproxEquals: defined as s2pointutil::ApproxEquals with tolerance // with the exception that the default S2Point is not approximately equal // to anything. Expected value is not permitted to be zero or near zero. // // Examples: // EXPECT_THAT(point, S2::PointEquals("10:10"); // EXPECT_THAT(point, S2::PointApproxEquals( // expected, S1Angle::Radians(1e-10)); // // ===================== // = S2Polygon = // ===================== // // Matchers: // * PolygonEquals: defined as S2Polygon::Equals // * PolygonApproxEquals: defined as S2Polygon::ApproxEquals // * PolygonBoundaryEquals: defined as S2Polygon::BoundaryEquals // * PolygonBoundaryApproxEquals: defined as S2Polygon::BoundaryApproxEquals // * PolygonBoundaryNear: defined as S2Polygon::BoundaryNear // * PolygonIdenticalTo: checks that two polygons are identical, including // their loops, bounds, and debug overrides. // // Examples: // EXPECT_THAT(polygon, S2::PolygonEquals("10:10,10:0,0:0"); // EXPECT_THAT(polygon, S2::PolygonApproxEquals( // expected, S1Angle::Radians(1e-10)); // EXPECT_THAT(polygon, S2::PolygonBoundaryEquals(expected); // EXPECT_THAT(polygon, S2::PolygonBoundaryApproxEquals( // expected, S1Angle::Radians(1e-10)); // EXPECT_THAT(polygon, S2::PolygonBoundaryNear( // expected, S1Angle::Radians(1e-10)); // EXPECT_THAT(polygon, S2::PolygonIdenticalTo(expected)); // // ====================== // = S2Polyline = // ====================== // // Matchers: // * PolylineEquals: defined as S2Polyline::Equals // * PolylineApproxEquals: defined as S2Polyline::ApproxEquals // * PolylineIdenticalTo: checks that two polylines are identical, including // their structure, bounds, and debug overrides. // // Examples: // EXPECT_THAT(line, S2::PolylineEquals(expected)); // EXPECT_THAT(line, S2::PolylineApproxEquals( // "10:10,20:20", S1Angle::Radians(1e-10))); // EXPECT_THAT(line, S2::PolylineIdenticalTo(expected)); // // ================== // = S2Loop = // ================== // // Matchers: // * LoopEquals: defined as S2Loop::Equals // * LoopBoundaryEquals: defined as S2Loop::BoundaryEquals // * LoopBoundaryApproxEquals: defined as S2Loop::BoundaryApproxEquals // * LoopBoundaryNear: defined as S2Loop::BoundaryNear // * LoopIdenticalTo: checks that two loops are identical, including their // structure, bounds, depth, and debug overrides. // // Examples: // EXPECT_THAT(loop, S2::LoopEquals("10:10,10:0,0:0")); // EXPECT_THAT(loop, S2::LoopBoundaryEquals("10:10,10:0,0:0")); // EXPECT_THAT(loop, S2::LoopBoundaryApproxEquals( // expected, S1Angle::Radians(1e-10))); // EXPECT_THAT(loop, S2::LoopBoundaryNear( // expected, S1Angle::Radians(1e-10))); // EXPECT_THAT(loop, S2::LoopIdenticalTo(expected_loop)); // Print methods necessary for gmock to print values of S2Point, S2Polyline, // S2Polygon, and S2LatLngRect. void PrintTo(const S2Point& p, std::ostream* os); void PrintTo(const S2Polyline& l, std::ostream* os); void PrintTo(const S2Polygon& p, std::ostream* os); void PrintTo(const S2LatLngRect& r, std::ostream* os); void PrintTo(const S2Loop& l, std::ostream* os); namespace S2 { // Matcher for S2Point. class S2PointMatcher { public: S2PointMatcher(const S2Point& expected, S1Angle tolerance); S2PointMatcher(absl::string_view expected, S1Angle tolerance) : expected_(s2textformat::MakePointOrDie(expected)), tolerance_(tolerance) {} bool MatchAndExplain(absl::string_view s, ::testing::MatchResultListener* listener) const; // When tolerance_ == S1Angle::Zero() the points will be matched with the // S2Point::operator== method. bool MatchAndExplain(const S2Point& g, ::testing::MatchResultListener* listener) const; void DescribeTo(std::ostream* os) const { *os << "== " << s2textformat::ToString(expected_); } void DescribeNegationTo(std::ostream* os) const { *os << "!= " << s2textformat::ToString(expected_); } private: S2Point expected_; S1Angle tolerance_; }; // Matcher for S2Polyline. class S2PolylineMatcher { public: struct Options { // The types of comparison correspond to methods in S2Polyline. Each type // uses the same name as the corresponding method in S2Polyline. enum ComparisonType { EQUALS, // S2Polyline::Equals APPROX_EQUALS // S2Polyline::ApproxEquals }; Options() = default; Options(ComparisonType a_type, S1Angle a_tolerance) : type(a_type), tolerance(a_tolerance) {} ComparisonType type; S1Angle tolerance; }; S2PolylineMatcher(const S2PolylineMatcher& other) { options_ = other.options_; expected_.reset(other.expected_->Clone()); } S2PolylineMatcher& operator=(const S2PolylineMatcher& other) { options_ = other.options_; expected_.reset(other.expected_->Clone()); return *this; } S2PolylineMatcher(const S2Polyline& expected, Options options) : expected_(expected.Clone()), options_(options) {} S2PolylineMatcher(absl::string_view expected, Options options) : expected_(s2textformat::MakePolylineOrDie(expected)), options_(options) {} virtual ~S2PolylineMatcher() = default; bool MatchAndExplain(absl::string_view s, ::testing::MatchResultListener* listener) const; bool MatchAndExplain(const S2Polyline& g, ::testing::MatchResultListener* listener) const; void DescribeTo(std::ostream* os) const { *os << "== " << s2textformat::ToString(*expected_); } void DescribeNegationTo(std::ostream* os) const { *os << "!= " << s2textformat::ToString(*expected_); } private: std::unique_ptr expected_; Options options_; }; // Matcher that checks that two polylines are identical, including their // structure, bounds, and debug overrides. // // Note: The matcher stores a pointer to the expected polyline, so the expected // polyline must outlive the matcher. class S2PolylineIdenticalToMatcher { public: explicit S2PolylineIdenticalToMatcher( const S2Polyline& expected ABSL_ATTRIBUTE_LIFETIME_BOUND); bool MatchAndExplain(const S2Polyline& g, ::testing::MatchResultListener* listener) const; void DescribeTo(::std::ostream* os) const; void DescribeNegationTo(std::ostream* os) const; private: const S2Polyline* expected_; }; // Matcher for S2Polygon. class S2PolygonMatcher { public: struct Options { // The types of comparison correspond to methods in S2Polygon. Each type // uses the same name as the corresponding method in S2Polygon. enum ComparisonType { EQUALS, // S2Polygon::Equals APPROX_EQUALS, // S2Polygon::ApproxEquals BOUNDARY_EQUALS, // S2Polygon::BoundaryEquals BOUNDARY_APPROX_EQUALS, // S2Polygon::BoundaryApproxEquals BOUNDARY_NEAR // S2Polygon::BoundaryNear }; Options() = default; Options(ComparisonType a_type, S1Angle a_tolerance) : type(a_type), tolerance(a_tolerance) {} ComparisonType type; S1Angle tolerance; }; S2PolygonMatcher(const S2Polygon& expected, Options options) : expected_(expected.Clone()), options_(options) {} S2PolygonMatcher(absl::string_view expected, Options options) : expected_(s2textformat::MakePolygonOrDie(expected, S2Debug::ALLOW)), options_(options) {} S2PolygonMatcher(const S2PolygonMatcher& other) { options_ = other.options_; expected_.reset(other.expected_->Clone()); } S2PolygonMatcher& operator=(const S2PolygonMatcher& other) { options_ = other.options_; expected_.reset(other.expected_->Clone()); return *this; } bool MatchAndExplain(absl::string_view s, ::testing::MatchResultListener* listener) const; bool MatchAndExplain(const S2Polygon& g, ::testing::MatchResultListener* listener) const; void DescribeTo(std::ostream* os) const { *os << "== " << s2textformat::ToString(*expected_); } void DescribeNegationTo(std::ostream* os) const { *os << "!= " << s2textformat::ToString(*expected_); } private: std::unique_ptr expected_; Options options_; }; // Matcher for S2Loop. class S2LoopMatcher { public: struct Options { // The types of comparison correspond to methods in S2Loop. Each type // uses the same name as the corresponding method in S2Loop. enum ComparisonType { EQUALS, // S2Loop::Equals BOUNDARY_EQUALS, // S2Loop::BoundaryEquals BOUNDARY_APPROX_EQUALS, // S2Loop::BoundaryApproxEquals BOUNDARY_NEAR // S2Loop::BoundaryNear }; Options() = default; Options(ComparisonType a_type, S1Angle a_tolerance) : type(a_type), tolerance(a_tolerance) {} ComparisonType type; S1Angle tolerance; }; S2LoopMatcher(const S2Loop& expected, Options options) : expected_(expected.Clone()), options_(options) {} S2LoopMatcher(absl::string_view expected, Options options) : expected_(s2textformat::MakeLoopOrDie(expected)), options_(options) {} S2LoopMatcher(const S2LoopMatcher& other) { options_ = other.options_; expected_.reset(other.expected_->Clone()); } S2LoopMatcher& operator=(const S2LoopMatcher& other) { options_ = other.options_; expected_.reset(other.expected_->Clone()); return *this; } bool MatchAndExplain(absl::string_view s, ::testing::MatchResultListener* listener) const; bool MatchAndExplain(const S2Loop& g, ::testing::MatchResultListener* listener) const; void DescribeTo(std::ostream* os) const { *os << "== " << s2textformat::ToString(*expected_); } void DescribeNegationTo(std::ostream* os) const { *os << "!= " << s2textformat::ToString(*expected_); } private: std::unique_ptr expected_; Options options_; }; // Matcher that checks that two loops are identical, including their // structure, bounds, depth, and debug overrides. class S2LoopIdenticalToMatcher { public: explicit S2LoopIdenticalToMatcher( const S2Loop& expected ABSL_ATTRIBUTE_LIFETIME_BOUND); bool MatchAndExplain(const S2Loop& g, ::testing::MatchResultListener* listener) const; void DescribeTo(::std::ostream* os) const; void DescribeNegationTo(std::ostream* os) const; private: const S2Loop* expected_; }; // Matcher that checks that two polygons are identical, including their // loops, bounds, and debug overrides. // // Note: The matcher stores a pointer to the expected polygon, so the expected // polygon must outlive the matcher. class S2PolygonIdenticalToMatcher { public: explicit S2PolygonIdenticalToMatcher( const S2Polygon& expected ABSL_ATTRIBUTE_LIFETIME_BOUND); bool MatchAndExplain(const S2Polygon& g, ::testing::MatchResultListener* listener) const; void DescribeTo(::std::ostream* os) const; void DescribeNegationTo(std::ostream* os) const; private: const S2Polygon* expected_; }; // Matcher for S2LatLngRect. class S2LatLngRectMatcher { public: struct Options { // The types of comparison correspond to methods in S2LatLngRect. Each type // uses the same name as the corresponding method in S2LatLngRect. enum ComparisonType { EQUALS, // S2LatLngRect::operator== APPROX_EQUALS, // S2LatLngRect::ApproxEquals. // Same tolerance for lat and lng. APPROX_EQUALS_2, // s2LatLngRect::ApproxEquals. // Separate tolerance for lat and lng. }; Options() = default; Options(ComparisonType a_type, S1Angle a_tolerance) : type(a_type), tolerance(a_tolerance) {} Options(ComparisonType a_type, S2LatLng tolerance) : type(a_type), tolerance_lat_lng(tolerance) {} ComparisonType type; S1Angle tolerance; S2LatLng tolerance_lat_lng; }; S2LatLngRectMatcher(const S2LatLngRect& expected, Options options) : expected_(expected), options_(options) {} S2LatLngRectMatcher(absl::string_view expected, Options options) : expected_(s2textformat::MakeLatLngRectOrDie(expected)), options_(options) {} S2LatLngRectMatcher(const S2LatLngRectMatcher& other) { options_ = other.options_; expected_ = other.expected_; } S2LatLngRectMatcher& operator=(const S2LatLngRectMatcher& other) = default; bool MatchAndExplain(absl::string_view s, ::testing::MatchResultListener* listener) const; bool MatchAndExplain(const S2LatLngRect& g, ::testing::MatchResultListener* listener) const; void DescribeTo(std::ostream* os) const { *os << "== " << s2textformat::ToString(expected_); } void DescribeNegationTo(std::ostream* os) const { *os << "!= " << s2textformat::ToString(expected_); } private: S2LatLngRect expected_; Options options_; }; // Matcher for S2LatLng. class S2LatLngMatcher { public: struct Options { // The types of comparison correspond to methods in S2LatLng. Each type // uses the same name as the corresponding method in S2LatLng. enum ComparisonType { EQUALS, // S2LatLng::operator== APPROX_EQUALS, // S2LatLng::ApproxEquals. // Same tolerance for lat and lng. }; Options() = default; Options(ComparisonType a_type, S1Angle a_tolerance) : type(a_type), tolerance(a_tolerance) {} ComparisonType type; S1Angle tolerance; }; S2LatLngMatcher(const S2LatLng& expected, Options options) : expected_(expected), options_(options) {} S2LatLngMatcher(absl::string_view expected, Options options) : expected_(s2textformat::MakeLatLngOrDie(expected)), options_(options) {} S2LatLngMatcher(const S2LatLngMatcher& other) { options_ = other.options_; expected_ = other.expected_; } S2LatLngMatcher& operator=(const S2LatLngMatcher& other) = default; bool MatchAndExplain(absl::string_view s, ::testing::MatchResultListener* listener) const; bool MatchAndExplain(const S2LatLng& g, ::testing::MatchResultListener* listener) const; void DescribeTo(std::ostream* os) const { *os << "== " << s2textformat::ToString(expected_); } void DescribeNegationTo(std::ostream* os) const { *os << "!= " << s2textformat::ToString(expected_); } private: S2LatLng expected_; Options options_; }; // Predefined matchers for S2Point, S2Polyline, S2Polygon, S2Loop, S2LatLngRect. // These matchers can be used in EXPECT_THAT statements. // Matchers for S2Points provided as objects. ::testing::PolymorphicMatcher PointEquals( const S2Point& expected); ::testing::PolymorphicMatcher PointApproxEquals( const S2Point& expected, S1Angle tolerance); // Matchers for S2Points provided as strings. ::testing::PolymorphicMatcher PointEquals( absl::string_view expected); ::testing::PolymorphicMatcher PointApproxEquals( absl::string_view expected, S1Angle tolerance); // Matchers for S2Polylines provided as objects. ::testing::PolymorphicMatcher PolylineEquals( const S2Polyline& expected); ::testing::PolymorphicMatcher PolylineApproxEquals( const S2Polyline& expected, S1Angle tolerance); // Matchers for S2Polylines provided as strings. ::testing::PolymorphicMatcher PolylineEquals( absl::string_view expected); ::testing::PolymorphicMatcher PolylineApproxEquals( absl::string_view expected, S1Angle tolerance); ::testing::PolymorphicMatcher PolylineIdenticalTo( const S2Polyline& expected); // Matchers for S2Polygons provided as objects. ::testing::PolymorphicMatcher PolygonEquals( const S2Polygon& expected); ::testing::PolymorphicMatcher PolygonApproxEquals( const S2Polygon& expected, S1Angle tolerance); ::testing::PolymorphicMatcher PolygonBoundaryEquals( const S2Polygon& expected); ::testing::PolymorphicMatcher PolygonBoundaryApproxEquals( const S2Polygon& expected, S1Angle tolerance); ::testing::PolymorphicMatcher PolygonBoundaryNear( const S2Polygon& expected, S1Angle tolerance); ::testing::PolymorphicMatcher PolygonIdenticalTo( const S2Polygon& expected); // Matchers for S2Polygons provided as string. ::testing::PolymorphicMatcher PolygonEquals( absl::string_view expected); ::testing::PolymorphicMatcher PolygonApproxEquals( absl::string_view expected, S1Angle tolerance); ::testing::PolymorphicMatcher PolygonBoundaryEquals( absl::string_view expected); ::testing::PolymorphicMatcher PolygonBoundaryApproxEquals( absl::string_view expected, S1Angle tolerance); ::testing::PolymorphicMatcher PolygonBoundaryNear( absl::string_view expected, S1Angle tolerance); // Matchers for S2Loops provided as objects. ::testing::PolymorphicMatcher LoopEquals(const S2Loop& expected); ::testing::PolymorphicMatcher LoopBoundaryEquals( const S2Loop& expected); ::testing::PolymorphicMatcher LoopBoundaryApproxEquals( const S2Loop& expected, S1Angle tolerance); ::testing::PolymorphicMatcher LoopBoundaryNear( const S2Loop& expected, S1Angle tolerance); ::testing::PolymorphicMatcher LoopIdenticalTo( const S2Loop& expected); // Matchers for S2Loops provided as string. ::testing::PolymorphicMatcher LoopEquals( absl::string_view expected); ::testing::PolymorphicMatcher LoopBoundaryEquals( absl::string_view expected); ::testing::PolymorphicMatcher LoopBoundaryApproxEquals( absl::string_view expected, S1Angle tolerance); ::testing::PolymorphicMatcher LoopBoundaryNear( absl::string_view expected, S1Angle tolerance); // Matchers for S2LatLngRect provided as objects. ::testing::PolymorphicMatcher LatLngRectEquals( const S2LatLngRect& expected); ::testing::PolymorphicMatcher LatLngRectApproxEquals( const S2LatLngRect& expected, S1Angle tolerance); ::testing::PolymorphicMatcher LatLngRectApproxEquals( const S2LatLngRect& expected, S2LatLng tolerance); // Matchers for S2LatLngRect provided as string. ::testing::PolymorphicMatcher LatLngRectEquals( absl::string_view expected); ::testing::PolymorphicMatcher LatLngRectApproxEquals( absl::string_view expected, S1Angle tolerance); ::testing::PolymorphicMatcher LatLngRectApproxEquals( absl::string_view expected, S2LatLng tolerance); // Matchers for S2LatLng provided as objects. ::testing::PolymorphicMatcher LatLngEquals( const S2LatLng& expected); ::testing::PolymorphicMatcher LatLngApproxEquals( const S2LatLng& expected, S1Angle tolerance = S1Angle::Radians(1e-15)); // Matchers for S2LatLng provided as string. ::testing::PolymorphicMatcher LatLngEquals( absl::string_view expected); ::testing::PolymorphicMatcher LatLngApproxEquals( absl::string_view expected, S1Angle tolerance = S1Angle::Radians(1e-15)); } // namespace S2 #endif // S2_GMOCK_MATCHERS_H_ src/s2/gmock_matchers_test.cc000066400000000000000000000466271524103652300165450ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "s2/gmock_matchers.h" #include #include #include #include #include #include "s2/s1angle.h" #include "s2/s2latlng.h" #include "s2/s2latlng_rect.h" #include "s2/s2point.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2text_format.h" namespace S2 { // Tests that the correct matchers are being invoked. Does not test for // the correctness of the s2 comparison methods, those are assumed to be // correct. using ::s2textformat::MakeLatLngOrDie; using ::s2textformat::MakeLatLngRectOrDie; using ::s2textformat::MakeLoopOrDie; using ::s2textformat::MakePointOrDie; using ::s2textformat::MakePolygonOrDie; using ::s2textformat::MakePolylineOrDie; using std::string; using ::testing::MatchesRegex; using ::testing::Not; using ::testing::StringMatchResultListener; TEST(S2testmatchersTest, PointEquals) { S2Point expected = MakePointOrDie("10:10"); // As object. EXPECT_THAT(s2textformat::MakePointOrDie("10:10"), PointEquals(expected)); // As string. EXPECT_THAT("10:10", PointEquals("10:10")); // Negation. EXPECT_THAT("10.01:10", Not(PointEquals("10:10"))); // Explain. StringMatchResultListener listener; S2PointMatcher m("10:10", S1Angle::Zero()); m.MatchAndExplain("10.01:10", &listener); EXPECT_EQ("angle in degrees: 0.0100000", listener.str()); } TEST(S2testmatchersTest, PointApproxEquals) { S2Point expected = MakePointOrDie("10:10"); // As object. EXPECT_THAT(MakePointOrDie("10:10"), PointApproxEquals(expected, S1Angle::Radians(1e-10))); // As string. EXPECT_THAT("10:10", PointApproxEquals("10:10", S1Angle::Radians(1e-10))); // Negation. EXPECT_THAT("11:10", Not(PointApproxEquals("10:10", S1Angle::Radians(1e-10)))); // Explain. { StringMatchResultListener listener; S2PointMatcher m("11:10", S1Angle::Radians(0.01)); m.MatchAndExplain("10:10", &listener); EXPECT_EQ("angle in degrees: 1.0000000", listener.str()); } // Default (uninitialized) point is not approximately equal to anything. S2Point default_point; EXPECT_THAT(default_point, Not(PointApproxEquals("10:10", S1Angle::Radians(1e-10)))); { StringMatchResultListener listener; S2PointMatcher m("10:10", S1Angle::Radians(0.01)); m.MatchAndExplain(default_point, &listener); EXPECT_EQ("point is uninitialized or almost zero", listener.str()); } // A point represented by a vector that is almost the zero-vector should also // not equal anything. S2Point nearly_zero_vector(std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()); EXPECT_THAT(nearly_zero_vector, Not(PointApproxEquals("10:10", S1Angle::Radians(1e-10)))); } TEST(S2testmatchersTest, PolylineEquals) { std::unique_ptr expected = MakePolylineOrDie("10:10,20:20"); std::unique_ptr value = MakePolylineOrDie("10:10,20:20"); // As object. EXPECT_THAT(*value, PolylineEquals(*expected)); // As string. EXPECT_THAT("10:10,20:20", PolylineEquals("10:10,20:20")); // Negation. EXPECT_THAT("10:10,5:5", Not(PolylineEquals("10:10,20:20"))); // Explain. StringMatchResultListener listener; S2PolylineMatcher m("10:10,20:20", S2PolylineMatcher::Options( S2PolylineMatcher::Options::EQUALS, S1Angle::Zero())); m.MatchAndExplain("10:10,5:5", &listener); EXPECT_EQ("S2Polylines don't match", listener.str()); } TEST(S2testmatchersTest, PolylineApproxEquals) { std::unique_ptr expected = MakePolylineOrDie("10:10,20:20"); std::unique_ptr value = MakePolylineOrDie("10:10,20:20"); // As object. EXPECT_THAT(*value, PolylineApproxEquals(*expected, S1Angle::Radians(1e-10))); // As string. EXPECT_THAT("10:10,20:20", PolylineApproxEquals("10:10,20:20", S1Angle::Radians(1e-10))); // Negation. EXPECT_THAT("10:10,5:5", Not(PolylineApproxEquals("10:10,20:20", S1Angle::Radians(1e-10)))); // Explain. StringMatchResultListener listener; S2PolylineMatcher m( "10:10,20:20", S2PolylineMatcher::Options(S2PolylineMatcher::Options::APPROX_EQUALS, S1Angle::Degrees(0.1))); m.MatchAndExplain("10:10,5:5", &listener); EXPECT_EQ("S2Polylines don't match with tolerance in degrees 0.1000000", listener.str()); } TEST(S2testmatchersTest, PolylineIdenticalTo) { auto expected = MakePolylineOrDie("10:10,20:20"); auto value = MakePolylineOrDie("10:10,20:20"); // As object. EXPECT_THAT(*value, PolylineIdenticalTo(*expected)); // Negation. EXPECT_THAT(*MakePolylineOrDie("10:10,20:21"), Not(PolylineIdenticalTo(*expected))); // Explain. ::testing::StringMatchResultListener listener; S2PolylineIdenticalToMatcher m(*expected); m.MatchAndExplain(*MakePolylineOrDie("10:10,20:21"), &listener); EXPECT_THAT(listener.str(), MatchesRegex("whose vertex\\(1\\) .* doesn't match .*")); } TEST(S2testmatchersTest, PolygonEquals) { std::unique_ptr expected = MakePolygonOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakePolygonOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, PolygonEquals(*expected)); // As string. EXPECT_THAT("10:10,10:0,0:0", PolygonEquals("10:10,10:0,0:0")); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(PolygonEquals("10:10,10:0,0:1"))); // Explain. StringMatchResultListener listener; S2PolygonMatcher m("10:10,10:0,0:0", S2PolygonMatcher::Options( S2PolygonMatcher::Options::EQUALS, S1Angle::Zero())); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Polygons don't match", listener.str()); } TEST(S2testmatchersTest, PolygonApproxEquals) { std::unique_ptr expected = MakePolygonOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakePolygonOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, PolygonApproxEquals(*expected, S1Angle::Radians(1e-10))); // As string. EXPECT_THAT("10:10,10:0,0:0", PolygonApproxEquals("10:10,10:0,0:0", S1Angle::Degrees(0.1))); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(PolygonApproxEquals( "10:10,10:0,0:1", S1Angle::Degrees(0.1)))); // Explain. StringMatchResultListener listener; S2PolygonMatcher m( "10:10,10:0,0:0", S2PolygonMatcher::Options(S2PolygonMatcher::Options::APPROX_EQUALS, S1Angle::Degrees(0.1))); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Polygons don't match with tolerance in degrees 0.1000000", listener.str()); } TEST(S2testmatchersTest, PolygonBoundaryEquals) { std::unique_ptr expected = MakePolygonOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakePolygonOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, PolygonBoundaryEquals(*expected)); // As string. EXPECT_THAT("10:10,10:0,0:0", PolygonBoundaryEquals("10:10,10:0,0:0")); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(PolygonBoundaryEquals("10:10,10:0,0:1"))); // Explain. StringMatchResultListener listener; S2PolygonMatcher m( "10:10,10:0,0:0", S2PolygonMatcher::Options(S2PolygonMatcher::Options::BOUNDARY_EQUALS, S1Angle::Zero())); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Polygons don't match", listener.str()); } TEST(S2testmatchersTest, PolygonBoundaryApproxEquals) { std::unique_ptr expected = MakePolygonOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakePolygonOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, PolygonBoundaryApproxEquals(*expected, S1Angle::Radians(1e-10))); // As string. EXPECT_THAT("10:10,10:0,0:0", PolygonBoundaryApproxEquals( "10:10,10:0,0:0", S1Angle::Radians(1e-10))); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(PolygonBoundaryApproxEquals( "10:10,10:0,0:1", S1Angle::Degrees(0.1)))); // Explain. StringMatchResultListener listener; S2PolygonMatcher m("10:10,10:0,0:0", S2PolygonMatcher::Options( S2PolygonMatcher::Options::BOUNDARY_APPROX_EQUALS, S1Angle::Degrees(0.1))); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Polygons don't match with tolerance in degrees 0.1000000", listener.str()); } TEST(S2testmatchersTest, PolygonBoundaryNear) { std::unique_ptr expected = MakePolygonOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakePolygonOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, PolygonBoundaryNear(*expected, S1Angle::Radians(1e-10))); // As string. EXPECT_THAT("10:10,10:0,0:0", PolygonBoundaryNear("10:10,10:0,0:0", S1Angle::Radians(1e-10))); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(PolygonBoundaryNear( "10:10,10:0,0:1", S1Angle::Degrees(0.1)))); // Explain. StringMatchResultListener listener; S2PolygonMatcher m( "10:10,10:0,0:0", S2PolygonMatcher::Options(S2PolygonMatcher::Options::BOUNDARY_NEAR, S1Angle::Degrees(0.1))); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Polygons don't match with tolerance in degrees 0.1000000", listener.str()); } TEST(S2testmatchersTest, LoopEquals) { std::unique_ptr expected = MakeLoopOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakeLoopOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, LoopEquals(*expected)); // As string. EXPECT_THAT("10:10,10:0,0:0", LoopEquals("10:10,10:0,0:0")); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(LoopEquals("10:10,10:0,0:1"))); // Explain. StringMatchResultListener listener; S2LoopMatcher m( "10:10,10:0,0:0", S2LoopMatcher::Options(S2LoopMatcher::Options::EQUALS, S1Angle::Zero())); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Loops don't match", listener.str()); } TEST(S2testmatchersTest, LoopBoundaryEquals) { std::unique_ptr expected = MakeLoopOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakeLoopOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, LoopBoundaryEquals(*expected)); // As string. EXPECT_THAT("10:10,10:0,0:0", LoopBoundaryEquals("10:10,10:0,0:0")); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(LoopBoundaryEquals("10:10,10:0,0:1"))); // Explain. StringMatchResultListener listener; S2LoopMatcher m("10:10,10:0,0:0", S2LoopMatcher::Options( S2LoopMatcher::Options::BOUNDARY_EQUALS, S1Angle::Zero())); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Loops don't match", listener.str()); } TEST(S2testmatchersTest, LoopBoundaryEqualsRotatedVertices) { string expected_str = "10:10,10:0,0:0"; std::unique_ptr expected = MakeLoopOrDie(expected_str); std::unique_ptr value = MakeLoopOrDie("10:0,0:0,10:10"); // As object. EXPECT_THAT(*value, LoopBoundaryEquals(*expected)); // As string. EXPECT_THAT("10:10,10:0,0:0", LoopBoundaryEquals(expected_str)); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(LoopBoundaryEquals("10:10,10:0,0:1"))); // Explain. StringMatchResultListener listener; S2LoopMatcher m("10:10,10:0,0:0", S2LoopMatcher::Options( S2LoopMatcher::Options::BOUNDARY_EQUALS, S1Angle::Zero())); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Loops don't match", listener.str()); } TEST(S2testmatchersTest, LoopBoundaryApproxEquals) { std::unique_ptr expected = MakeLoopOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakeLoopOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, LoopBoundaryApproxEquals(*expected, S1Angle::Radians(1e-10))); // As string. EXPECT_THAT("10:10,10:0,0:0", LoopBoundaryApproxEquals( "10:10,10:0,0:0", S1Angle::Radians(1e-10))); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(LoopBoundaryApproxEquals( "10:10,10:0,0:1", S1Angle::Degrees(0.1)))); // Explain. StringMatchResultListener listener; S2LoopMatcher m( "10:10,10:0,0:0", S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_APPROX_EQUALS, S1Angle::Degrees(0.1))); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Loops don't match with tolerance in degrees 0.1000000", listener.str()); } TEST(S2testmatchersTest, LoopBoundaryNear) { std::unique_ptr expected = MakeLoopOrDie("10:10,10:0,0:0"); std::unique_ptr value = MakeLoopOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, LoopBoundaryNear(*expected, S1Angle::Radians(1e-10))); // As string. EXPECT_THAT("10:10,10:0,0:0", LoopBoundaryNear("10:10,10:0,0:0", S1Angle::Radians(1e-10))); // Negation. EXPECT_THAT("10:10,10:0,0:0", Not(LoopBoundaryNear("10:10,10:0,0:1", S1Angle::Degrees(0.1)))); // Explain. StringMatchResultListener listener; S2LoopMatcher m("10:10,10:0,0:0", S2LoopMatcher::Options(S2LoopMatcher::Options::BOUNDARY_NEAR, S1Angle::Degrees(0.1))); m.MatchAndExplain("10:10,10:0,0:1", &listener); EXPECT_EQ("S2Loops don't match with tolerance in degrees 0.1000000", listener.str()); } TEST(S2testmatchersTest, LoopIdenticalTo) { auto expected = MakeLoopOrDie("10:10,10:0,0:0"); auto value = MakeLoopOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, LoopIdenticalTo(*expected)); // Negation. EXPECT_THAT(*MakeLoopOrDie("10:10,10:0,0:1"), Not(LoopIdenticalTo(*expected))); // Explain. ::testing::StringMatchResultListener listener; S2LoopIdenticalToMatcher m(*expected); m.MatchAndExplain(*MakeLoopOrDie("10:10,10:0,0:1"), &listener); EXPECT_THAT(listener.str(), MatchesRegex("whose vertex\\(2\\) .* doesn't match .*")); } TEST(S2testmatchersTest, PolygonIdenticalTo) { auto expected = MakePolygonOrDie("10:10,10:0,0:0"); auto value = MakePolygonOrDie("10:10,10:0,0:0"); // As object. EXPECT_THAT(*value, PolygonIdenticalTo(*expected)); // Negation. EXPECT_THAT(*MakePolygonOrDie("10:10,10:0,0:1"), Not(PolygonIdenticalTo(*expected))); // Explain. ::testing::StringMatchResultListener listener; S2PolygonIdenticalToMatcher m(*expected); m.MatchAndExplain(*MakePolygonOrDie("10:10,10:0,0:1"), &listener); EXPECT_THAT( listener.str(), MatchesRegex("whose vertex\\(2\\) .* doesn't match .* in loop 0")); } TEST(S2testmatchersTest, LatLngRectEquals) { S2LatLngRect expected = MakeLatLngRectOrDie("0:0,10:10"); S2LatLngRect value = MakeLatLngRectOrDie("0:0,10:10"); // As object. EXPECT_THAT(value, LatLngRectEquals(expected)); // As string. EXPECT_THAT("0:0,10:10", LatLngRectEquals("0:0,10:10")); // Negation. EXPECT_THAT("0:0,10:10", Not(LatLngRectEquals("0:0,11:10"))); // Explain. StringMatchResultListener listener; S2LatLngRectMatcher m( "0:0,10:10", S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::EQUALS, S1Angle::Zero())); m.MatchAndExplain("0:0,11:10", &listener); EXPECT_EQ("S2LatLngRects don't match", listener.str()); } TEST(S2testmatchersTest, LatLngRectApproxEquals) { S2LatLngRect expected = MakeLatLngRectOrDie("0:0,10:10"); S2LatLngRect value = MakeLatLngRectOrDie("0:0,10:10"); // As object. EXPECT_THAT(value, LatLngRectApproxEquals(expected, S1Angle::Degrees(0.1))); // As string. EXPECT_THAT("0:0,10:10", LatLngRectApproxEquals("0:0,10:10", S1Angle::Degrees(0.1))); // Negation. EXPECT_THAT("0:0,10:10", Not(LatLngRectApproxEquals("0:0,11:10", S1Angle::Degrees(0.1)))); // Explain. StringMatchResultListener listener; S2LatLngRectMatcher m( "0:0,10:10", S2LatLngRectMatcher::Options(S2LatLngRectMatcher::Options::APPROX_EQUALS, S1Angle::Degrees(0.1))); m.MatchAndExplain("0:0,11:10", &listener); EXPECT_EQ("S2LatLngRects don't match with tolerance in degrees 0.1000000", listener.str()); } TEST(S2testmatchersTest, LatLngRectApproxEquals2) { S2LatLngRect expected = MakeLatLngRectOrDie("0:0,10:10"); S2LatLngRect value = MakeLatLngRectOrDie("0:0,10:10"); S2LatLng tolerance = S2LatLng::FromDegrees(0.1, 0.2); // As object. EXPECT_THAT(value, LatLngRectApproxEquals(expected, tolerance)); // As string. EXPECT_THAT("0:0,10:10", LatLngRectApproxEquals("0:0,10:10", tolerance)); // Negation. EXPECT_THAT("0:0,10:10", Not(LatLngRectApproxEquals("0:0,11:10", tolerance))); // Explain. StringMatchResultListener listener; S2LatLngRectMatcher m( "0:0,10:10", S2LatLngRectMatcher::Options( S2LatLngRectMatcher::Options::APPROX_EQUALS_2, tolerance)); m.MatchAndExplain("0:0,11:10", &listener); EXPECT_EQ( "S2LatLngRects don't match with tolerance in degrees [0.1000000, " "0.2000000]", listener.str()); } TEST(S2testmatchersTest, LatLngEquals) { S2LatLng expected = MakeLatLngOrDie("10:10"); S2LatLng value = MakeLatLngOrDie("10:10"); // As object. EXPECT_THAT(value, LatLngEquals(expected)); // As string. EXPECT_THAT("10:10", LatLngEquals("10:10")); // Negation. EXPECT_THAT("10:10", Not(LatLngEquals("11:10"))); // Explain. StringMatchResultListener listener; S2LatLngMatcher m("10:10", S2LatLngMatcher::Options(S2LatLngMatcher::Options::EQUALS, S1Angle::Zero())); m.MatchAndExplain("11:10", &listener); EXPECT_EQ("S2LatLngs don't match", listener.str()); } TEST(S2testmatchersTest, LatLngApproxEquals) { S2LatLng expected = MakeLatLngOrDie("10:10"); S2LatLng value = MakeLatLngOrDie("10:10"); // As object. EXPECT_THAT(value, LatLngApproxEquals(expected, S1Angle::Degrees(0.1))); // As string, testing tolerances in both directions EXPECT_THAT("10.095:9.95", LatLngApproxEquals("10:10", S1Angle::Degrees(0.1))); EXPECT_THAT("9.95:10.095", LatLngApproxEquals("10:10", S1Angle::Degrees(0.1))); // Negation. EXPECT_THAT("10:10", Not(LatLngApproxEquals("11:10", S1Angle::Degrees(0.1)))); // Explain. StringMatchResultListener listener; S2LatLngMatcher m( "10:10", S2LatLngMatcher::Options(S2LatLngMatcher::Options::APPROX_EQUALS, S1Angle::Degrees(0.1))); m.MatchAndExplain("11:10", &listener); EXPECT_EQ("S2LatLngs don't match with tolerance in degrees 0.1000000", listener.str()); } } // namespace S2 src/s2/id_set_lexicon.cc000066400000000000000000000051051524103652300154720ustar00rootroot00000000000000// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/id_set_lexicon.h" #include #include #include #include #include "absl/log/absl_check.h" #include "s2/sequence_lexicon.h" using std::vector; IdSetLexicon::IdSetLexicon() = default; IdSetLexicon::~IdSetLexicon() = default; // We define the copy/move constructors and assignment operators explicitly // in order to avoid copying/moving the temporary storage vector "tmp_". IdSetLexicon::IdSetLexicon(const IdSetLexicon& x) : id_sets_(x.id_sets_) { } IdSetLexicon::IdSetLexicon(IdSetLexicon&& x) noexcept : id_sets_(std::move(x.id_sets_)) {} IdSetLexicon& IdSetLexicon::operator=(const IdSetLexicon& x) { id_sets_ = x.id_sets_; return *this; } IdSetLexicon& IdSetLexicon::operator=(IdSetLexicon&& x) noexcept { id_sets_ = std::move(x.id_sets_); return *this; } void IdSetLexicon::Clear() { id_sets_.Clear(); } int32_t IdSetLexicon::AddInternal(vector* ids) { if (ids->empty()) { // Empty sets have a special id chosen not to conflict with other ids. return kEmptySetId; } else if (ids->size() == 1) { // Singleton sets are represented by their element. return (*ids)[0]; } else { // Canonicalize the set by sorting and removing duplicates. std::sort(ids->begin(), ids->end()); ids->erase(std::unique(ids->begin(), ids->end()), ids->end()); // After eliminating duplicates, we may now have a singleton. if (ids->size() == 1) return (*ids)[0]; // Non-singleton sets are represented by the bitwise complement of the id // returned by SequenceLexicon. return ~id_sets_.Add(*ids); } } IdSetLexicon::IdSet IdSetLexicon::id_set(int32_t set_id) const { if (set_id >= 0) { return IdSet(set_id); } else if (set_id == kEmptySetId) { return IdSet(); } else { auto sequence = id_sets_.sequence(~set_id); ABSL_DCHECK_NE(0, sequence.size()); return IdSet(&*sequence.begin(), &*sequence.begin() + sequence.size()); } } src/s2/id_set_lexicon.h000066400000000000000000000156531524103652300153450ustar00rootroot00000000000000// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_ID_SET_LEXICON_H_ #define S2_ID_SET_LEXICON_H_ #include #include #include #include #include #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/sequence_lexicon.h" // IdSetLexicon is a class for compactly representing sets of non-negative // integers such as array indices ("id sets"). It is especially suitable when // either (1) there are many duplicate sets, or (2) there are many singleton // or empty sets. See also ValueLexicon and SequenceLexicon. // // Each distinct id set is mapped to a 32-bit integer. Empty and singleton // sets take up no additional space whatsoever; the set itself is represented // by the unique id assigned to the set. Sets of size 2 or more occupy about // 11 bytes per set plus 4 bytes per element (as compared to 24 bytes per set // plus 4 bytes per element for std::vector). Duplicate sets are // automatically eliminated. Note also that id sets are referred to using // 32-bit integers rather than 64-bit pointers. // // This class is especially useful in conjunction with ValueLexicon. For // example, suppose that you want to label objects with a set of strings. You // could use a ValueLexicon to map the strings to "label ids" (32-bit // integers), and then use IdSetLexicon to map each set of labels to a "label // set id". Each reference to that label set then takes up only 4 bytes. // // Example usage: // // ValueLexicon labels_; // IdSetLexicon label_sets_; // // int32_t GetLabelSet(const vector& label_strings) { // vector label_ids; // for (const auto& str : label_strings) { // label_ids.push_back(labels_.Add(str)); // } // return label_sets_.Add(label_ids); // } // // int label_set_id = GetLabelSet(...); // for (auto id : label_sets_.id_set(label_set_id)) { // ABSL_LOG(INFO) << id; // } // // This class is similar to SequenceLexicon, except: // // 1. Empty and singleton sets are represented implicitly; they use no space. // 2. Sets are represented rather than sequences; values are reordered to be in // sorted order, and duplicates are removed. // 3. The values must be 32-bit non-negative integers (only). class IdSetLexicon { public: IdSetLexicon(); ~IdSetLexicon(); // IdSetLexicon is movable and copyable. IdSetLexicon(const IdSetLexicon&); IdSetLexicon& operator=(const IdSetLexicon&); IdSetLexicon(IdSetLexicon&&) noexcept; IdSetLexicon& operator=(IdSetLexicon&&) noexcept; // Clears all data from the lexicon. void Clear(); // Add the given set of integers to the lexicon if it is not already // present, and return the unique id for this set. "begin" and "end" are // forward iterators over a sequence of values that can be converted to // non-negative 32-bit integers. The values are automatically sorted and // duplicates are removed. Returns a signed integer representing this set. // // REQUIRES: All values in [begin, end) are non-negative 32-bit integers. template int32_t Add(FwdIterator begin, FwdIterator end); // Add the given set of integers to the lexicon if it is not already // present, and return the unique id for this set. This is a convenience // method equivalent to Add(std::begin(container), std::end(container)). template int32_t Add(const Container& container); // Convenience method that returns the unique id for a singleton set. // Note that because singleton sets take up no space, this method is // const. Equivalent to calling Add(&id, &id + 1). int32_t AddSingleton(int32_t id) const; // Convenience method that returns the unique id for the empty set. Note // that because the empty set takes up no space and has a fixed id, this // method is static. Equivalent to calling Add() with an empty container. static int32_t EmptySetId(); // Iterator type; please treat this as an opaque forward iterator. using Iterator = const int32_t*; // This class represents a set of integers stored in the IdSetLexicon. class IdSet { public: using value_type = const int32_t; Iterator begin() const; Iterator end() const; size_t size() const; private: friend class IdSetLexicon; IdSet(); IdSet(Iterator begin, Iterator end); explicit IdSet(int32_t singleton_id); Iterator begin_, end_; int32_t singleton_id_; }; // Return the set of integers corresponding to an id returned by Add(). IdSet id_set(int32_t set_id) const; private: // Choose kEmptySetId to be the last id that will ever be generated. // (Non-negative ids are reserved for singleton sets.) static constexpr int32_t kEmptySetId = std::numeric_limits::min(); int32_t AddInternal(std::vector* ids); SequenceLexicon id_sets_; std::vector tmp_; // temporary storage used during Add() }; ////////////////// Implementation details follow //////////////////// inline IdSetLexicon::Iterator IdSetLexicon::IdSet::begin() const { return begin_; } inline IdSetLexicon::Iterator IdSetLexicon::IdSet::end() const { return end_; } inline size_t IdSetLexicon::IdSet::size() const { return end_ - begin_; } inline IdSetLexicon::IdSet::IdSet() : begin_(&singleton_id_), end_(begin_) { } inline IdSetLexicon::IdSet::IdSet(Iterator begin, Iterator end) : begin_(begin), end_(end) { } inline IdSetLexicon::IdSet::IdSet(int32_t singleton_id) : begin_(&singleton_id_), end_(&singleton_id_ + 1), singleton_id_(singleton_id) {} inline int32_t IdSetLexicon::AddSingleton(int32_t id) const { ABSL_DCHECK_GE(id, 0); ABSL_DCHECK_LE(id, std::numeric_limits::max()); // Singleton sets are represented by their element. return id; } /*static*/ inline int32_t IdSetLexicon::EmptySetId() { return kEmptySetId; } template int32_t IdSetLexicon::Add(FwdIterator begin, FwdIterator end) { tmp_.clear(); for (; begin != end; ++begin) { ABSL_DCHECK_GE(*begin, 0); ABSL_DCHECK_LE(*begin, std::numeric_limits::max()); tmp_.push_back(*begin); } return AddInternal(&tmp_); } template int32_t IdSetLexicon::Add(const Container& container) { return Add(std::begin(container), std::end(container)); } #endif // S2_ID_SET_LEXICON_H_ src/s2/id_set_lexicon_test.cc000066400000000000000000000043241524103652300165330ustar00rootroot00000000000000// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/id_set_lexicon.h" #include #include #include #include #include #include #include "absl/types/span.h" using std::vector; void ExpectIdSet(absl::Span expected, const IdSetLexicon::IdSet& actual) { EXPECT_EQ(expected.size(), actual.size()); EXPECT_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); } using IdSet = IdSetLexicon::IdSet; using Seq = vector; TEST(IdSetLexicon, EmptySet) { IdSetLexicon lexicon; ExpectIdSet({}, lexicon.id_set(lexicon.Add(Seq{}))); } TEST(IdSetLexicon, SingletonSets) { IdSetLexicon lexicon; EXPECT_EQ(5, lexicon.Add(Seq{5})); EXPECT_EQ(0, lexicon.Add(Seq{0, 0})); EXPECT_EQ(1, lexicon.AddSingleton(1)); int32_t m = std::numeric_limits::max(); EXPECT_EQ(m, lexicon.Add(&m, &m + 1)); ExpectIdSet({0}, lexicon.id_set(0)); ExpectIdSet({1}, lexicon.id_set(1)); ExpectIdSet({5}, lexicon.id_set(5)); ExpectIdSet({m}, lexicon.id_set(m)); } TEST(IdSetLexicon, SetsAreSorted) { IdSetLexicon lexicon; EXPECT_EQ(~0, lexicon.Add(Seq{2, 5})); EXPECT_EQ(~1, lexicon.Add(Seq{3, 2, 5})); EXPECT_EQ(~0, lexicon.Add(Seq{5, 2})); EXPECT_EQ(~1, lexicon.Add(Seq{5, 3, 2, 5})); ExpectIdSet({2, 5}, lexicon.id_set(~0)); ExpectIdSet({2, 3, 5}, lexicon.id_set(~1)); } TEST(IdSetLexicon, Clear) { IdSetLexicon lexicon; EXPECT_EQ(~0, lexicon.Add(Seq{1, 2})); EXPECT_EQ(~1, lexicon.Add(Seq{3, 4})); lexicon.Clear(); EXPECT_EQ(~0, lexicon.Add(Seq{3, 4})); EXPECT_EQ(~1, lexicon.Add(Seq{1, 2})); } src/s2/internal/000077500000000000000000000000001524103652300140065ustar00rootroot00000000000000src/s2/internal/s2disjoint_set.h000066400000000000000000000113351524103652300171250ustar00rootroot00000000000000// Copyright 2022 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: smcallis@google.com (Sean McAllister) #ifndef S2_INTERNAL_S2DISJOINT_SET_H_ #define S2_INTERNAL_S2DISJOINT_SET_H_ #include #include "absl/container/flat_hash_map.h" #include "absl/log/absl_check.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep namespace internal { // A disjoint set (AKA union-find set, AKA merge-find set) is a data structure // that stores a partition of a set into disjoint subsets. It allows us to // efficiently add, merge and find a representative member of a set. // // In practice, disjoint sets are used for connected-component like algorithms // where we want to build up relationships between subsets and query the final // connected pieces. // // This implementation uses both path compression and union-by-size, so both the // Union and FindRoot operations have O(a(N)) amortized complexity, where a(n) // is the inverse Ackermann function. For any value that we'll ever care about, // a(n) is less than 5, which is, for all practical purposes, constant. template class DisjointSet { public: // Adds a new element to the set. The root of the element is itself, that is, // it's disjoint from all the other elements of the set. // // If the element is already in the set, no changes are made and false is // returned, otherwise true. // // Immediately after calling Add(val), FindRoot(val) == val. bool Add(const T& val); // Finds the root of the given element. If the element isn't in the set, // the returned optional has no value, otherwise it will contain the root. std::optional FindRoot(const T& val); // Performs union of two subsets. Makes the parent of a's subset equal to the // parent of b's subset. If either a or b isn't in the set, returns false and // does not modify the set. bool Union(const T& a, const T& b); // Returns the total number of elements in the set. int Size() const { return nodes_.size(); } // Clears the set so that Size() == 0. void Clear() { nodes_.clear(); } // Reserve space for at least num elements. void Reserve(int num) { nodes_.reserve(num); } private: struct Node { explicit Node(const T& value) : value(value) {} T value; int size = 1; }; // Implementation for find root, expects that val is in the set. Recursively // seeks to the root of the set and sets each element's parent to the root as // it goes, returning a reference to the root node. Node& FindRootImpl(const T& val); absl::flat_hash_map nodes_; }; template bool DisjointSet::Add(const T& val) { return nodes_.emplace(val, Node(val)).second; } template std::optional DisjointSet::FindRoot(const T& val) { // Val might not be in the table at all, so use find for first lookup. auto iter = nodes_.find(val); if (iter == nodes_.end()) { return {}; } Node& node = iter->second; if (node.value == val) { return val; } return node.value = FindRootImpl(node.value).value; } template typename DisjointSet::Node& DisjointSet::FindRootImpl(const T& val) { auto iter = nodes_.find(val); ABSL_DCHECK(iter != nodes_.end()); Node& node = iter->second; if (node.value == val) { return node; } // It can be shown that a disjoint set of size N has an upper bound on its // height of floor(log(N)). So even a billion element set will only recurse // 30 levels in the worst case here. Node& root = FindRootImpl(node.value); node.value = root.value; return root; } template bool DisjointSet::Union(const T& a, const T& b) { auto iter_a = nodes_.find(a); if (iter_a == nodes_.end()) { return false; } auto iter_b = nodes_.find(b); if (iter_b == nodes_.end()) { return false; } Node& root_a = FindRootImpl(iter_a->second.value); Node& root_b = FindRootImpl(iter_b->second.value); if (root_a.value != root_b.value) { if (root_a.size < root_b.size) { root_a.value = root_b.value; root_b.size += root_a.size; } else { root_b.value = root_a.value; root_a.size += root_b.size; } } return true; } } // namespace internal #endif // S2_INTERNAL_S2DISJOINT_SET_H_ src/s2/internal/s2disjoint_set_test.cc000066400000000000000000000063701524103652300203250ustar00rootroot00000000000000// Copyright 2022 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: smcallis@google.com (Sean McAllister) #include "s2/internal/s2disjoint_set.h" #include #include #include #include "absl/log/absl_check.h" #include "s2/s2point.h" namespace internal { namespace { TEST(DisjointSetTest, S2PointSetCompiles) { DisjointSet set; (void)set; } TEST(DisjointSetTest, InsertMoreThanOnceFails) { DisjointSet set; EXPECT_TRUE(set.Add(1)); EXPECT_FALSE(set.Add(1)); EXPECT_FALSE(set.Add(1)); } TEST(DisjointSetTest, FindRootWorks) { DisjointSet set; set.Add(1); std::optional root = set.FindRoot(1); ABSL_CHECK(root.has_value()); EXPECT_EQ(root.value(), 1); EXPECT_FALSE(set.FindRoot(2).has_value()); } TEST(DisjointSetTest, UnionWorks) { DisjointSet set; for (int i = 0; i < 10; ++i) { ABSL_CHECK(set.Add(i)); } // Union into two disjoint sets for (int i = 0; i < 4; ++i) { ABSL_CHECK(set.Union(i + 0, i + 1)); ABSL_CHECK(set.Union(i + 5, i + 6)); } // The values in the two sets should all have the same root now. for (int i = 0; i < 5; ++i) { std::optional root = set.FindRoot(i); ABSL_CHECK(root.has_value()); EXPECT_EQ(root.value(), 0); root = set.FindRoot(i + 5); ABSL_CHECK(root.has_value()); EXPECT_EQ(root.value(), 5); } // Check that attempting to union with something not in the set fails. EXPECT_FALSE(set.Union(0, 13)); EXPECT_FALSE(set.Union(13, 0)); EXPECT_FALSE(set.Union(12, 13)); // Union of two elements from two sets should unify the sets ABSL_CHECK(set.Union(3, 7)); for (int i = 0; i < 10; ++i) { std::optional root = set.FindRoot(i); ABSL_CHECK(root.has_value()); EXPECT_EQ(root.value(), 0); } } TEST(DisjointSetTest, SizeAndClearWorks) { DisjointSet set; set.Reserve(10); for (int i = 0; i < 10; ++i) { ABSL_CHECK(set.Add(i)); } EXPECT_EQ(set.Size(), 10); for (int i = 0; i < set.Size() - 1; ++i) { ABSL_CHECK(set.Union(i, i + 1)); } // Unioning doesn't change size. EXPECT_EQ(set.Size(), 10); set.Clear(); EXPECT_EQ(set.Size(), 0); } void BM_FindRoot(benchmark::State &state) { int size = state.range(0); DisjointSet set; set.Reserve(size); for (int i = 0; i < size; ++i) { set.Add(i); } // Union consecutive sets together to form a chain that can be length N. for (int i = 0; i < set.Size() - 1; ++i) { set.Union(i, i + 1); } // Benchmark the FindRoot time. for (auto _ : state) { benchmark::DoNotOptimize(set.FindRoot(1)); } state.SetItemsProcessed(state.iterations()); } BENCHMARK(BM_FindRoot)->Range(2, 1 << 20); } // namespace } // namespace internal src/s2/internal/s2incident_edge_tracker.cc000066400000000000000000000057611524103652300210670ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "s2/internal/s2incident_edge_tracker.h" #include #include #include "absl/log/absl_check.h" namespace internal { void S2IncidentEdgeTracker::StartShape(int shape_id) { nursery_.clear(); current_shape_ = shape_id; } void S2IncidentEdgeTracker::AddEdge(int edge_id, const S2Shape::Edge& edge) { ABSL_DCHECK_GE(current_shape_, 0); // Push non-degenerate edges into the nursery. nursery_.push_back({edge.v0, edge_id}); if (!edge.IsDegenerate()) { nursery_.push_back({edge.v1, edge_id}); } } void S2IncidentEdgeTracker::FinishShape() { ABSL_DCHECK_GE(current_shape_, 0); using std::swap; // We want to keep any vertices with more than two incident edges. We could // sort the array by vertex and remove any with fewer, but that would require // shifting the array and could turn quadratic quickly. // // Instead we'll scan forward from each vertex, swapping entries with the same // vertex into a contiguous range. Once we've done all the swapping we can // just make sure that we have at least three edges in the range. const int nursery_size = nursery_.size(); for (int start = 0; start < nursery_size;) { int end = start + 1; // Scan to the end of the array, swap entries so that entries with the same // vertex as the start are adjacent. int next = start; const S2Point& curr_vertex = nursery_[start].vertex; while (++next < nursery_size) { if (nursery_[next].vertex == curr_vertex) { swap(nursery_[next], nursery_[end++]); } } // Most vertices will have two incident edges (the incoming edge and the // outgoing edge), which aren't interesting, skip them. const int num_edges = end - start; if (ABSL_PREDICT_TRUE(num_edges <= 2)) { start = end; continue; } const IncidentEdgeKey key = {current_shape_, nursery_[start].vertex}; // If we don't have this key yet, create it manually with a pre-sized // hash set to avoid rehashes. Start with a size of 8, which is four // edges with a load factor of 50%. auto iter = incident_edge_map_.find(key); if (iter == incident_edge_map_.end()) { iter = incident_edge_map_.emplace(key, 8).first; } absl::flat_hash_set& edges = iter->second; edges.reserve(edges.size() + num_edges); while (start != end) { edges.insert({nursery_[start++].edge_id}); } } } } // namespace internal src/s2/internal/s2incident_edge_tracker.h000066400000000000000000000125201524103652300207200ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_INTERNAL_S2INCIDENT_EDGE_TRACKER_H_ #define S2_INTERNAL_S2INCIDENT_EDGE_TRACKER_H_ #include #include #include #include #include "absl/container/btree_map.h" #include "absl/container/flat_hash_set.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/s2point.h" #include "s2/s2shape.h" namespace internal { // A tuple of (shape id, vertex) that compares by shape id. struct IncidentEdgeKey { IncidentEdgeKey() = default; explicit IncidentEdgeKey(int shape_id) : shape_id(shape_id) { /* Leave vertex undefined */ } IncidentEdgeKey(int shape_id, S2Point vertex) : shape_id(shape_id), vertex(vertex) {} int32_t shape_id; S2Point vertex; // We need a strict ordering to be a valid key for an ordered container, but // we don't actually care about the ordering of the vertices (as long as // they're grouped by shape id). Vertices are 3D points so they don't have a // natural ordering, so we'll just compare them lexicographically. bool operator<(const IncidentEdgeKey& b) const { if (shape_id < b.shape_id) return true; if (shape_id > b.shape_id) return false; for (int i = 0; i < 3; ++i) { if (vertex[i] < b.vertex[i]) return true; if (vertex[i] > b.vertex[i]) return false; } return false; // Must be equal. } }; // Map from keys of (shape id, vertex) to a set of edge_ids. We can and do // encounter the same edges multiple times, so we need to use a set to // deduplicate edges as they're inserted. using IncidentEdgeSet = absl::btree_map>; // A class for detecting and tracking shape edges that are incident on the same // vertex. Edges of multiple shapes may be tracked, but lookup is by shape id // and vertex: there is no facility to get all edges of all shapes at a vertex. // Edge vertices must compare exactly equal to be considered the same vertex, no // tolerance is applied as this isn't intended for e.g.: snapping shapes // together, which S2Builder does better and more robustly. // // To use, instantiate and then add edges with one or more sequences of calls, // where each sequence begins with StartShape(), followed by AddEdge() calls to // add edges for that shape, and ends with FinishShape(). Those sequences do // not need to visit shapes or edges in order. Then, call incidentEdges() to get // the resulting map from IncidentEdgeKeys (which are shapeId, vertex pairs) to // a set of edgeIds of the shape that are incident to that vertex.. // // This works on a block of edges at a time, meaning that to detect incident // edges on a particular vertex, we must have at least three edges incident // at that vertex when FinishShape() is called. We don't maintain partial // information between calls. However, subject to this constraint, a single // shape's edges may be defined with multiple sequences of StartShape(), // AddEdge()... , FinishShape() calls. // // The reason for this is simple: most edges don't have more than two incident // edges (the incoming and outgoing edge). If we had to maintain information // between calls, we'd end up with a map that contains every vertex, to no // benefit. Instead, when FinishShape() is called, we discard vertices that // contain two or fewer incident edges. // // In principle this isn't a real limitation because generally we process an // S2ShapeIndex cell at a time, and, if a vertex has multiple edges, we'll see // all the edges in the same cell as the vertex, and, in general, it's possible // to aggregate edges before calling. // // The tracker maintains incident edges until it's cleared. If you call it with // each cell from an S2ShapeIndex, then at the end you will have all the // incident edge information for the whole index. If only a subset is needed, // call Reset() when you're done. class S2IncidentEdgeTracker { public: // Add edges to the edge tracker. After calling, any vertices with multiple // (> 2) incident edges will appear in the incident edge map. void StartShape(int shape_id); void AddEdge(int edge_id, const S2Shape::Edge& edge); void FinishShape(); // Clear any accumulated state. void Reset() { incident_edge_map_.clear(); } // Returns a const reference to the incident edge map. const IncidentEdgeSet& IncidentEdges() const { return incident_edge_map_; } private: // Scratch space to temporarily store incident edges in. Having a separate // space for these lets us remove vertices with only one incident edge // easily. struct VertexEdge { S2Point vertex; int32_t edge_id; }; std::vector nursery_; int current_shape_ = -1; // Actual incident edge map. IncidentEdgeSet incident_edge_map_; }; } // namespace internal #endif // S2_INTERNAL_S2INCIDENT_EDGE_TRACKER_H_ src/s2/internal/s2index_cell_data.cc000066400000000000000000000146231524103652300176670ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "s2/internal/s2index_cell_data.h" #include #include #include #include "absl/log/absl_check.h" #include "s2/mutable_s2shape_index.h" #include "s2/s2cell.h" #include "s2/s2padded_cell.h" #include "s2/s2shape.h" namespace internal { void S2IndexCellData::LoadCell(const S2ShapeIndex* index, S2CellId id, const S2ShapeIndexCell* cell) { ABSL_DCHECK_NE(index, nullptr); if (index_ == index && cell_id_ == id) { return; } index_ = index; // Cache cell information. cell_ = cell; cell_id_ = id; // Reset atomic flags so we'll recompute cached values. These form a write // barrier with the write to cell_id_ above and so should stay below it. s2cell_set_.store(false, std::memory_order_release); center_set_.store(false, std::memory_order_release); // Clear previous edges. Reserve one slot in case we don't decode _any_ edges // (e.g. an interior cell or all the dimensions are unwanted, so we don't // try to create spans with a nullptr). edges_.clear(); shape_regions_.clear(); // Reset per-dimension region information. for (auto& region : dim_regions_) { region = Region(); } int min_dim = 0; while (min_dim <= 2 && !dim_wanted(min_dim)) { ++min_dim; } int max_dim = 2; while (max_dim >= 0 && !dim_wanted(max_dim)) { --max_dim; } // No dimensions wanted, we're done. if (min_dim > 2 || max_dim < 0) { return; } for (int dim = min_dim; dim <= max_dim; ++dim) { int dim_start = edges_.size(); for (const S2ClippedShape& clipped : cell_->clipped_shapes()) { int shape_id = clipped.shape_id(); const S2Shape& shape = *index->shape(shape_id); // Only process the current dimension. if (shape.dimension() != dim) { continue; } // In the event we wanted dimensions 0 and 2, but not 1. if (!dim_wanted(dim)) { continue; } // Materialize clipped shape edges into the edges vector. Track where we // start so we can add information about the region for this shape. int shape_start = edges_.size(); for (int i = 0; i < clipped.num_edges(); ++i) { int edge_id = clipped.edge(i); // Looking up an edge requires looking up which chain it's in, which is // often a binary search. So let's manually lookup the chain // information and use that to find the edge, so we only have to do that // search once. S2Shape::ChainPosition position = shape.chain_position(edge_id); S2Shape::Edge edge = shape.chain_edge(position.chain_id, position.offset); edges_.emplace_back(edge, edge_id, position); } // Note which block of edges belongs to the shape. shape_regions_.emplace_back(std::make_pair( shape_id, Region{shape_start, edges_.size() - shape_start})); } // Save region information for the current dimension. dim_regions_[dim] = {dim_start, edges_.size() - dim_start}; } } absl::Span S2IndexCellData::shape_edges( int id) const { for (const auto& iter : shape_regions_) { if (iter.first == id) { Region region = iter.second; if (static_cast(region.start) < edges_.size()) { return {&edges_[region.start], region.size}; } return {}; } } return {}; } absl::Span S2IndexCellData::dim_edges( int dim) const { ABSL_DCHECK(0 <= dim && dim <= 2); const Region& region = dim_regions_[dim]; if (static_cast(region.start) < edges_.size()) { return {&edges_[region.start], region.size}; } return {}; } absl::Span S2IndexCellData::dim_range_edges(int dim0, int dim1) const { ABSL_DCHECK_LE(dim0, dim1); ABSL_DCHECK(0 <= dim0 && dim0 <= 2); ABSL_DCHECK(0 <= dim1 && dim1 <= 2); size_t start = dim_regions_[dim0].start; size_t size = 0; for (int dim = dim0; dim <= dim1; ++dim) { start = std::min(start, static_cast(dim_regions_[dim].start)); size += dim_regions_[dim].size; } if (start < edges_.size()) { return {&edges_[start], size}; } return {}; } bool S2IndexCellData::ShapeContains(const S2ClippedShape& clipped, const S2Point& point, S2VertexModel model) const { #ifndef NDEBUG R2Rect bounds = S2PaddedCell(id(), MutableS2ShapeIndex::kCellPadding).bound(); R2Point uv; S2::ValidFaceXYZtoUV(S2Cell(id()).face(), point, &uv); ABSL_DCHECK(bounds.Contains(uv)); #endif // Points and polylines don't contain anything except under the CLOSED model. const S2Shape& shape = *index_->shape(clipped.shape_id()); if (shape.dimension() < 2) { if (model != S2VertexModel::CLOSED) { return false; } // Point/polyline only contains point if it's a vertex. for (const EdgeAndIdChain& edge : shape_edges(clipped.shape_id())) { if (edge.v0 == point || edge.v1 == point) { return true; } } return false; } // Test containment by drawing a line segment from the cell center to the // given point and counting edge crossings. S2Point center = this->center(); S2EdgeCrosser crosser(¢er, &point); bool inside = clipped.contains_center(); for (const EdgeAndIdChain& edge : shape_edges(clipped.shape_id())) { int sign = crosser.CrossingSign(&edge.v0, &edge.v1); if (sign < 0) continue; if (sign == 0) { // For the OPEN and CLOSED models, check whether point is a vertex. if (model != S2VertexModel::SEMI_OPEN && (edge.v0 == point || edge.v1 == point)) { return (model == S2VertexModel::CLOSED); } sign = S2::VertexCrossing(*crosser.a(), *crosser.b(), edge.v0, edge.v1); } inside ^= sign; } return inside; } } // namespace internal src/s2/internal/s2index_cell_data.h000066400000000000000000000246161524103652300175340ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_INTERNAL_S2INDEX_CELL_DATA_H_ #define S2_INTERNAL_S2INDEX_CELL_DATA_H_ #include #include #include #include #include #include "absl/base/thread_annotations.h" #include "absl/log/absl_check.h" #include "absl/synchronization/mutex.h" #include "absl/types/span.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/s2cell.h" #include "s2/s2cell_id.h" #include "s2/s2contains_point_query.h" #include "s2/s2point.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" // A class for working with S2ShapeIndexCell data. For larger queries like // validation, we often look up edges multiple times, and sometimes need to // work with the edges themselves, their edge ids, or their chain and offset. // // S2ShapeIndexCell and the S2ClippedShape APIs fundamentally work with edge ids // and can't be re-worked without significant effort and loss of efficiency. // This class provides an alternative API than repeatedly querying through the // shapes in the index. // // This is meant to support larger querying and validation operations such as // S2ValidationQuery that have to proceed cell-by cell through an index. // // To use, simply call LoadCell() to decode the contents of a cell. // // The class promises that the edges will be looked up once when LoadCell() is // called, and the edges, edge_ids, chain, and chain offsets are loaded into a // contiguous chunk of memory that we can serve requests from via absl::Span. // Since the chain and offset are computed anyways when looking up an edge via // the shape.edge() API, we simply cache those values so the cost is minimal. // // The memory layout looks like this: // // | 0D Shapes | 1D Shapes | 2D Shapes | Dimensions // | 5 | 1 | 3 | 2 | 7 | 0 | 6 | 4 | 8 | Shapes // [ ......................... Edges ..........................] Edges // // This allows us to look up individual shapes very quickly, as well as all // shapes in a given dimension or contiguous range of dimensions: // // Edges() - Return Span over all edges. // ShapeEdges() - Return Span over edges of a given shape. // DimEdges() - Return Span over all edges of a given dimension. // DimRangeEges() - Return Span over all edges of a range of dimensions. // // We use a stable sort, so similarly to S2ShapeIndexCell, we promise that // shapes _within a dimension_ are in the same order they are in the index // itself, and the edges _within a shape_ are similarly in the same order. // // The clipped shapes in a cell are exposed through the Shapes() method. // namespace internal { class S2IndexCellData { public: // Extension of Edge with fields for the edge id, chain id, and offset. It's // useful to bundle these together when decoding S2ShapeIndex cells because it // allows us to avoid repetitive edge and chain lookups in many cases. struct EdgeAndIdChain : S2Shape::Edge { EdgeAndIdChain() = default; EdgeAndIdChain(const Edge& edge, int edge_id, int chain, int offset) : Edge(edge), id(edge_id), chain(chain), offset(offset) {} EdgeAndIdChain(const Edge& edge, int edge_id, S2Shape::ChainPosition pos) : Edge(edge), id(edge_id), chain(pos.chain_id), offset(pos.offset) {} friend bool operator==(const EdgeAndIdChain& x, const EdgeAndIdChain& y) { return x.v0 == y.v0 && x.v1 == y.v1; } friend bool operator<(const EdgeAndIdChain& x, const EdgeAndIdChain& y) { return x.v0 < y.v0 || (x.v0 == y.v0 && x.v1 < y.v1); } int32_t id; // Id of the edge within its shape. int32_t chain; // Id of the chain the edge belongs to. int32_t offset; // Offset of the edge within the chain. }; S2IndexCellData() = default; S2IndexCellData(const S2ShapeIndex* index, S2CellId id, const S2ShapeIndexCell* cell) { LoadCell(index, id, cell); } // Resets internal state to defaults without de-allocating memory. The next // call to LoadCell() will process the cell regardless of whether it was // already loaded. Should be called when processing a new index. void Reset() { index_ = nullptr; cell_ = nullptr; edges_.clear(); shape_regions_.clear(); dim_wanted_[0] = dim_wanted_[1] = dim_wanted_[2] = true; } // Returns true if a dimension (0, 1, or 2) is set to be decoded. bool dim_wanted(int dim) const { ABSL_DCHECK(0 <= dim && dim <= 2); return dim_wanted_[dim]; } // Configures whether a particular dimension of shape should be decoded. void set_dim_wanted(int dim, bool wanted) { ABSL_DCHECK(0 <= dim && dim <= 2); dim_wanted_[dim] = wanted; } // Returns the id of the current cell. S2CellId id() const { return cell_id_; } // Returns a const pointer to the index of the current cell. const S2ShapeIndex* index() const { return index_; } // Returns an S2Cell instance for the current cell. const S2Cell& cell() const { if (!s2cell_set_.load(std::memory_order_acquire)) { absl::MutexLock lock(lock_); if (!s2cell_set_.load(std::memory_order_relaxed)) { s2cell_ = S2Cell(cell_id_); s2cell_set_.store(true, std::memory_order_release); } } // `s2cell_` is set once an for all, it won't change after this function // returns. return ABSL_TS_UNCHECKED_READ(s2cell_); } // Returns the center point of the current cell. const S2Point& center() const { if (!center_set_.load(std::memory_order_acquire)) { absl::MutexLock lock(lock_); if (!center_set_.load(std::memory_order_relaxed)) { cell_center_ = cell_id_.ToPoint(); center_set_.store(true, std::memory_order_release); } } // `cell_center_` is set once an for all, it won't change after this // function returns. return ABSL_TS_UNCHECKED_READ(cell_center_); } // Loads the data from the given cell, previous cell data is cleared. Both // the index and cell lifetimes must span the lifetime until the class is // destroyed or LoadCell() is called again, so we take by const pointer to // avoid binding temporaries. // // If the index, id and cell pointer are the same as in the previous call to // LoadCell, loading is not performed since we already have the data decoded. void LoadCell(const S2ShapeIndex* index, S2CellId id, const S2ShapeIndexCell* cell); // Returns the number of clipped shapes in the cell. int num_clipped() const { return cell_->num_clipped(); } // Returns a reference to the S2Shape for the given clipped shape. The // returned reference is to a shape owned by the index passed to LoadCell(). const S2Shape& shape(const S2ClippedShape& clipped) const { const S2Shape* shape = index_->shape(clipped.shape_id()); ABSL_DCHECK_NE(shape, nullptr); return *shape; } // Same as above but takes the shape id directly. const S2Shape& shape(int shape_id) const { const S2Shape* shape = index_->shape(shape_id); ABSL_DCHECK_NE(shape, nullptr); return *shape; } // Return a constant view over the clipped shapes in the cell. absl::Span clipped_shapes() const { return cell_->clipped_shapes(); } // Returns a view into all the edges in the current cell. absl::Span edges() const { return edges_; } // Returns a view into the edges in the current cell for a given shape. // REQUIRES: id is an id for one of the shapes in Shapes() absl::Span shape_edges(int shape_id) const; // Returns a view into the edges in the current cell for a given dimension. // REQUIRES: dim is a valid dimension (0, 1, or 2) absl::Span dim_edges(int dim) const; // Returns a view into the edges in the current cell for a range of // dimensions. // REQUIRES: dimensions are valid (0, 1, or 2) absl::Span dim_range_edges(int dim0, int dim1) const; // Tests whether a shape in the current cell contains a point. The logic here // is is the same as S2ContainsPointQuery::ShapeContains but only applies to // the current cell and doesn't have to lookup edges or cell centers again. // // Since this _only_ operates on edges within the current cell, it must not // be used to test points that are outside of the current cell, as there may // be intervening edges between the point and the cell center that we can't // see. // // By default operates with an OPEN vertex model. // // REQUIRES: The cell must contain point. bool ShapeContains(const S2ClippedShape& clipped, const S2Point& point, S2VertexModel model = S2VertexModel::OPEN) const; private: const S2ShapeIndex* index_ = nullptr; const S2ShapeIndexCell* cell_ = nullptr; S2CellId cell_id_; // Computing the cell center and S2Cell can cost as much as looking up the // edges themselves, so defer doing it until needed. We want to be able to // access the values through a const reference though, so we have to // synchronize access ourselves. // // TODO(b/335677213): Use std::atomic_flag instead when C++20 is allowed. mutable std::atomic s2cell_set_ = false; mutable std::atomic center_set_ = false; mutable absl::Mutex lock_; mutable S2Cell s2cell_ ABSL_GUARDED_BY(lock_); mutable S2Point cell_center_ ABSL_GUARDED_BY(lock_); // Dimensions that we wish to decode, the default is all of them. bool dim_wanted_[3] = {true, true, true}; // Storage space for edges of the current cell. std::vector edges_; // Simple pair for defining an integer valued region. struct Region { int start = 0; size_t size = 0; }; // Map from shape id to the region of the edges_ array it's stored in. std::vector> shape_regions_; // Region for each dimension we might encounter. Region dim_regions_[3]; }; } // namespace internal #endif // S2_INTERNAL_S2INDEX_CELL_DATA_H_ src/s2/internal/s2index_cell_data_test.cc000066400000000000000000000125731524103652300207300ustar00rootroot00000000000000// Copyright 2022 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: smcallis@google.com (Sean McAllister) #include "s2/internal/s2index_cell_data.h" #include #include #include #include "absl/log/absl_check.h" #include "s2/mutable_s2shape_index.h" #include "s2/s2cell_range_iterator.h" #include "s2/s2testing.h" #include "s2/s2text_format.h" namespace internal { namespace { using ::std::unique_ptr; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Ne; using ::testing::Not; using ::testing::NotNull; TEST(S2IndexCellData, Accessors) { // Provide some test coverage for accessors so they are not detected as // dead code. unique_ptr index = s2textformat::MakeIndexOrDie("0:0 ##"); MutableS2ShapeIndex::Iterator iter(index.get(), S2ShapeIndex::BEGIN); S2IndexCellData data; data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.index(), NotNull()); EXPECT_THAT(data.num_clipped(), Eq(1)); } TEST(S2IndexCellData, DimensionFilteringWorks) { unique_ptr index = s2textformat::MakeIndexOrDie( "0:0" "#1:1, 2:2" "#1:0, 0:1, -1:0, 0:-1"); MutableS2ShapeIndex::Iterator iter(index.get(), S2ShapeIndex::BEGIN); { // Check that we get all dimensions by default. S2IndexCellData data; data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.dim_edges(0), Not(IsEmpty())); EXPECT_THAT(data.dim_edges(1), Not(IsEmpty())); EXPECT_THAT(data.dim_edges(2), Not(IsEmpty())); } { // No dimensions should work too, we just don't decode edges. S2IndexCellData data; data.set_dim_wanted(0, false); data.set_dim_wanted(1, false); data.set_dim_wanted(2, false); data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.dim_edges(0), IsEmpty()); EXPECT_THAT(data.dim_edges(1), IsEmpty()); EXPECT_THAT(data.dim_edges(2), IsEmpty()); } // Should be able to get ranges even if a dimension is turned off. { S2IndexCellData data; data.set_dim_wanted(0, false); data.set_dim_wanted(1, true); data.set_dim_wanted(2, true); data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.dim_range_edges(0, 0), IsEmpty()); EXPECT_THAT(data.dim_range_edges(0, 2), Not(IsEmpty())); } { S2IndexCellData data; data.set_dim_wanted(0, false); data.set_dim_wanted(1, true); data.set_dim_wanted(2, false); data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.dim_edges(0), IsEmpty()); EXPECT_THAT(data.dim_edges(1), Not(IsEmpty())); EXPECT_THAT(data.dim_edges(2), IsEmpty()); } { S2IndexCellData data; data.set_dim_wanted(0, true); data.set_dim_wanted(1, false); data.set_dim_wanted(2, true); data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.dim_edges(0), Not(IsEmpty())); EXPECT_THAT(data.dim_edges(1), IsEmpty()); EXPECT_THAT(data.dim_edges(2), Not(IsEmpty())); } { S2IndexCellData data; data.set_dim_wanted(0, true); data.set_dim_wanted(1, false); data.set_dim_wanted(2, false); data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.dim_edges(0), Not(IsEmpty())); EXPECT_THAT(data.dim_edges(1), IsEmpty()); EXPECT_THAT(data.dim_edges(2), IsEmpty()); } { S2IndexCellData data; data.set_dim_wanted(0, false); data.set_dim_wanted(1, false); data.set_dim_wanted(2, true); data.LoadCell(index.get(), iter.id(), &iter.cell()); EXPECT_THAT(data.dim_edges(0), IsEmpty()); EXPECT_THAT(data.dim_edges(1), IsEmpty()); EXPECT_THAT(data.dim_edges(2), Not(IsEmpty())); } } // We cache cell centers and S2Cell instances because they're expensive to // compute if they're not needed. Make sure that when we load a new unique // cell, those values are updated if we access them. TEST(S2IndexCellData, CellAndCenterRecomputed) { // A line between two faces will guarantee we get at least two cells. unique_ptr index = s2textformat::MakeIndexOrDie("# 0:0, 0:-90 #"); S2IndexCellData data; auto iter = MakeS2CellRangeIterator(index.get()); data.LoadCell(index.get(), iter.id(), &iter.iterator().cell()); const S2Point center0 = data.center(); const S2Cell cell0 = data.cell(); iter.Next(); ABSL_CHECK(!iter.done()); data.LoadCell(index.get(), iter.id(), &iter.iterator().cell()); const S2Point center1 = data.center(); const S2Cell cell1 = data.cell(); EXPECT_THAT(cell0, Ne(cell1)); EXPECT_THAT(center0, Ne(center1)); // Load the same cell again, nothing should change. data.LoadCell(index.get(), iter.id(), &iter.iterator().cell()); const S2Point center2 = data.center(); const S2Cell cell2 = data.cell(); EXPECT_THAT(cell1, Eq(cell2)); EXPECT_THAT(center1, Eq(center2)); } } // namespace } // namespace internal src/s2/internal/s2meta.h000066400000000000000000000033021524103652300153500ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_INTERNAL_S2META_H_ #define S2_INTERNAL_S2META_H_ #include #include "absl/meta/type_traits.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep // This file contains functions for meta programming, primarily related to // checking that the type of an opaque template parameter is an instance of some // S2 base type. These are defined internally to avoid clients relying on them. // A variable template to check if a type is derived from another type ignoring // cv and reference qualifiers. This is similar to std::derived_from which was // added in C++20. // // TODO(b/335677213): Remove this when we have access to C++20. namespace s2meta { template using derived_from = absl::conjunction< std::is_base_of, std::decay_t>, std::is_convertible*, const volatile std::decay_t*>>; template constexpr bool derived_from_v = derived_from::value; } // namespace s2meta #endif // S2_INTERNAL_S2META_H_ src/s2/mutable_s2shape_index.cc000066400000000000000000002670221524103652300167570ustar00rootroot00000000000000// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/mutable_s2shape_index.h" #include #include #include #include #include #include #include #include #include "absl/base/attributes.h" #include "absl/container/btree_map.h" #include "absl/flags/flag.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/synchronization/mutex.h" #include "absl/types/span.h" #include "s2/util/coding/coder.h" #include "s2/util/coding/varint.h" #include "s2/encoded_s2cell_id_vector.h" #include "s2/encoded_string_vector.h" #include "s2/r1interval.h" #include "s2/r2.h" #include "s2/r2rect.h" #include "s2/s2cell_id.h" #include "s2/s2cell_iterator.h" #include "s2/s2cell_union.h" #include "s2/s2coords.h" #include "s2/s2edge_clipping.h" #include "s2/s2edge_crosser.h" #include "s2/s2edge_vector_shape.h" #include "s2/s2memory_tracker.h" #include "s2/s2metrics.h" #include "s2/s2padded_cell.h" #include "s2/s2point.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2shapeutil_contains_brute_force.h" #include "s2/s2shapeutil_shape_edge_id.h" #include "s2/util/gtl/compact_array.h" using std::fabs; using std::make_pair; using std::make_unique; using std::max; using std::min; using std::unique_ptr; using std::vector; // FLAGS_s2shape_index_default_max_edges_per_cell // // The default maximum number of edges per cell (not counting 'long' edges). // If a cell has more than this many edges, and it is not a leaf cell, then it // is subdivided. This flag can be overridden via MutableS2ShapeIndex::Options. // Reasonable values range from 10 to about 50 or so. ABSL_FLAG( int32_t, s2shape_index_default_max_edges_per_cell, 10, "Default maximum number of edges per cell (not counting 'long' edges); " "reasonable values range from 10 to 50. Small values makes queries " "faster, while large values make construction faster and use less memory."); // FLAGS_s2shape_index_tmp_memory_budget // // Attempt to limit the amount of temporary memory allocated while building or // updating a MutableS2ShapeIndex to at most this value. This is achieved by // splitting the updates into multiple batches when necessary. (The memory // required is proportional to the number of edges being updated at once.) // // Note that this limit is not a hard guarantee, for several reasons: // (1) the memory estimates are only approximations; // (2) all edges in a given shape are added or removed at once, so shapes // with huge numbers of edges may exceed the budget; // (3) shapes being removed are always processed in a single batch. (This // could be fixed, but it seems better to keep the code simpler for now.) ABSL_FLAG( int64_t, s2shape_index_tmp_memory_budget, int64_t{100} << 20 /*100 MB*/, "Attempts to limit the amount of temporary memory used by " "MutableS2ShapeIndex when creating or updating very large indexes to at " "most this number of bytes. If more memory than this is needed, updates " "will automatically be split into batches internally."); // FLAGS_s2shape_index_cell_size_to_long_edge_ratio // // The maximum cell size, relative to an edge's length, for which that edge is // considered 'long'. Cell size is defined as the average edge length of all // cells at a given level. For example, a value of 2.0 means that an edge E // is long at cell level k iff the average edge length at level k is at most // twice the length of E. Long edges edges are not counted towards the // max_edges_per_cell() limit because such edges typically need to be // propagated to several children, which increases time and memory costs // without commensurate benefits. ABSL_FLAG( double, s2shape_index_cell_size_to_long_edge_ratio, 1.0, "The maximum cell size, relative to an edge's length, for which that " "edge is considered 'long'. Long edges are not counted towards the " "max_edges_per_cell() limit. The size and speed of the index are " "typically not very sensitive to this parameter. Reasonable values range " "from 0.1 to 10, with smaller values causing more aggressive subdivision " "of long edges grouped closely together."); // FLAGS_s2shape_index_min_short_edge_fraction // // The minimum fraction of 'short' edges that must be present in a cell in // order for it to be subdivided. If this parameter is non-zero then the // total index size and construction time are guaranteed to be linear in the // number of input edges; this prevents the worst-case quadratic space and // time usage that can otherwise occur with certain input configurations. // Specifically, the maximum index size is // // O((c1 + c2 * (1 - f) / f) * n) // // where n is the number of input edges, f is this parameter value, and // constant c2 is roughly 20 times larger than constant c1. (The exact values // of c1 and c2 depend on the cell_size_to_long_edge_ratio and // max_edges_per_cell parameters and certain properties of the input geometry // such as whether it consists of O(1) shapes, whether it includes polygons, // and whether the polygon interiors are disjoint.) // // Reasonable parameter values range from 0.1 up to perhaps 0.95. The main // factors to consider when choosing this parameter are: // // - For pathological geometry, larger values result in indexes that are // smaller and faster to construct but have worse query performance (due to // having more edges per cell). However note that even a setting of 0.1 // reduces the worst case by 100x compared with a setting of 0.001. // // - For normal geometry, values up to about 0.8 result in indexes that are // virtually unchanged except for a slight increase in index construction // time (proportional to the parameter value f) for very large inputs. // With millions of edges, indexing time increases by about (15% * f), // e.g. a parameter value of 0.5 slows down indexing for very large inputs // by about 7.5%. (Indexing time for small inputs is not affected.) // // - Values larger than about 0.8 start to affect index construction even for // normal geometry, resulting in smaller indexes and faster construction // times but gradually worse query performance. // // Essentially this parameter provides control over a space-time tradeoff that // largely affects only pathological geometry. The default value of 0.2 was // chosen to make index construction as fast as possible while still // protecting against possible quadratic space usage. ABSL_FLAG( double, s2shape_index_min_short_edge_fraction, 0.2, "The minimum fraction of 'short' edges that must be present in a cell in " "order for it to be subdivided. If this parameter is non-zero then the " "total index size and construction time are guaranteed to be linear in the " "number of input edges, where the constant of proportionality has the " "form (c1 + c2 * (1 - f) / f). Reasonable values range from 0.1 to " "perhaps 0.95. Values up to about 0.8 have almost no effect on 'normal' " "geometry except for a small increase in index construction time " "(proportional to f) for very large inputs. For worst-case geometry, " "larger parameter values result in indexes that are smaller and faster " "to construct but have worse query performance (due to having more edges " "per cell). Essentially this parameter provides control over a space-time " "tradeoff that largely affects only pathological geometry."); // The total error when clipping an edge comes from two sources: // (1) Clipping the original spherical edge to a cube face (the "face edge"). // The maximum error in this step is S2::kFaceClipErrorUVCoord. // (2) Clipping the face edge to the u- or v-coordinate of a cell boundary. // The maximum error in this step is S2::kEdgeClipErrorUVCoord. // Finally, since we encounter the same errors when clipping query edges, we // double the total error so that we only need to pad edges during indexing // and not at query time. const double MutableS2ShapeIndex::kCellPadding = 2 * (S2::kFaceClipErrorUVCoord + S2::kEdgeClipErrorUVCoord); MutableS2ShapeIndex::Options::Options() : max_edges_per_cell_( absl::GetFlag(FLAGS_s2shape_index_default_max_edges_per_cell)) {} void MutableS2ShapeIndex::Options::set_max_edges_per_cell( int max_edges_per_cell) { max_edges_per_cell_ = max_edges_per_cell; } // FaceEdge and ClippedEdge store temporary edge data while the index is being // updated. FaceEdge represents an edge that has been projected onto a given // face, while ClippedEdge represents the portion of that edge that has been // clipped to a given S2Cell. // // While it would be possible to combine all the edge information into one // structure, there are two good reasons for separating it: // // - Memory usage. Separating the two classes means that we only need to // store one copy of the per-face data no matter how many times an edge is // subdivided, and it also lets us delay computing bounding boxes until // they are needed for processing each face (when the dataset spans // multiple faces). // // - Performance. UpdateEdges is significantly faster on large polygons when // the data is separated, because it often only needs to access the data in // ClippedEdge and this data is cached more successfully. struct MutableS2ShapeIndex::FaceEdge { int32_t shape_id; // The shape that this edge belongs to int32_t edge_id; // Edge id within that shape int32_t max_level; // Not desirable to subdivide this edge beyond this level bool has_interior; // Belongs to a shape of dimension 2. R2Point a, b; // The edge endpoints, clipped to a given face S2Shape::Edge edge; // The edge endpoints }; struct MutableS2ShapeIndex::ClippedEdge { const FaceEdge* face_edge; // The original unclipped edge R2Rect bound; // Bounding box for the clipped portion }; // Given a set of shapes, InteriorTracker keeps track of which shapes contain // a particular point (the "focus"). It provides an efficient way to move the // focus from one point to another and incrementally update the set of shapes // which contain it. We use this to compute which shapes contain the center // of every S2CellId in the index, by advancing the focus from one cell center // to the next. // // Initially the focus is at the start of the S2CellId space-filling curve. // We then visit all the cells that are being added to the MutableS2ShapeIndex // in increasing order of S2CellId. For each cell, we draw two edges: one // from the entry vertex to the center, and another from the center to the // exit vertex (where "entry" and "exit" refer to the points where the // space-filling curve enters and exits the cell). By counting edge crossings // we can incrementally compute which shapes contain the cell center. Note // that the same set of shapes will always contain the exit point of one cell // and the entry point of the next cell in the index, because either (a) these // two points are actually the same, or (b) the intervening cells in S2CellId // order are all empty, and therefore there are no edge crossings if we follow // this path from one cell to the other. class MutableS2ShapeIndex::InteriorTracker { public: // Constructs the InteriorTracker. You must call AddShape() for each shape // that will be tracked before calling MoveTo() or DrawTo(). InteriorTracker(); // Returns the initial focus point when the InteriorTracker is constructed // (corresponding to the start of the S2CellId space-filling curve). static S2Point Origin(); // Returns the current focus point (see above). const S2Point& focus() { return b_; } // Returns true if any shapes are being tracked. bool is_active() const { return is_active_; } // Adds a shape whose interior should be tracked. "contains_focus" indicates // whether the current focus point is inside the shape. Alternatively, if the // focus point is in the process of being moved (via MoveTo/DrawTo), you can // also specify "contains_focus" at the old focus point and call TestEdge() // for every edge of the shape that might cross the current DrawTo() line. // This updates the state to correspond to the new focus point. // // REQUIRES: shape->dimension() == 2 void AddShape(int32_t shape_id, bool contains_focus); // Moves the focus to the given point. This method should only be used when // it is known that there are no edge crossings between the old and new // focus locations; otherwise use DrawTo(). void MoveTo(const S2Point& b) { b_ = b; } // Moves the focus to the given point. After this method is called, // TestEdge() should be called with all edges that may cross the line // segment between the old and new focus locations. void DrawTo(const S2Point& b); // Indicates that the given edge of the given shape may cross the line // segment between the old and new focus locations (see DrawTo). // REQUIRES: shape->dimension() == 2 inline void TestEdge(int32_t shape_id, const S2Shape::Edge& edge); // The set of shape ids that contain the current focus. const ShapeIdSet& shape_ids() const { return shape_ids_; } // Indicates that the last argument to MoveTo() or DrawTo() was the entry // vertex of the given S2CellId, i.e. the tracker is positioned at the start // of this cell. By using this method together with at_cellid(), the caller // can avoid calling MoveTo() in cases where the exit vertex of the previous // cell is the same as the entry vertex of the current cell. void set_next_cellid(S2CellId next_cellid) { next_cellid_ = next_cellid.range_min(); } // Returns true if the focus is already at the entry vertex of the given // S2CellId (provided that the caller calls set_next_cellid() as each cell // is processed). bool at_cellid(S2CellId cellid) const { return cellid.range_min() == next_cellid_; } // Makes an internal copy of the state for shape ids below the given limit, // and then clear the state for those shapes. This is used during // incremental updates to track the state of added and removed shapes // separately. void SaveAndClearStateBefore(int32_t limit_shape_id); // Restores the state previously saved by SaveAndClearStateBefore(). This // only affects the state for shape_ids below "limit_shape_id". void RestoreStateBefore(int32_t limit_shape_id); // Indicates that only some edges of the given shape are being added, and // therefore its interior should not be processed yet. int partial_shape_id() const { return partial_shape_id_; } void set_partial_shape_id(int shape_id) { partial_shape_id_ = shape_id; } private: // Removes "shape_id" from shape_ids_ if it exists, otherwise insert it. void ToggleShape(int shape_id); // Returns a pointer to the first entry "x" where x >= shape_id. ShapeIdSet::iterator lower_bound(int32_t shape_id); bool is_active_ = false; S2Point a_, b_; S2CellId next_cellid_; S2EdgeCrosser crosser_; ShapeIdSet shape_ids_; // Shape ids saved by SaveAndClearStateBefore(). The state is never saved // recursively so we don't need to worry about maintaining a stack. ShapeIdSet saved_ids_; // As an optimization, we also save is_active_ so that RestoreStateBefore() // can deactivate the tracker again in the case where the shapes being added // and removed do not have an interior, but some existing shapes do. bool saved_is_active_; // If non-negative, indicates that only some edges of the given shape are // being added and therefore its interior should not be tracked yet. int partial_shape_id_ = -1; }; // As shapes are added, we compute which ones contain the start of the // S2CellId space-filling curve by drawing an edge from S2::Origin() to this // point and counting how many shape edges cross this edge. MutableS2ShapeIndex::InteriorTracker::InteriorTracker() : b_(Origin()), next_cellid_(S2CellId::Begin(S2CellId::kMaxLevel)) { } S2Point MutableS2ShapeIndex::InteriorTracker::Origin() { // The start of the S2CellId space-filling curve. return S2::FaceUVtoXYZ(0, -1, -1).Normalize(); } void MutableS2ShapeIndex::InteriorTracker::AddShape(int32_t shape_id, bool contains_focus) { is_active_ = true; if (contains_focus) { ToggleShape(shape_id); } } void MutableS2ShapeIndex::InteriorTracker::ToggleShape(int shape_id) { // Since shape_ids_.size() is typically *very* small (0, 1, or 2), it turns // out to be significantly faster to maintain a sorted array rather than // using an STL set or btree_set. if (shape_ids_.empty()) { shape_ids_.push_back(shape_id); } else if (shape_ids_[0] == shape_id) { shape_ids_.erase(shape_ids_.begin()); } else { ShapeIdSet::iterator pos = shape_ids_.begin(); while (*pos < shape_id) { if (++pos == shape_ids_.end()) { shape_ids_.push_back(shape_id); return; } } if (*pos == shape_id) { shape_ids_.erase(pos); } else { shape_ids_.insert(pos, shape_id); } } } void MutableS2ShapeIndex::InteriorTracker::DrawTo(const S2Point& b) { a_ = b_; b_ = b; crosser_.Init(&a_, &b_); } ABSL_ATTRIBUTE_ALWAYS_INLINE // ~1% faster inline void MutableS2ShapeIndex::InteriorTracker::TestEdge(int32_t shape_id, const S2Shape::Edge& edge) { if (crosser_.EdgeOrVertexCrossing(&edge.v0, &edge.v1)) { ToggleShape(shape_id); } } // Like std::lower_bound(shape_ids_.begin(), shape_ids_.end(), shape_id), but // implemented with linear rather than binary search because the number of // shapes being tracked is typically very small. inline MutableS2ShapeIndex::ShapeIdSet::iterator MutableS2ShapeIndex::InteriorTracker::lower_bound(int32_t shape_id) { ShapeIdSet::iterator pos = shape_ids_.begin(); while (pos != shape_ids_.end() && *pos < shape_id) { ++pos; } return pos; } void MutableS2ShapeIndex::InteriorTracker::SaveAndClearStateBefore( int32_t limit_shape_id) { ABSL_DCHECK(saved_ids_.empty()); ShapeIdSet::iterator limit = lower_bound(limit_shape_id); saved_ids_.assign(shape_ids_.begin(), limit); shape_ids_.erase(shape_ids_.begin(), limit); saved_is_active_ = is_active_; } void MutableS2ShapeIndex::InteriorTracker::RestoreStateBefore( int32_t limit_shape_id) { shape_ids_.erase(shape_ids_.begin(), lower_bound(limit_shape_id)); shape_ids_.insert(shape_ids_.begin(), saved_ids_.begin(), saved_ids_.end()); saved_ids_.clear(); is_active_ = saved_is_active_; } MutableS2ShapeIndex::MutableS2ShapeIndex() = default; MutableS2ShapeIndex::MutableS2ShapeIndex(const Options& options) { Init(options); } MutableS2ShapeIndex::MutableS2ShapeIndex(MutableS2ShapeIndex&& b) noexcept // S2ShapeIndex has no members. : shapes_(std::move(b.shapes_)), cell_map_(std::move(b.cell_map_)), options_(std::move(b.options_)), pending_additions_begin_(std::exchange(b.pending_additions_begin_, 0)), pending_removals_(std::move(b.pending_removals_)), index_status_(b.index_status_.exchange(FRESH, std::memory_order_relaxed)), mem_tracker_(std::move(b.mem_tracker_)) {} MutableS2ShapeIndex& MutableS2ShapeIndex::operator=( MutableS2ShapeIndex&& b) noexcept { // S2ShapeIndex has no members. shapes_ = std::move(b.shapes_); cell_map_.swap(b.cell_map_); options_ = std::move(b.options_); pending_additions_begin_ = std::exchange(b.pending_additions_begin_, 0); pending_removals_ = std::move(b.pending_removals_); index_status_.store( b.index_status_.exchange(FRESH, std::memory_order_relaxed), std::memory_order_relaxed); mem_tracker_ = std::move(b.mem_tracker_); return *this; } void MutableS2ShapeIndex::Init(const Options& options) { ABSL_DCHECK(shapes_.empty()); options_ = options; // Memory tracking is not affected by this method. } MutableS2ShapeIndex::~MutableS2ShapeIndex() { Clear(); } void MutableS2ShapeIndex::set_memory_tracker(S2MemoryTracker* tracker) { mem_tracker_.Tally(-mem_tracker_.client_usage_bytes()); mem_tracker_.Init(tracker); if (mem_tracker_.is_active()) mem_tracker_.Tally(SpaceUsed()); } // Called to set the index status when the index needs to be rebuilt. void MutableS2ShapeIndex::MarkIndexStale() { // The UPDATING status can only be changed in ApplyUpdatesThreadSafe(). if (index_status_.load(std::memory_order_relaxed) == UPDATING) return; // If a memory tracking error has occurred we set the index status to FRESH // in order to prevent us from attempting to rebuild it. IndexStatus status = (shapes_.empty() || !mem_tracker_.ok()) ? FRESH : STALE; index_status_.store(status, std::memory_order_relaxed); } void MutableS2ShapeIndex::Minimize() { mem_tracker_.Tally(-mem_tracker_.client_usage_bytes()); cell_map_.clear(); pending_removals_.reset(); pending_additions_begin_ = 0; MarkIndexStale(); if (mem_tracker_.is_active()) mem_tracker_.Tally(SpaceUsed()); } int MutableS2ShapeIndex::Add(unique_ptr shape) { // Additions are processed lazily by ApplyUpdates(). Note that in order to // avoid unexpected client behavior, this method continues to add shapes // even once the specified S2MemoryTracker limit has been exceeded. const int id = shapes_.size(); mem_tracker_.AddSpace(&shapes_, 1); shapes_.push_back(std::move(shape)); MarkIndexStale(); return id; } bool MutableS2ShapeIndex::MaybeCreatePendingRemovals() { if (!pending_removals_) { if (!mem_tracker_.Tally(sizeof(*pending_removals_))) { Minimize(); return false; } pending_removals_ = make_unique>(); } if (!mem_tracker_.AddSpace(pending_removals_.get(), 1)) { Minimize(); return false; } return true; } unique_ptr MutableS2ShapeIndex::Release(int shape_id) { // This class updates itself lazily, because it is much more efficient to // process additions and removals in batches. However this means that when // a shape is removed we need to make a copy of all its edges, since the // client is free to delete "shape" once this call is finished. ABSL_DCHECK(shapes_[shape_id] != nullptr); auto shape = std::move(shapes_[shape_id]); if (shape_id >= pending_additions_begin_) { // We are removing a shape that has not yet been added to the index, // so there is nothing else to do. } else { if (!MaybeCreatePendingRemovals()) return nullptr; // We need to make a copy of the shape data since the caller now owns the // original shape and may delete it. auto shape_copy = make_unique(); shape_copy->set_dimension(shape->dimension()); for (int i = 0; i < shape->num_edges(); ++i) { shape_copy->Add(shape->edge(i).v0, shape->edge(i).v1); } pending_removals_->push_back({shape_id, std::move(shape_copy)}); } MarkIndexStale(); return shape; } void MutableS2ShapeIndex::Remove(int shape_id) { ABSL_DCHECK(shapes_[shape_id] != nullptr); if (shape_id >= pending_additions_begin_) { // We are removing a shape that has not yet been added to the index, // so there is nothing else to do. shapes_[shape_id] = nullptr; } else { if (!MaybeCreatePendingRemovals()) return; // We don't need to copy the shape data since we own it. pending_removals_->push_back({shape_id, std::move(shapes_[shape_id])}); } MarkIndexStale(); } vector> MutableS2ShapeIndex::ReleaseAll() { ABSL_DCHECK(update_state_ == nullptr); vector> result; result.swap(shapes_); Minimize(); return result; } void MutableS2ShapeIndex::Clear() { ReleaseAll(); } // Apply any pending updates in a thread-safe way. void MutableS2ShapeIndex::ApplyUpdatesThreadSafe() { lock_.lock(); if (index_status_.load(std::memory_order_relaxed) == FRESH) { lock_.unlock(); } else if (index_status_.load(std::memory_order_relaxed) == UPDATING) { // Wait until the updating thread is finished. We do this by attempting // to lock a mutex that is held by the updating thread. When this mutex // is unlocked the index_status_ is guaranteed to be FRESH. ++update_state_->num_waiting; lock_.unlock(); update_state_->wait_mutex.lock(); lock_.lock(); --update_state_->num_waiting; UnlockAndSignal(); // Notify other waiting threads. } else { ABSL_DCHECK_EQ(STALE, index_status_); index_status_.store(UPDATING, std::memory_order_relaxed); // Allocate the extra state needed for thread synchronization. We keep // the spinlock held while doing this, because (1) memory allocation is // fast, so the chance of a context switch while holding the lock is low; // (2) by far the most common situation is that there is no contention, // and this saves an extra lock and unlock step; (3) even in the rare case // where there is contention, the main side effect is that some other // thread will burn a few CPU cycles rather than sleeping. update_state_ = make_unique(); // lock_.Lock wait_mutex *before* calling Unlock() to ensure that all other // threads will block on it. update_state_->wait_mutex.lock(); // Release the spinlock before doing any real work. lock_.unlock(); ApplyUpdatesInternal(); lock_.lock(); // index_status_ can be updated to FRESH only while locked *and* using // an atomic store operation, so that MaybeApplyUpdates() can check // whether the index is FRESH without acquiring the spinlock. index_status_.store(FRESH, std::memory_order_release); UnlockAndSignal(); // Notify any waiting threads. } } // Releases lock_ and wakes up any waiting threads by releasing wait_mutex. // If this was the last waiting thread, also deletes update_state_. // REQUIRES: lock_ is held. // REQUIRES: wait_mutex is held. inline void MutableS2ShapeIndex::UnlockAndSignal() { ABSL_DCHECK_EQ(FRESH, index_status_); int num_waiting = update_state_->num_waiting; lock_.unlock(); // Allow another waiting thread to proceed. Note that no new threads can // start waiting because the index_status_ is now FRESH, and the caller is // required to prevent any new mutations from occurring while these const // methods are running. // // We need to unlock wait_mutex before destroying it even if there are no // waiting threads. update_state_->wait_mutex.unlock(); if (num_waiting == 0) { update_state_.reset(); } } // This method updates the index by applying all pending additions and // removals. It does *not* update index_status_ (see ApplyUpdatesThreadSafe). void MutableS2ShapeIndex::ApplyUpdatesInternal() { // Check whether we have so many edges to process that we should process // them in multiple batches to save memory. Building the index can use up // to 20x as much memory (per edge) as the final index size. vector batches = GetUpdateBatches(); for (const BatchDescriptor& batch : batches) { if (mem_tracker_.is_active()) { ABSL_DCHECK_EQ(mem_tracker_.client_usage_bytes(), SpaceUsed()); // Invariant. } vector all_edges[6]; ReserveSpace(batch, all_edges); if (!mem_tracker_.ok()) return Minimize(); InteriorTracker tracker; if (pending_removals_) { // The first batch implicitly includes all shapes being removed. for (const auto& item : *pending_removals_) { RemoveShape(item.shape.get(), item.shape_id, all_edges, &tracker); } pending_removals_.reset(nullptr); } // A batch consists of zero or more full shapes followed by zero or one // partial shapes. The loop below handles all such cases. for (auto begin = batch.begin; begin < batch.end; ++begin.shape_id, begin.edge_id = 0) { const S2Shape* shape = this->shape(begin.shape_id); if (shape == nullptr) continue; // Already removed. int edges_end = begin.shape_id == batch.end.shape_id ? batch.end.edge_id : shape->num_edges(); AddShape(shape, begin.shape_id, begin.edge_id, edges_end, all_edges, &tracker); } for (int face = 0; face < 6; ++face) { UpdateFaceEdges(face, all_edges[face], &tracker); // Save memory by clearing vectors after we are done with them. vector().swap(all_edges[face]); } pending_additions_begin_ = batch.end.shape_id; if (batch.begin.edge_id > 0 && batch.end.edge_id == 0) { // We have just finished adding the edges of shape that was split over // multiple batches. Now we need to mark the interior of the shape, if // any, by setting contains_center() on the appropriate index cells. FinishPartialShape(tracker.partial_shape_id()); } if (mem_tracker_.is_active()) { mem_tracker_.Tally(-mem_tracker_.client_usage_bytes()); if (!mem_tracker_.Tally(SpaceUsed())) return Minimize(); } } // It is the caller's responsibility to update index_status_. } // Count the number of edges being updated, and break them into several // batches if necessary to reduce the amount of memory needed. (See the // documentation for FLAGS_s2shape_index_tmp_memory_budget.) vector MutableS2ShapeIndex::GetUpdateBatches() const { // Count the edges being removed and added. int num_edges_removed = 0; if (pending_removals_) { for (const auto& item : *pending_removals_) { num_edges_removed += item.shape->num_edges(); } } int64_t num_edges_added = 0; for (size_t id = pending_additions_begin_; id < shapes_.size(); ++id) { const S2Shape* shape = this->shape(id); if (shape) num_edges_added += shape->num_edges(); } BatchGenerator batch_gen(num_edges_removed, num_edges_added, pending_additions_begin_); for (size_t id = pending_additions_begin_; id < shapes_.size(); ++id) { const S2Shape* shape = this->shape(id); if (shape) batch_gen.AddShape(id, shape->num_edges()); } return batch_gen.Finish(); } // The following memory estimates are based on heap profiling. // The batch sizes during a given update gradually decrease as the space // occupied by the index itself grows. In order to do this, we need a // conservative lower bound on how much the index grows per edge. // // The final size of a MutableS2ShapeIndex depends mainly on how finely the // index is subdivided, as controlled by Options::max_edges_per_cell() and // --s2shape_index_default_max_edges_per_cell. For realistic values of // max_edges_per_cell() and shapes with moderate numbers of edges, it is // difficult to get much below 8 bytes per edge. *The minimum possible size // is 4 bytes per edge (to store a 32-bit edge id in an S2ClippedShape) plus // 24 bytes per shape (for the S2ClippedShape itself plus a pointer in the // shapes_ vector.) Note that this value is a lower bound; a typical final // index size is closer to 24 bytes per edge. static constexpr size_t kFinalBytesPerEdge = 8; // The temporary memory consists mainly of the FaceEdge and ClippedEdge // structures plus a ClippedEdge pointer for every level of recursive // subdivision. This can be more than 220 bytes per edge even for typical // geometry. (The pathological worst case is higher, but we don't use this to // determine the batch sizes.) static constexpr size_t kTmpBytesPerEdge = 226; // We arbitrarily limit the number of batches as a safety measure. With the // current default memory budget of 100 MB, this limit is not reached even // when building an index of 350 million edges. static constexpr int kMaxBatches = 100; MutableS2ShapeIndex::BatchGenerator::BatchGenerator(int64_t num_edges_removed, int64_t num_edges_added, int shape_id_begin) : max_batch_sizes_(GetMaxBatchSizes(num_edges_removed, num_edges_added)), batch_begin_(shape_id_begin, 0), shape_id_end_(shape_id_begin) { if (max_batch_sizes_.size() > 1) { ABSL_VLOG(1) << "Removing " << num_edges_removed << ", adding " << num_edges_added << " edges in " << max_batch_sizes_.size() << " batches"; } // Duplicate the last entry to simplify next_max_batch_size(). max_batch_sizes_.push_back(max_batch_sizes_.back()); // We process edge removals before additions, and edges are always removed // in a single batch. The reasons for this include: (1) removed edges use // quite a bit of memory (about 50 bytes each) and this space can be freed // immediately when we process them in one batch; (2) removed shapes are // expected to be small fraction of the index size in typical use cases // (e.g. incremental updates of large indexes), and (3) AbsorbIndexCell() // uses (shape(id) == nullptr) to detect when a shape is being removed, so // in order to split the removed shapes into multiple batches we would need // a different approach (e.g., temporarily adding fake entries to shapes_ // and restoring them back to nullptr as shapes are removed). Removing // individual shapes over multiple batches would be even more work. batch_size_ = num_edges_removed; } void MutableS2ShapeIndex::BatchGenerator::AddShape(int shape_id, int num_edges) { int batch_remaining = max_batch_size() - batch_size_; if (num_edges <= batch_remaining) { ExtendBatch(num_edges); } else if (num_edges <= next_max_batch_size()) { // Avoid splitting shapes across batches unnecessarily. FinishBatch(0, ShapeEdgeId(shape_id, 0)); ExtendBatch(num_edges); } else { // This shape must be split across at least two batches. We simply fill // each batch until the remaining edges will fit in two batches, and then // divide those edges such that both batches have the same amount of // remaining space relative to their maximum size. int e_begin = 0; while (batch_remaining + next_max_batch_size() < num_edges) { e_begin += batch_remaining; FinishBatch(batch_remaining, ShapeEdgeId(shape_id, e_begin)); num_edges -= batch_remaining; batch_remaining = max_batch_size(); } // Figure out how many edges to add to the current batch so that it will // have the same amount of remaining space as the next batch. int n = (num_edges + batch_remaining - next_max_batch_size()) / 2; FinishBatch(n, ShapeEdgeId(shape_id, e_begin + n)); FinishBatch(num_edges - n, ShapeEdgeId(shape_id + 1, 0)); } shape_id_end_ = shape_id + 1; } vector MutableS2ShapeIndex::BatchGenerator::Finish() { // We must generate at least one batch even when num_edges_removed == // num_edges_added == 0, because some shapes have an interior but no edges. // (Specifically, the full polygon has this property.) if (batches_.empty() || shape_id_end_ != batch_begin_.shape_id) { FinishBatch(0, ShapeEdgeId(shape_id_end_, 0)); } return std::move(batches_); } void MutableS2ShapeIndex::BatchGenerator::FinishBatch(int num_edges, ShapeEdgeId batch_end) { ExtendBatch(num_edges); batches_.push_back(BatchDescriptor{batch_begin_, batch_end, batch_size_}); batch_begin_ = batch_end; batch_index_edges_left_ -= batch_size_; while (batch_index_edges_left_ < 0) { batch_index_edges_left_ += max_batch_size(); batch_index_ += 1; } batch_size_ = 0; } // Divides "num_edges" edges into batches where each batch needs about the // same total amount of memory. (The total memory needed by a batch consists // of the temporary memory needed to process the edges in that batch plus the // final representations of the edges that have already been indexed.) It // uses the fewest number of batches (up to kMaxBatches) such that the total // memory usage does not exceed the combined final size of all the edges plus // FLAGS_s2shape_index_tmp_memory_budget. Returns a vector of sizes // indicating the desired number of edges in each batch. /* static */ vector MutableS2ShapeIndex::BatchGenerator::GetMaxBatchSizes( int64_t num_edges_removed, int64_t num_edges_added) { // Check whether we can update all the edges at once. int64_t num_edges_total = num_edges_removed + num_edges_added; const double tmp_memory_budget_bytes = absl::GetFlag(FLAGS_s2shape_index_tmp_memory_budget); if (num_edges_total * kTmpBytesPerEdge <= tmp_memory_budget_bytes) { return vector{static_cast(num_edges_total)}; } // Each batch is allowed to use up to "total_budget_bytes". The memory // usage consists of some number of edges already added by previous batches // (at kFinalBytesPerEdge each), plus some number being updated in the // current batch (at kTmpBytesPerEdge each). The available free space is // multiplied by (1 - kFinalBytesPerEdge / kTmpBytesPerEdge) after each // batch is processed as edges are converted into their final form. const double final_bytes = num_edges_added * kFinalBytesPerEdge; constexpr double kFinalBytesRatio = 1.0 * kFinalBytesPerEdge / kTmpBytesPerEdge; constexpr double kTmpSpaceMultiplier = 1 - kFinalBytesRatio; // The total memory budget is the greater of the final size plus the allowed // temporary memory, or the minimum amount of memory required to limit the // number of batches to "kMaxBatches". const double total_budget_bytes = max( final_bytes + tmp_memory_budget_bytes, final_bytes / (1 - std::pow(kTmpSpaceMultiplier, kMaxBatches - 1))); // "ideal_batch_size" is the number of edges in the current batch before // rounding to an integer. double ideal_batch_size = total_budget_bytes / kTmpBytesPerEdge; // Removed edges are always processed in the first batch, even if this might // use more memory than requested (see the BatchGenerator constructor). vector batch_sizes; int64_t num_edges_left = num_edges_added; if (num_edges_removed > ideal_batch_size) { batch_sizes.push_back(num_edges_removed); } else { num_edges_left += num_edges_removed; } while (num_edges_left > 0) { int batch_size = static_cast(ideal_batch_size + 1); batch_sizes.push_back(batch_size); num_edges_left -= batch_size; ideal_batch_size *= kTmpSpaceMultiplier; } ABSL_DCHECK_LE(batch_sizes.size(), kMaxBatches); return batch_sizes; } // Reserve an appropriate amount of space for the top-level face edges in the // current batch. This data structure uses about half of the temporary memory // needed during index construction. Furthermore, if the arrays are grown via // push_back() then up to 10% of the total run time consists of copying data // as these arrays grow, so it is worthwhile to preallocate space for them. void MutableS2ShapeIndex::ReserveSpace( const BatchDescriptor& batch, vector all_edges[6]) { // The following accounts for the temporary space needed for everything // except the FaceEdge vectors (which are allocated separately below). int64_t other_usage = batch.num_edges * (kTmpBytesPerEdge - sizeof(FaceEdge)); // If the number of edges is relatively small, then the fastest approach is // to simply reserve space on every face for the maximum possible number of // edges. (We use a different threshold for this calculation than for // deciding when to break updates into batches because the cost/benefit // ratio is different. Here the only extra expense is that we need to // sample the edges to estimate how many edges per face there are, and // therefore we generally use a lower threshold.) const size_t kMaxCheapBytes = min(absl::GetFlag(FLAGS_s2shape_index_tmp_memory_budget) / 2, int64_t{30} << 20 /*30 MB*/); int64_t face_edge_usage = batch.num_edges * (6 * sizeof(FaceEdge)); if (static_cast(face_edge_usage) <= kMaxCheapBytes) { if (!mem_tracker_.TallyTemp(face_edge_usage + other_usage)) { return; } for (int face = 0; face < 6; ++face) { all_edges[face].reserve(batch.num_edges); } return; } // Otherwise we estimate the number of edges on each face by taking a random // sample. The goal is to come up with an estimate that is fast and // accurate for non-pathological geometry. If our estimates happen to be // wrong, the vector will still grow automatically - the main side effects // are that memory usage will be larger (by up to a factor of 3), and // constructing the index will be about 10% slower. // // Given a desired sample size, we choose equally spaced edges from // throughout the entire data set. We use a Bresenham-type algorithm to // choose the samples. const int kDesiredSampleSize = 10000; const int sample_interval = max(1, batch.num_edges / kDesiredSampleSize); // Initialize "edge_id" to be midway through the first sample interval. // Because samples are equally spaced the actual sample size may differ // slightly from the desired sample size. int edge_id = sample_interval / 2; const int actual_sample_size = (batch.num_edges + edge_id) / sample_interval; int face_count[6] = { 0, 0, 0, 0, 0, 0 }; if (pending_removals_) { for (const auto& item : *pending_removals_) { const S2Shape* shape = item.shape.get(); edge_id += shape->num_edges(); while (edge_id >= sample_interval) { edge_id -= sample_interval; face_count[S2::GetFace(shape->edge(edge_id).v0)] += 1; } } } for (auto begin = batch.begin; begin < batch.end; ++begin.shape_id, begin.edge_id = 0) { const S2Shape* shape = this->shape(begin.shape_id); if (shape == nullptr) continue; // Already removed. int edges_end = begin.shape_id == batch.end.shape_id ? batch.end.edge_id : shape->num_edges(); edge_id += edges_end - begin.edge_id; while (edge_id >= sample_interval) { edge_id -= sample_interval; // For speed, we only count the face containing one endpoint of the // edge. In general the edge could span all 6 faces (with padding), but // it's not worth the expense to compute this more accurately. face_count[S2::GetFace(shape->edge(edge_id + begin.edge_id).v0)] += 1; } } // Now given the raw face counts, compute a confidence interval such that we // will be unlikely to allocate too little space. Computing accurate // binomial confidence intervals is expensive and not really necessary. // Instead we use a simple approximation: // - For any face with at least 1 sample, we use at least a 4-sigma // confidence interval. (The chosen width is adequate for the worst case // accuracy, which occurs when the face contains approximately 50% of the // edges.) Assuming that our sample is representative, the probability of // reserving too little space is approximately 1 in 30,000. // - For faces with no samples at all, we don't bother reserving space. // It is quite likely that such faces are truly empty, so we save time // and memory this way. If the face does contain some edges, there will // only be a few so it is fine to let the vector grow automatically. // On average, we reserve 2% extra space for each face that has geometry // (which could be up to 12% extra space overall, but typically 2%). // kMaxSemiWidth is the maximum semi-width over all probabilities p of a // 4-sigma binomial confidence interval with a sample size of 10,000. const double kMaxSemiWidth = 0.02; // First estimate the total amount of memory we are about to allocate. double multiplier = 1.0; for (int face = 0; face < 6; ++face) { if (face_count[face] != 0) multiplier += kMaxSemiWidth; } face_edge_usage = multiplier * batch.num_edges * sizeof(FaceEdge); if (!mem_tracker_.TallyTemp(face_edge_usage + other_usage)) { return; } const double sample_ratio = 1.0 / actual_sample_size; for (int face = 0; face < 6; ++face) { if (face_count[face] == 0) continue; double fraction = sample_ratio * face_count[face] + kMaxSemiWidth; all_edges[face].reserve(fraction * batch.num_edges); } } // Clips the edges of the given shape to the six cube faces, add the clipped // edges to "all_edges", and start tracking its interior if necessary. void MutableS2ShapeIndex::AddShape(const S2Shape* shape, int shape_id, int edges_begin, int edges_end, vector all_edges[6], InteriorTracker* tracker) const { // Construct a template for the edges to be added. FaceEdge edge; edge.shape_id = shape_id; edge.has_interior = false; if (shape->dimension() == 2) { // To add a single shape with an interior over multiple batches, we first // add all the edges without tracking the interior. After all edges have // been added, the interior is updated in a separate step by setting the // contains_center() flags appropriately. if (edges_begin > 0 || edges_end < shape->num_edges()) { tracker->set_partial_shape_id(edge.shape_id); } else { edge.has_interior = true; tracker->AddShape( edge.shape_id, s2shapeutil::ContainsBruteForce(*shape, tracker->focus())); } } for (int e = edges_begin; e < edges_end; ++e) { edge.edge_id = e; edge.edge = shape->edge(e); edge.max_level = GetEdgeMaxLevel(edge.edge); AddFaceEdge(&edge, all_edges); } } void MutableS2ShapeIndex::RemoveShape(const S2Shape* shape, int shape_id, vector all_edges[6], InteriorTracker* tracker) const { FaceEdge edge; edge.edge_id = -1; // Not used or needed for removed edges. edge.shape_id = shape_id; edge.has_interior = (shape->dimension() == 2); if (edge.has_interior) { // Use a stale iterator to avoid triggering a recursive index update. // This is much faster than using ContainsBruteForce(), since the removed // shape is already in the index. Iterator it; bool inside = false; it.InitStale(this, InitialPosition::BEGIN); if (it.Locate(InteriorTracker::Origin())) { const S2ClippedShape* clipped = it.cell().find_clipped(shape_id); if (clipped != nullptr) { inside = clipped->contains_center(); S2CopyingEdgeCrosser x(it.id().ToPoint(), InteriorTracker::Origin()); for (int i = 0; i < clipped->num_edges(); ++i) { auto edge = shape->edge(clipped->edge(i)); inside ^= x.EdgeOrVertexCrossing(edge.v0, edge.v1); } } } tracker->AddShape(shape_id, inside); } for (int e = 0; e < shape->num_edges(); ++e) { edge.edge = shape->edge(e); edge.max_level = GetEdgeMaxLevel(edge.edge); AddFaceEdge(&edge, all_edges); } } void MutableS2ShapeIndex::FinishPartialShape(int shape_id) { if (shape_id < 0) return; // The partial shape did not have an interior. const S2Shape* shape = this->shape(shape_id); // Filling in the interior of a partial shape can grow the cell_map_ // significantly, however the new cells have just one shape and no edges. // The following is a rough estimate of how much extra memory is needed // based on experiments. It assumes that one new cell is required for every // 10 shape edges, and that the cell map uses 50% more space than necessary // for the new entries because they are inserted between existing entries // (which means that the btree nodes are not full). if (mem_tracker_.is_active()) { const int64_t new_usage = SpaceUsed() - mem_tracker_.client_usage_bytes() + 0.1 * shape->num_edges() * (1.5 * sizeof(CellMap::value_type) + sizeof(S2ShapeIndexCell) + sizeof(S2ClippedShape)); if (!mem_tracker_.TallyTemp(new_usage)) return; } // All the edges of the partial shape have already been indexed, now we just // need to set the contains_center() flags appropriately. We use a fresh // InteriorTracker for this purpose since we don't want to continue tracking // the interior state of any other shapes in this batch. // // We have implemented this below in the simplest way possible, namely by // scanning through the entire index. In theory it would be more efficient // to keep track of the set of index cells that were modified when the // partial shape's edges were added, and then visit only those cells. // However in practice any shape that is added over multiple batches is // likely to occupy most or all of the index anyway, so it is faster and // simpler to just iterate through the entire index. // // "tmp_edges" below speeds up large polygon index construction by 3-12%. vector tmp_edges; // Temporary storage. InteriorTracker tracker; tracker.AddShape(shape_id, s2shapeutil::ContainsBruteForce(*shape, tracker.focus())); S2CellId begin = S2CellId::Begin(S2CellId::kMaxLevel); for (CellMap::iterator index_it = cell_map_.begin(); ; ++index_it) { if (!tracker.shape_ids().empty()) { // Check whether we need to add new cells that are entirely contained by // the partial shape. S2CellId fill_end = (index_it != cell_map_.end()) ? index_it->first.range_min() : S2CellId::End(S2CellId::kMaxLevel); if (begin != fill_end) { for (S2CellId cellid : S2CellUnion::FromBeginEnd(begin, fill_end)) { auto cell = make_unique(); S2ClippedShape* clipped = cell->add_shapes(1); clipped->Init(shape_id, 0); clipped->set_contains_center(true); index_it = cell_map_.insert(index_it, make_pair(cellid, std::move(cell))); ++index_it; } } } if (index_it == cell_map_.end()) break; // Now check whether the current index cell needs to be updated. S2CellId cellid = index_it->first; S2ShapeIndexCell& cell = *index_it->second; int n = cell.shapes_.size(); if (n > 0 && cell.shapes_[n - 1].shape_id() == shape_id) { // This cell contains edges of the partial shape. If the partial shape // contains the center of this cell, we must update the index. S2PaddedCell pcell(cellid, kCellPadding); if (!tracker.at_cellid(cellid)) { tracker.MoveTo(pcell.GetEntryVertex()); } tracker.DrawTo(pcell.GetCenter()); S2ClippedShape* clipped = &cell.shapes_[n - 1]; int num_edges = clipped->num_edges(); ABSL_DCHECK_GT(num_edges, 0); for (int i = 0; i < num_edges; ++i) { tmp_edges.push_back(shape->edge(clipped->edge(i))); } for (const auto& edge : tmp_edges) { tracker.TestEdge(shape_id, edge); } if (!tracker.shape_ids().empty()) { // The partial shape contains the center of this index cell. clipped->set_contains_center(true); } tracker.DrawTo(pcell.GetExitVertex()); for (const auto& edge : tmp_edges) { tracker.TestEdge(shape_id, edge); } tracker.set_next_cellid(cellid.next()); tmp_edges.clear(); } else if (!tracker.shape_ids().empty()) { // The partial shape contains the center of an existing index cell that // does not intersect any of its edges. S2ClippedShape* clipped = cell.add_shapes(1); clipped->Init(shape_id, 0); clipped->set_contains_center(true); } begin = cellid.range_max().next(); } } inline void MutableS2ShapeIndex::AddFaceEdge( FaceEdge* edge, vector all_edges[6]) const { // Fast path: both endpoints are on the same face, and are far enough from // the edge of the face that don't intersect any (padded) adjacent face. int a_face = S2::GetFace(edge->edge.v0); if (a_face == S2::GetFace(edge->edge.v1)) { S2::ValidFaceXYZtoUV(a_face, edge->edge.v0, &edge->a); S2::ValidFaceXYZtoUV(a_face, edge->edge.v1, &edge->b); const double kMaxUV = 1 - kCellPadding; if (fabs(edge->a[0]) <= kMaxUV && fabs(edge->a[1]) <= kMaxUV && fabs(edge->b[0]) <= kMaxUV && fabs(edge->b[1]) <= kMaxUV) { all_edges[a_face].push_back(*edge); return; } } // Otherwise we simply clip the edge to all six faces. for (int face = 0; face < 6; ++face) { if (S2::ClipToPaddedFace(edge->edge.v0, edge->edge.v1, face, kCellPadding, &edge->a, &edge->b)) { all_edges[face].push_back(*edge); } } } // Returns the first level for which the given edge will be considered "long", // i.e. it will not count towards the max_edges_per_cell() limit. int MutableS2ShapeIndex::GetEdgeMaxLevel(const S2Shape::Edge& edge) const { // Compute the maximum cell edge length for which this edge is considered // "long". The calculation does not need to be perfectly accurate, so we // use Norm() rather than Angle() for speed. double max_cell_edge = ((edge.v0 - edge.v1).Norm() * absl::GetFlag(FLAGS_s2shape_index_cell_size_to_long_edge_ratio)); // Now return the first level encountered during subdivision where the // average cell edge length at that level is at most "max_cell_edge". return S2::kAvgEdge.GetLevelForMaxValue(max_cell_edge); } // EdgeAllocator provides temporary storage for new ClippedEdges that are // created during indexing. It is essentially a stack model, where edges are // allocated as the recursion does down and freed as it comes back up. // // It also provides a mutable vector of FaceEdges that is used when // incrementally updating the index (see AbsorbIndexCell). class MutableS2ShapeIndex::EdgeAllocator { public: EdgeAllocator() = default; // Return a pointer to a newly allocated edge. The EdgeAllocator // retains ownership. ClippedEdge* NewClippedEdge() { if (size_ == clipped_edges_.size()) { clipped_edges_.emplace_back(new ClippedEdge); } return clipped_edges_[size_++].get(); } // Return the number of allocated edges. size_t size() const { return size_; } // Reset the allocator to only contain the first "size" allocated edges. void Reset(size_t size) { size_ = size; } vector* mutable_face_edges() { return &face_edges_; } private: // We can't use vector because edges are not allowed to move // once they have been allocated. Instead we keep a pool of allocated edges // that are all deleted together at the end. size_t size_ = 0; vector> clipped_edges_; // On the other hand, we can use vector because they are allocated // only at one level during the recursion (namely, the level at which we // absorb an existing index cell). vector face_edges_; EdgeAllocator(const EdgeAllocator&) = delete; void operator=(const EdgeAllocator&) = delete; }; // Given a face and a vector of edges that intersect that face, add or remove // all the edges from the index. (An edge is added if shapes_[id] is not // nullptr, and removed otherwise.) void MutableS2ShapeIndex::UpdateFaceEdges(int face, absl::Span face_edges, InteriorTracker* tracker) { int num_edges = face_edges.size(); if (num_edges == 0 && tracker->shape_ids().empty()) return; // Create the initial ClippedEdge for each FaceEdge. Additional clipped // edges are created when edges are split between child cells. We create // two arrays, one containing the edge data and another containing pointers // to those edges, so that during the recursion we only need to copy // pointers in order to propagate an edge to the correct child. vector clipped_edge_storage; vector clipped_edges; clipped_edge_storage.reserve(num_edges); clipped_edges.reserve(num_edges); R2Rect bound = R2Rect::Empty(); for (int e = 0; e < num_edges; ++e) { ClippedEdge clipped; clipped.face_edge = &face_edges[e]; clipped.bound = R2Rect::FromPointPair(face_edges[e].a, face_edges[e].b); clipped_edge_storage.push_back(clipped); clipped_edges.push_back(&clipped_edge_storage.back()); bound.AddRect(clipped.bound); } // Construct the initial face cell containing all the edges, and then update // all the edges in the index recursively. EdgeAllocator alloc; S2CellId face_id = S2CellId::FromFace(face); S2PaddedCell pcell(face_id, kCellPadding); // "disjoint_from_index" means that the current cell being processed (and // all its descendants) are not already present in the index. It is set to // true during the recursion whenever we detect that the current cell is // disjoint from the index. We could save a tiny bit of work by setting // this flag to true here on the very first update, however currently there // is no easy way to check that. (It's not sufficient to test whether // cell_map_.empty() or pending_additions_begin_ == 0.) bool disjoint_from_index = false; if (num_edges > 0) { S2CellId shrunk_id = ShrinkToFit(pcell, bound); if (shrunk_id != pcell.id()) { // All the edges are contained by some descendant of the face cell. We // can save a lot of work by starting directly with that cell, but if we // are in the interior of at least one shape then we need to create // index entries for the cells we are skipping over. SkipCellRange(face_id.range_min(), shrunk_id.range_min(), tracker, &alloc, disjoint_from_index); pcell = S2PaddedCell(shrunk_id, kCellPadding); UpdateEdges(pcell, &clipped_edges, tracker, &alloc, disjoint_from_index); SkipCellRange(shrunk_id.range_max().next(), face_id.range_max().next(), tracker, &alloc, disjoint_from_index); return; } } // Otherwise (no edges, or no shrinking is possible), subdivide normally. UpdateEdges(pcell, &clipped_edges, tracker, &alloc, disjoint_from_index); } S2CellId MutableS2ShapeIndex::ShrinkToFit(const S2PaddedCell& pcell, const R2Rect& bound) const { S2CellId shrunk_id = pcell.ShrinkToFit(bound); if (shrunk_id != pcell.id()) { // Don't shrink any smaller than the existing index cells, since we need // to combine the new edges with those cells. Use InitStale() to avoid // applying updates recursively. Iterator iter; iter.InitStale(this); S2CellRelation r = iter.Locate(shrunk_id); if (r == S2CellRelation::INDEXED) { shrunk_id = iter.id(); } } return shrunk_id; } // Skip over the cells in the given range, creating index cells if we are // currently in the interior of at least one shape. void MutableS2ShapeIndex::SkipCellRange(S2CellId begin, S2CellId end, InteriorTracker* tracker, EdgeAllocator* alloc, bool disjoint_from_index) { // If we aren't in the interior of a shape, then skipping over cells is easy. if (tracker->shape_ids().empty()) return; // Otherwise generate the list of cell ids that we need to visit, and create // an index entry for each one. for (S2CellId skipped_id : S2CellUnion::FromBeginEnd(begin, end)) { vector clipped_edges; UpdateEdges(S2PaddedCell(skipped_id, kCellPadding), &clipped_edges, tracker, alloc, disjoint_from_index); } } // Given an edge and an interval "middle" along the v-axis, clip the edge // against the boundaries of "middle" and add the edge to the corresponding // children. /* static */ ABSL_ATTRIBUTE_ALWAYS_INLINE // ~8% faster inline void MutableS2ShapeIndex::ClipVAxis( const ClippedEdge* edge, const R1Interval& middle, vector child_edges[2], EdgeAllocator* alloc) { if (edge->bound[1].hi() <= middle.lo()) { // Edge is entirely contained in the lower child. child_edges[0].push_back(edge); } else if (edge->bound[1].lo() >= middle.hi()) { // Edge is entirely contained in the upper child. child_edges[1].push_back(edge); } else { // The edge bound spans both children. child_edges[0].push_back(ClipVBound(edge, 1, middle.hi(), alloc)); child_edges[1].push_back(ClipVBound(edge, 0, middle.lo(), alloc)); } } // Given a cell and a set of ClippedEdges whose bounding boxes intersect that // cell, add or remove all the edges from the index. Temporary space for // edges that need to be subdivided is allocated from the given EdgeAllocator. // "disjoint_from_index" is an optimization hint indicating that cell_map_ // does not contain any entries that overlap the given cell. void MutableS2ShapeIndex::UpdateEdges(const S2PaddedCell& pcell, vector* edges, InteriorTracker* tracker, EdgeAllocator* alloc, bool disjoint_from_index) { // Cases where an index cell is not needed should be detected before this. ABSL_DCHECK(!edges->empty() || !tracker->shape_ids().empty()); // This function is recursive with a maximum recursion depth of 30 // (S2CellId::kMaxLevel). Note that using an explicit stack does not seem // to be any faster based on profiling. // Incremental updates are handled as follows. All edges being added or // removed are combined together in "edges", and all shapes with interiors // are tracked using "tracker". We subdivide recursively as usual until we // encounter an existing index cell. At this point we "absorb" the index // cell as follows: // // - Edges and shapes that are being removed are deleted from "edges" and // "tracker". // - All remaining edges and shapes from the index cell are added to // "edges" and "tracker". // - Continue subdividing recursively, creating new index cells as needed. // - When the recursion gets back to the cell that was absorbed, we // restore "edges" and "tracker" to their previous state. // // Note that the only reason that we include removed shapes in the recursive // subdivision process is so that we can find all of the index cells that // contain those shapes efficiently, without maintaining an explicit list of // index cells for each shape (which would be expensive in terms of memory). bool index_cell_absorbed = false; if (!disjoint_from_index) { // There may be existing index cells contained inside "pcell". If we // encounter such a cell, we need to combine the edges being updated with // the existing cell contents by "absorbing" the cell. We use InitStale() // to avoid applying updates recursively. Iterator iter; iter.InitStale(this); S2CellRelation r = iter.Locate(pcell.id()); if (r == S2CellRelation::DISJOINT) { disjoint_from_index = true; } else if (r == S2CellRelation::INDEXED) { // Absorb the index cell by transferring its contents to "edges" and // deleting it. We also start tracking the interior of any new shapes. AbsorbIndexCell(pcell, iter, edges, tracker, alloc); index_cell_absorbed = true; disjoint_from_index = true; } else { ABSL_DCHECK_EQ(S2CellRelation::SUBDIVIDED, r); } } // If there are existing index cells below us, then we need to keep // subdividing so that we can merge with those cells. Otherwise, // MakeIndexCell checks if the number of edges is small enough, and creates // an index cell if possible (returning true when it does so). if (!disjoint_from_index || !MakeIndexCell(pcell, *edges, tracker)) { // Reserve space for the edges that will be passed to each child. This is // important since otherwise the running time is dominated by the time // required to grow the vectors. The amount of memory involved is // relatively small, so we simply reserve the maximum space for every child. vector child_edges[2][2]; // [i][j] int num_edges = edges->size(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { child_edges[i][j].reserve(num_edges); } } // Remember the current size of the EdgeAllocator so that we can free any // edges that are allocated during edge splitting. size_t alloc_size = alloc->size(); // Compute the middle of the padded cell, defined as the rectangle in // (u,v)-space that belongs to all four (padded) children. By comparing // against the four boundaries of "middle" we can determine which children // each edge needs to be propagated to. const R2Rect& middle = pcell.middle(); // Build up a vector edges to be passed to each child cell. The (i,j) // directions are left (i=0), right (i=1), lower (j=0), and upper (j=1). // Note that the vast majority of edges are propagated to a single child. // This case is very fast, consisting of between 2 and 4 floating-point // comparisons and copying one pointer. (ClipVAxis is inline.) for (int e = 0; e < num_edges; ++e) { const ClippedEdge* edge = (*edges)[e]; if (edge->bound[0].hi() <= middle[0].lo()) { // Edge is entirely contained in the two left children. ClipVAxis(edge, middle[1], child_edges[0], alloc); } else if (edge->bound[0].lo() >= middle[0].hi()) { // Edge is entirely contained in the two right children. ClipVAxis(edge, middle[1], child_edges[1], alloc); } else if (edge->bound[1].hi() <= middle[1].lo()) { // Edge is entirely contained in the two lower children. child_edges[0][0].push_back(ClipUBound(edge, 1, middle[0].hi(), alloc)); child_edges[1][0].push_back(ClipUBound(edge, 0, middle[0].lo(), alloc)); } else if (edge->bound[1].lo() >= middle[1].hi()) { // Edge is entirely contained in the two upper children. child_edges[0][1].push_back(ClipUBound(edge, 1, middle[0].hi(), alloc)); child_edges[1][1].push_back(ClipUBound(edge, 0, middle[0].lo(), alloc)); } else { // The edge bound spans all four children. The edge itself intersects // either three or four (padded) children. const ClippedEdge* left = ClipUBound(edge, 1, middle[0].hi(), alloc); ClipVAxis(left, middle[1], child_edges[0], alloc); const ClippedEdge* right = ClipUBound(edge, 0, middle[0].lo(), alloc); ClipVAxis(right, middle[1], child_edges[1], alloc); } } // Free any memory reserved for children that turned out to be empty. This // step is cheap and reduces peak memory usage by about 10% when building // large indexes (> 10M edges). for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (child_edges[i][j].empty()) { vector().swap(child_edges[i][j]); } } } // Now recursively update the edges in each child. We call the children in // increasing order of S2CellId so that when the index is first constructed, // all insertions into cell_map_ are at the end (which is much faster). for (int pos = 0; pos < 4; ++pos) { int i, j; pcell.GetChildIJ(pos, &i, &j); if (!child_edges[i][j].empty() || !tracker->shape_ids().empty()) { UpdateEdges(S2PaddedCell(pcell, i, j), &child_edges[i][j], tracker, alloc, disjoint_from_index); } } // Free any temporary edges that were allocated during clipping. alloc->Reset(alloc_size); } if (index_cell_absorbed) { // Restore the state for any edges being removed that we are tracking. tracker->RestoreStateBefore(pending_additions_begin_); } } // Given an edge, clip the given endpoint (lo=0, hi=1) of the u-axis so that // it does not extend past the given value. /* static */ const MutableS2ShapeIndex::ClippedEdge* MutableS2ShapeIndex::ClipUBound(const ClippedEdge* edge, int u_end, double u, EdgeAllocator* alloc) { // First check whether the edge actually requires any clipping. (Sometimes // this method is called when clipping is not necessary, e.g. when one edge // endpoint is in the overlap area between two padded child cells.) if (u_end == 0) { if (edge->bound[0].lo() >= u) return edge; } else { if (edge->bound[0].hi() <= u) return edge; } // We interpolate the new v-value from the endpoints of the original edge. // This has two advantages: (1) we don't need to store the clipped endpoints // at all, just their bounding box; and (2) it avoids the accumulation of // roundoff errors due to repeated interpolations. The result needs to be // clamped to ensure that it is in the appropriate range. const FaceEdge& e = *edge->face_edge; double v = edge->bound[1].Project( S2::InterpolateDouble(u, e.a[0], e.b[0], e.a[1], e.b[1])); // Determine which endpoint of the v-axis bound to update. If the edge // slope is positive we update the same endpoint, otherwise we update the // opposite endpoint. int v_end = u_end ^ ((e.a[0] > e.b[0]) != (e.a[1] > e.b[1])); return UpdateBound(edge, u_end, u, v_end, v, alloc); } // Given an edge, clip the given endpoint (lo=0, hi=1) of the v-axis so that // it does not extend past the given value. /* static */ const MutableS2ShapeIndex::ClippedEdge* MutableS2ShapeIndex::ClipVBound(const ClippedEdge* edge, int v_end, double v, EdgeAllocator* alloc) { // See comments in ClipUBound. if (v_end == 0) { if (edge->bound[1].lo() >= v) return edge; } else { if (edge->bound[1].hi() <= v) return edge; } const FaceEdge& e = *edge->face_edge; double u = edge->bound[0].Project( S2::InterpolateDouble(v, e.a[1], e.b[1], e.a[0], e.b[0])); int u_end = v_end ^ ((e.a[0] > e.b[0]) != (e.a[1] > e.b[1])); return UpdateBound(edge, u_end, u, v_end, v, alloc); } // Given an edge and two bound endpoints that need to be updated, allocate and // return a new edge with the updated bound. /* static */ inline const MutableS2ShapeIndex::ClippedEdge* MutableS2ShapeIndex::UpdateBound(const ClippedEdge* edge, int u_end, double u, int v_end, double v, EdgeAllocator* alloc) { ClippedEdge* clipped = alloc->NewClippedEdge(); clipped->face_edge = edge->face_edge; clipped->bound[0][u_end] = u; clipped->bound[1][v_end] = v; clipped->bound[0][1-u_end] = edge->bound[0][1-u_end]; clipped->bound[1][1-v_end] = edge->bound[1][1-v_end]; ABSL_DCHECK(!clipped->bound.is_empty()); ABSL_DCHECK(edge->bound.Contains(clipped->bound)); return clipped; } // Absorb an index cell by transferring its contents to "edges" and/or // "tracker", and then delete this cell from the index. If "edges" includes // any edges that are being removed, this method also updates their // InteriorTracker state to correspond to the exit vertex of this cell, and // saves the InteriorTracker state by calling SaveAndClearStateBefore(). It // is the caller's responsibility to restore this state by calling // RestoreStateBefore() when processing of this cell is finished. void MutableS2ShapeIndex::AbsorbIndexCell(const S2PaddedCell& pcell, const Iterator& iter, vector* edges, InteriorTracker* tracker, EdgeAllocator* alloc) { ABSL_DCHECK_EQ(pcell.id(), iter.id()); // When we absorb a cell, we erase all the edges that are being removed. // However when we are finished with this cell, we want to restore the state // of those edges (since that is how we find all the index cells that need // to be updated). The edges themselves are restored automatically when // UpdateEdges returns from its recursive call, but the InteriorTracker // state needs to be restored explicitly. // // Here we first update the InteriorTracker state for removed edges to // correspond to the exit vertex of this cell, and then save the // InteriorTracker state. This state will be restored by UpdateEdges when // it is finished processing the contents of this cell. (Note in the test // below that removed edges are always sorted before added edges.) if (tracker->is_active() && !edges->empty() && is_shape_being_removed((*edges)[0]->face_edge->shape_id)) { // We probably need to update the InteriorTracker. ("Probably" because // it's possible that all shapes being removed do not have interiors.) if (!tracker->at_cellid(pcell.id())) { tracker->MoveTo(pcell.GetEntryVertex()); } tracker->DrawTo(pcell.GetExitVertex()); tracker->set_next_cellid(pcell.id().next()); for (const ClippedEdge* edge : *edges) { const FaceEdge* face_edge = edge->face_edge; if (!is_shape_being_removed(face_edge->shape_id)) { break; // All shapes being removed come first. } if (face_edge->has_interior) { tracker->TestEdge(face_edge->shape_id, face_edge->edge); } } } // Save the state of the edges being removed so that it can be restored when // we are finished processing this cell and its children. Below we not only // remove those edges but also add new edges whose state only needs to be // tracked within this subtree. We don't need to save the state of the // edges being added because they aren't being removed from "edges" and will // therefore be updated normally as we visit this cell and its children. tracker->SaveAndClearStateBefore(pending_additions_begin_); // Create a FaceEdge for each edge in this cell that isn't being removed. vector* face_edges = alloc->mutable_face_edges(); face_edges->clear(); bool tracker_moved = false; const S2ShapeIndexCell& cell = iter.cell(); for (int s = 0; s < cell.num_clipped(); ++s) { const S2ClippedShape& clipped = cell.clipped(s); int shape_id = clipped.shape_id(); const S2Shape* shape = this->shape(shape_id); if (shape == nullptr) continue; // This shape is being removed. int num_edges = clipped.num_edges(); // If this shape has an interior, start tracking whether we are inside the // shape. UpdateEdges() wants to know whether the entry vertex of this // cell is inside the shape, but we only know whether the center of the // cell is inside the shape, so we need to test all the edges against the // line segment from the cell center to the entry vertex. FaceEdge edge; edge.shape_id = shape_id; edge.has_interior = (shape->dimension() == 2 && shape_id != tracker->partial_shape_id()); if (edge.has_interior) { tracker->AddShape(shape_id, clipped.contains_center()); // There might not be any edges in this entire cell (i.e., it might be // in the interior of all shapes), so we delay updating the tracker // until we see the first edge. if (!tracker_moved && num_edges > 0) { tracker->MoveTo(pcell.GetCenter()); tracker->DrawTo(pcell.GetEntryVertex()); tracker->set_next_cellid(pcell.id()); tracker_moved = true; } } for (int i = 0; i < num_edges; ++i) { int e = clipped.edge(i); edge.edge_id = e; edge.edge = shape->edge(e); edge.max_level = GetEdgeMaxLevel(edge.edge); if (edge.has_interior) tracker->TestEdge(shape_id, edge.edge); if (!S2::ClipToPaddedFace(edge.edge.v0, edge.edge.v1, pcell.id().face(), kCellPadding, &edge.a, &edge.b)) { ABSL_LOG(DFATAL) << "Invariant failure in MutableS2ShapeIndex"; } face_edges->push_back(edge); } } // Now create a ClippedEdge for each FaceEdge, and put them in "new_edges". vector new_edges; for (const FaceEdge& face_edge : *face_edges) { ClippedEdge* clipped = alloc->NewClippedEdge(); clipped->face_edge = &face_edge; clipped->bound = S2::GetClippedEdgeBound(face_edge.a, face_edge.b, pcell.bound()); new_edges.push_back(clipped); } // Discard any edges from "edges" that are being removed, and append the // remainder to "new_edges". (This keeps the edges sorted by shape id.) for (size_t i = 0; i < edges->size(); ++i) { const ClippedEdge* clipped = (*edges)[i]; if (!is_shape_being_removed(clipped->face_edge->shape_id)) { new_edges.insert(new_edges.end(), edges->begin() + i, edges->end()); break; } } // Update the edge list and delete this cell from the index. edges->swap(new_edges); cell_map_.erase(pcell.id()); } // Attempt to build an index cell containing the given edges, and return true // if successful. (Otherwise the edges should be subdivided further.) bool MutableS2ShapeIndex::MakeIndexCell(const S2PaddedCell& pcell, const vector& edges, InteriorTracker* tracker) { if (edges.empty() && tracker->shape_ids().empty()) { // No index cell is needed. (In most cases this situation is detected // before we get to this point, but this can happen when all shapes in a // cell are removed.) return true; } // We can show using amortized analysis that the total index size is // // O(c1 * n + c2 * (1 - f) / f * n) // // where n is the number of input edges (and where we also count an "edge" // for each shape with an interior but no edges), f is the value of // FLAGS_s2shape_index_min_short_edge_fraction, and c1 and c2 are constants // where c2 is about 20 times larger than c1. // // First observe that the space used by a MutableS2ShapeIndex is // proportional to the space used by all of its index cells, and the space // used by an S2ShapeIndexCell is proportional to the number of edges that // intersect that cell plus the number of shapes that contain the entire // cell ("containing shapes"). Define an "index entry" as an intersecting // edge or containing shape stored by an index cell. Our goal is then to // bound the number of index entries. // // We divide the index entries into two groups. An index entry is "short" // if it represents an edge that was considered short in that index cell's // parent, and "long" otherwise. (Note that the long index entries also // include the containing shapes mentioned above.) We then bound the // maximum number of both types of index entries by associating them with // edges that were considered short in those index cells' parents. // // First consider the short index entries for a given edge E. Let S be the // set of index cells that intersect E and where E was considered short in // those index cells' parents. Since E was short in each parent cell, the // width of those parent cells is at least some fraction "g" of E's length // (as controlled by FLAGS_s2shape_index_cell_size_to_long_edge_ratio). // Therefore the minimum width of each cell in S is also at least some // fraction of E's length (i.e., g / 2). This implies that there are at most // a constant number c1 of such cells, since they all intersect E and do not // overlap, which means that there are at most (c1 * n) short entries in // total. // // With index_cell_size_to_long_edge_ratio = 1.0 (the default value), it can // be shown that c1 = 10. In other words, it is not possible for a given // edge to intersect more than 10 index cells where it was considered short // in those cells' parents. The value of c1 can be reduced as low c1 = 4 by // increasing index_cell_size_to_long_edge_ratio to about 3.1. (The reason // the minimum value is 3.1 rather than 2.0 is that this ratio is defined in // terms of the average edge length of cells at a given level, rather than // their minimum width, and 2 * (S2::kAvgEdge / S2::kMinWidth) ~= 3.1.) // // Next we consider the long index entries. Let c2 be the maximum number of // index cells where a given edge E was considered short in those cells' // parents. (Unlike the case above, we do not require that these cells // intersect E.) Because the minimum width of each parent cell is at least // some fraction of E's length and the parent cells at a given level do not // overlap, there can be at most a small constant number of index cells at // each level where E is considered short in those cells' parents. For // example, consider a very short edge E that intersects the midpoint of a // cell edge at level 0. There are 16 cells at level 30 where E was // considered short in the parent cell, 12 cells at each of levels 29..2, and // 4 cells at levels 1 and 0 (pretending that all 6 face cells share a common // "parent"). This yields a total of c2 = 360 index cells. This is actually // the worst case for index_cell_size_to_long_edge_ratio >= 3.1; with the // default value of 1.0 it is possible to have a few more index cells at // levels 29 and 30, for a maximum of c2 = 366 index cells. // // The code below subdivides a given cell only if // // s > f * (s + l) // // where "f" is the min_short_edge_fraction parameter, "s" is the number of // short edges that intersect the cell, and "l" is the number of long edges // that intersect the cell plus an upper bound on the number of shapes that // contain the entire cell. (It is an upper bound rather than an exact count // because we use the number of shapes that contain an arbitrary vertex of // the cell.) Note that the number of long index entries in each child of // this cell is at most "l" because no child intersects more edges than its // parent or is entirely contained by more shapes than its parent. // // The inequality above can be rearranged to give // // l < s * (1 - f) / f // // This says that each long index entry in a child cell can be associated // with at most (1 - f) / f edges that were considered short when the parent // cell was subdivided. Furthermore we know that there are at most c2 index // cells where a given edge was considered short in the parent cell. Since // there are only n edges in total, this means that the maximum number of // long index entries is at most // // c2 * (1 - f) / f * n // // and putting this together with the result for short index entries gives // the desired bound. // // There are a variety of ways to make this bound tighter, e.g. when "n" is // relatively small. For example when the indexed geometry satisfies the // requirements of S2BooleanOperation (i.e., shape interiors are disjoint) // and the min_short_edge_fraction parameter is not too large, then the // constant c2 above is only about half as big (i.e., c2 ~= 180). This is // because the worst case under these circumstances requires having many // shapes whose interiors overlap. // Continue subdividing if the proposed index cell would contain too many // edges that are "short" relative to its size (as controlled by the // FLAGS_s2shape_index_cell_size_to_long_edge_ratio parameter). Usually "too // many" means more than options_.max_edges_per_cell(), but this value might // be increased if the cell has a lot of long edges and/or containing shapes. // This strategy ensures that the total index size is linear (see above). if (edges.size() > static_cast(options_.max_edges_per_cell())) { int max_short_edges = max(options_.max_edges_per_cell(), static_cast( absl::GetFlag(FLAGS_s2shape_index_min_short_edge_fraction) * (edges.size() + tracker->shape_ids().size()))); int count = 0; for (const ClippedEdge* edge : edges) { count += (pcell.level() < edge->face_edge->max_level); if (count > max_short_edges) return false; } } // Possible optimization: Continue subdividing as long as exactly one child // of "pcell" intersects the given edges. This can be done by finding the // bounding box of all the edges and calling ShrinkToFit(): // // S2CellId cellid = pcell.ShrinkToFit(GetRectBound(edges)); // // Currently this is not beneficial; it slows down construction by 4-25% // (mainly computing the union of the bounding rectangles) and also slows // down queries (since more recursive clipping is required to get down to // the level of a spatial index cell). But it may be worth trying again // once "contains_center" is computed and all algorithms are modified to // take advantage of it. // We update the InteriorTracker as follows. For every S2Cell in the index // we construct two edges: one edge from entry vertex of the cell to its // center, and one from the cell center to its exit vertex. Here "entry" // and "exit" refer the S2CellId ordering, i.e. the order in which points // are encountered along the S2 space-filling curve. The exit vertex then // becomes the entry vertex for the next cell in the index, unless there are // one or more empty intervening cells, in which case the InteriorTracker // state is unchanged because the intervening cells have no edges. // Shift the InteriorTracker focus point to the center of the current cell. if (tracker->is_active() && !edges.empty()) { if (!tracker->at_cellid(pcell.id())) { tracker->MoveTo(pcell.GetEntryVertex()); } tracker->DrawTo(pcell.GetCenter()); TestAllEdges(edges, tracker); } // Allocate and fill a new index cell. To get the total number of shapes we // need to merge the shapes associated with the intersecting edges together // with the shapes that happen to contain the cell center. const ShapeIdSet& cshape_ids = tracker->shape_ids(); int num_shapes = CountShapes(edges, cshape_ids); auto cell = make_unique(); S2ClippedShape* base = cell->add_shapes(num_shapes); // To fill the index cell we merge the two sources of shapes: "edge shapes" // (those that have at least one edge that intersects this cell), and // "containing shapes" (those that contain the cell center). We keep track // of the index of the next intersecting edge and the next containing shape // as we go along. Both sets of shape ids are already sorted. size_t enext = 0; ShapeIdSet::const_iterator cnext = cshape_ids.begin(); for (int i = 0; i < num_shapes; ++i) { S2ClippedShape* clipped = base + i; int eshape_id = num_shape_ids(), cshape_id = eshape_id; // Sentinels if (enext != edges.size()) { eshape_id = edges[enext]->face_edge->shape_id; } if (cnext != cshape_ids.end()) { cshape_id = *cnext; } int ebegin = enext; if (cshape_id < eshape_id) { // The entire cell is in the shape interior. clipped->Init(cshape_id, 0); clipped->set_contains_center(true); ++cnext; } else { // Count the number of edges for this shape and allocate space for them. while (enext < edges.size() && edges[enext]->face_edge->shape_id == eshape_id) { ++enext; } clipped->Init(eshape_id, enext - ebegin); for (size_t e = ebegin; e < enext; ++e) { clipped->set_edge(e - ebegin, edges[e]->face_edge->edge_id); } if (cshape_id == eshape_id) { clipped->set_contains_center(true); ++cnext; } } } // UpdateEdges() visits cells in increasing order of S2CellId, so during // initial construction of the index all insertions happen at the end. It // is much faster to give an insertion hint in this case. Otherwise the // hint doesn't do much harm. With more effort we could provide a hint even // during incremental updates, but this is probably not worth the effort. cell_map_.insert(cell_map_.end(), make_pair(pcell.id(), std::move(cell))); // Shift the InteriorTracker focus point to the exit vertex of this cell. if (tracker->is_active() && !edges.empty()) { tracker->DrawTo(pcell.GetExitVertex()); TestAllEdges(edges, tracker); tracker->set_next_cellid(pcell.id().next()); } return true; } // Call tracker->TestEdge() on all edges from shapes that have interiors. /* static */ void MutableS2ShapeIndex::TestAllEdges(const vector& edges, InteriorTracker* tracker) { for (const ClippedEdge* edge : edges) { const FaceEdge* face_edge = edge->face_edge; if (face_edge->has_interior) { tracker->TestEdge(face_edge->shape_id, face_edge->edge); } } } // Return the number of distinct shapes that are either associated with the // given edges, or that are currently stored in the InteriorTracker. /* static */ int MutableS2ShapeIndex::CountShapes(const vector& edges, const ShapeIdSet& cshape_ids) { int count = 0; int last_shape_id = -1; ShapeIdSet::const_iterator cnext = cshape_ids.begin(); // Next shape for (const ClippedEdge* edge : edges) { if (edge->face_edge->shape_id != last_shape_id) { ++count; last_shape_id = edge->face_edge->shape_id; // Skip over any containing shapes up to and including this one, // updating "count" appropriately. for (; cnext != cshape_ids.end(); ++cnext) { if (*cnext > last_shape_id) break; if (*cnext < last_shape_id) ++count; } } } // Count any remaining containing shapes. count += (cshape_ids.end() - cnext); return count; } size_t MutableS2ShapeIndex::SpaceUsed() const { size_t size = sizeof(*this); size += shapes_.capacity() * sizeof(unique_ptr); // cell_map_ itself is already included in sizeof(*this). size += cell_map_.bytes_used() - sizeof(cell_map_); size += cell_map_.size() * sizeof(S2ShapeIndexCell); Iterator it; for (it.InitStale(this, S2ShapeIndex::BEGIN); !it.done(); it.Next()) { const S2ShapeIndexCell& cell = it.cell(); size += cell.shapes_.capacity() * sizeof(S2ClippedShape); for (int s = 0; s < cell.num_clipped(); ++s) { const S2ClippedShape& clipped = cell.clipped(s); if (!clipped.is_inline()) { size += clipped.num_edges() * sizeof(int32_t); } } } if (pending_removals_ != nullptr) { size += sizeof(*pending_removals_); size += pending_removals_->capacity() * sizeof(PendingRemoval); } return size; } void MutableS2ShapeIndex::Encode(Encoder* encoder) const { // The version number is encoded in 2 bits, under the assumption that by the // time we need 5 versions the first version can be permanently retired. // This only saves 1 byte, but that's significant for very small indexes. encoder->Ensure(Varint::kMax64); uint64_t max_edges = options_.max_edges_per_cell(); encoder->put_varint64(max_edges << 2 | kCurrentEncodingVersionNumber); // The index will be built anyway when we iterate through it, but building // it in advance lets us size the cell_ids vector correctly. ForceBuild(); vector cell_ids; cell_ids.reserve(cell_map_.size()); s2coding::StringVectorEncoder encoded_cells; for (Iterator it(this, S2ShapeIndex::BEGIN); !it.done(); it.Next()) { cell_ids.push_back(it.id()); it.cell().Encode(num_shape_ids(), encoded_cells.AddViaEncoder()); } s2coding::EncodeS2CellIdVector(cell_ids, encoder); encoded_cells.Encode(encoder); } bool MutableS2ShapeIndex::Init(Decoder* decoder, const ShapeFactory& shape_factory) { Clear(); uint64_t max_edges_version; if (!decoder->get_varint64(&max_edges_version)) return false; int version = max_edges_version & 3; if (version != kCurrentEncodingVersionNumber) return false; options_.set_max_edges_per_cell(max_edges_version >> 2); uint32_t num_shapes = shape_factory.size(); shapes_.reserve(num_shapes); for (size_t shape_id = 0; shape_id < num_shapes; ++shape_id) { auto shape = shape_factory[shape_id]; shapes_.push_back(std::move(shape)); } s2coding::EncodedS2CellIdVector cell_ids; s2coding::EncodedStringVector encoded_cells; if (!cell_ids.Init(decoder)) return false; if (!encoded_cells.Init(decoder)) return false; for (size_t i = 0; i < cell_ids.size(); ++i) { S2CellId id = cell_ids[i]; auto cell = make_unique(); Decoder cell_decoder = encoded_cells.GetDecoder(i); if (!cell->Decode(num_shapes, &cell_decoder)) { return false; } cell_map_.insert(cell_map_.end(), make_pair(id, std::move(cell))); } return true; } src/s2/mutable_s2shape_index.h000066400000000000000000001013051524103652300166100ustar00rootroot00000000000000// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_MUTABLE_S2SHAPE_INDEX_H_ #define S2_MUTABLE_S2SHAPE_INDEX_H_ #include #include #include #include #include #include #include "absl/base/thread_annotations.h" #include "absl/container/btree_map.h" #include "absl/flags/declare.h" #include "absl/log/absl_check.h" #include "absl/synchronization/mutex.h" #include "absl/types/span.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/base/spinlock.h" #include "s2/r1interval.h" #include "s2/r2rect.h" #include "s2/s2cell_id.h" #include "s2/s2cell_iterator.h" #include "s2/s2memory_tracker.h" #include "s2/s2point.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2shapeutil_shape_edge_id.h" #include "s2/util/coding/coder.h" class S2PaddedCell; namespace s2internal { // Hack to expose bytes_used. template class BTreeMap : public absl::btree_map { public: size_t bytes_used() const { return this->tree_.bytes_used(); } }; } // namespace s2internal // MutableS2ShapeIndex is a class for in-memory indexing of polygonal geometry. // The objects in the index are known as "shapes", and may consist of points, // polylines, and/or polygons, possibly overlapping. The index makes it very // fast to answer queries such as finding nearby shapes, measuring distances, // testing for intersection and containment, etc. It is one of several // implementations of the S2ShapeIndex interface (see EncodedS2ShapeIndex). // // MutableS2ShapeIndex allows not only building an index, but also updating it // incrementally by adding or removing shapes (hence its name). It is designed // to be compact; usually the index is smaller than the underlying geometry. // It is capable of indexing up to hundreds of millions of edges. The index is // also fast to construct. The index size and construction time are guaranteed // to be linear in the number of input edges. // // There are a number of built-in classes that work with S2ShapeIndex objects. // Generally these classes accept any collection of geometry that can be // represented by an S2ShapeIndex, i.e. any combination of points, polylines, // and polygons. Such classes include: // // - S2ContainsPointQuery: returns the shape(s) that contain a given point. // // - S2ClosestEdgeQuery: returns the closest edge(s) to a given point, edge, // S2CellId, or S2ShapeIndex. // // - S2CrossingEdgeQuery: returns the edge(s) that cross a given edge. // // - S2BooleanOperation: computes boolean operations such as union, // and boolean predicates such as containment. // // - S2ShapeIndexRegion: can be used together with S2RegionCoverer to // approximate geometry as a set of S2CellIds. // // - S2ShapeIndexBufferedRegion: computes approximations that have been // expanded by a given radius. // // Here is an example showing how to build an index for a set of polygons, and // then then determine which polygon(s) contain each of a set of query points: // // void TestContainment(const vector& points, // const vector& polygons) { // MutableS2ShapeIndex index; // for (auto polygon : polygons) { // index.Add(std::make_unique(polygon)); // } // S2ContainsPointQuery query(&index); // for (const auto& point : points) { // for (int shape_id : query.GetContainingShapeIds(point)) { // S2Polygon* polygon = polygons[shape_id]; // ... do something with (point, polygon) ... // } // } // } // // This example uses S2Polygon::Shape, which is one example of an S2Shape // object. S2Polyline and S2Loop also have nested Shape classes, and there are // additional S2Shape types defined in *_shape.h. // // Internally, MutableS2ShapeIndex is essentially a map from S2CellIds to the // set of shapes that intersect each S2CellId. It is adaptively refined to // ensure that no cell contains more than a small number of edges. // // For efficiency, updates are batched together and applied lazily on the // first subsequent query. Locking is used to ensure that MutableS2ShapeIndex // has the same thread-safety properties as "vector": const methods are // thread-safe, while non-const methods are not thread-safe. This means that // if one thread updates the index, you must ensure that no other thread is // reading or updating the index at the same time. // // MutableS2ShapeIndex has an Encode() method that allows the index to be // serialized. An encoded S2ShapeIndex can be decoded either into its // original form (MutableS2ShapeIndex) or into an EncodedS2ShapeIndex. The // key property of EncodedS2ShapeIndex is that it can be constructed // instantaneously, since the index is kept in its original encoded form. // Data is decoded only when an operation needs it. For example, to determine // which shapes(s) contain a given query point only requires decoding the data // in the S2ShapeIndexCell that contains that point. class MutableS2ShapeIndex final : public S2ShapeIndex { private: using CellMap = s2internal::BTreeMap>; public: // The amount by which cells are "padded" to compensate for numerical errors // when clipping line segments to cell boundaries. static const double kCellPadding; // Options that affect construction of the MutableS2ShapeIndex. class Options { public: Options(); // The maximum number of edges per cell. If a cell has more than this // many edges that are not considered "long" relative to the cell size, // then it is subdivided. (Whether an edge is considered "long" is // controlled by --s2shape_index_cell_size_to_long_edge_ratio flag.) // // Values between 10 and 50 represent a reasonable balance between memory // usage, construction time, and query time. Small values make queries // faster, while large values make construction faster and use less memory. // Values higher than 50 do not save significant additional memory, and // query times can increase substantially, especially for algorithms that // visit all pairs of potentially intersecting edges (such as polygon // validation), since this is quadratic in the number of edges per cell. // // Note that the *average* number of edges per cell is generally slightly // less than half of the maximum value defined here. // // Defaults to value given by --s2shape_index_default_max_edges_per_cell. int max_edges_per_cell() const { return max_edges_per_cell_; } void set_max_edges_per_cell(int max_edges_per_cell); private: int max_edges_per_cell_; }; // Creates a MutableS2ShapeIndex that uses the default option settings. // Option values may be changed by calling Init(). MutableS2ShapeIndex(); // Create a MutableS2ShapeIndex with the given options. explicit MutableS2ShapeIndex(const Options& options); ~MutableS2ShapeIndex() override; MutableS2ShapeIndex(MutableS2ShapeIndex&&) noexcept; MutableS2ShapeIndex& operator=(MutableS2ShapeIndex&&) noexcept; // Initialize a MutableS2ShapeIndex with the given options. This method may // only be called when the index is empty (i.e. newly created or Clear() has // just been called). May be called before or after set_memory_tracker(). void Init(const Options& options); const Options& options() const { return options_; } // Specifies that memory usage should be tracked and/or limited by the given // S2MemoryTracker. For example: // // S2MemoryTracker tracker; // tracker.set_limit(500 << 20); // 500 MB memory limit // MutableS2ShapeIndex index; // index.set_memory_tracker(&tracker); // // If the memory limit is exceeded, an appropriate status is returned in // memory_tracker()->error() and any partially built index is discarded // (equivalent to calling Minimize()). // // This method may be called multiple times in order to switch from one // memory tracker to another or stop memory tracking altogether (by passing // nullptr) in which case the memory usage due to this index is subtracted. // // REQUIRES: The lifetime of "tracker" must exceed the lifetime of the index // unless set_memory_tracker(nullptr) is called to stop memory // tracking before the index destructor is called. // // This implies that the S2MemoryTracker must be declared *before* // the MutableS2ShapeIndex in the example above. // // CAVEATS: // // - This method is not const and is therefore not thread-safe. // // - Does not track memory used by the S2Shapes in the index. // // - While the index representation itself is tracked very accurately, // the temporary data needed for index construction is tracked using // heuristics and may be underestimated or overestimated. // // - Temporary memory usage is typically 10x larger than the final index // size, however it can be reduced by specifying a suitable value for // FLAGS_s2shape_index_tmp_memory_budget (the default is 100 MB). If // more temporary memory than this is needed during construction, index // updates will be split into multiple batches in order to keep the // estimated temporary memory usage below this limit. // // - S2MemoryTracker::limit() has no effect on how much temporary memory // MutableS2ShapeIndex will attempt to use during index construction; it // simply causes an error to be returned when the limit would otherwise // be exceeded. If you set a memory limit smaller than 100MB and want to // reduce memory usage rather than simply generating an error then you // should also set FLAGS_s2shape_index_tmp_memory_budget appropriately. void set_memory_tracker(S2MemoryTracker* tracker); S2MemoryTracker* memory_tracker() const { return mem_tracker_.tracker(); } // The number of distinct shape ids that have been assigned. This equals // the number of shapes in the index provided that no shapes have ever been // removed. (Shape ids are not reused.) int num_shape_ids() const override { return static_cast(shapes_.size()); } // Returns a pointer to the shape with the given id, or nullptr if the shape // has been removed from the index. const S2Shape* shape(int id) const override { return shapes_[id].get(); } // Minimizes memory usage by requesting that any data structures that can be // rebuilt should be discarded. This method invalidates all iterators. // // Like all non-const methods, this method is not thread-safe. void Minimize() override; // Appends an encoded representation of the S2ShapeIndex to "encoder". // // This method does not encode the S2Shapes in the index; it is the client's // responsibility to encode them separately. For example: // // s2shapeutil::CompactEncodeTaggedShapes(index, encoder); // index.Encode(encoder); // // The encoded size is typically much smaller than the in-memory size. // Here are a few examples: // // Number of edges In-memory space used Encoded size (%) // -------------------------------------------------------------- // 8 192 8 4% // 768 18,264 2,021 11% // 3,784,212 80,978,992 17,039,020 21% // // The encoded form also has the advantage of being a contiguous block of // memory. // // REQUIRES: "encoder" uses the default constructor, so that its buffer // can be enlarged as necessary by calling Ensure(int). void Encode(Encoder* encoder) const override; // Decodes an S2ShapeIndex, returning true on success. // // This method does not decode the S2Shape objects in the index; this is // the responsibility of the client-provided function "shape_factory" // (see s2shapeutil_coding.h). Example usage: // // index.Init(decoder, s2shapeutil::LazyDecodeShapeFactory(decoder)); // // Note that the S2Shape vector must be encoded *before* the S2ShapeIndex in // this example. bool Init(Decoder* decoder, const ShapeFactory& shape_factory); class Iterator final : public IteratorBase { public: // Default constructor; must be followed by a call to Init(). Iterator() = default; // Constructs an iterator positioned as specified. By default iterators // are unpositioned, since this avoids an extra seek in this situation // where one of the seek methods (such as Locate) is immediately called. // // If you want to position the iterator at the beginning, e.g. in order to // loop through the entire index, do this instead: // // for (MutableS2ShapeIndex::Iterator it(&index, S2ShapeIndex::BEGIN); // !it.done(); it.Next()) { ... } explicit Iterator(const MutableS2ShapeIndex* index, InitialPosition pos = UNPOSITIONED); // Initializes an iterator for the given MutableS2ShapeIndex. This method // may also be called in order to restore an iterator to a valid state // after the underlying index has been updated (although it is usually // easier just to declare a new iterator whenever required, since iterator // construction is cheap). void Init(const MutableS2ShapeIndex* index, InitialPosition pos = UNPOSITIONED); // Initialize an iterator for the given MutableS2ShapeIndex without // applying any pending updates. This can be used to observe the actual // current state of the index without modifying it in any way. void InitStale(const MutableS2ShapeIndex* index, InitialPosition pos = UNPOSITIONED); S2CellId id() const override { S2CellId id = S2CellId::Sentinel(); if (!done()) { id = iter_->first; } return id; } const S2ShapeIndexCell& cell() const override { ABSL_DCHECK(!done()); return *iter_->second; } bool done() const override { return iter_ == end_; } // S2CellIterator API: void Begin() override; void Finish() override; void Next() override; bool Prev() override; void Seek(S2CellId target) override; bool Locate(const S2Point& target) override { return LocateImpl(*this, target); } S2CellRelation Locate(S2CellId target) override { return LocateImpl(*this, target); } std::unique_ptr Clone() const override { return std::make_unique(*this); } private: const MutableS2ShapeIndex* index_ = nullptr; CellMap::const_iterator iter_, end_; }; // Takes ownership of the given shape and adds it to the index. Assigns a // unique id to the shape for this index and returns it. Shape ids are // assigned sequentially starting from 0 in the order shapes are added. // Invalidates all iterators and their associated data. // // Note that this method is not affected by S2MemoryTracker, i.e. shapes can // continue to be added even once the specified limit has been reached. int Add(std::unique_ptr shape); // Removes the given shape from the index. Invalidates all iterators and // their associated data. To retain ownership of the shape, use Release() // instead. // // Note that SpaceUsed() does not consider the size of removed shapes, causing // it to undercount the memory used by removed shapes. This memory is released // when the index is next built. void Remove(int shape_id); // Removes the given shape from the index and return ownership to the caller. // Invalidates all iterators and their associated data. To simply remove the // shape and destroy it, use Remove() instead. std::unique_ptr Release(int shape_id); // Resets the index to its original state and returns ownership of all // shapes to the caller. This method is much more efficient than removing // all shapes one at a time. std::vector> ReleaseAll(); // Resets the index to its original state and deletes all shapes. Any // options specified via Init() are preserved. void Clear(); // Returns the number of bytes currently occupied by the index (including any // unused space at the end of vectors, etc). It has the same thread safety // as the other "const" methods (see introduction). size_t SpaceUsed() const override; // Calls to Add() and Release() are normally queued and processed on the // first subsequent query (in a thread-safe way). Building the index lazily // in this way has several advantages, the most important of which is that // sometimes there *is* no subsequent query and the index doesn't need to be // built at all. // // In contrast, ForceBuild() causes any pending updates to be applied // immediately. It is thread-safe and may be called simultaneously with // other "const" methods (see notes on thread safety above). Similarly this // method is "const" since it does not modify the visible index contents. // // ForceBuild() should not normally be called since it prevents lazy index // construction (which is usually beneficial). Some reasons to use it // include: // // - To exclude the cost of building the index from benchmark results. // - To ensure that the first subsequent query is as fast as possible. // - To ensure that the index can be built successfully without exceeding a // specified S2MemoryTracker limit (see the constructor for details). // // Note that this method is thread-safe. void ForceBuild() const; // Returns true if there are no pending updates that need to be applied. // This can be useful to avoid building the index unnecessarily, or for // choosing between two different algorithms depending on whether the index // is available. // // The returned index status may be slightly out of date if the index was // built in a different thread. This is fine for the intended use (as an // efficiency hint), but it should not be used by internal methods (see // MaybeApplyUpdates). bool is_fresh() const; protected: std::unique_ptr NewIterator(InitialPosition pos) const override; private: friend class EncodedS2ShapeIndex; friend class Iterator; friend class MutableS2ShapeIndexTest; friend class S2Stats; class BatchGenerator; class EdgeAllocator; class InteriorTracker; struct BatchDescriptor; struct ClippedEdge; struct FaceEdge; struct PendingRemoval; using ShapeEdgeId = s2shapeutil::ShapeEdgeId; using ShapeIdSet = std::vector; // When adding a new encoding, be aware that old binaries will not be able // to decode it. static constexpr unsigned char kCurrentEncodingVersionNumber = 0; // Internal methods are documented with their definitions. bool is_shape_being_removed(int shape_id) const; bool MaybeCreatePendingRemovals(); void MarkIndexStale(); void MaybeApplyUpdates() const; void ApplyUpdatesThreadSafe(); void ApplyUpdatesInternal(); std::vector GetUpdateBatches() const; void ReserveSpace(const BatchDescriptor& batch, std::vector all_edges[6]); void AddShape(const S2Shape* shape, int shape_id, int edges_begin, int edges_end, std::vector all_edges[6], InteriorTracker* tracker) const; void RemoveShape(const S2Shape* shape, int shape_id, std::vector all_edges[6], InteriorTracker* tracker) const; void FinishPartialShape(int shape_id); void AddFaceEdge(FaceEdge* edge, std::vector all_edges[6]) const; void UpdateFaceEdges(int face, absl::Span face_edges, InteriorTracker* tracker); S2CellId ShrinkToFit(const S2PaddedCell& pcell, const R2Rect& bound) const; void SkipCellRange(S2CellId begin, S2CellId end, InteriorTracker* tracker, EdgeAllocator* alloc, bool disjoint_from_index); void UpdateEdges(const S2PaddedCell& pcell, std::vector* edges, InteriorTracker* tracker, EdgeAllocator* alloc, bool disjoint_from_index); void AbsorbIndexCell(const S2PaddedCell& pcell, const Iterator& iter, std::vector* edges, InteriorTracker* tracker, EdgeAllocator* alloc); int GetEdgeMaxLevel(const S2Shape::Edge& edge) const; static int CountShapes(const std::vector& edges, const ShapeIdSet& cshape_ids); bool MakeIndexCell(const S2PaddedCell& pcell, const std::vector& edges, InteriorTracker* tracker); static void TestAllEdges(const std::vector& edges, InteriorTracker* tracker); inline static const ClippedEdge* UpdateBound(const ClippedEdge* edge, int u_end, double u, int v_end, double v, EdgeAllocator* alloc); static const ClippedEdge* ClipUBound(const ClippedEdge* edge, int u_end, double u, EdgeAllocator* alloc); static const ClippedEdge* ClipVBound(const ClippedEdge* edge, int v_end, double v, EdgeAllocator* alloc); static void ClipVAxis(const ClippedEdge* edge, const R1Interval& middle, std::vector child_edges[2], EdgeAllocator* alloc); // The shapes in the index, accessed by their shape id. Removed shapes are // replaced by nullptr pointers. std::vector> shapes_; // A map from S2CellId to the set of clipped shapes that intersect that // cell. The cell ids cover a set of non-overlapping regions on the // sphere. Note that this field is updated lazily (see below). Const // methods *must* call MaybeApplyUpdates() before accessing this field. // (The easiest way to achieve this is simply to use an Iterator.) CellMap cell_map_; // The options supplied for this index. Options options_; // The id of the first shape that has been queued for addition but not // processed yet. int pending_additions_begin_ = 0; // The set of shapes that have been queued for removal but not processed // yet. Shapes are moved here from the main shapes_ vector when Release() // is called (Remove just moves the original shape). This field is present // only when there are removed shapes to process (to save memory). std::unique_ptr> pending_removals_; // Additions and removals are queued and processed on the first subsequent // query. There are several reasons to do this: // // - It is significantly more efficient to process updates in batches. // - Often the index will never be queried, in which case we can save both // the time and memory required to build it. Examples: // + S2Loops that are created simply to pass to an S2Polygon. (We don't // need the S2Loop index, because S2Polygon builds its own index.) // + Applications that load a database of geometry and then query only // a small fraction of it. // + Applications that only read and write geometry (Decode/Encode). // // The main drawback is that we need to go to some extra work to ensure that // "const" methods are still thread-safe. Note that the goal is *not* to // make this class thread-safe in general, but simply to hide the fact that // we defer some of the indexing work until query time. // // The textbook approach to this problem would be to use a mutex and a // condition variable. Unfortunately pthread mutexes are huge (40 bytes). // Instead we use spinlock (which is only 4 bytes) to guard a few small // fields representing the current update status, and only create additional // state while the update is actually occurring. mutable SpinLock lock_; enum IndexStatus { STALE, // There are pending updates. UPDATING, // Updates are currently being applied. FRESH, // There are no pending updates. }; // Reads and writes to this field are guarded by "lock_". std::atomic index_status_{FRESH}; // UpdateState holds temporary data related to thread synchronization. It // is only allocated while updates are being applied. struct UpdateState { // This mutex is used as a condition variable. It is locked by the // updating thread for the entire duration of the update; other threads // lock it in order to wait until the update is finished. absl::Mutex wait_mutex; // The number of threads currently waiting on "wait_mutex_". The // UpdateState can only be freed when this number reaches zero. // // Reads and writes to this field are guarded by "lock_". int num_waiting = 0; ~UpdateState() { ABSL_DCHECK_EQ(0, num_waiting); } }; std::unique_ptr update_state_; S2MemoryTracker::Client mem_tracker_; #ifndef SWIG // Documented in the .cc file. void UnlockAndSignal() ABSL_UNLOCK_FUNCTION(lock_) ABSL_UNLOCK_FUNCTION(update_state_->wait_mutex); #endif MutableS2ShapeIndex(const MutableS2ShapeIndex&) = delete; MutableS2ShapeIndex& operator=(const MutableS2ShapeIndex&) = delete; }; // The following flag can be used to limit the amount of temporary memory used // when building an S2ShapeIndex. See the .cc file for details. // // DEFAULT: 100 MB ABSL_DECLARE_FLAG(int64_t, s2shape_index_tmp_memory_budget); ////////////////// Implementation details follow //////////////////// // A BatchDescriptor represents a set of pending updates that will be applied // at the same time. The batch consists of all edges in (shape id, edge id) // order from "begin" (inclusive) to "end" (exclusive). Note that the last // shape in a batch may have only some of its edges added. The first batch // also implicitly includes all shapes being removed. "num_edges" is the // total number of edges that will be added or removed in this batch. struct MutableS2ShapeIndex::BatchDescriptor { // REQUIRES: If end.edge_id != 0, it must refer to a valid edge. ShapeEdgeId begin, end; int num_edges; }; // A shape that has been queued for removal. struct MutableS2ShapeIndex::PendingRemoval { int shape_id; std::unique_ptr shape; }; // The purpose of BatchGenerator is to divide large updates into batches such // that all batches use approximately the same amount of high-water memory. // This class is defined here so that it can be tested independently. class MutableS2ShapeIndex::BatchGenerator { public: // Given the total number of edges that will be removed and added, prepares // to divide the edges into batches. "shape_id_begin" identifies the first // shape whose edges will be added. BatchGenerator(int64_t num_edges_removed, int64_t num_edges_added, int shape_id_begin); // Indicates that the given shape will be added to the index. Shapes with // few edges will be grouped together into a single batch, while shapes with // many edges will be split over several batches if necessary. void AddShape(int shape_id, int num_edges); // Returns a vector describing each batch. This method should be called // once all shapes have been added. std::vector Finish(); private: // Returns a vector indicating the maximum number of edges in each batch. // (The actual batch sizes are adjusted later in order to avoid splitting // shapes between batches unnecessarily.) static std::vector GetMaxBatchSizes(int64_t num_edges_removed, int64_t num_edges_added); // Returns the maximum number of edges in the current batch. int max_batch_size() const { return max_batch_sizes_[batch_index_]; } // Returns the maximum number of edges in the next batch. int next_max_batch_size() const { return max_batch_sizes_[batch_index_ + 1]; } // Adds the given number of edges to the current batch. void ExtendBatch(int num_edges) { batch_size_ += num_edges; } // Adds the given number of edges to the current batch, ending with the edge // just before "batch_end", and then starts a new batch. void FinishBatch(int num_edges, ShapeEdgeId batch_end); // A vector representing the ideal number of edges in each batch; the batch // sizes gradually decrease to ensure that each batch uses approximately the // same total amount of memory as the index grows. The actual batch sizes // are then adjusted based on how many edges each shape has in order to // avoid splitting shapes between batches unnecessarily. std::vector max_batch_sizes_; // The maximum size of the current batch is determined by how many edges // have been added to the index so far. For example if GetBatchSizes() // returned {100, 70, 50, 30} and we have added 0 edges, the current batch // size is 100. But if we have already added 90 edges then the current // batch size would be 70, and if have added 150 edges the batch size would // be 50. We keep track of (1) the current index into batch_sizes and (2) // the number of edges remaining before we increment the batch index. int batch_index_ = 0; int batch_index_edges_left_ = 0; ShapeEdgeId batch_begin_; // The start of the current batch. int shape_id_end_; // One beyond the last shape to be added. int batch_size_ = 0; // The number of edges in the current batch. std::vector batches_; // The completed batches so far. }; inline MutableS2ShapeIndex::Iterator::Iterator( const MutableS2ShapeIndex* index, InitialPosition pos) { Init(index, pos); } inline void MutableS2ShapeIndex::Iterator::Init( const MutableS2ShapeIndex* index, InitialPosition pos) { index->MaybeApplyUpdates(); InitStale(index, pos); } inline void MutableS2ShapeIndex::Iterator::InitStale( const MutableS2ShapeIndex* index, InitialPosition pos) { index_ = index; end_ = index_->cell_map_.end(); iter_ = end_; if (pos == BEGIN) { iter_ = index_->cell_map_.begin(); } } inline void MutableS2ShapeIndex::Iterator::Begin() { // Make sure that the index has not been modified since Init() was called. ABSL_DCHECK(index_->is_fresh()); iter_ = index_->cell_map_.begin(); } inline void MutableS2ShapeIndex::Iterator::Finish() { iter_ = end_; } inline void MutableS2ShapeIndex::Iterator::Next() { ABSL_DCHECK(!done()); ++iter_; } inline bool MutableS2ShapeIndex::Iterator::Prev() { if (iter_ == index_->cell_map_.begin()) { return false; } --iter_; return true; } inline void MutableS2ShapeIndex::Iterator::Seek(S2CellId target) { iter_ = index_->cell_map_.lower_bound(target); } inline std::unique_ptr MutableS2ShapeIndex::NewIterator(InitialPosition pos) const { return std::make_unique(this, pos); } inline void MutableS2ShapeIndex::ForceBuild() const { MaybeApplyUpdates(); } inline bool MutableS2ShapeIndex::is_fresh() const { return index_status_.load(std::memory_order_relaxed) == FRESH; } // Given that the given shape is being updated, return true if it is being // removed (as opposed to being added). inline bool MutableS2ShapeIndex::is_shape_being_removed(int shape_id) const { // All shape ids being removed are less than all shape ids being added. return shape_id < pending_additions_begin_; } // Ensure that any pending updates have been applied. This method must be // called before accessing the cell_map_ field, even if the index_status_ // appears to be FRESH, because a memory barrier is required in order to // ensure that all the index updates are visible if the updates were done in // another thread. inline void MutableS2ShapeIndex::MaybeApplyUpdates() const { // To avoid acquiring and releasing the spinlock on every query, we use // atomic operations when testing whether the status is FRESH and when // updating the status to be FRESH. This guarantees that any thread that // sees a status of FRESH will also see the corresponding index updates. if (index_status_.load(std::memory_order_acquire) != FRESH) { const_cast(this)->ApplyUpdatesThreadSafe(); } } #endif // S2_MUTABLE_S2SHAPE_INDEX_H_ src/s2/mutable_s2shape_index_test.cc000066400000000000000000001126551524103652300200170ustar00rootroot00000000000000// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/mutable_s2shape_index.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "absl/flags/declare.h" #include "absl/flags/flag.h" #include "absl/flags/reflection.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/log/log_streamer.h" #include "absl/random/random.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/types/span.h" #include "s2/base/log_severity.h" #include "s2/r2.h" #include "s2/r2rect.h" #include "s2/s1angle.h" #include "s2/s2cell.h" #include "s2/s2cell_id.h" #include "s2/s2cell_union.h" #include "s2/s2coords.h" #include "s2/s2edge_clipping.h" #include "s2/s2edge_distances.h" #include "s2/s2edge_vector_shape.h" #include "s2/s2error.h" #include "s2/s2fractal.h" #include "s2/s2lax_polygon_shape.h" #include "s2/s2lax_polyline_shape.h" #include "s2/s2loop.h" #include "s2/s2memory_tracker.h" #include "s2/s2padded_cell.h" #include "s2/s2point.h" #include "s2/s2point_vector_shape.h" #include "s2/s2pointutil.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2random.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2shapeutil_coding.h" #include "s2/s2shapeutil_contains_brute_force.h" #include "s2/s2shapeutil_testing.h" #include "s2/s2testing.h" #include "s2/s2text_format.h" #include "s2/thread_testing.h" #include "s2/util/coding/coder.h" #include "s2/util/math/matrix3x3.h" #include "s2/util/random/shared_bit_gen.h" using absl::WrapUnique; using s2textformat::MakePolylineOrDie; using std::make_unique; using std::string; using std::unique_ptr; using std::vector; ABSL_DECLARE_FLAG(double, s2shape_index_min_short_edge_fraction); class MutableS2ShapeIndexTest : public ::testing::Test { protected: // This test harness owns a MutableS2ShapeIndex for convenience. MutableS2ShapeIndex index_; // Verifies that that every cell of the index contains the correct edges, and // that no cells are missing from the index. The running time of this // function is quadratic in the number of edges. void QuadraticValidate(); // Given an edge and a cell id, determines whether or not the edge should be // present in that cell and verify that this matches "index_has_edge". void ValidateEdge(const S2Point& a, const S2Point& b, S2CellId id, bool index_has_edge); // Given a shape and a cell id, determines whether or not the shape contains // the cell center and verify that this matches "index_contains_center". void ValidateInterior(const S2Shape* shape, S2CellId id, bool index_contains_center); // Verifies that the index can be encoded and decoded without change. void TestEncodeDecode(); using BatchDescriptor = MutableS2ShapeIndex::BatchDescriptor; // Converts the given vector of batches to a human-readable form. static string ToString(absl::Span batches); // Verifies that removing and adding the given combination of shapes with // the given memory budget yields the expected vector of batches. void TestBatchGenerator(int num_edges_removed, absl::Span shape_edges_added, int64_t tmp_memory_budget, int shape_id_begin, absl::Span expected_batches); }; void MutableS2ShapeIndexTest::QuadraticValidate() { // Iterate through a sequence of nonoverlapping cell ids that cover the // sphere and include as a subset all the cell ids used in the index. For // each cell id, verify that the expected set of edges is present. // "min_cellid" is the first S2CellId that has not been validated yet. S2CellId min_cellid = S2CellId::Begin(S2CellId::kMaxLevel); for (MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); ; it.Next()) { // Generate a list of S2CellIds ("skipped cells") that cover the gap // between the last cell we validated and the next cell in the index. S2CellUnion skipped; if (!it.done()) { S2CellId cellid = it.id(); EXPECT_GE(cellid, min_cellid); skipped.InitFromBeginEnd(min_cellid, cellid.range_min()); min_cellid = cellid.range_max().next(); } else { // Validate the empty cells beyond the last cell in the index. skipped.InitFromBeginEnd(min_cellid, S2CellId::End(S2CellId::kMaxLevel)); } // Iterate through all the shapes, simultaneously validating the current // index cell and all the skipped cells. int num_edges = 0; // all edges in the cell int num_short_edges = 0; // "short" edges int num_containing_shapes = 0; // shapes containing cell's entry vertex for (int id = 0; id < index_.num_shape_ids(); ++id) { const S2Shape* shape = index_.shape(id); const S2ClippedShape* clipped = nullptr; if (!it.done()) clipped = it.cell().find_clipped(id); // First check that contains_center() is set correctly. for (S2CellId skipped_id : skipped) { ValidateInterior(shape, skipped_id, false); } if (!it.done()) { bool contains_center = clipped && clipped->contains_center(); ValidateInterior(shape, it.id(), contains_center); S2PaddedCell pcell(it.id(), MutableS2ShapeIndex::kCellPadding); if (shape != nullptr) { num_containing_shapes += s2shapeutil::ContainsBruteForce(*shape, pcell.GetEntryVertex()); } } // If this shape has been released, it should not be present at all. if (shape == nullptr) { EXPECT_EQ(nullptr, clipped); continue; } // Otherwise check that the appropriate edges are present. for (int e = 0; e < shape->num_edges(); ++e) { auto edge = shape->edge(e); for (int j = 0; j < skipped.num_cells(); ++j) { ValidateEdge(edge.v0, edge.v1, skipped.cell_id(j), false); } if (!it.done()) { bool has_edge = clipped && clipped->ContainsEdge(e); ValidateEdge(edge.v0, edge.v1, it.id(), has_edge); int max_level = index_.GetEdgeMaxLevel(edge); if (has_edge) { ++num_edges; if (it.id().level() < max_level) ++num_short_edges; } } } } // This mirrors the calculation in MutableS2ShapeIndex::MakeIndexCell(). // It is designed to ensure that the index size is always linear in the // number of indexed edges. int max_short_edges = std::max( index_.options().max_edges_per_cell(), static_cast( absl::GetFlag(FLAGS_s2shape_index_min_short_edge_fraction) * (num_edges + num_containing_shapes))); EXPECT_LE(num_short_edges, max_short_edges); if (it.done()) break; } } // Verify that "index_has_edge" is true if and only if the edge AB intersects // the given cell id. void MutableS2ShapeIndexTest::ValidateEdge(const S2Point& a, const S2Point& b, S2CellId id, bool index_has_edge) { // Expand or shrink the padding slightly to account for errors in the // function we use to test for intersection (IntersectsRect). double padding = MutableS2ShapeIndex::kCellPadding; padding += (index_has_edge ? 1 : -1) * S2::kIntersectsRectErrorUVDist; R2Rect bound = id.GetBoundUV().Expanded(padding); R2Point a_uv, b_uv; EXPECT_EQ(S2::ClipToPaddedFace(a, b, id.face(), padding, &a_uv, &b_uv) && S2::IntersectsRect(a_uv, b_uv, bound), index_has_edge); } void MutableS2ShapeIndexTest::ValidateInterior( const S2Shape* shape, S2CellId id, bool index_contains_center) { if (shape == nullptr) { EXPECT_FALSE(index_contains_center); } else { EXPECT_EQ(s2shapeutil::ContainsBruteForce(*shape, id.ToPoint()), index_contains_center); } } void MutableS2ShapeIndexTest::TestEncodeDecode() { Encoder encoder; index_.Encode(&encoder); Decoder decoder(encoder.base(), encoder.length()); MutableS2ShapeIndex index2; ASSERT_TRUE(index2.Init(&decoder, s2shapeutil::WrappedShapeFactory(&index_))); s2testing::ExpectEqual(index_, index2); } /*static*/ string MutableS2ShapeIndexTest::ToString( absl::Span batches) { string result; for (const auto& batch : batches) { if (!result.empty()) result += ", "; absl::StrAppendFormat(&result, "(%d:%d, %d:%d, %d)", batch.begin.shape_id, batch.begin.edge_id, batch.end.shape_id, batch.end.edge_id, batch.num_edges); } return result; } void MutableS2ShapeIndexTest::TestBatchGenerator( int num_edges_removed, absl::Span shape_edges_added, int64_t tmp_memory_budget, int shape_id_begin, absl::Span expected_batches) { absl::FlagSaver fs; absl::SetFlag(&FLAGS_s2shape_index_tmp_memory_budget, tmp_memory_budget); int num_edges_added = 0; for (auto n : shape_edges_added) num_edges_added += n; MutableS2ShapeIndex::BatchGenerator bgen(num_edges_removed, num_edges_added, shape_id_begin); for (int i = 0; i < shape_edges_added.size(); ++i) { bgen.AddShape(shape_id_begin + i, shape_edges_added[i]); } auto actual_batches = bgen.Finish(); EXPECT_EQ(ToString(actual_batches), ToString(expected_batches)); } namespace { void TestIteratorMethods(const MutableS2ShapeIndex& index) { MutableS2ShapeIndex::Iterator it(&index, S2ShapeIndex::BEGIN); EXPECT_FALSE(it.Prev()); it.Finish(); EXPECT_TRUE(it.done()); vector ids; MutableS2ShapeIndex::Iterator it2(&index); S2CellId min_cellid = S2CellId::Begin(S2CellId::kMaxLevel); for (it.Begin(); !it.done(); it.Next()) { S2CellId cellid = it.id(); auto skipped = S2CellUnion::FromBeginEnd(min_cellid, cellid.range_min()); for (S2CellId skipped_id : skipped) { EXPECT_FALSE(it2.Locate(skipped_id.ToPoint())); EXPECT_EQ(S2CellRelation::DISJOINT, it2.Locate(skipped_id)); it2.Begin(); it2.Seek(skipped_id); EXPECT_EQ(cellid, it2.id()); } if (!ids.empty()) { it2 = it; EXPECT_TRUE(it2.Prev()); EXPECT_EQ(ids.back(), it2.id()); it2.Next(); EXPECT_EQ(cellid, it2.id()); it2.Seek(ids.back()); EXPECT_EQ(ids.back(), it2.id()); } it2.Begin(); EXPECT_EQ(cellid.ToPoint(), it.id().ToPoint()); EXPECT_TRUE(it2.Locate(it.id().ToPoint())); EXPECT_EQ(cellid, it2.id()); it2.Begin(); EXPECT_EQ(S2CellRelation::INDEXED, it2.Locate(cellid)); EXPECT_EQ(cellid, it2.id()); if (!cellid.is_face()) { it2.Begin(); EXPECT_EQ(S2CellRelation::SUBDIVIDED, it2.Locate(cellid.parent())); EXPECT_LE(it2.id(), cellid); EXPECT_GE(it2.id(), cellid.parent().range_min()); } if (!cellid.is_leaf()) { for (int i = 0; i < 4; ++i) { it2.Begin(); EXPECT_EQ(S2CellRelation::INDEXED, it2.Locate(cellid.child(i))); EXPECT_EQ(cellid, it2.id()); } } ids.push_back(cellid); min_cellid = cellid.range_max().next(); } } // NOTE(ericv): The tests below are all somewhat fragile since they depend on // the internal BatchGenerator heuristics; if these heuristics change // (including constants) then the tests below may need to change as well. TEST_F(MutableS2ShapeIndexTest, RemoveFullPolygonBatch) { TestBatchGenerator(0, {}, 100 /*bytes*/, 7, {{{7, 0}, {7, 0}, 0}}); } TEST_F(MutableS2ShapeIndexTest, AddFullPolygonBatch) { TestBatchGenerator(0, {0}, 100 /*bytes*/, 7, {{{7, 0}, {8, 0}, 0}}); } TEST_F(MutableS2ShapeIndexTest, RemoveManyEdgesInOneBatch) { // Test removing more edges than would normally fit in a batch. For good // measure we also add two full polygons in the same batch. TestBatchGenerator(1000, {0, 0}, 100 /*bytes*/, 7, {{{7, 0}, {9, 0}, 1000}}); } TEST_F(MutableS2ShapeIndexTest, RemoveAndAddEdgesInOneBatch) { // Test removing and adding edges in one batch. TestBatchGenerator(3, {4, 5}, 10000 /*bytes*/, 7, {{{7, 0}, {9, 0}, 12}}); } TEST_F(MutableS2ShapeIndexTest, RemoveAndAddEdgesInTwoBatches) { // Test removing many edges and then adding a few. TestBatchGenerator(1000, {3}, 1000 /*bytes*/, 7, {{{7, 0}, {7, 0}, 1000}, {{7, 0}, {8, 0}, 3}}); } TEST_F(MutableS2ShapeIndexTest, RemoveAndAddEdgesAndFullPolygonsInTwoBatches) { // Like the above, but also add two full polygons such that one polygon is // processed in each batch. TestBatchGenerator(1000, {0, 3, 0}, 1000 /*bytes*/, 7, {{{7, 0}, {8, 0}, 1000}, {{8, 0}, {10, 0}, 3}}); } TEST_F(MutableS2ShapeIndexTest, SeveralShapesInOneBatch) { // Test adding several shapes in one batch. TestBatchGenerator(0, {3, 4, 5}, 10000 /*bytes*/, 7, {{{7, 0}, {10, 0}, 12}}); } TEST_F(MutableS2ShapeIndexTest, GroupSmallShapesIntoBatches) { // Test adding several small shapes that must be split into batches. // 10000 bytes ~= temporary space to process 48 edges. TestBatchGenerator(0, {20, 20, 20, 20, 20}, 10000 /*bytes*/, 7, {{{7, 0}, {9, 0}, 40}, {{9, 0}, {11, 0}, 40}, {{11, 0}, {12, 0}, 20}}); } TEST_F(MutableS2ShapeIndexTest, AvoidPartialShapeInBatch) { // Test adding a small shape followed by a large shape that won't fit in the // same batch as the small shape, but will fit in its own separate batch. // 10000 bytes ~= temporary space to process 48 edges. TestBatchGenerator(0, {20, 40, 20}, 10000 /*bytes*/, 7, {{{7, 0}, {8, 0}, 20}, {{8, 0}, {9, 0}, 40}, {{9, 0}, {10, 0}, 20}}); } TEST_F(MutableS2ShapeIndexTest, SplitShapeIntoTwoBatches) { // Test adding a few small shapes, then a large shape that can be split // across the remainder of the first batch plus the next batch. The first // two batches should have the same amount of remaining space relative to // their maximum size. (For 10000 bytes of temporary space, the ideal batch // sizes are 48, 46, 45.) // // Note that we need a separate batch for the full polygon at the end, even // though it has no edges, because partial shapes must always be the last // shape in their batch. TestBatchGenerator(0, {20, 60, 0}, 10000 /*bytes*/, 7, {{{7, 0}, {8, 21}, 41}, {{8, 21}, {9, 0}, 39}, {{9, 0}, {10, 0}, 0}}); } TEST_F(MutableS2ShapeIndexTest, RemoveEdgesAndAddPartialShapeInSameBatch) { // Test a batch that consists of removing some edges and then adding a // partial shape. We also check that the small shape at the end is put into // its own batch, since partial shapes must be the last shape in their batch. TestBatchGenerator(20, {60, 5}, 10000 /*bytes*/, 7, {{{7, 0}, {7, 21}, 41}, {{7, 21}, {8, 0}, 39}, {{8, 0}, {9, 0}, 5}}); } TEST_F(MutableS2ShapeIndexTest, SplitShapeIntoManyBatches) { // Like the above except that the shape is split into 10 batches. With // 10000 bytes of temporary space, the ideal batch sizes are 63, 61, 59, 57, // 55, 53, 51, 49, 48, 46. The first 8 batches are as full as possible, // while the last two batches have the same amount of remaining space // relative to their ideal size. There is also a small batch at the end. TestBatchGenerator(0, {20, 500, 5}, 10000 /*bytes*/, 7, {{{7, 0}, {8, 43}, 63}, {{8, 43}, {8, 104}, 61}, {{8, 104}, {8, 163}, 59}, {{8, 163}, {8, 220}, 57}, {{8, 220}, {8, 275}, 55}, {{8, 275}, {8, 328}, 53}, {{8, 328}, {8, 379}, 51}, {{8, 379}, {8, 428}, 49}, {{8, 428}, {8, 465}, 37}, {{8, 465}, {9, 0}, 35}, {{9, 0}, {10, 0}, 5}}); } TEST_F(MutableS2ShapeIndexTest, SpaceUsed) { index_.Add(make_unique(S2Point(1, 0, 0), S2Point(0, 1, 0))); EXPECT_FALSE(index_.is_fresh()); size_t size_before = index_.SpaceUsed(); EXPECT_FALSE(index_.is_fresh()); QuadraticValidate(); size_t size_after = index_.SpaceUsed(); EXPECT_TRUE(index_.is_fresh()); EXPECT_TRUE(size_after > size_before); } TEST_F(MutableS2ShapeIndexTest, NoEdges) { MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); EXPECT_TRUE(it.done()); TestIteratorMethods(index_); TestEncodeDecode(); } TEST_F(MutableS2ShapeIndexTest, OneEdge) { EXPECT_EQ(0, index_.Add(make_unique(S2Point(1, 0, 0), S2Point(0, 1, 0)))); QuadraticValidate(); TestIteratorMethods(index_); TestEncodeDecode(); } TEST_F(MutableS2ShapeIndexTest, ShrinkToFitOptimization) { // This used to trigger a bug in the ShrinkToFit optimization. The loop // below contains almost all of face 0 except for a small region in the // 0/00000 subcell. That subcell is the only one that contains any edges. // This caused the index to be built only in that subcell. However, all the // other cells on that face should also have index entries, in order to // indicate that they are contained by the loop. unique_ptr loop(S2Loop::MakeRegularLoop( S2Point(1, 0.5, 0.5).Normalize(), S1Angle::Degrees(89), 100)); index_.Add(make_unique(loop.get())); QuadraticValidate(); TestEncodeDecode(); } TEST_F(MutableS2ShapeIndexTest, LoopsSpanningThreeFaces) { S2Polygon polygon; constexpr int kNumEdges = 100; // Validation is quadratic // Construct two loops consisting of kNumEdges vertices each, centered // around the cube vertex at the start of the Hilbert curve. S2Testing::ConcentricLoopsPolygon(S2Point(1, -1, -1).Normalize(), 2, kNumEdges, &polygon); vector> loops = polygon.Release(); for (auto& loop : loops) { index_.Add(make_unique(&*loop)); } QuadraticValidate(); TestIteratorMethods(index_); TestEncodeDecode(); } TEST_F(MutableS2ShapeIndexTest, ManyIdenticalEdges) { constexpr int kNumEdges = 100; // Validation is quadratic S2Point a = S2Point(0.99, 0.99, 1).Normalize(); S2Point b = S2Point(-0.99, -0.99, 1).Normalize(); for (int i = 0; i < kNumEdges; ++i) { EXPECT_EQ(i, index_.Add(make_unique(a, b))); } QuadraticValidate(); TestIteratorMethods(index_); TestEncodeDecode(); // Since all edges span the diagonal of a face, no subdivision should // have occurred (with the default index options). for (MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); !it.done(); it.Next()) { EXPECT_EQ(0, it.id().level()); } } TEST_F(MutableS2ShapeIndexTest, DegenerateEdge) { // This test verifies that degenerate edges are supported. The following // point is a cube face vertex, and so it should be indexed in 3 cells. S2Point a = S2Point(1, 1, 1).Normalize(); auto shape = make_unique(); shape->Add(a, a); index_.Add(std::move(shape)); QuadraticValidate(); TestEncodeDecode(); // Check that exactly 3 index cells contain the degenerate edge. int count = 0; for (MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); !it.done(); it.Next(), ++count) { EXPECT_TRUE(it.id().is_leaf()); EXPECT_EQ(1, it.cell().num_clipped()); EXPECT_EQ(1, it.cell().clipped(0).num_edges()); } EXPECT_EQ(3, count); } TEST_F(MutableS2ShapeIndexTest, ManyTinyEdges) { // This test adds many edges to a single leaf cell, to check that // subdivision stops when no further subdivision is possible. constexpr int kNumEdges = 100; // Validation is quadratic // Construct two points in the same leaf cell. S2Point a = S2CellId(S2Point(1, 0, 0)).ToPoint(); S2Point b = (a + S2Point(0, 1e-12, 0)).Normalize(); auto shape = make_unique(); for (int i = 0; i < kNumEdges; ++i) { shape->Add(a, b); } index_.Add(std::move(shape)); QuadraticValidate(); TestEncodeDecode(); // Check that there is exactly one index cell and that it is a leaf cell. MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); ASSERT_TRUE(!it.done()); EXPECT_TRUE(it.id().is_leaf()); it.Next(); EXPECT_TRUE(it.done()); } TEST_F(MutableS2ShapeIndexTest, SimpleUpdates) { // Add 5 loops one at a time, then release them one at a time, // validating the index at each step. S2Polygon polygon; S2Testing::ConcentricLoopsPolygon(S2Point(1, 0, 0), 5, 20, &polygon); for (int i = 0; i < polygon.num_loops(); ++i) { index_.Add(make_unique(polygon.loop(i))); QuadraticValidate(); } for (int id = 0; id < polygon.num_loops(); ++id) { index_.Release(id); EXPECT_EQ(index_.shape(id), nullptr); QuadraticValidate(); TestEncodeDecode(); } } TEST_F(MutableS2ShapeIndexTest, RandomUpdates) { // Set the temporary memory budget such that at least one shape needs to be // split into multiple update batches (namely, the "5 concentric rings" // polygon below which needs ~25KB of temporary space). absl::FlagSaver fs; absl::SetFlag(&FLAGS_s2shape_index_tmp_memory_budget, 10000); // Allow the seed to be varied from the command line. absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "RANDOM_UPDATES", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); // A few polylines. index_.Add(make_unique( MakePolylineOrDie("0:0, 2:1, 0:2, 2:3, 0:4, 2:5, 0:6"))); index_.Add(make_unique( MakePolylineOrDie("1:0, 3:1, 1:2, 3:3, 1:4, 3:5, 1:6"))); index_.Add(make_unique( MakePolylineOrDie("2:0, 4:1, 2:2, 4:3, 2:4, 4:5, 2:6"))); // A loop that used to trigger an indexing bug. index_.Add(make_unique(S2Loop::MakeRegularLoop( S2Point(1, 0.5, 0.5).Normalize(), S1Angle::Degrees(89), 20))); // Five concentric loops. S2Polygon polygon5; S2Testing::ConcentricLoopsPolygon(S2Point(1, -1, -1).Normalize(), 5, 20, &polygon5); for (int i = 0; i < polygon5.num_loops(); ++i) { index_.Add(make_unique(polygon5.loop(i))); } // Two clockwise loops around S2Cell cube vertices. index_.Add(make_unique(S2Loop::MakeRegularLoop( S2Point(-1, 1, 1).Normalize(), S1Angle::Radians(M_PI - 0.001), 10))); index_.Add(make_unique(S2Loop::MakeRegularLoop( S2Point(-1, -1, -1).Normalize(), S1Angle::Radians(M_PI - 0.001), 10))); // A shape with no edges and no interior. index_.Add(make_unique( make_unique(S2Loop::kEmpty()))); // A shape with no edges that covers the entire sphere. index_.Add(make_unique( make_unique(S2Loop::kFull()))); vector> released; vector added(index_.num_shape_ids()); std::iota(added.begin(), added.end(), 0); QuadraticValidate(); TestEncodeDecode(); for (int iter = 0; iter < 100; ++iter) { ABSL_VLOG(1) << "Iteration: " << iter; // Choose some shapes to add and release. int num_updates = 1 + s2random::SkewedInt(bitgen, 5); for (int n = 0; n < num_updates; ++n) { if (absl::Bernoulli(bitgen, 0.5) && !added.empty()) { size_t i = absl::Uniform(bitgen, 0, added.size()); ABSL_VLOG(1) << " Released shape " << added[i] << " (" << index_.shape(added[i]) << ")"; released.push_back(index_.Release(added[i])); added.erase(added.begin() + i); } else if (!released.empty()) { size_t i = absl::Uniform(bitgen, 0, released.size()); S2Shape* shape = released[i].get(); int shape_id = index_.Add(std::move(released[i])); released.erase(released.begin() + i); added.push_back(shape_id); ABSL_VLOG(1) << " Added shape " << shape_id << " (" << shape << ")"; } } QuadraticValidate(); TestEncodeDecode(); } } // A test that repeatedly updates "index_" in one thread and attempts to // concurrently read the index_ from several other threads. When all threads // have finished reading, the first thread makes another update. // // Note that we only test concurrent read access, since MutableS2ShapeIndex // requires all updates to be single-threaded and not concurrent with any // reads. class LazyUpdatesTest : public s2testing::ReaderWriterTest { public: LazyUpdatesTest() = default; void WriteOp() override { util_random::SharedBitGen bitgen; index_.Clear(); int num_vertices = 4 * s2random::SkewedInt(bitgen, 10); // Up to 4K vertices unique_ptr loop(S2Loop::MakeRegularLoop( s2random::Point(bitgen), S2Testing::KmToAngle(5), num_vertices)); index_.Add(make_unique(std::move(loop))); } void ReadOp() override { for (MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); !it.done(); it.Next()) { continue; // NOLINT } } protected: MutableS2ShapeIndex index_; }; TEST(MutableS2ShapeIndex, ConstMethodsThreadSafe) { // Ensure that lazy updates are thread-safe. In other words, make sure that // nothing bad happens when multiple threads call "const" methods that // cause pending updates to be applied. LazyUpdatesTest test; // The number of readers should be large enough so that it is likely that // several readers will be running at once (with a multiple-core CPU). constexpr int kNumReaders = 8; constexpr int kIters = 100; test.Run(kNumReaders, kIters); } TEST(MutableS2ShapeIndex, MixedGeometry) { // This test used to trigger a bug where the presence of a shape with an // interior could cause shapes that don't have an interior to suddenly // acquire one. This would cause extra S2ShapeIndex cells to be created // that are outside the bounds of the given geometry. vector> polylines; polylines.push_back(MakePolylineOrDie("0:0, 2:1, 0:2, 2:3, 0:4, 2:5, 0:6")); polylines.push_back(MakePolylineOrDie("1:0, 3:1, 1:2, 3:3, 1:4, 3:5, 1:6")); polylines.push_back(MakePolylineOrDie("2:0, 4:1, 2:2, 4:3, 2:4, 4:5, 2:6")); MutableS2ShapeIndex index; for (auto& polyline : polylines) { index.Add(make_unique(std::move(polyline))); } S2Loop loop(S2Cell(S2CellId::Begin(S2CellId::kMaxLevel))); index.Add(make_unique(&loop)); MutableS2ShapeIndex::Iterator it(&index); // No geometry intersects face 1, so there should be no index cells there. EXPECT_EQ(S2CellRelation::DISJOINT, it.Locate(S2CellId::FromFace(1))); } TEST_F(MutableS2ShapeIndexTest, LinearSpace) { // Build an index that requires FLAGS_s2shape_index_min_short_edge_fraction // to be non-zero in order to use a non-quadratic amount of space. // Uncomment the following line to check whether this test works properly. // FLAGS_s2shape_index_min_short_edge_fraction = 0; // Set the maximum number of "short" edges per cell to 1 so that we can // implement this test using a smaller index. MutableS2ShapeIndex::Options options; options.set_max_edges_per_cell(1); index_.Init(options); // The idea is to create O(n) copies of a single long edge, along with O(n) // clusters of (M + 1) points equally spaced along the long edge, where "M" // is the max_edges_per_cell() parameter. The edges are divided such that // there are equal numbers of long and short edges; this maximizes the index // size when FLAGS_s2shape_index_min_short_edge_fraction is set to zero. constexpr int kNumEdges = 100; // Validation is quadratic int edges_per_cluster = options.max_edges_per_cell() + 1; int num_clusters = (kNumEdges / 2) / edges_per_cluster; // Create the long edges. S2Point a(1, 0, 0), b(0, 1, 0); for (int i = 0; i < kNumEdges / 2; ++i) { index_.Add(make_unique(a, b)); } // Create the clusters of short edges. for (int k = 0; k < num_clusters; ++k) { S2Point p = S2::Interpolate(a, b, k / (num_clusters - 1.0)); vector points(edges_per_cluster, p); index_.Add(make_unique(points)); } QuadraticValidate(); // The number of index cells should not exceed the number of clusters. int cell_count = 0; for (MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); !it.done(); it.Next()) { ++cell_count; } EXPECT_LE(cell_count, num_clusters); } TEST_F(MutableS2ShapeIndexTest, LongIndexEntriesBound) { // This test demonstrates that the c2 = 366 upper bound (using default // parameter values) mentioned in the .cc file is achievable. // Set the maximum number of "short" edges per cell to 1 so that we can test // using a smaller index. MutableS2ShapeIndex::Options options; options.set_max_edges_per_cell(1); index_.Init(options); // This is a worst-case edge AB that touches as many cells as possible at // level 30 while still being considered "short" at level 29. We create an // index consisting of two copies of this edge plus a full polygon. S2Point a = S2::FaceSiTitoXYZ(0, 0, (1 << 30) + 0).Normalize(); S2Point b = S2::FaceSiTitoXYZ(0, 0, (1 << 30) + 6).Normalize(); for (int i = 0; i < 2; ++i) { index_.Add(make_unique(a, b)); } index_.Add(make_unique(vector>{{}})); // Count the number of index cells at each level. vector counts(S2CellId::kMaxLevel + 1); for (MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); !it.done(); it.Next()) { ++counts[it.id().level()]; } int sum = 0; for (int i = 0; i < counts.size(); ++i) { ABSL_LOG(INFO) << i << ": " << counts[i]; sum += counts[i]; } EXPECT_EQ(sum, 366); } TEST_F(MutableS2ShapeIndexTest, AddRemoveShapeContainingOrigin) { // Add a shape that contains InteriorTracker::Origin(). S2Point origin = S2::FaceUVtoXYZ(0, -1, -1).Normalize(); index_.Add(make_unique( S2Loop::MakeRegularLoop(origin, S1Angle::Degrees(1), 10))); // Force an index update. index_.ForceBuild(); // Remove the shape. index_.Remove(0); // Force another index update. index_.ForceBuild(); // The iterator should be empty. MutableS2ShapeIndex::Iterator it(&index_, S2ShapeIndex::BEGIN); EXPECT_TRUE(it.done()); } TEST_F(MutableS2ShapeIndexTest, DecoderCatchesInvalidIndex) { // An S2Shape index with one face cell but no actual shapes encoded. const std::string encoded{"E\000P\340\010\020\000"}; Decoder decoder(encoded.data(), encoded.size()); MutableS2ShapeIndex index; bool ok = index.Init(&decoder, s2shapeutil::FullDecodeShapeFactory(&decoder)); EXPECT_FALSE(ok); } TEST(S2Shape, user_data) { struct MyData { int x, y; MyData(int _x, int _y) : x(_x), y(_y) {} }; class MyEdgeVectorShape : public S2EdgeVectorShape { public: explicit MyEdgeVectorShape(const MyData& data) : S2EdgeVectorShape(), data_(data) { } const void* user_data() const override { return &data_; } void* mutable_user_data() override { return &data_; } private: MyData data_; }; MyEdgeVectorShape shape(MyData(3, 5)); MyData* data = static_cast(shape.mutable_user_data()); ABSL_DCHECK_EQ(3, data->x); data->y = 10; ABSL_DCHECK_EQ(10, static_cast(shape.user_data())->y); } static void BenchmarkConstruction(benchmark::State& state) { // The intent is not to include the destructor time, but it turns out that // PauseTiming() / ResumeTiming() is so expensive that it is faster to // simply run the destructor when the number of edges is small. int num_edges = state.range(0); bool omit_destructor = num_edges > 100; const string seed_str = absl::StrCat("BENCHMARK_CONSTRUCTION", absl::GetFlag(FLAGS_s2_random_seed)); std::seed_seq seed(seed_str.begin(), seed_str.end()); std::mt19937_64 bitgen(seed); for (auto _ : state) { state.PauseTiming(); { MutableS2ShapeIndex index; unique_ptr loop(S2Loop::MakeRegularLoop( s2random::Point(bitgen), S2Testing::KmToAngle(5), num_edges)); state.ResumeTiming(); index.Add(make_unique(loop.get())); index.ForceBuild(); if (omit_destructor) state.PauseTiming(); } if (omit_destructor) state.ResumeTiming(); } } void BM_Construction(benchmark::State& state) { BenchmarkConstruction(state); } BENCHMARK(BM_Construction)->Arg(4)->Arg(16)->Arg(1024); } // namespace ABSL_FLAG(int32_t, bm_num_edges_per_loop, 100, "Benchmarks: number of edges per loop"); ABSL_FLAG(double, bm_loop_overlap_fraction, 0.0, "Benchmarks: fractional overlap between adjacent loops"); namespace { static void BenchmarkLoopGridAddRelease(benchmark::State& state, int num_edges_per_loop, bool benchmark_release) { int num_loops = state.range(0); int num_loops_per_update = state.range(1); ABSL_CHECK_LE(num_loops_per_update, num_loops); // Construct a grid of loops that optionally overlap. const std::string seed_str = absl::StrCat( "BENCHMARK_LOOP_GRID_ADD_RELEASE", absl::GetFlag(FLAGS_s2_random_seed)); std::seed_seq seed(seed_str.begin(), seed_str.end()); std::mt19937_64 bitgen(seed); int sqrt_num_loops = ceil(sqrt(num_loops)); double max_angle = S2Testing::KmToAngle(100).radians(); double spacing = 2 * max_angle / sqrt_num_loops; // The cos(max_angle) factor ensures that the grids don't overlap when // FLAGS_bm_loop_overlap_fraction is set to zero. double radius = 0.5 * spacing * cos(max_angle) * (1 + absl::GetFlag(FLAGS_bm_loop_overlap_fraction)); MutableS2ShapeIndex index; vector ids; // The shape ids currently in the index. // If "num_loops" is not a perfect square, make the grid slightly larger // and leave some locations empty. int left = num_loops; Matrix3x3_d frame = s2random::Frame(bitgen); for (int i = 0; i < sqrt_num_loops && left > 0; ++i) { for (int j = 0; j < sqrt_num_loops && left > 0; ++j, --left) { S2Point center(tan((i + 0.5) * spacing - max_angle), tan((j + 0.5) * spacing - max_angle), 1.0); const int shape_id = index.Add(make_unique(S2Loop::MakeRegularLoop( S2::FromFrame(frame, center).Normalize(), S1Angle::Radians(radius), num_edges_per_loop))); ids.push_back(shape_id); } } index.ForceBuild(); for (auto _ : state) { state.PauseTiming(); vector> released; for (int j = 0; j < num_loops_per_update; ++j) { size_t k = absl::Uniform(bitgen, 0, ids.size()); released.emplace_back(ids[k], const_cast(index.shape(ids[k]))); ids[k] = ids.back(); ids.pop_back(); } // Either time releasing shapes from the index. if (benchmark_release) state.ResumeTiming(); for (const auto& item : released) { index.Release(item.first).release(); } index.ForceBuild(); // Or time adding them to the index, save their new ids after adding. if (!benchmark_release) state.ResumeTiming(); for (const auto& item : released) { ids.push_back(index.Add(WrapUnique(item.second))); } index.ForceBuild(); } } void BM_IncrementalAddLoopGrid(benchmark::State& state) { BenchmarkLoopGridAddRelease(state, absl::GetFlag(FLAGS_bm_num_edges_per_loop), false /*benchmark_release*/); } BENCHMARK(BM_IncrementalAddLoopGrid) ->ArgPair(10, 1) ->ArgPair(100, 10) ->ArgPair(1000, 1) ->ArgPair(1000, 50); void BM_IncrementalReleaseLoopGrid(benchmark::State& state) { BenchmarkLoopGridAddRelease(state, absl::GetFlag(FLAGS_bm_num_edges_per_loop), true /*benchmark_release*/); } BENCHMARK(BM_IncrementalReleaseLoopGrid) ->ArgPair(10, 1) ->ArgPair(100, 10) ->ArgPair(1000, 1) ->ArgPair(1000, 50); // Tests indexing a fractal with 12,582,912 edges. void BM_BigFractalConstruction(benchmark::State& state) { const string seed_str = absl::StrCat("BIG_FRACTAL_CONSTRUCTION", absl::GetFlag(FLAGS_s2_random_seed)); std::seed_seq seed(seed_str.begin(), seed_str.end()); std::mt19937_64 bitgen(seed); absl::SetFlag(&FLAGS_s2shape_index_tmp_memory_budget, static_cast(state.range(0)) << 20); S2Fractal fractal(bitgen); fractal.set_max_level(11); S2Polygon polygon(fractal.MakeLoop( s2random::FrameAt(bitgen, S2Point(1, 0, 0)), S1Angle::Degrees(40))); for (auto _ : state) { { MutableS2ShapeIndex index; index.Add(make_unique(&polygon)); index.ForceBuild(); state.PauseTiming(); } state.ResumeTiming(); } } BENCHMARK(BM_BigFractalConstruction)->Arg(100 /*MB*/)->Arg(10000 /*MB*/); } // namespace src/s2/r1interval.h000066400000000000000000000205401524103652300144330ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_R1INTERVAL_H_ #define S2_R1INTERVAL_H_ #include #include #include #include #include #include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/util/math/vector.h" // IWYU pragma: export // An R1Interval represents a closed, bounded interval on the real line. // It is capable of representing the empty interval (containing no points) // and zero-length intervals (containing a single point). // // This class is intended to be copied by value as desired. It uses // the default copy constructor and assignment operator. class R1Interval { public: // Constructor. If lo > hi, the interval is empty. R1Interval(double lo, double hi) : bounds_(lo, hi) {} // The default constructor creates an empty interval. (Any interval where // lo > hi is considered to be empty.) // // Note: Don't construct an interval using the default constructor and // set_lo()/set_hi(), since this technique doesn't work with S1Interval and // is bad programming style anyways. If you need to set both endpoints, use // the constructor above: // // lat_bounds_ = R1Interval(lat_lo, lat_hi); R1Interval() : bounds_(1, 0) {} // Returns an empty interval. static R1Interval Empty() { return R1Interval(); } // Convenience method to construct an interval containing a single point. static R1Interval FromPoint(double p) { return R1Interval(p, p); } // Convenience method to construct the minimal interval containing // the two given points. This is equivalent to starting with an empty // interval and calling AddPoint() twice, but it is more efficient. static R1Interval FromPointPair(double p1, double p2) { if (p1 <= p2) { return R1Interval(p1, p2); } else { return R1Interval(p2, p1); } } // The low bound of the interval. double lo() const { return bounds_[0]; } // The high bound of the interval. double hi() const { return bounds_[1]; } // Methods to modify one endpoint of an existing R1Interval. Do not use // these methods if you want to replace both endpoints of the interval; use // a constructor instead. For example: // // *lat_bounds = R1Interval(lat_lo, lat_hi); void set_lo(double p) { bounds_[0] = p; } void set_hi(double p) { bounds_[1] = p; } // Methods that allow the R1Interval to be accessed as a vector. (The // recommended style is to use lo() and hi() whenever possible, but these // methods are useful when the endpoint to be selected is not constant.) double operator[](int i) const { return bounds_[i]; } double& operator[](int i) { return bounds_[i]; } const Vector2_d& bounds() const { return bounds_; } Vector2_d* mutable_bounds() { return &bounds_; } // Return true if the interval is empty, i.e. it contains no points. bool is_empty() const { return lo() > hi(); } // Return the center of the interval. For empty intervals, // the result is arbitrary. double GetCenter() const { return 0.5 * (lo() + hi()); } // Return the length of the interval. The length of an empty interval // is negative. double GetLength() const { return hi() - lo(); } // Returns true if the given point is in the closed interval [lo, hi]. bool Contains(double p) const { return p >= lo() && p <= hi(); } // Returns true if the given point is in the open interval (lo, hi). bool InteriorContains(double p) const { return p > lo() && p < hi(); } // Return true if this interval contains the interval 'y'. bool Contains(const R1Interval& y) const { if (y.is_empty()) return true; return y.lo() >= lo() && y.hi() <= hi(); } // Return true if the interior of this interval contains the entire // interval 'y' (including its boundary). bool InteriorContains(const R1Interval& y) const { if (y.is_empty()) return true; return y.lo() > lo() && y.hi() < hi(); } // Return true if this interval intersects the given interval, // i.e. if they have any points in common. bool Intersects(const R1Interval& y) const { if (lo() <= y.lo()) { return y.lo() <= hi() && y.lo() <= y.hi(); } else { return lo() <= y.hi() && lo() <= hi(); } } // Return true if the interior of this interval intersects // any point of the given interval (including its boundary). bool InteriorIntersects(const R1Interval& y) const { return y.lo() < hi() && lo() < y.hi() && lo() < hi() && y.lo() <= y.hi(); } // Return the Hausdorff distance to the given interval 'y'. For two // R1Intervals x and y, this distance is defined as // h(x, y) = max_{p in x} min_{q in y} d(p, q). double GetDirectedHausdorffDistance(const R1Interval& y) const { if (is_empty()) return 0.0; if (y.is_empty()) return HUGE_VAL; return std::max(0.0, std::max(hi() - y.hi(), y.lo() - lo())); } // Expand the interval so that it contains the given point "p". void AddPoint(double p) { if (is_empty()) { set_lo(p); set_hi(p); } else if (p < lo()) { set_lo(p); } else if (p > hi()) { set_hi(p); } } // Expand the interval so that it contains the given interval "y". void AddInterval(const R1Interval& y) { if (y.is_empty()) return; if (is_empty()) { *this = y; return; } if (y.lo() < lo()) set_lo(y.lo()); if (y.hi() > hi()) set_hi(y.hi()); } // Return the closest point in the interval to the given point "p". // The interval must be non-empty. double Project(double p) const { ABSL_DCHECK(!is_empty()); return std::clamp(p, lo(), hi()); } // Return an interval that has been expanded on each side by the given // distance "margin". If "margin" is negative, then shrink the interval on // each side by "margin" instead. The resulting interval may be empty. Any // expansion of an empty interval remains empty. R1Interval Expanded(double margin) const { if (is_empty()) return *this; return R1Interval(lo() - margin, hi() + margin); } // Return the smallest interval that contains this interval and the // given interval "y". R1Interval Union(const R1Interval& y) const { if (is_empty()) return y; if (y.is_empty()) return *this; return R1Interval(std::min(lo(), y.lo()), std::max(hi(), y.hi())); } // Return the intersection of this interval with the given interval. // Empty intervals do not need to be special-cased. R1Interval Intersection(const R1Interval& y) const { return R1Interval(std::max(lo(), y.lo()), std::min(hi(), y.hi())); } // Return true if two intervals contain the same set of points. bool operator==(const R1Interval& y) const { return (lo() == y.lo() && hi() == y.hi()) || (is_empty() && y.is_empty()); } // Return true if two intervals do not contain the same set of points. bool operator!=(const R1Interval& y) const { return !operator==(y); } // Return true if this interval can be transformed into the given interval // by moving each endpoint by at most "max_error". The empty interval is // considered to be positioned arbitrarily on the real line, thus any // interval with (length <= 2*max_error) matches the empty interval. bool ApproxEquals(const R1Interval& y, double max_error = 1e-15) const { if (is_empty()) return y.GetLength() <= 2 * max_error; if (y.is_empty()) return GetLength() <= 2 * max_error; return (std::fabs(y.lo() - lo()) <= max_error && std::fabs(y.hi() - hi()) <= max_error); } private: Vector2_d bounds_; }; inline std::ostream& operator<<(std::ostream& os, const R1Interval& x) { return os << "[" << x.lo() << ", " << x.hi() << "]"; } template H AbslHashValue(H h, const R1Interval& interval) { return H::combine(std::move(h), interval.lo(), interval.hi()); } #endif // S2_R1INTERVAL_H_ src/s2/r1interval_test.cc000066400000000000000000000166151524103652300156400ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/r1interval.h" #include #include #include #include "absl/hash/hash_testing.h" #include "absl/strings/string_view.h" using absl::string_view; static void TestIntervalOps(const R1Interval& x, const R1Interval& y, string_view expected) { // Test all of the interval operations on the given pair of intervals. // "expected" is a sequence of "T" and "F" characters corresponding to // the expected results of Contains(), InteriorContains(), Intersects(), // and InteriorIntersects() respectively. EXPECT_EQ(expected[0] == 'T', x.Contains(y)); EXPECT_EQ(expected[1] == 'T', x.InteriorContains(y)); EXPECT_EQ(expected[2] == 'T', x.Intersects(y)); EXPECT_EQ(expected[3] == 'T', x.InteriorIntersects(y)); EXPECT_EQ(x.Contains(y), x.Union(y) == x); EXPECT_EQ(x.Intersects(y), !x.Intersection(y).is_empty()); R1Interval z = x; z.AddInterval(y); EXPECT_EQ(x.Union(y), z); } TEST(R1Interval, TestBasic) { // Constructors and accessors. R1Interval unit(0, 1); R1Interval negunit(-1, 0); EXPECT_EQ(0, unit.lo()); EXPECT_EQ(1, unit.hi()); EXPECT_EQ(-1, negunit[0]); EXPECT_EQ(0, negunit[1]); R1Interval ten(0, 0); ten.set_hi(10); EXPECT_EQ(R1Interval(0, 10), ten); ten[0] = -10; EXPECT_EQ(R1Interval(-10, 10), ten); ten[1] = 0; EXPECT_EQ(Vector2_d(-10, 0), ten.bounds()); *ten.mutable_bounds() = Vector2_d(0, 10); EXPECT_EQ(R1Interval(0, 10), ten); // is_empty() R1Interval half(0.5, 0.5); EXPECT_FALSE(unit.is_empty()); EXPECT_FALSE(half.is_empty()); R1Interval empty = R1Interval::Empty(); EXPECT_TRUE(empty.is_empty()); // == and != EXPECT_TRUE(empty == empty); EXPECT_TRUE(unit == unit); EXPECT_TRUE(unit != empty); EXPECT_TRUE(R1Interval(1, 2) != R1Interval(1, 3)); // Check that the default R1Interval is identical to Empty(). R1Interval default_empty; EXPECT_TRUE(default_empty.is_empty()); EXPECT_EQ(empty.lo(), default_empty.lo()); EXPECT_EQ(empty.hi(), default_empty.hi()); // GetCenter(), GetLength() EXPECT_EQ(unit.GetCenter(), 0.5); EXPECT_EQ(half.GetCenter(), 0.5); EXPECT_EQ(negunit.GetLength(), 1.0); EXPECT_EQ(half.GetLength(), 0); EXPECT_LT(empty.GetLength(), 0); // Contains(double), InteriorContains(double) EXPECT_TRUE(unit.Contains(0.5)); EXPECT_TRUE(unit.InteriorContains(0.5)); EXPECT_TRUE(unit.Contains(0)); EXPECT_FALSE(unit.InteriorContains(0)); EXPECT_TRUE(unit.Contains(1)); EXPECT_FALSE(unit.InteriorContains(1)); // Contains(R1Interval), InteriorContains(R1Interval) // Intersects(R1Interval), InteriorIntersects(R1Interval) { SCOPED_TRACE(""); TestIntervalOps(empty, empty, "TTFF"); } { SCOPED_TRACE(""); TestIntervalOps(empty, unit, "FFFF"); } { SCOPED_TRACE(""); TestIntervalOps(unit, half, "TTTT"); } { SCOPED_TRACE(""); TestIntervalOps(unit, unit, "TFTT"); } { SCOPED_TRACE(""); TestIntervalOps(unit, empty, "TTFF"); } { SCOPED_TRACE(""); TestIntervalOps(unit, negunit, "FFTF"); } { SCOPED_TRACE(""); TestIntervalOps(unit, R1Interval(0, 0.5), "TFTT"); } { SCOPED_TRACE(""); TestIntervalOps(half, R1Interval(0, 0.5), "FFTF"); } // AddPoint() R1Interval r = empty; r.AddPoint(5); EXPECT_EQ(5, r.lo()); EXPECT_EQ(5, r.hi()); r.AddPoint(-1); EXPECT_EQ(-1, r.lo()); EXPECT_EQ(5, r.hi()); r.AddPoint(0); EXPECT_EQ(-1, r.lo()); EXPECT_EQ(5, r.hi()); // Project() EXPECT_EQ(0.3, R1Interval(0.1, 0.4).Project(0.3)); EXPECT_EQ(0.1, R1Interval(0.1, 0.4).Project(-7.0)); EXPECT_EQ(0.4, R1Interval(0.1, 0.4).Project(0.6)); // FromPointPair() EXPECT_EQ(R1Interval(4, 4), R1Interval::FromPointPair(4, 4)); EXPECT_EQ(R1Interval(-2, -1), R1Interval::FromPointPair(-1, -2)); EXPECT_EQ(R1Interval(-5, 3), R1Interval::FromPointPair(-5, 3)); // Expanded() EXPECT_EQ(empty, empty.Expanded(0.45)); EXPECT_EQ(R1Interval(-0.5, 1.5), unit.Expanded(0.5)); EXPECT_EQ(R1Interval(0.5, 0.5), unit.Expanded(-0.5)); EXPECT_TRUE(unit.Expanded(-0.51).is_empty()); EXPECT_TRUE(unit.Expanded(-0.51).Expanded(0.51).is_empty()); // Union(), Intersection() EXPECT_EQ(R1Interval(99, 100), R1Interval(99, 100).Union(empty)); EXPECT_EQ(R1Interval(99, 100), empty.Union(R1Interval(99, 100))); EXPECT_TRUE(R1Interval(5, 3).Union(R1Interval(0, -2)).is_empty()); EXPECT_TRUE(R1Interval(0, -2).Union(R1Interval(5, 3)).is_empty()); EXPECT_EQ(unit, unit.Union(unit)); EXPECT_EQ(R1Interval(-1, 1), unit.Union(negunit)); EXPECT_EQ(R1Interval(-1, 1), negunit.Union(unit)); EXPECT_EQ(unit, half.Union(unit)); EXPECT_EQ(half, unit.Intersection(half)); EXPECT_EQ(R1Interval(0, 0), unit.Intersection(negunit)); EXPECT_TRUE(negunit.Intersection(half).is_empty()); EXPECT_TRUE(unit.Intersection(empty).is_empty()); EXPECT_TRUE(empty.Intersection(unit).is_empty()); } TEST(R1Interval, ApproxEquals) { // Choose two values kLo and kHi such that it's okay to shift an endpoint by // kLo (i.e., the resulting interval is equivalent) but not by kHi. static const double kLo = 4 * DBL_EPSILON; // < max_error default static const double kHi = 6 * DBL_EPSILON; // > max_error default // Empty intervals. R1Interval empty = R1Interval::Empty(); EXPECT_TRUE(empty.ApproxEquals(empty)); EXPECT_TRUE(R1Interval(0, 0).ApproxEquals(empty)); EXPECT_TRUE(empty.ApproxEquals(R1Interval(0, 0))); EXPECT_TRUE(R1Interval(1, 1).ApproxEquals(empty)); EXPECT_TRUE(empty.ApproxEquals(R1Interval(1, 1))); EXPECT_FALSE(empty.ApproxEquals(R1Interval(0, 1))); EXPECT_TRUE(empty.ApproxEquals(R1Interval(1, 1 + 2*kLo))); EXPECT_FALSE(empty.ApproxEquals(R1Interval(1, 1 + 2*kHi))); // Singleton intervals. EXPECT_TRUE(R1Interval(1, 1).ApproxEquals(R1Interval(1, 1))); EXPECT_TRUE(R1Interval(1, 1).ApproxEquals(R1Interval(1 - kLo, 1 - kLo))); EXPECT_TRUE(R1Interval(1, 1).ApproxEquals(R1Interval(1 + kLo, 1 + kLo))); EXPECT_FALSE(R1Interval(1, 1).ApproxEquals(R1Interval(1 - kHi, 1))); EXPECT_FALSE(R1Interval(1, 1).ApproxEquals(R1Interval(1, 1 + kHi))); EXPECT_TRUE(R1Interval(1, 1).ApproxEquals(R1Interval(1 - kLo, 1 + kLo))); EXPECT_FALSE(R1Interval(0, 0).ApproxEquals(R1Interval(1, 1))); // Other intervals. EXPECT_TRUE(R1Interval(1 - kLo, 2 + kLo).ApproxEquals(R1Interval(1, 2))); EXPECT_TRUE(R1Interval(1 + kLo, 2 - kLo).ApproxEquals(R1Interval(1, 2))); EXPECT_FALSE(R1Interval(1 - kHi, 2 + kLo).ApproxEquals(R1Interval(1, 2))); EXPECT_FALSE(R1Interval(1 + kHi, 2 - kLo).ApproxEquals(R1Interval(1, 2))); EXPECT_FALSE(R1Interval(1 - kLo, 2 + kHi).ApproxEquals(R1Interval(1, 2))); EXPECT_FALSE(R1Interval(1 + kLo, 2 - kHi).ApproxEquals(R1Interval(1, 2))); } TEST(R1Interval, SupportsAbslHash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ R1Interval::Empty(), R1Interval(0, 0), R1Interval(0, 1), R1Interval(1, 2), R1Interval(-1, 1), R1Interval(0.5, 1.5), })); } src/s2/r2.h000066400000000000000000000023031524103652300126640ustar00rootroot00000000000000// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_R2_H_ #define S2_R2_H_ #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/util/math/vector.h" // IWYU pragma: export using R2Point = Vector2_d; // An edge in R2 space. struct R2Edge { R2Edge() = default; R2Edge(const R2Point& v0, const R2Point& v1) : v0(v0), v1(v1) {} bool operator==(const R2Edge& b) const { return v0 == b.v0 && v1 == b.v1; } template friend H AbslHashValue(H h, const R2Edge& e) { return H::combine(std::move(h), e.v0, e.v1); } R2Point v0; R2Point v1; }; #endif // S2_R2_H_ src/s2/r2rect.cc000066400000000000000000000053331524103652300137060ustar00rootroot00000000000000// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/r2rect.h" #include #include "s2/r1interval.h" #include "s2/r2.h" R2Rect R2Rect::FromCenterSize(const R2Point& center, const R2Point& size) { return R2Rect(R1Interval(center.x() - 0.5 * size.x(), center.x() + 0.5 * size.x()), R1Interval(center.y() - 0.5 * size.y(), center.y() + 0.5 * size.y())); } bool R2Rect::Contains(const R2Rect& other) const { return x().Contains(other.x()) && y().Contains(other.y()); } bool R2Rect::InteriorContains(const R2Rect& other) const { return x().InteriorContains(other.x()) && y().InteriorContains(other.y()); } bool R2Rect::Intersects(const R2Rect& other) const { return x().Intersects(other.x()) && y().Intersects(other.y()); } bool R2Rect::InteriorIntersects(const R2Rect& other) const { return x().InteriorIntersects(other.x()) && y().InteriorIntersects(other.y()); } void R2Rect::AddPoint(const R2Point& p) { bounds_[0].AddPoint(p[0]); bounds_[1].AddPoint(p[1]); } void R2Rect::AddRect(const R2Rect& other) { bounds_[0].AddInterval(other[0]); bounds_[1].AddInterval(other[1]); } R2Point R2Rect::Project(const R2Point& p) const { return R2Point(x().Project(p.x()), y().Project(p.y())); } R2Rect R2Rect::Expanded(const R2Point& margin) const { R1Interval xx = x().Expanded(margin.x()); R1Interval yy = y().Expanded(margin.y()); if (xx.is_empty() || yy.is_empty()) return Empty(); return R2Rect(xx, yy); } R2Rect R2Rect::Union(const R2Rect& other) const { return R2Rect(x().Union(other.x()), y().Union(other.y())); } R2Rect R2Rect::Intersection(const R2Rect& other) const { R1Interval xx = x().Intersection(other.x()); R1Interval yy = y().Intersection(other.y()); if (xx.is_empty() || yy.is_empty()) return Empty(); return R2Rect(xx, yy); } bool R2Rect::ApproxEquals(const R2Rect& other, double max_error) const { return (x().ApproxEquals(other.x(), max_error) && y().ApproxEquals(other.y(), max_error)); } std::ostream& operator<<(std::ostream& os, const R2Rect& r) { return os << "[Lo" << r.lo() << ", Hi" << r.hi() << "]"; } src/s2/r2rect.h000066400000000000000000000217731524103652300135560ustar00rootroot00000000000000// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_R2RECT_H_ #define S2_R2RECT_H_ #include #include #include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/r1interval.h" #include "s2/r2.h" // An R2Rect represents a closed axis-aligned rectangle in the (x,y) plane. // // This class is intended to be copied by value as desired. It uses // the default copy constructor and assignment operator. class R2Rect { public: // Construct a rectangle from the given lower-left and upper-right points. R2Rect(const R2Point& lo, const R2Point& hi); // Construct a rectangle from the given intervals in x and y. The two // intervals must either be both empty or both non-empty. R2Rect(const R1Interval& x, const R1Interval& y); // The default constructor creates an empty R2Rect. R2Rect(); // The canonical empty rectangle. Use is_empty() to test for empty // rectangles, since they have more than one representation. static R2Rect Empty(); // Construct a rectangle from a center point and size in each dimension. // Both components of size should be non-negative, i.e. this method cannot // be used to create an empty rectangle. static R2Rect FromCenterSize(const R2Point& center, const R2Point& size); // Convenience method to construct a rectangle containing a single point. static R2Rect FromPoint(const R2Point& p); // Convenience method to construct the minimal bounding rectangle containing // the two given points. This is equivalent to starting with an empty // rectangle and calling AddPoint() twice. Note that it is different than // the R2Rect(lo, hi) constructor, where the first point is always // used as the lower-left corner of the resulting rectangle. static R2Rect FromPointPair(const R2Point& p1, const R2Point& p2); // Accessor methods. const R1Interval& x() const { return bounds_[0]; } const R1Interval& y() const { return bounds_[1]; } R2Point lo() const { return R2Point(x().lo(), y().lo()); } R2Point hi() const { return R2Point(x().hi(), y().hi()); } // Methods that allow the R2Rect to be accessed as a vector. const R1Interval& operator[](int i) const { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 2); return bounds_[i]; } R1Interval& operator[](int i) { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 2); return bounds_[i]; } // Return true if the rectangle is valid, which essentially just means // that if the bound for either axis is empty then both must be. bool is_valid() const; // Return true if the rectangle is empty, i.e. it contains no points at all. bool is_empty() const; // Return the k-th vertex of the rectangle (k = 0,1,2,3) in CCW order. // Vertex 0 is in the lower-left corner. For convenience, the argument is // reduced modulo 4 to the range [0..3]. R2Point GetVertex(int k) const; // Return the vertex in direction "i" along the x-axis (0=left, 1=right) and // direction "j" along the y-axis (0=down, 1=up). Equivalently, return the // vertex constructed by selecting endpoint "i" of the x-interval (0=lo, // 1=hi) and vertex "j" of the y-interval. R2Point GetVertex(int i, int j) const; // Return the center of the rectangle in (x,y)-space. R2Point GetCenter() const; // Return the width and height of this rectangle in (x,y)-space. Empty // rectangles have a negative width and height. R2Point GetSize() const; // Return true if the rectangle contains the given point. Note that // rectangles are closed regions, i.e. they contain their boundary. bool Contains(const R2Point& p) const; // Return true if and only if the given point is contained in the interior // of the region (i.e. the region excluding its boundary). bool InteriorContains(const R2Point& p) const; // Return true if and only if the rectangle contains the given other // rectangle. bool Contains(const R2Rect& other) const; // Return true if and only if the interior of this rectangle contains all // points of the given other rectangle (including its boundary). bool InteriorContains(const R2Rect& other) const; // Return true if this rectangle and the given other rectangle have any // points in common. bool Intersects(const R2Rect& other) const; // Return true if and only if the interior of this rectangle intersects // any point (including the boundary) of the given other rectangle. bool InteriorIntersects(const R2Rect& other) const; // Expand the rectangle to include the given point. The rectangle is // expanded by the minimum amount possible. void AddPoint(const R2Point& p); // Expand the rectangle to include the given other rectangle. This is the // same as replacing the rectangle by the union of the two rectangles, but // is somewhat more efficient. void AddRect(const R2Rect& other); // Return the closest point in the rectangle to the given point "p". // The rectangle must be non-empty. R2Point Project(const R2Point& p) const; // Return a rectangle that has been expanded on each side in the x-direction // by margin.x(), and on each side in the y-direction by margin.y(). If // either margin is negative, then shrink the interval on the corresponding // sides instead. The resulting rectangle may be empty. Any expansion of // an empty rectangle remains empty. R2Rect Expanded(const R2Point& margin) const; R2Rect Expanded(double margin) const; // Return the smallest rectangle containing the union of this rectangle and // the given rectangle. R2Rect Union(const R2Rect& other) const; // Return the smallest rectangle containing the intersection of this // rectangle and the given rectangle. R2Rect Intersection(const R2Rect& other) const; // Return true if two rectangles contains the same set of points. bool operator==(const R2Rect& other) const; // Return true if two rectangles do not contain the same set of points. bool operator!=(const R2Rect& other) const; // Return true if the x- and y-intervals of the two rectangles are the same // up to the given tolerance (see r1interval.h for details). bool ApproxEquals(const R2Rect& other, double max_error = 1e-15) const; private: R1Interval bounds_[2]; }; inline R2Rect::R2Rect(const R2Point& lo, const R2Point& hi) { bounds_[0] = R1Interval(lo.x(), hi.x()); bounds_[1] = R1Interval(lo.y(), hi.y()); ABSL_DCHECK(is_valid()); } inline R2Rect::R2Rect(const R1Interval& x, const R1Interval& y) { bounds_[0] = x; bounds_[1] = y; ABSL_DCHECK(is_valid()); } inline R2Rect::R2Rect() { // The default R1Interval constructor creates an empty interval. ABSL_DCHECK(is_valid()); } inline R2Rect R2Rect::Empty() { return R2Rect(R1Interval::Empty(), R1Interval::Empty()); } inline R2Rect R2Rect::FromPointPair(const R2Point& p1, const R2Point& p2) { return R2Rect(R1Interval::FromPointPair(p1.x(), p2.x()), R1Interval::FromPointPair(p1.y(), p2.y())); } inline bool R2Rect::is_valid() const { // The x/y ranges must either be both empty or both non-empty. return x().is_empty() == y().is_empty(); } inline bool R2Rect::is_empty() const { return x().is_empty(); } inline R2Rect R2Rect::FromPoint(const R2Point& p) { return R2Rect(p, p); } inline R2Point R2Rect::GetVertex(int k) const { // Twiddle bits to return the points in CCW order (lower left, lower right, // upper right, upper left). int j = (k >> 1) & 1; return GetVertex(j ^ (k & 1), j); } inline R2Point R2Rect::GetVertex(int i, int j) const { return R2Point(bounds_[0][i], bounds_[1][j]); } inline R2Point R2Rect::GetCenter() const { return R2Point(x().GetCenter(), y().GetCenter()); } inline R2Point R2Rect::GetSize() const { return R2Point(x().GetLength(), y().GetLength()); } inline bool R2Rect::Contains(const R2Point& p) const { return x().Contains(p.x()) && y().Contains(p.y()); } inline bool R2Rect::InteriorContains(const R2Point& p) const { return x().InteriorContains(p.x()) && y().InteriorContains(p.y()); } inline R2Rect R2Rect::Expanded(double margin) const { return Expanded(R2Point(margin, margin)); } inline bool R2Rect::operator==(const R2Rect& other) const { return x() == other.x() && y() == other.y(); } inline bool R2Rect::operator!=(const R2Rect& other) const { return !operator==(other); } std::ostream& operator<<(std::ostream& os, const R2Rect& r); template H AbslHashValue(H h, const R2Rect& rect) { return H::combine(std::move(h), rect.x(), rect.y()); } #endif // S2_R2RECT_H_ src/s2/r2rect_test.cc000066400000000000000000000222421524103652300147430ustar00rootroot00000000000000// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) // // Most of the R2Rect methods have trivial implementations in terms of the // R1Interval class, so most of the testing is done in that unit test. #include "s2/r2rect.h" #include #include #include "absl/hash/hash_testing.h" #include "absl/strings/string_view.h" #include "s2/r1interval.h" #include "s2/r2.h" using absl::string_view; static void TestIntervalOps(const R2Rect& x, const R2Rect& y, string_view expected_rexion, const R2Rect& expected_union, const R2Rect& expected_intersection) { // Test all of the interval operations on the given pair of intervals. // "expected_rexion" is a sequence of "T" and "F" characters corresponding // to the expected results of Contains(), InteriorContains(), Intersects(), // and InteriorIntersects() respectively. EXPECT_EQ(expected_rexion[0] == 'T', x.Contains(y)); EXPECT_EQ(expected_rexion[1] == 'T', x.InteriorContains(y)); EXPECT_EQ(expected_rexion[2] == 'T', x.Intersects(y)); EXPECT_EQ(expected_rexion[3] == 'T', x.InteriorIntersects(y)); EXPECT_EQ(x.Union(y) == x, x.Contains(y)); EXPECT_EQ(!x.Intersection(y).is_empty(), x.Intersects(y)); EXPECT_EQ(expected_union, x.Union(y)); EXPECT_EQ(expected_intersection, x.Intersection(y)); R2Rect r = x; r.AddRect(y); EXPECT_EQ(expected_union, r); if (y.GetSize() == R2Point(0, 0)) { r = x; r.AddPoint(y.lo()); EXPECT_EQ(expected_union, r); } } TEST(R2Rect, EmptyRectangles) { // Test basic properties of empty rectangles. R2Rect empty = R2Rect::Empty(); EXPECT_TRUE(empty.is_valid()); EXPECT_TRUE(empty.is_empty()); EXPECT_EQ(empty, empty); } TEST(R2Rect, ConstructorsAndAccessors) { // Check various constructors and accessor methods. R2Rect r = R2Rect(R2Point(0.1, 0), R2Point(0.25, 1)); EXPECT_EQ(0.1, r.x().lo()); EXPECT_EQ(0.25, r.x().hi()); EXPECT_EQ(0.0, r.y().lo()); EXPECT_EQ(1.0, r.y().hi()); EXPECT_EQ(0.1, r[0][0]); EXPECT_EQ(0.25, r[0][1]); EXPECT_EQ(0.0, r[1][0]); EXPECT_EQ(1.0, r[1][1]); EXPECT_EQ(R1Interval(0.1, 0.25), r.x()); EXPECT_EQ(R1Interval(0, 1), r.y()); EXPECT_EQ(R1Interval(0.1, 0.25), r[0]); EXPECT_EQ(R1Interval(0, 1), r[1]); r[0] = R1Interval(3, 4); r[1][0] = 5; r[1][1] = 6; EXPECT_EQ(R1Interval(3, 4), r[0]); EXPECT_EQ(R1Interval(5, 6), r[1]); EXPECT_EQ(r, r); EXPECT_NE(r, R2Rect::Empty()); R2Rect r2; EXPECT_TRUE(r2.is_empty()); EXPECT_EQ(r2, R2Rect::Empty()); } TEST(R2Rect, FromCenterSize) { // FromCenterSize() EXPECT_TRUE(R2Rect::FromCenterSize(R2Point(0.3, 0.5), R2Point(0.2, 0.4)). ApproxEquals(R2Rect(R2Point(0.2, 0.3), R2Point(0.4, 0.7)))); EXPECT_TRUE(R2Rect::FromCenterSize(R2Point(1, 0.1), R2Point(0, 2)). ApproxEquals(R2Rect(R2Point(1, -0.9), R2Point(1, 1.1)))); } TEST(R2Rect, FromPoint) { // FromPoint(), FromPointPair() R2Rect d1 = R2Rect(R2Point(0.1, 0), R2Point(0.25, 1)); EXPECT_EQ(R2Rect(d1.lo(), d1.lo()), R2Rect::FromPoint(d1.lo())); EXPECT_EQ(R2Rect(R2Point(0.15, 0.3), R2Point(0.35, 0.9)), R2Rect::FromPointPair(R2Point(0.15, 0.9), R2Point(0.35, 0.3))); EXPECT_EQ(R2Rect(R2Point(0.12, 0), R2Point(0.83, 0.5)), R2Rect::FromPointPair(R2Point(0.83, 0), R2Point(0.12, 0.5))); } TEST(R2Rect, SimplePredicates) { // GetCenter(), GetVertex(), Contains(R2Point), InteriorContains(R2Point). R2Point sw1 = R2Point(0, 0.25); R2Point ne1 = R2Point(0.5, 0.75); R2Rect r1(sw1, ne1); EXPECT_EQ(R2Point(0.25, 0.5), r1.GetCenter()); EXPECT_EQ(R2Point(0, 0.25), r1.GetVertex(0)); EXPECT_EQ(R2Point(0.5, 0.25), r1.GetVertex(1)); EXPECT_EQ(R2Point(0.5, 0.75), r1.GetVertex(2)); EXPECT_EQ(R2Point(0, 0.75), r1.GetVertex(3)); EXPECT_TRUE(r1.Contains(R2Point(0.2, 0.4))); EXPECT_FALSE(r1.Contains(R2Point(0.2, 0.8))); EXPECT_FALSE(r1.Contains(R2Point(-0.1, 0.4))); EXPECT_FALSE(r1.Contains(R2Point(0.6, 0.1))); EXPECT_TRUE(r1.Contains(sw1)); EXPECT_TRUE(r1.Contains(ne1)); EXPECT_FALSE(r1.InteriorContains(sw1)); EXPECT_FALSE(r1.InteriorContains(ne1)); // Make sure that GetVertex() returns vertices in CCW order. for (int k = 0; k < 4; ++k) { R2Point a = r1.GetVertex(k - 1); R2Point b = r1.GetVertex(k); R2Point c = r1.GetVertex(k + 1); EXPECT_GT((b - a).Ortho().DotProd(c - a), 0); } } TEST(R2Rect, IntervalOperations) { // Contains(R2Rect), InteriorContains(R2Rect), // Intersects(), InteriorIntersects(), Union(), Intersection(). // // Much more testing of these methods is done in s1interval_test // and r1interval_test. R2Rect empty = R2Rect::Empty(); R2Point sw1 = R2Point(0, 0.25); R2Point ne1 = R2Point(0.5, 0.75); R2Rect r1(sw1, ne1); R2Rect r1_mid = R2Rect(R2Point(0.25, 0.5), R2Point(0.25, 0.5)); R2Rect r_sw1(sw1, sw1); R2Rect r_ne1(ne1, ne1); TestIntervalOps(r1, r1_mid, "TTTT", r1, r1_mid); TestIntervalOps(r1, r_sw1, "TFTF", r1, r_sw1); TestIntervalOps(r1, r_ne1, "TFTF", r1, r_ne1); EXPECT_EQ(R2Rect(R2Point(0, 0.25), R2Point(0.5, 0.75)), r1); TestIntervalOps(r1, R2Rect(R2Point(0.45, 0.1), R2Point(0.75, 0.3)), "FFTT", R2Rect(R2Point(0, 0.1), R2Point(0.75, 0.75)), R2Rect(R2Point(0.45, 0.25), R2Point(0.5, 0.3))); TestIntervalOps(r1, R2Rect(R2Point(0.5, 0.1), R2Point(0.7, 0.3)), "FFTF", R2Rect(R2Point(0, 0.1), R2Point(0.7, 0.75)), R2Rect(R2Point(0.5, 0.25), R2Point(0.5, 0.3))); TestIntervalOps(r1, R2Rect(R2Point(0.45, 0.1), R2Point(0.7, 0.25)), "FFTF", R2Rect(R2Point(0, 0.1), R2Point(0.7, 0.75)), R2Rect(R2Point(0.45, 0.25), R2Point(0.5, 0.25))); TestIntervalOps(R2Rect(R2Point(0.1, 0.2), R2Point(0.1, 0.3)), R2Rect(R2Point(0.15, 0.7), R2Point(0.2, 0.8)), "FFFF", R2Rect(R2Point(0.1, 0.2), R2Point(0.2, 0.8)), empty); // Check that the intersection of two rectangles that overlap in x but not y // is valid, and vice versa. TestIntervalOps(R2Rect(R2Point(0.1, 0.2), R2Point(0.4, 0.5)), R2Rect(R2Point(0, 0), R2Point(0.2, 0.1)), "FFFF", R2Rect(R2Point(0, 0), R2Point(0.4, 0.5)), empty); TestIntervalOps(R2Rect(R2Point(0, 0), R2Point(0.1, 0.3)), R2Rect(R2Point(0.2, 0.1), R2Point(0.3, 0.4)), "FFFF", R2Rect(R2Point(0, 0), R2Point(0.3, 0.4)), empty); } TEST(R2Rect, AddPoint) { // AddPoint() R2Point sw1 = R2Point(0, 0.25); R2Point ne1 = R2Point(0.5, 0.75); R2Rect r1(sw1, ne1); R2Rect r2 = R2Rect::Empty(); r2.AddPoint(R2Point(0, 0.25)); r2.AddPoint(R2Point(0.5, 0.25)); r2.AddPoint(R2Point(0, 0.75)); r2.AddPoint(R2Point(0.1, 0.4)); EXPECT_EQ(r1, r2); } TEST(R2Rect, Project) { R2Rect r1(R1Interval(0, 0.5), R1Interval(0.25, 0.75)); EXPECT_EQ(R2Point(0, 0.25), r1.Project(R2Point(-0.01, 0.24))); EXPECT_EQ(R2Point(0, 0.48), r1.Project(R2Point(-5.0, 0.48))); EXPECT_EQ(R2Point(0, 0.75), r1.Project(R2Point(-5.0, 2.48))); EXPECT_EQ(R2Point(0.19, 0.75), r1.Project(R2Point(0.19, 2.48))); EXPECT_EQ(R2Point(0.5, 0.75), r1.Project(R2Point(6.19, 2.48))); EXPECT_EQ(R2Point(0.5, 0.53), r1.Project(R2Point(6.19, 0.53))); EXPECT_EQ(R2Point(0.5, 0.25), r1.Project(R2Point(6.19, -2.53))); EXPECT_EQ(R2Point(0.33, 0.25), r1.Project(R2Point(0.33, -2.53))); EXPECT_EQ(R2Point(0.33, 0.37), r1.Project(R2Point(0.33, 0.37))); } TEST(R2Rect, Expanded) { // Expanded() EXPECT_TRUE(R2Rect::Empty().Expanded(R2Point(0.1, 0.3)).is_empty()); EXPECT_TRUE(R2Rect::Empty().Expanded(R2Point(-0.1, -0.3)).is_empty()); EXPECT_TRUE(R2Rect(R2Point(0.2, 0.4), R2Point(0.3, 0.7)). Expanded(R2Point(0.1, 0.3)). ApproxEquals(R2Rect(R2Point(0.1, 0.1), R2Point(0.4, 1.0)))); EXPECT_TRUE(R2Rect(R2Point(0.2, 0.4), R2Point(0.3, 0.7)). Expanded(R2Point(-0.1, 0.3)).is_empty()); EXPECT_TRUE(R2Rect(R2Point(0.2, 0.4), R2Point(0.3, 0.7)). Expanded(R2Point(0.1, -0.2)).is_empty()); EXPECT_TRUE(R2Rect(R2Point(0.2, 0.4), R2Point(0.3, 0.7)). Expanded(R2Point(0.1, -0.1)). ApproxEquals(R2Rect(R2Point(0.1, 0.5), R2Point(0.4, 0.6)))); EXPECT_TRUE(R2Rect(R2Point(0.2, 0.4), R2Point(0.3, 0.7)).Expanded(0.1). ApproxEquals(R2Rect(R2Point(0.1, 0.3), R2Point(0.4, 0.8)))); } TEST(R2Rect, SupportsAbslHash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ R2Rect::Empty(), R2Rect(R2Point(0, 0), R2Point(0, 0)), R2Rect(R2Point(0, 0), R2Point(1, 1)), R2Rect(R2Point(1, 2), R2Point(3, 4)), R2Rect(R2Point(-1, -2), R2Point(1, 2)), R2Rect(R1Interval(0, 1), R1Interval(2, 3)), })); } src/s2/s1angle.cc000066400000000000000000000034401524103652300140340ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/s1angle.h" #include #include #include "absl/strings/str_format.h" #include "s2/util/coding/coder.h" #include "s2/s2error.h" #include "s2/s2latlng.h" #include "s2/s2point.h" S1Angle::S1Angle(const S2Point& x, const S2Point& y) : radians_(x.Angle(y)) { } S1Angle::S1Angle(const S2LatLng& x, const S2LatLng& y) : radians_(x.GetDistance(y).radians()) { } S1Angle S1Angle::Normalized() const { S1Angle a(radians_); a.Normalize(); return a; } void S1Angle::Normalize() { radians_ = remainder(radians_, 2.0 * M_PI); if (radians_ <= -M_PI) radians_ = M_PI; } void S1Angle::Coder::Encode(Encoder& encoder, const S1Angle& angle) const { encoder.Ensure(sizeof(double)); encoder.putdouble(angle.radians()); } bool S1Angle::Coder::Decode(Decoder& decoder, S1Angle& angle, S2Error& error) const { if (decoder.avail() < sizeof(double)) { error = S2Error::DataLoss("Could not decode S1Angle."); return false; } angle = Radians(decoder.getdouble()); return true; } std::ostream& operator<<(std::ostream& os, S1Angle a) { return os << absl::StreamFormat("%.7f", a.degrees()); } src/s2/s1angle.h000066400000000000000000000320121524103652300136730ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_S1ANGLE_H_ #define S2_S1ANGLE_H_ #include #include #include #include #include #include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "s2/util/coding/coder.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/s2coder.h" #include "s2/s2error.h" #include "s2/s2point.h" #include "s2/util/math/mathutil.h" class S2LatLng; // This class represents a one-dimensional angle (as opposed to a // two-dimensional solid angle). It has methods for converting angles to // or from radians, degrees, and the E5/E6/E7 representations (i.e. degrees // multiplied by 1e5/1e6/1e7 and rounded to the nearest integer). // // The internal representation is a double-precision value in radians, so // conversion to and from radians is exact. Conversions between E5, E6, E7, // and Degrees are not always exact; for example, Degrees(3.1) is different // from E6(3100000) or E7(31000000). However, the following properties are // guaranteed for any integer "n", provided that "n" is in the input range of // both functions: // // Degrees(n) == E6(1000000 * n) // Degrees(n) == E7(10000000 * n) // E6(n) == E7(10 * n) // // The corresponding properties are *not* true for E5, so if you use E5 then // don't test for exact equality when comparing to other formats such as // Degrees or E7. // // The following conversions between degrees and radians are exact: // // Degrees(180) == Radians(M_PI) // Degrees(45 * k) == Radians(k * M_PI / 4) for k == 0..8 // // These identities also hold when the arguments are scaled up or down by any // power of 2. Some similar identities are also true, for example, // Degrees(60) == Radians(M_PI / 3), but be aware that this type of identity // does not hold in general. For example, Degrees(3) != Radians(M_PI / 60). // // Similarly, the conversion to radians means that Angle::Degrees(x).degrees() // does not always equal "x". For example, // // S1Angle::Degrees(45 * k).degrees() == 45 * k for k == 0..8 // but S1Angle::Degrees(60).degrees() != 60. // // This means that when testing for equality, you should allow for numerical // errors (EXPECT_DOUBLE_EQ) or convert to discrete E5/E6/E7 values first. // // CAVEAT: All of the above properties depend on "double" being the usual // 64-bit IEEE 754 type (which is true on almost all modern platforms). // // This class is intended to be copied by value as desired. It uses // the default copy constructor and assignment operator. class S1Angle { public: // These methods construct S1Angle objects from their measure in radians // or degrees. static constexpr S1Angle Radians(double radians); static constexpr S1Angle Degrees(double degrees); static constexpr S1Angle E5(int32_t e5); static constexpr S1Angle E6(int32_t e6); static constexpr S1Angle E7(int32_t e7); // Convenience functions -- to use when args have been fixed32s in protos. // // The arguments are static_cast into int32_t, so very large unsigned values // are treated as negative numbers. static constexpr S1Angle UnsignedE6(uint32_t e6); static constexpr S1Angle UnsignedE7(uint32_t e7); // The default constructor yields a zero angle. This is useful for STL // containers and class methods with output arguments. constexpr S1Angle() = default; // Return an angle larger than any finite angle. static constexpr S1Angle Infinity(); // A explicit shorthand for the default constructor. static constexpr S1Angle Zero(); // Return the angle between two points, which is also equal to the distance // between these points on the unit sphere. The points do not need to be // normalized. This function has a maximum error of 3.25 * DBL_EPSILON (or // 2.5 * DBL_EPSILON for angles up to 1 radian). If either point is // zero-length (e.g. an uninitialized S2Point), or almost zero-length, the // resulting angle will be zero. S1Angle(const S2Point& x, const S2Point& y); // Like the constructor above, but return the angle (i.e., distance) between // two S2LatLng points. This function has about 15 digits of accuracy for // small distances but only about 8 digits of accuracy as the distance // approaches 180 degrees (i.e., nearly-antipodal points). S1Angle(const S2LatLng& x, const S2LatLng& y); constexpr double radians() const; constexpr double degrees() const; // Returns the E5/E6/E7 representation (i.e. degrees multiplied by // 1e5/1e6/1e7 and rounded to the nearest integer). The angle in degrees // must be in the interval (-180, 180]. (`Normalize` and `Normalized` // will ensure this.) int32_t e5() const; int32_t e6() const; int32_t e7() const; // Return the absolute value of an angle. S1Angle abs() const; friend S1Angle abs(S1Angle a); #ifndef SWIG // `friend operator`s are incompatible with SWIG 4.0, but work with 4.3. // Comparison operators. friend constexpr bool operator==(S1Angle x, S1Angle y); #if defined(__cpp_impl_three_way_comparison) && \ __cpp_impl_three_way_comparison >= 201907L // This should be `= default`, but can't be due to PyCLIF limitations. // NOLINTNEXTLINE(clang-diagnostic-pre-c++20-compat) friend constexpr auto operator<=>(S1Angle x, S1Angle y) { // NOLINTNEXTLINE(clang-diagnostic-pre-c++20-compat) return x.radians() <=> y.radians(); } #else friend constexpr bool operator!=(S1Angle x, S1Angle y) { return x.radians() != y.radians(); } friend constexpr bool operator<(S1Angle x, S1Angle y) { return x.radians() < y.radians(); } friend constexpr bool operator>(S1Angle x, S1Angle y) { return x.radians() > y.radians(); } friend constexpr bool operator<=(S1Angle x, S1Angle y) { return x.radians() <= y.radians(); } friend constexpr bool operator>=(S1Angle x, S1Angle y) { return x.radians() >= y.radians(); } #endif // Simple arithmetic operators for manipulating S1Angles. friend constexpr S1Angle operator-(S1Angle a); friend constexpr S1Angle operator+(S1Angle a, S1Angle b); friend constexpr S1Angle operator-(S1Angle a, S1Angle b); friend constexpr S1Angle operator*(double m, S1Angle a); friend constexpr S1Angle operator*(S1Angle a, double m); friend constexpr S1Angle operator/(S1Angle a, double m); friend constexpr double operator/(S1Angle a, S1Angle b); #endif // !SWIG S1Angle& operator+=(S1Angle a); S1Angle& operator-=(S1Angle a); S1Angle& operator*=(double m); S1Angle& operator/=(double m); // Trigonometric functions (not necessary but slightly more convenient). friend double sin(S1Angle a); friend double cos(S1Angle a); friend double tan(S1Angle a); struct SinCosPair { double sin; double cos; }; // Return the sine and cosine of the angle. This may be more efficient than // calling sin() and cos() separately. SinCosPair SinCos() const; // Returns true if the angle is in the normalized range (-180, 180] // degrees, which is the valid input range for e5(), e6(), and e7(). bool IsNormalized() const; // Return the angle normalized to the range (-180, 180] degrees. S1Angle Normalized() const; // Normalize this angle to the range (-180, 180] degrees. void Normalize(); // Class for encoding and decoding the object when used in Flume pipelines. class Coder : public s2coding::S2Coder { public: void Encode(Encoder& encoder, const S1Angle& angle) const override; bool Decode(Decoder& decoder, S1Angle& angle, S2Error& error) const override; }; // When S1Angle is used as a key in one of the absl::btree container types, // indicate that linear rather than binary search should be used. This is // much faster when the comparison function is cheap. typedef std::true_type absl_btree_prefer_linear_node_search; private: explicit constexpr S1Angle(double radians) : radians_(radians) {} double radians_ = 0.0; }; ////////////////// Implementation details follow //////////////////// inline constexpr S1Angle S1Angle::Infinity() { return S1Angle(std::numeric_limits::infinity()); } inline constexpr S1Angle S1Angle::Zero() { return S1Angle(0); } inline constexpr double S1Angle::radians() const { return radians_; } inline constexpr double S1Angle::degrees() const { return (180 / M_PI) * radians_; } // Note that the E5, E6, and E7 conversion involve two multiplications rather // than one. This is mainly for backwards compatibility (changing this would // break many tests), but it does have the nice side effect that conversions // between Degrees, E6, and E7 are exact when the arguments are integers. inline int32_t S1Angle::e5() const { // TODO(user,b/298298095): Tighten this to (-180, 180] (see IsNormalized). ABSL_DCHECK_LE(std::numeric_limits::min() / 1e5, degrees()); ABSL_DCHECK_LE(degrees(), std::numeric_limits::max() / 1e5); return MathUtil::Round(1e5 * degrees()); } inline int32_t S1Angle::e6() const { ABSL_DCHECK_LE(std::numeric_limits::min() / 1e6, degrees()); ABSL_DCHECK_LE(degrees(), std::numeric_limits::max() / 1e6); return MathUtil::Round(1e6 * degrees()); } inline int32_t S1Angle::e7() const { ABSL_DCHECK_LE(std::numeric_limits::min() / 1e7, degrees()); ABSL_DCHECK_LE(degrees(), std::numeric_limits::max() / 1e7); return MathUtil::Round(1e7 * degrees()); } inline bool S1Angle::IsNormalized() const { return radians() > -M_PI && radians() <= M_PI; } inline S1Angle S1Angle::abs() const { return S1Angle(std::fabs(radians_)); } inline S1Angle abs(S1Angle a) { return S1Angle(std::fabs(a.radians_)); } inline constexpr bool operator==(S1Angle x, S1Angle y) { return x.radians() == y.radians(); } inline constexpr S1Angle operator-(S1Angle a) { return S1Angle::Radians(-a.radians()); } inline constexpr S1Angle operator+(S1Angle a, S1Angle b) { return S1Angle::Radians(a.radians() + b.radians()); } inline constexpr S1Angle operator-(S1Angle a, S1Angle b) { return S1Angle::Radians(a.radians() - b.radians()); } inline constexpr S1Angle operator*(double m, S1Angle a) { return S1Angle::Radians(m * a.radians()); } inline constexpr S1Angle operator*(S1Angle a, double m) { return S1Angle::Radians(m * a.radians()); } inline constexpr S1Angle operator/(S1Angle a, double m) { return S1Angle::Radians(a.radians() / m); } inline constexpr double operator/(S1Angle a, S1Angle b) { return a.radians() / b.radians(); } inline S1Angle& S1Angle::operator+=(S1Angle a) { radians_ += a.radians(); return *this; } inline S1Angle& S1Angle::operator-=(S1Angle a) { radians_ -= a.radians(); return *this; } inline S1Angle& S1Angle::operator*=(double m) { radians_ *= m; return *this; } inline S1Angle& S1Angle::operator/=(double m) { radians_ /= m; return *this; } inline double sin(S1Angle a) { return sin(a.radians()); } inline double cos(S1Angle a) { return cos(a.radians()); } inline double tan(S1Angle a) { return tan(a.radians()); } inline S1Angle::SinCosPair S1Angle::SinCos() const { // TODO(b/370513151): Remove once Clang can optimize this. // NB: __sincos() provided by __APPLE__ is not bit-identical to sin(), cos() // under `--config=darwin_arm64`. Windows does not support sincos(). // `sincos` gives different results on Ubuntu 22. Disable for glibc until // this can be narrowed down further. // https://github.com/google/s2geometry/issues/413 #if defined(__ANDROID__) double sin_angle, cos_angle; sincos(radians(), &sin_angle, &cos_angle); return {sin_angle, cos_angle}; #else return {sin(radians()), cos(radians())}; #endif } inline constexpr S1Angle S1Angle::Radians(double radians) { return S1Angle(radians); } inline constexpr S1Angle S1Angle::Degrees(double degrees) { return S1Angle((M_PI / 180) * degrees); } inline constexpr S1Angle S1Angle::E5(int32_t e5) { return Degrees(1e-5 * e5); } inline constexpr S1Angle S1Angle::E6(int32_t e6) { return Degrees(1e-6 * e6); } inline constexpr S1Angle S1Angle::E7(int32_t e7) { return Degrees(1e-7 * e7); } inline constexpr S1Angle S1Angle::UnsignedE6(uint32_t e6) { return E6(static_cast(e6)); } inline constexpr S1Angle S1Angle::UnsignedE7(uint32_t e7) { return E7(static_cast(e7)); } // Writes the angle in degrees with 7 digits of precision after the // decimal point, e.g. "17.3745904". std::ostream& operator<<(std::ostream& os, S1Angle a); template H AbslHashValue(H h, S1Angle angle) { return H::combine(std::move(h), angle.radians()); } #endif // S2_S1ANGLE_H_ src/s2/s1angle_test.cc000066400000000000000000000251251524103652300150770ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/s1angle.h" #include #include #include #include #include #include "absl/hash/hash_testing.h" #include "absl/log/log_streamer.h" #include "absl/random/random.h" #include "s2/s2error.h" #include "s2/s2latlng.h" #include "s2/s2point.h" #include "s2/s2testing.h" #include "s2/util/coding/coder.h" TEST(S1Angle, DefaultConstructor) { // Check that the default constructor returns an angle of 0. S1Angle a; EXPECT_EQ(0, a.radians()); } TEST(S1Angle, Infinity) { EXPECT_LT(S1Angle::Radians(1e30), S1Angle::Infinity()); EXPECT_LT(-S1Angle::Infinity(), S1Angle::Zero()); EXPECT_EQ(S1Angle::Infinity(), S1Angle::Infinity()); } TEST(S1Angle, Zero) { EXPECT_EQ(S1Angle::Radians(0), S1Angle::Zero()); } TEST(S1Angle, PiRadiansExactly180Degrees) { // Check that the conversion between Pi radians and 180 degrees is exact. EXPECT_EQ(M_PI, S1Angle::Radians(M_PI).radians()); EXPECT_EQ(180.0, S1Angle::Radians(M_PI).degrees()); EXPECT_EQ(M_PI, S1Angle::Degrees(180).radians()); EXPECT_EQ(180.0, S1Angle::Degrees(180).degrees()); EXPECT_EQ(90.0, S1Angle::Radians(M_PI_2).degrees()); // Check negative angles. EXPECT_EQ(-90.0, S1Angle::Radians(-M_PI_2).degrees()); EXPECT_EQ(-M_PI_4, S1Angle::Degrees(-45).radians()); } TEST(S1Angle, E5E6E7Representations) { // Check that E5/E6/E7 representations work as expected. EXPECT_DOUBLE_EQ(S1Angle::Degrees(-45).radians(), S1Angle::E5(-4500000).radians()); EXPECT_DOUBLE_EQ(S1Angle::Degrees(-60).radians(), S1Angle::E6(-60000000).radians()); EXPECT_DOUBLE_EQ(S1Angle::Degrees(75).radians(), S1Angle::E7(750000000).radians()); EXPECT_EQ(-17256123, S1Angle::Degrees(-172.56123).e5()); EXPECT_EQ(12345678, S1Angle::Degrees(12.345678).e6()); EXPECT_EQ(-123456789, S1Angle::Degrees(-12.3456789).e7()); } TEST(S1Angle, E6E7RepresentationsUnsigned) { // Check that unsigned E6/E7 representations work as expected. EXPECT_DOUBLE_EQ( S1Angle::Degrees(60).radians(), S1Angle::UnsignedE6(static_cast(60000000)).radians()); EXPECT_DOUBLE_EQ( S1Angle::Degrees(-60).radians(), S1Angle::UnsignedE6(static_cast(-60000000)).radians()); EXPECT_DOUBLE_EQ( S1Angle::Degrees(75).radians(), S1Angle::UnsignedE7(static_cast(750000000)).radians()); EXPECT_DOUBLE_EQ( S1Angle::Degrees(-75).radians(), S1Angle::UnsignedE7(static_cast(-750000000)).radians()); } TEST(S1Angle, NormalizeCorrectlyCanonicalizesAngles) { EXPECT_DOUBLE_EQ(0.0, S1Angle::Degrees(360.0).Normalized().degrees()); EXPECT_DOUBLE_EQ(-90.0, S1Angle::Degrees(-90.0).Normalized().degrees()); EXPECT_DOUBLE_EQ(180.0, S1Angle::Degrees(-180.0).Normalized().degrees()); EXPECT_DOUBLE_EQ(180.0, S1Angle::Degrees(180.0).Normalized().degrees()); EXPECT_DOUBLE_EQ(180.0, S1Angle::Degrees(540.0).Normalized().degrees()); EXPECT_DOUBLE_EQ(90.0, S1Angle::Degrees(-270.0).Normalized().degrees()); } TEST(S1Angle, ArithmeticOperationsOnAngles) { EXPECT_DOUBLE_EQ(0.3, S1Angle::Radians(-0.3).abs().radians()); EXPECT_DOUBLE_EQ(0.3, abs(S1Angle::Radians(-0.3)).radians()); EXPECT_DOUBLE_EQ(-0.1, (-S1Angle::Radians(0.1)).radians()); EXPECT_DOUBLE_EQ(0.4, (S1Angle::Radians(0.1) + S1Angle::Radians(0.3)).radians()); EXPECT_DOUBLE_EQ(-0.2, (S1Angle::Radians(0.1) - S1Angle::Radians(0.3)).radians()); EXPECT_DOUBLE_EQ(0.6, (2 * S1Angle::Radians(0.3)).radians()); EXPECT_DOUBLE_EQ(0.6, (S1Angle::Radians(0.3) * 2).radians()); EXPECT_DOUBLE_EQ(0.15, (S1Angle::Radians(0.3) / 2).radians()); EXPECT_DOUBLE_EQ(0.5, (S1Angle::Radians(0.3) / S1Angle::Radians(0.6))); S1Angle tmp = S1Angle::Radians(1.0); tmp += S1Angle::Radians(0.5); EXPECT_DOUBLE_EQ(1.5, tmp.radians()); tmp -= S1Angle::Radians(1.0); EXPECT_DOUBLE_EQ(0.5, tmp.radians()); tmp *= 5; EXPECT_DOUBLE_EQ(2.5, tmp.radians()); tmp /= 2; EXPECT_DOUBLE_EQ(1.25, tmp.radians()); } TEST(S1Angle, Trigonometry) { // Spot check a few angles to ensure that the correct function is called. EXPECT_DOUBLE_EQ(1, cos(S1Angle::Degrees(0))); EXPECT_DOUBLE_EQ(1, sin(S1Angle::Degrees(90))); EXPECT_DOUBLE_EQ(1, tan(S1Angle::Degrees(45))); // Expect that SinCos is exactly [sin, cos]. for (int k = -1000; k <= 1000; ++k) { const S1Angle angle = S1Angle::Degrees(k); const S1Angle::SinCosPair sin_cos = angle.SinCos(); // If this fails once, it will likely fail many times. ASSERT_EQ(sin_cos.sin, sin(angle)) << k; ASSERT_EQ(sin_cos.cos, cos(angle)) << k; } } TEST(S1Angle, ConstructorsThatMeasureAngles) { EXPECT_DOUBLE_EQ(M_PI_2, S1Angle(S2Point(1, 0, 0), S2Point(0, 0, 2)).radians()); EXPECT_DOUBLE_EQ(0.0, S1Angle(S2Point(1, 0, 0), S2Point(1, 0, 0)).radians()); EXPECT_NEAR(50.0, S1Angle(S2LatLng::FromDegrees(20, 20), S2LatLng::FromDegrees(70, 20)).degrees(), 1e-13); } TEST(S1Angle, TestFormatting) { std::ostringstream ss; ss << S1Angle::Degrees(180.0); EXPECT_EQ("180.0000000", ss.str()); } TEST(S1Angle, RoundtripEncodingSucceeds) { S1Angle angle = S1Angle::Radians(4.4); Encoder encoder; S1Angle::Coder().Encode(encoder, angle); S1Angle decoded_angle; S2Error error; Decoder decoder(encoder.base(), encoder.length()); EXPECT_TRUE(S1Angle::Coder().Decode(decoder, decoded_angle, error)); EXPECT_EQ(angle, decoded_angle); } TEST(S1Angle, DecodeFailsWithTruncatedBuffer) { S1Angle angle = S1Angle::Radians(1.1); Encoder encoder; S1Angle::Coder().Encode(encoder, angle); S1Angle decoded_angle; S2Error error; Decoder decoder(encoder.base(), encoder.length() - 2); EXPECT_FALSE(S1Angle::Coder().Decode(decoder, decoded_angle, error)); } // Benchmarks to verify that the conversion to E5/E6/E7 is not much slower // than the conversion from E5/E6/E7. (Float-to-integer conversions can be // quite slow on some platforms.) We only check the times for E6; the times // for E5/E7 should be similar. // Inspect the results to make sure that the To/From E6 times are not // much different. The difference factor slightly less than 2 on an x86_64. // To reduce the impact of loop overhead, we do kOpsPerLoop ops per loop. static constexpr int kOpsPerLoop = 8; static void BM_E6ToRadians(benchmark::State& state) { // Time conversion from E6 to radians. int i = 0; while (state.KeepRunningBatch(kOpsPerLoop)) { benchmark::DoNotOptimize(S1Angle::E6(i + 0).radians()); benchmark::DoNotOptimize(S1Angle::E6(i + 1).radians()); benchmark::DoNotOptimize(S1Angle::E6(i + 2).radians()); benchmark::DoNotOptimize(S1Angle::E6(i + 3).radians()); benchmark::DoNotOptimize(S1Angle::E6(i + 4).radians()); benchmark::DoNotOptimize(S1Angle::E6(i + 5).radians()); benchmark::DoNotOptimize(S1Angle::E6(i + 6).radians()); benchmark::DoNotOptimize(S1Angle::E6(i + 7).radians()); i += kOpsPerLoop; } } BENCHMARK(BM_E6ToRadians); static void BM_RadiansToE6(benchmark::State& state) { // Time conversion from radians to E6. const double delta = (2 * M_PI) / (state.max_iterations + kOpsPerLoop); double angle = -M_PI; while (state.KeepRunningBatch(kOpsPerLoop)) { // clang-format off benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; benchmark::DoNotOptimize(S1Angle::Radians(angle).e6()); angle += delta; // clang-format on } } BENCHMARK(BM_RadiansToE6); // The current implementation guarantees exact conversions between // Degrees() and E6() when the Degrees() argument is an integer. TEST(S1Angle, DegreesVsE6) { for (int i = 0; i <= 180; ++i) { EXPECT_EQ(S1Angle::Degrees(i), S1Angle::E6(1000000 * i)); } } // The current implementation guarantees exact conversions between // Degrees() and E7() when the Degrees() argument is an integer. TEST(S1Angle, DegreesVsE7) { for (int i = 0; i <= 180; ++i) { EXPECT_EQ(S1Angle::Degrees(i), S1Angle::E7(10000000 * i)); } } // The current implementation guarantees exact conversions between // E6() and E7() when the E6() argument is an integer. TEST(S1Angle, E6VsE7) { absl::BitGen bitgen( S2Testing::MakeTaggedSeedSeq("E6_VS_E7", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); for (int iter = 0; iter < 1000; ++iter) { int i = absl::Uniform(bitgen, 0, 180000000); EXPECT_EQ(S1Angle::E6(i), S1Angle::E7(10 * i)); } } // The current implementation guarantees certain exact conversions between // degrees and radians (see the header file for details). TEST(S1Angle, DegreesVsRadians) { for (int k = -8; k <= 8; ++k) { EXPECT_EQ(S1Angle::Degrees(45 * k), S1Angle::Radians(k * M_PI / 4)); EXPECT_EQ(45 * k, S1Angle::Degrees(45 * k).degrees()); } for (int k = 0; k <= 30; ++k) { int n = 1 << k; EXPECT_EQ(S1Angle::Degrees(180. / n), S1Angle::Radians(M_PI / n)); EXPECT_EQ(S1Angle::Degrees(60. / n), S1Angle::Radians(M_PI / (3. * n))); EXPECT_EQ(S1Angle::Degrees(36. / n), S1Angle::Radians(M_PI / (5. * n))); EXPECT_EQ(S1Angle::Degrees(20. / n), S1Angle::Radians(M_PI / (9. * n))); EXPECT_EQ(S1Angle::Degrees(4. / n), S1Angle::Radians(M_PI / (45. * n))); } // We also spot check a couple of non-identities. EXPECT_NE(S1Angle::Degrees(3), S1Angle::Radians(M_PI / 60)); EXPECT_NE(60, S1Angle::Degrees(60).degrees()); } TEST(S1Angle, SupportsAbslHash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ S1Angle::Zero(), S1Angle::Radians(1), S1Angle::Radians(-1), S1Angle::Degrees(90), S1Angle::Degrees(180), S1Angle::Degrees(-90), S1Angle::Infinity(), })); } src/s2/s1chord_angle.cc000066400000000000000000000127501524103652300152170ustar00rootroot00000000000000// Copyright 2013 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/s1chord_angle.h" #include #include #include #include #include "absl/log/absl_check.h" #include "s2/s1angle.h" using std::max; using std::min; using std::nextafter; static constexpr double kMaxLength2 = 4.0; S1Angle S1ChordAngle::ToAngle() const { if (is_negative()) return S1Angle::Radians(-1); if (is_infinity()) return S1Angle::Infinity(); return S1Angle::Radians(2 * asin(0.5 * sqrt(length2_))); } S1ChordAngle S1ChordAngle::Successor() const { if (length2_ >= kMaxLength2) return Infinity(); if (length2_ < 0.0) return Zero(); return S1ChordAngle(nextafter(length2_, 10.0)); } S1ChordAngle S1ChordAngle::Predecessor() const { if (length2_ <= 0.0) return Negative(); if (length2_ > kMaxLength2) return Straight(); return S1ChordAngle(nextafter(length2_, -10.0)); } S1ChordAngle S1ChordAngle::PlusError(double error) const { // If angle is Negative() or Infinity(), don't change it. // Otherwise clamp it to the valid range. if (is_special()) return *this; return S1ChordAngle(max(0.0, min(kMaxLength2, length2_ + error))); } double S1ChordAngle::GetS2PointConstructorMaxError() const { // There is a relative error of 2.5 * DBL_EPSILON when computing the squared // distance, plus a relative error of 2 * DBL_EPSILON and an absolute error // of (16 * DBL_EPSILON**2) because the lengths of the input points may // differ from 1 by up to (2 * DBL_EPSILON) each. (This is the maximum // length error in S2Point::Normalize.) return 4.5 * DBL_EPSILON * length2_ + 16 * DBL_EPSILON * DBL_EPSILON; } double S1ChordAngle::GetS1AngleConstructorMaxError() const { // Assuming that an accurate math library is being used, the sin() call and // the multiply each have a relative error of 0.5 * DBL_EPSILON. However // the sin() error is squared. return 1.5 * DBL_EPSILON * length2_; } S1ChordAngle operator+(S1ChordAngle a, S1ChordAngle b) { // Error Analysis: // // u is the unit round-off, equal to ε/2 = 2^-53 // x and y below are both computed with (1+u)² error. So we have // length2 = x + y + 2*sqrt(x * y) // length2 = ((x + y)(1+u)³ + 2*sqrt((x * y)((1+u)³))(1+u))(1+u) // // Taking (1+u)^1.5 out of the square root and rounding (1+u)^2.5 to (1+u)³: // length2 = (x + y + 2*sqrt(x * y))(1+u)� // // Bounding (1+u)� as 4*1.01u = 4.04*ε/2 = 2.02ε, total relative error is: // length2()*2.02ε. // Note that this method is much more efficient than converting the chord // angles to S1Angles and adding those. It requires only one square root // plus a few additions and multiplications. ABSL_DCHECK(!a.is_special()) << a; ABSL_DCHECK(!b.is_special()) << b; // Optimization for the common case where "b" is an error tolerance // parameter that happens to be set to zero. double a2 = a.length2(), b2 = b.length2(); if (b2 == 0) return a; // Clamp the angle sum to at most 180 degrees. if (a2 + b2 >= kMaxLength2) return S1ChordAngle::Straight(); // Let "a" and "b" be the (non-squared) chord lengths, and let c = a+b. // Let A, B, and C be the corresponding half-angles (a = 2*sin(A), etc). // Then the formula below can be derived from c = 2 * sin(A+B) and the // relationships sin(A+B) = sin(A)*cos(B) + sin(B)*cos(A) // cos(X) = sqrt(1 - sin^2(X)) . double x = a2 * (1 - 0.25 * b2); // is_valid() => non-negative double y = b2 * (1 - 0.25 * a2); // is_valid() => non-negative return S1ChordAngle(min(kMaxLength2, x + y + 2 * sqrt(x * y))); } S1ChordAngle operator-(S1ChordAngle a, S1ChordAngle b) { // See comments in operator+(). ABSL_DCHECK(!a.is_special()) << a; ABSL_DCHECK(!b.is_special()) << b; double a2 = a.length2(), b2 = b.length2(); if (b2 == 0) return a; if (a2 <= b2) return S1ChordAngle::Zero(); double x = a2 * (1 - 0.25 * b2); double y = b2 * (1 - 0.25 * a2); // The calculation below is formulated differently (with two square roots // rather than one) to avoid excessive cancellation error when two nearly // equal values are subtracted. double c = max(0.0, sqrt(x) - sqrt(y)); return S1ChordAngle(c * c); } double sin2(S1ChordAngle a) { ABSL_DCHECK(!a.is_special()); // Let "a" be the (non-squared) chord length, and let A be the corresponding // half-angle (a = 2*sin(A)). The formula below can be derived from: // sin(2*A) = 2 * sin(A) * cos(A) // cos^2(A) = 1 - sin^2(A) // This is much faster than converting to an angle and computing its sine. return a.length2() * (1 - 0.25 * a.length2()); } double sin(S1ChordAngle a) { return sqrt(sin2(a)); } double cos(S1ChordAngle a) { // cos(2*A) = cos^2(A) - sin^2(A) = 1 - 2*sin^2(A) ABSL_DCHECK(!a.is_special()); return 1 - 0.5 * a.length2(); } double tan(S1ChordAngle a) { return sin(a) / cos(a); } std::ostream& operator<<(std::ostream& os, S1ChordAngle a) { return os << a.ToAngle(); } src/s2/s1chord_angle.h000066400000000000000000000416651524103652300150700ustar00rootroot00000000000000// Copyright 2013 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_S1CHORD_ANGLE_H_ #define S2_S1CHORD_ANGLE_H_ #include #include #include #include #include #include #include #include "absl/log/absl_check.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/s1angle.h" #include "s2/s2point.h" #include "s2/s2pointutil.h" // S1ChordAngle represents the angle subtended by a chord (i.e., the straight // line segment connecting two points on the sphere). Its representation // makes it very efficient for computing and comparing distances, but unlike // S1Angle it is only capable of representing angles between 0 and Pi radians. // S1ChordAngle is intended for applications where many angles need to be // computed and compared, otherwise it is simpler to use S1Angle. // // S1ChordAngle also loses some accuracy as the angle approaches Pi radians. // There are several different ways to measure this error, including the // representational error (i.e., how accurately S1ChordAngle can represent // angles near Pi radians), the conversion error (i.e., how much precision is // lost when an S1Angle is converted to an S1ChordAngle), and the measurement // error (i.e., how accurate the S1ChordAngle(a, b) constructor is when the // points A and B are separated by angles close to Pi radians). All of these // errors differ by a small constant factor. // // For the measurement error (which is the largest of these errors and also // the most important in practice), let the angle between A and B be (Pi - x) // radians, i.e. A and B are within "x" radians of being antipodal. The // corresponding chord length is // // r = 2 * sin((Pi - x) / 2) = 2 * cos(x / 2) . // // For values of x not close to Pi the relative error in the squared chord // length is at most 4.5 * DBL_EPSILON (see GetS2PointConstructorMaxError). // The relative error in "r" is thus at most 2.25 * DBL_EPSILON ~= 5e-16. To // convert this error into an equivalent angle, we have // // |dr / dx| = sin(x / 2) // // and therefore // // |dx| = dr / sin(x / 2) // = 5e-16 * (2 * cos(x / 2)) / sin(x / 2) // = 1e-15 / tan(x / 2) // // The maximum error is attained when // // x = |dx| // = 1e-15 / tan(x / 2) // ~= 1e-15 / (x / 2) // ~= sqrt(2e-15) // // In summary, the measurement error for an angle (Pi - x) is at most // // dx = min(1e-15 / tan(x / 2), sqrt(2e-15)) // (~= min(2e-15 / x, sqrt(2e-15)) when x is small). // // On the Earth's surface (assuming a radius of 6371km), this corresponds to // the following worst-case measurement errors: // // Accuracy: Unless antipodal to within: // --------- --------------------------- // 6.4 nanometers 10,000 km (90 degrees) // 1 micrometer 81.2 kilometers // 1 millimeter 81.2 meters // 1 centimeter 8.12 meters // 28.5 centimeters 28.5 centimeters // // The representational and conversion errors referred to earlier are somewhat // smaller than this. For example, maximum distance between adjacent // representable S1ChordAngle values is only 13.5 cm rather than 28.5 cm. To // see this, observe that the closest representable value to r^2 = 4 is // r^2 = 4 * (1 - DBL_EPSILON / 2). Thus r = 2 * (1 - DBL_EPSILON / 4) and // the angle between these two representable values is // // x = 2 * acos(r / 2) // = 2 * acos(1 - DBL_EPSILON / 4) // ~= 2 * asin(sqrt(DBL_EPSILON / 2) // ~= sqrt(2 * DBL_EPSILON) // ~= 2.1e-8 // // which is 13.5 cm on the Earth's surface. // // The worst case rounding error occurs when the value halfway between these // two representable values is rounded up to 4. This halfway value is // r^2 = (4 * (1 - DBL_EPSILON / 4)), thus r = 2 * (1 - DBL_EPSILON / 8) and // the worst case rounding error is // // x = 2 * acos(r / 2) // = 2 * acos(1 - DBL_EPSILON / 8) // ~= 2 * asin(sqrt(DBL_EPSILON / 4) // ~= sqrt(DBL_EPSILON) // ~= 1.5e-8 // // which is 9.5 cm on the Earth's surface. // // This class is intended to be copied by value as desired. It uses // the default copy constructor and assignment operator. class S1ChordAngle { public: // Maximum relative error when summing two S1ChordAngles together. // Absolute error is length2() of the summed S1ChordAngle() times this value. // See the definition of operator+() for the error analysis. static constexpr double kRelativeSumError = 2.02 * DBL_EPSILON; // The default constructor yields a zero angle. This is useful for STL // containers and class methods with output arguments. constexpr S1ChordAngle() = default; // Construct the S1ChordAngle corresponding to the distance between the two // given points. The points must be unit length. S1ChordAngle(const S2Point& x, const S2Point& y); // Return the zero chord angle. static constexpr S1ChordAngle Zero(); // Return a chord angle of 90 degrees (a "right angle"). static constexpr S1ChordAngle Right(); // Return a chord angle of 180 degrees (a "straight angle"). This is the // maximum finite chord angle. static constexpr S1ChordAngle Straight(); // Return a chord angle larger than any finite chord angle. The only valid // operations on Infinity() are comparisons, S1Angle conversions, and // Successor() / Predecessor(). static constexpr S1ChordAngle Infinity(); // Return a chord angle smaller than Zero(). The only valid operations on // Negative() are comparisons, S1Angle conversions, and Successor() / // Predecessor(). static constexpr S1ChordAngle Negative(); // Conversion from an S1Angle. Angles outside the range [0, Pi] are handled // as follows: Infinity() is mapped to Infinity(), negative angles are // mapped to Negative(), and finite angles larger than Pi are mapped to // Straight(). // // Note that this operation is relatively expensive and should be avoided. // To use S1ChordAngle effectively, you should structure your code so that // input arguments are converted to S1ChordAngles at the beginning of your // algorithm, and results are converted back to S1Angles only at the end. explicit S1ChordAngle(S1Angle angle); // Convenience methods implemented by converting from an S1Angle. static S1ChordAngle Radians(double radians); static S1ChordAngle Degrees(double degrees); static S1ChordAngle E5(int32_t e5); static S1ChordAngle E6(int32_t e6); static S1ChordAngle E7(int32_t e7); // Construct an S1ChordAngle that is an upper bound on the given S1Angle, // i.e. such that FastUpperBoundFrom(x).ToAngle() >= x. Unlike the S1Angle // constructor above, this method is very fast, and the bound is accurate to // within 1% for distances up to about 3100km on the Earth's surface. static constexpr S1ChordAngle FastUpperBoundFrom(S1Angle angle); // Construct an S1ChordAngle from the squared chord length. Note that the // argument is automatically clamped to a maximum of 4.0 to handle possible // roundoff errors. The argument must be non-negative. static constexpr S1ChordAngle FromLength2(double length2); // Converts to an S1Angle. Can be used just like an S1Angle constructor: // // S1ChordAngle x = ...; // return S1Angle(x); // // Infinity() is converted to S1Angle::Infinity(), and Negative() is // converted to an unspecified negative S1Angle. // // Note that the conversion uses trigonometric functions and therefore // should be avoided in inner loops. explicit operator S1Angle() const; // Converts to an S1Angle (equivalent to the operator above). S1Angle ToAngle() const; // Convenience methods implemented by calling ToAngle() first. Note that // because of the S1Angle conversion these methods are relatively expensive // (despite their lowercase names), so the results should be cached if they // are needed inside loops. double radians() const; double degrees() const; int32_t e5() const; int32_t e6() const; int32_t e7() const; // All operators and functions are declared here so that we can put them all // in one place. (The compound assignment operators must be put here.) #ifndef SWIG // `friend operator`s are incompatible with SWIG 4.0, but work with 4.3. // Comparison operators. friend constexpr bool operator==(S1ChordAngle x, S1ChordAngle y); #if defined(__cpp_impl_three_way_comparison) && \ __cpp_impl_three_way_comparison >= 201907L // This should be `= default`, but can't be due to PyCLIF limitations. // NOLINTNEXTLINE(clang-diagnostic-pre-c++20-compat) friend constexpr auto operator<=>(S1ChordAngle x, S1ChordAngle y) { // NOLINTNEXTLINE(clang-diagnostic-pre-c++20-compat) return x.length2() <=> y.length2(); } #else friend constexpr bool operator!=(S1ChordAngle x, S1ChordAngle y) { return x.length2() != y.length2(); } friend constexpr bool operator<(S1ChordAngle x, S1ChordAngle y) { return x.length2() < y.length2(); } friend constexpr bool operator>(S1ChordAngle x, S1ChordAngle y) { return x.length2() > y.length2(); } friend constexpr bool operator<=(S1ChordAngle x, S1ChordAngle y) { return x.length2() <= y.length2(); } friend constexpr bool operator>=(S1ChordAngle x, S1ChordAngle y) { return x.length2() >= y.length2(); } #endif #endif // !SWIG // Comparison predicates. constexpr bool is_zero() const; constexpr bool is_negative() const; constexpr bool is_infinity() const; constexpr bool is_special() const; // Negative or infinity. // Only addition and subtraction of S1ChordAngles is supported. These // methods add or subtract the corresponding S1Angles, and clamp the result // to the range [0, Pi]. Both arguments must be non-negative and // non-infinite. // // REQUIRES: !a.is_special() && !b.is_special() friend S1ChordAngle operator+(S1ChordAngle a, S1ChordAngle b); friend S1ChordAngle operator-(S1ChordAngle a, S1ChordAngle b); S1ChordAngle& operator+=(S1ChordAngle a); S1ChordAngle& operator-=(S1ChordAngle a); // Trigonmetric functions. It is more accurate and efficient to call these // rather than first converting to an S1Angle. friend double sin(S1ChordAngle a); friend double cos(S1ChordAngle a); friend double tan(S1ChordAngle a); // Returns sin(a)**2, but computed more efficiently. friend double sin2(S1ChordAngle a); // The squared length of the chord. (Most clients will not need this.) constexpr double length2() const { return length2_; } // Returns the smallest representable S1ChordAngle larger than this object. // This can be used to convert a "<" comparison to a "<=" comparison. For // example: // // S2ClosestEdgeQuery query(...); // S1ChordAngle limit = ...; // if (query.IsDistanceLess(target, limit.Successor())) { // // Distance to "target" is less than or equal to "limit". // } // // Note the following special cases: // Negative().Successor() == Zero() // Straight().Successor() == Infinity() // Infinity().Successor() == Infinity() S1ChordAngle Successor() const; // Like Successor(), but returns the largest representable S1ChordAngle less // than this object. // // Note the following special cases: // Infinity().Predecessor() == Straight() // Zero().Predecessor() == Negative() // Negative().Predecessor() == Negative() S1ChordAngle Predecessor() const; // Returns a new S1ChordAngle that has been adjusted by the given error // bound (which can be positive or negative). "error" should be the value // returned by one of the error bound methods below. For example: // S1ChordAngle a(x, y); // S1ChordAngle a1 = a.PlusError(a.GetS2PointConstructorMaxError()); S1ChordAngle PlusError(double error) const; // Return the maximum error in length2() for the S1ChordAngle(x, y) // constructor, assuming that "x" and "y" are normalized to within the // bounds guaranteed by S2Point::Normalize(). (The error is defined with // respect to the true distance after the points are projected to lie // exactly on the sphere.) double GetS2PointConstructorMaxError() const; // Return the maximum error in length2() for the S1Angle constructor. double GetS1AngleConstructorMaxError() const; // Return true if the internal representation is valid. Negative() and // Infinity() are both considered valid. constexpr bool is_valid() const; // When S1ChordAngle is used as a key in one of the absl::btree container // types, indicate that linear rather than binary search should be used. // This is much faster when the comparison function is cheap. typedef std::true_type absl_btree_prefer_linear_node_search; private: // S1ChordAngles are represented by the squared chord length, which can // range from 0 to 4. Infinity() uses an infinite squared length. explicit constexpr S1ChordAngle(double length2) : length2_(length2) { ABSL_DCHECK(is_valid()); } double length2_ = 0.0; }; ////////////////// Implementation details follow //////////////////// inline S1ChordAngle::S1ChordAngle(S1Angle angle) { if (angle.radians() < 0) { *this = Negative(); } else if (angle == S1Angle::Infinity()) { *this = Infinity(); } else { // The chord length is 2 * sin(angle / 2). double length = 2 * sin(0.5 * std::min(M_PI, angle.radians())); length2_ = length * length; } ABSL_DCHECK(is_valid()); } inline S1ChordAngle::S1ChordAngle(const S2Point& x, const S2Point& y) : length2_(std::min(4.0, (x - y).Norm2())) { ABSL_DCHECK(S2::IsUnitLength(x)); ABSL_DCHECK(S2::IsUnitLength(y)); // The squared distance may slightly exceed 4.0 due to roundoff errors. // The maximum error in the result is 2 * DBL_EPSILON * length2_. ABSL_DCHECK(is_valid()); } inline constexpr bool S1ChordAngle::is_valid() const { return (length2_ >= 0 && length2_ <= 4.0) || is_special(); } inline constexpr S1ChordAngle S1ChordAngle::FromLength2(double length2) { return S1ChordAngle(std::min(4.0, length2)); } inline constexpr S1ChordAngle S1ChordAngle::Zero() { return S1ChordAngle(0); } inline constexpr S1ChordAngle S1ChordAngle::Right() { return S1ChordAngle(2); } inline constexpr S1ChordAngle S1ChordAngle::Straight() { return S1ChordAngle(4); } inline constexpr S1ChordAngle S1ChordAngle::Infinity() { return S1ChordAngle(std::numeric_limits::infinity()); } inline constexpr S1ChordAngle S1ChordAngle::Negative() { return S1ChordAngle(-1); } inline S1ChordAngle S1ChordAngle::Radians(double radians) { return S1ChordAngle(S1Angle::Radians(radians)); } inline S1ChordAngle S1ChordAngle::Degrees(double degrees) { return S1ChordAngle(S1Angle::Degrees(degrees)); } inline S1ChordAngle S1ChordAngle::E5(int32_t e5) { return S1ChordAngle(S1Angle::E5(e5)); } inline S1ChordAngle S1ChordAngle::E6(int32_t e6) { return S1ChordAngle(S1Angle::E6(e6)); } inline S1ChordAngle S1ChordAngle::E7(int32_t e7) { return S1ChordAngle(S1Angle::E7(e7)); } inline constexpr S1ChordAngle S1ChordAngle::FastUpperBoundFrom(S1Angle angle) { // This method uses the distance along the surface of the sphere as an upper // bound on the distance through the sphere's interior. return S1ChordAngle::FromLength2(angle.radians() * angle.radians()); } inline S1ChordAngle::operator S1Angle() const { return ToAngle(); } inline double S1ChordAngle::radians() const { return ToAngle().radians(); } inline double S1ChordAngle::degrees() const { return ToAngle().degrees(); } inline int32_t S1ChordAngle::e5() const { return ToAngle().e5(); } inline int32_t S1ChordAngle::e6() const { return ToAngle().e6(); } inline int32_t S1ChordAngle::e7() const { return ToAngle().e7(); } inline constexpr bool S1ChordAngle::is_zero() const { return length2_ == 0; } inline constexpr bool S1ChordAngle::is_negative() const { // TODO(ericv): Consider stricter check here -- only allow Negative(). return length2_ < 0; } inline constexpr bool S1ChordAngle::is_infinity() const { return length2_ == std::numeric_limits::infinity(); } inline constexpr bool S1ChordAngle::is_special() const { return is_negative() || is_infinity(); } inline constexpr bool operator==(S1ChordAngle x, S1ChordAngle y) { return x.length2() == y.length2(); } inline S1ChordAngle& S1ChordAngle::operator+=(S1ChordAngle a) { return (*this = *this + a); } inline S1ChordAngle& S1ChordAngle::operator-=(S1ChordAngle a) { return (*this = *this - a); } // Outputs the chord angle as the equivalent S1Angle. std::ostream& operator<<(std::ostream& os, S1ChordAngle a); #endif // S2_S1CHORD_ANGLE_H_ src/s2/s1chord_angle_test.cc000066400000000000000000000256521524103652300162630ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "s2/s1chord_angle.h" #include #include #include #include #include "absl/log/log_streamer.h" #include "absl/random/random.h" #include "s2/s1angle.h" #include "s2/s2edge_distances.h" #include "s2/s2point.h" #include "s2/s2predicates.h" #include "s2/s2random.h" #include "s2/s2testing.h" #include "s2/util/math/matrix3x3.h" using std::numeric_limits; TEST(S1ChordAngle, ConstexprFunctionsWork) { // Test constexpr constructors. static constexpr auto kTestZero = S1ChordAngle::Zero(); static constexpr auto kTestRight = S1ChordAngle::Right(); static constexpr auto kTestStraight = S1ChordAngle::Straight(); static constexpr auto kTestInfinity = S1ChordAngle::Infinity(); static constexpr auto kTestNegative = S1ChordAngle::Negative(); static constexpr auto kTestFastUpperBound = S1ChordAngle::FastUpperBoundFrom(S1Angle::Radians(1)); static constexpr auto kTestFromLength2 = S1ChordAngle::FromLength2(2); EXPECT_EQ(kTestRight, S1ChordAngle::Right()); EXPECT_EQ(kTestStraight, S1ChordAngle::Straight()); EXPECT_EQ(kTestFromLength2.length2(), 2); constexpr bool kIsZero = kTestZero.is_zero(); EXPECT_TRUE(kIsZero); constexpr bool kIsNegative = kTestNegative.is_negative(); EXPECT_TRUE(kIsNegative); constexpr bool kIsInfinity = kTestInfinity.is_infinity(); EXPECT_TRUE(kIsInfinity); constexpr bool kIsSpecial = kTestNegative.is_special(); EXPECT_TRUE(kIsSpecial); constexpr bool kIsValid = kTestFastUpperBound.is_valid(); EXPECT_TRUE(kIsValid); } TEST(S1ChordAngle, DefaultConstructor) { // Check that the default constructor returns an angle of 0. S1ChordAngle a; EXPECT_EQ(S1ChordAngle::Zero(), a); } TEST(S1ChordAngle, TwoPointConstructor) { absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "TWO_POINT_CONSTRUCTOR", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); for (int iter = 0; iter < 100; ++iter) { S2Point x, y, z; s2random::Frame(bitgen, x, y, z); EXPECT_EQ(S1Angle::Zero(), S1Angle(S1ChordAngle(z, z))); EXPECT_NEAR(M_PI, S1ChordAngle(-z, z).radians(), 1e-7); EXPECT_DOUBLE_EQ(M_PI_2, S1ChordAngle(x, z).radians()); S2Point w = (y + z).Normalize(); EXPECT_DOUBLE_EQ(M_PI_4, S1ChordAngle(w, z).radians()); } } TEST(S1ChordAngle, FromLength2) { EXPECT_EQ(0, S1ChordAngle::FromLength2(0).degrees()); EXPECT_DOUBLE_EQ(60, S1ChordAngle::FromLength2(1).degrees()); EXPECT_DOUBLE_EQ(90, S1ChordAngle::FromLength2(2).degrees()); EXPECT_EQ(180, S1ChordAngle::FromLength2(4).degrees()); EXPECT_EQ(180, S1ChordAngle::FromLength2(5).degrees()); } TEST(S1ChordAngle, Zero) { EXPECT_EQ(S1Angle::Zero(), S1Angle(S1ChordAngle::Zero())); } TEST(S1ChordAngle, Right) { EXPECT_DOUBLE_EQ(90, S1ChordAngle::Right().degrees()); } TEST(S1ChordAngle, Straight) { EXPECT_EQ(S1Angle::Degrees(180), S1Angle(S1ChordAngle::Straight())); } TEST(S1ChordAngle, Infinity) { EXPECT_LT(S1ChordAngle::Straight(), S1ChordAngle::Infinity()); EXPECT_EQ(S1ChordAngle::Infinity(), S1ChordAngle::Infinity()); EXPECT_EQ(S1Angle::Infinity(), S1Angle(S1ChordAngle::Infinity())); } TEST(S1ChordAngle, Negative) { EXPECT_LT(S1ChordAngle::Negative(), S1ChordAngle::Zero()); EXPECT_EQ(S1ChordAngle::Negative(), S1ChordAngle::Negative()); EXPECT_LT(S1ChordAngle::Negative().ToAngle(), S1Angle::Zero()); } TEST(S1ChordAngle, Predicates) { EXPECT_TRUE(S1ChordAngle::Zero().is_zero()); EXPECT_FALSE(S1ChordAngle::Zero().is_negative()); EXPECT_FALSE(S1ChordAngle::Zero().is_special()); EXPECT_FALSE(S1ChordAngle::Straight().is_special()); EXPECT_TRUE(S1ChordAngle::Negative().is_negative()); EXPECT_TRUE(S1ChordAngle::Negative().is_special()); EXPECT_TRUE(S1ChordAngle::Infinity().is_infinity()); EXPECT_TRUE(S1ChordAngle::Infinity().is_special()); } TEST(S1ChordAngle, ToFromS1Angle) { EXPECT_EQ(0, S1ChordAngle(S1Angle::Zero()).radians()); EXPECT_EQ(4, S1ChordAngle(S1Angle::Radians(M_PI)).length2()); EXPECT_EQ(M_PI, S1ChordAngle(S1Angle::Radians(M_PI)).radians()); EXPECT_EQ(S1Angle::Infinity(), S1Angle(S1ChordAngle(S1Angle::Infinity()))); EXPECT_LT(S1ChordAngle(S1Angle::Radians(-1)).radians(), 0); EXPECT_DOUBLE_EQ(1.0, S1ChordAngle(S1Angle::Radians(1.0)).radians()); } TEST(S1ChordAngle, Successor) { EXPECT_EQ(S1ChordAngle::Zero(), S1ChordAngle::Negative().Successor()); EXPECT_EQ(S1ChordAngle::Infinity(), S1ChordAngle::Straight().Successor()); EXPECT_EQ(S1ChordAngle::Infinity(), S1ChordAngle::Infinity().Successor()); S1ChordAngle x = S1ChordAngle::Negative(); for (int i = 0; i < 10; ++i) { EXPECT_LT(x, x.Successor()); x = x.Successor(); } } TEST(S1ChordAngle, Predecessor) { EXPECT_EQ(S1ChordAngle::Straight(), S1ChordAngle::Infinity().Predecessor()); EXPECT_EQ(S1ChordAngle::Negative(), S1ChordAngle::Zero().Predecessor()); EXPECT_EQ(S1ChordAngle::Negative(), S1ChordAngle::Negative().Predecessor()); S1ChordAngle x = S1ChordAngle::Infinity(); for (int i = 0; i < 10; ++i) { EXPECT_GT(x, x.Predecessor()); x = x.Predecessor(); } } TEST(S1ChordAngle, Arithmetic) { S1ChordAngle zero = S1ChordAngle::Zero(); S1ChordAngle degree30 = S1ChordAngle::Degrees(30); S1ChordAngle degree60 = S1ChordAngle::Degrees(60); S1ChordAngle degree90 = S1ChordAngle::Degrees(90); S1ChordAngle degree120 = S1ChordAngle::Degrees(120); S1ChordAngle degree180 = S1ChordAngle::Straight(); EXPECT_EQ(0, (zero + zero).degrees()); EXPECT_EQ(0, (zero - zero).degrees()); EXPECT_EQ(0, (degree60 - degree60).degrees()); EXPECT_EQ(0, (degree180 - degree180).degrees()); EXPECT_EQ(0, (zero - degree60).degrees()); EXPECT_EQ(0, (degree30 - degree90).degrees()); // `EXPECT_DOUBLE_EQ` compares with 4 ULP tolerance. EXPECT_DOUBLE_EQ(60, (degree60 + zero).degrees()); EXPECT_DOUBLE_EQ(60, (degree60 - zero).degrees()); EXPECT_DOUBLE_EQ(60, (zero + degree60).degrees()); EXPECT_DOUBLE_EQ(90, (degree30 + degree60).degrees()); EXPECT_DOUBLE_EQ(90, (degree60 + degree30).degrees()); EXPECT_DOUBLE_EQ(60, (degree90 - degree30).degrees()); #ifndef _WIN32 EXPECT_DOUBLE_EQ(30, (degree90 - degree60).degrees()); #else // TODO(b/387870507): Figure out if this is a bug or the tolerance is // wrong. EXPECT_DOUBLE_EQ(30.000000000000018, (degree90 - degree60).degrees()); #endif // defined(_WIN32) EXPECT_EQ(180, (degree180 + zero).degrees()); EXPECT_EQ(180, (degree180 - zero).degrees()); EXPECT_EQ(180, (degree90 + degree90).degrees()); EXPECT_EQ(180, (degree120 + degree90).degrees()); EXPECT_EQ(180, (degree120 + degree120).degrees()); EXPECT_EQ(180, (degree30 + degree180).degrees()); EXPECT_EQ(180, (degree180 + degree180).degrees()); } TEST(S1ChordAngle, ArithmeticPrecision) { // Verifies that S1ChordAngle is capable of adding and subtracting angles // extremely accurately up to Pi/2 radians. (Accuracy continues to be good // well beyond this value but degrades as angles approach Pi.) S1ChordAngle kEps = S1ChordAngle::Radians(1e-15); S1ChordAngle k90 = S1ChordAngle::Right(); S1ChordAngle k90MinusEps = k90 - kEps; S1ChordAngle k90PlusEps = k90 + kEps; double kMaxError = 2 * DBL_EPSILON; EXPECT_NEAR(k90MinusEps.radians(), M_PI_2 - kEps.radians(), kMaxError); EXPECT_NEAR(k90PlusEps.radians(), M_PI_2 + kEps.radians(), kMaxError); EXPECT_NEAR((k90 - k90MinusEps).radians(), kEps.radians(), kMaxError); EXPECT_NEAR((k90PlusEps - k90).radians(), kEps.radians(), kMaxError); EXPECT_NEAR((k90MinusEps + kEps).radians(), M_PI_2, kMaxError); } TEST(S1ChordAngle, Trigonometry) { static constexpr int kIters = 20; for (int iter = 0; iter <= kIters; ++iter) { double radians = M_PI * iter / kIters; S1ChordAngle angle(S1Angle::Radians(radians)); EXPECT_NEAR(sin(radians), sin(angle), 1e-15) << radians; EXPECT_NEAR(cos(radians), cos(angle), 1e-15) << radians; // Since the tan(x) is unbounded near Pi/4, we map the result back to an // angle before comparing. (The assertion is that the result is equal to // the tangent of a nearby angle.) #ifndef _WIN32 EXPECT_NEAR(atan(tan(radians)), atan(tan(angle)), 1e-15) << radians; #else // TODO(b/387870507): On Windows, we get -pi/2 (instead of pi/2) for an // input of pi/2. Figure out why this is happening. if (iter == kIters / 2) { EXPECT_NEAR(-M_PI_2, atan(tan(angle)), 1e-15) << radians; } else { EXPECT_NEAR(atan(tan(radians)), atan(tan(angle)), 1e-15) << radians; } #endif // defined(_WIN32) } // Unlike S1Angle, S1ChordAngle can represent 90 and 180 degrees exactly. S1ChordAngle angle90 = S1ChordAngle::FromLength2(2); S1ChordAngle angle180 = S1ChordAngle::FromLength2(4); EXPECT_EQ(1, sin(angle90)); EXPECT_EQ(0, cos(angle90)); EXPECT_EQ(numeric_limits::infinity(), tan(angle90)); EXPECT_EQ(0, sin(angle180)); EXPECT_EQ(-1, cos(angle180)); EXPECT_EQ(0, tan(angle180)); } TEST(S1ChordAngle, PlusError) { EXPECT_EQ(S1ChordAngle::Negative(), S1ChordAngle::Negative().PlusError(5)); EXPECT_EQ(S1ChordAngle::Infinity(), S1ChordAngle::Infinity().PlusError(-5)); EXPECT_EQ(S1ChordAngle::Straight(), S1ChordAngle::Straight().PlusError(5)); EXPECT_EQ(S1ChordAngle::Zero(), S1ChordAngle::Zero().PlusError(-5)); EXPECT_EQ(S1ChordAngle::FromLength2(1.25), S1ChordAngle::FromLength2(1).PlusError(0.25)); EXPECT_EQ(S1ChordAngle::FromLength2(0.75), S1ChordAngle::FromLength2(1).PlusError(-0.25)); } TEST(S1ChordAngle, GetS2PointConstructorMaxError) { // Check that the error bound returned by GetS2PointConstructorMaxError() is // large enough. absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "GET_S2_POINT_CONSTRUCTOR_MAX_ERROR", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); for (int iter = 0; iter < 100000; ++iter) { S2Point x = s2random::Point(bitgen); S2Point y = s2random::Point(bitgen); if (absl::Bernoulli(bitgen, 0.1)) { // Occasionally test a point pair that is nearly identical or antipodal. S1Angle r = S1Angle::Radians(1e-15 * absl::Uniform(bitgen, 0.0, 1.0)); y = S2::GetPointOnLine(x, y, r); if (absl::Bernoulli(bitgen, 0.5)) y = -y; } S1ChordAngle dist = S1ChordAngle(x, y); double error = dist.GetS2PointConstructorMaxError(); EXPECT_LE(s2pred::CompareDistance(x, y, dist.PlusError(error)), 0) << "angle=" << S1Angle(dist) << ", iter=" << iter; EXPECT_GE(s2pred::CompareDistance(x, y, dist.PlusError(-error)), 0) << "angle=" << S1Angle(dist) << ", iter=" << iter; } } src/s2/s1interval.cc000066400000000000000000000240651524103652300146000ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/s1interval.h" #include #include #include #include "absl/log/absl_check.h" using std::fabs; using std::max; S1Interval S1Interval::FromPoint(double p) { if (p == -M_PI) p = M_PI; return S1Interval(p, p, ARGS_CHECKED); } double S1Interval::GetCenter() const { double center = 0.5 * (lo() + hi()); if (!is_inverted()) return center; // Return the center in the range (-Pi, Pi]. return (center <= 0) ? (center + M_PI) : (center - M_PI); } double S1Interval::GetLength() const { double length = hi() - lo(); if (length >= 0) return length; length += 2 * M_PI; // Empty intervals have a negative length. return (length > 0) ? length : -1; } S1Interval S1Interval::Complement() const { if (lo() == hi()) return Full(); // Singleton. return S1Interval(hi(), lo(), ARGS_CHECKED); // Handles empty and full. } double S1Interval::GetComplementCenter() const { if (lo() != hi()) { return Complement().GetCenter(); } else { // Singleton. return (hi() <= 0) ? (hi() + M_PI) : (hi() - M_PI); } } bool S1Interval::FastContains(double p) const { if (is_inverted()) { return (p >= lo() || p <= hi()) && !is_empty(); } else { return p >= lo() && p <= hi(); } } bool S1Interval::Contains(double p) const { // Works for empty, full, and singleton intervals. ABSL_DCHECK(IsValidPoint(p)) << p; if (p == -M_PI) p = M_PI; return FastContains(p); } bool S1Interval::InteriorContains(double p) const { // Works for empty, full, and singleton intervals. ABSL_DCHECK(IsValidPoint(p)) << p; if (p == -M_PI) p = M_PI; if (is_inverted()) { return p > lo() || p < hi(); } else { return (p > lo() && p < hi()) || is_full(); } } bool S1Interval::Contains(const S1Interval& y) const { // It might be helpful to compare the structure of these tests to // the simpler Contains(double) method above. if (is_inverted()) { if (y.is_inverted()) return y.lo() >= lo() && y.hi() <= hi(); return (y.lo() >= lo() || y.hi() <= hi()) && !is_empty(); } else { if (y.is_inverted()) return is_full() || y.is_empty(); return y.lo() >= lo() && y.hi() <= hi(); } } bool S1Interval::InteriorContains(const S1Interval& y) const { if (is_inverted()) { if (!y.is_inverted()) return y.lo() > lo() || y.hi() < hi(); return (y.lo() > lo() && y.hi() < hi()) || y.is_empty(); } else { if (y.is_inverted()) return is_full() || y.is_empty(); return (y.lo() > lo() && y.hi() < hi()) || is_full(); } } bool S1Interval::Intersects(const S1Interval& y) const { if (is_empty() || y.is_empty()) return false; if (is_inverted()) { // Every non-empty inverted interval contains Pi. return y.is_inverted() || y.lo() <= hi() || y.hi() >= lo(); } else { if (y.is_inverted()) return y.lo() <= hi() || y.hi() >= lo(); return y.lo() <= hi() && y.hi() >= lo(); } } bool S1Interval::InteriorIntersects(const S1Interval& y) const { if (is_empty() || y.is_empty() || lo() == hi()) return false; if (is_inverted()) { return y.is_inverted() || y.lo() < hi() || y.hi() > lo(); } else { if (y.is_inverted()) return y.lo() < hi() || y.hi() > lo(); return (y.lo() < hi() && y.hi() > lo()) || is_full(); } } inline static double PositiveDistance(double a, double b) { // Compute the distance from "a" to "b" in the range [0, 2*Pi). // This is equivalent to (remainder(b - a - M_PI, 2 * M_PI) + M_PI), // except that it is more numerically stable (it does not lose // precision for very small positive distances). double d = b - a; if (d >= 0) return d; // We want to ensure that if b == Pi and a == (-Pi + eps), // the return result is approximately 2*Pi and not zero. return (b + M_PI) - (a - M_PI); } double S1Interval::GetDirectedHausdorffDistance(const S1Interval& y) const { if (y.Contains(*this)) return 0.0; // this includes the case *this is empty if (y.is_empty()) return M_PI; // maximum possible distance on S1 double y_complement_center = y.GetComplementCenter(); if (Contains(y_complement_center)) { return PositiveDistance(y.hi(), y_complement_center); } else { // The Hausdorff distance is realized by either two hi() endpoints or two // lo() endpoints, whichever is farther apart. double hi_hi = S1Interval(y.hi(), y_complement_center).Contains(hi()) ? PositiveDistance(y.hi(), hi()) : 0; double lo_lo = S1Interval(y_complement_center, y.lo()).Contains(lo()) ? PositiveDistance(lo(), y.lo()) : 0; ABSL_DCHECK(hi_hi > 0 || lo_lo > 0); return max(hi_hi, lo_lo); } } void S1Interval::AddPoint(double p) { ABSL_DCHECK(IsValidPoint(p)) << p; if (p == -M_PI) p = M_PI; if (FastContains(p)) return; if (is_empty()) { set_hi(p); set_lo(p); } else { // Compute distance from p to each endpoint. double dlo = PositiveDistance(p, lo()); double dhi = PositiveDistance(hi(), p); if (dlo < dhi) { set_lo(p); } else { set_hi(p); } // Adding a point can never turn a non-full interval into a full one. } } double S1Interval::Project(double p) const { ABSL_DCHECK(!is_empty()); ABSL_DCHECK(IsValidPoint(p)) << p; if (p == -M_PI) p = M_PI; if (FastContains(p)) return p; // Compute distance from p to each endpoint. double dlo = PositiveDistance(p, lo()); double dhi = PositiveDistance(hi(), p); return (dlo < dhi) ? lo() : hi(); } S1Interval S1Interval::FromPointPair(double p1, double p2) { ABSL_DCHECK(IsValidPoint(p1)) << p1; ABSL_DCHECK(IsValidPoint(p2)) << p2; if (p1 == -M_PI) p1 = M_PI; if (p2 == -M_PI) p2 = M_PI; if (PositiveDistance(p1, p2) <= M_PI) { return S1Interval(p1, p2, ARGS_CHECKED); } else { return S1Interval(p2, p1, ARGS_CHECKED); } } S1Interval S1Interval::Expanded(double margin) const { if (margin >= 0) { if (is_empty()) return *this; // Check whether this interval will be full after expansion, allowing // for a 1-bit rounding error when computing each endpoint. if (GetLength() + 2 * margin + 2 * DBL_EPSILON >= 2 * M_PI) return Full(); } else { if (is_full()) return *this; // Check whether this interval will be empty after expansion, allowing // for a 1-bit rounding error when computing each endpoint. if (GetLength() + 2 * margin - 2 * DBL_EPSILON <= 0) return Empty(); } S1Interval result(remainder(lo() - margin, 2*M_PI), remainder(hi() + margin, 2*M_PI)); if (result.lo() <= -M_PI) result.set_lo(M_PI); return result; } S1Interval S1Interval::Union(const S1Interval& y) const { // The y.is_full() case is handled correctly in all cases by the code // below, but can follow three separate code paths depending on whether // this interval is inverted, is non-inverted but contains Pi, or neither. if (y.is_empty()) return *this; if (FastContains(y.lo())) { if (FastContains(y.hi())) { // Either this interval contains y, or the union of the two // intervals is the Full() interval. if (Contains(y)) return *this; // is_full() code path return Full(); } return S1Interval(lo(), y.hi(), ARGS_CHECKED); } if (FastContains(y.hi())) return S1Interval(y.lo(), hi(), ARGS_CHECKED); // This interval contains neither endpoint of y. This means that either y // contains all of this interval, or the two intervals are disjoint. if (is_empty() || y.FastContains(lo())) return y; // Check which pair of endpoints are closer together. double dlo = PositiveDistance(y.hi(), lo()); double dhi = PositiveDistance(hi(), y.lo()); if (dlo < dhi) { return S1Interval(y.lo(), hi(), ARGS_CHECKED); } else { return S1Interval(lo(), y.hi(), ARGS_CHECKED); } } S1Interval S1Interval::Intersection(const S1Interval& y) const { // The y.is_full() case is handled correctly in all cases by the code // below, but can follow three separate code paths depending on whether // this interval is inverted, is non-inverted but contains Pi, or neither. if (y.is_empty()) return Empty(); if (FastContains(y.lo())) { if (FastContains(y.hi())) { // Either this interval contains y, or the region of intersection // consists of two disjoint subintervals. In either case, we want // to return the shorter of the two original intervals. if (y.GetLength() < GetLength()) return y; // is_full() code path return *this; } return S1Interval(y.lo(), hi(), ARGS_CHECKED); } if (FastContains(y.hi())) return S1Interval(lo(), y.hi(), ARGS_CHECKED); // This interval contains neither endpoint of y. This means that either y // contains all of this interval, or the two intervals are disjoint. if (y.FastContains(lo())) return *this; // is_empty() okay here ABSL_DCHECK(!Intersects(y)); return Empty(); } bool S1Interval::ApproxEquals(const S1Interval& y, double max_error) const { // Full and empty intervals require special cases because the "endpoints" // are considered to be positioned arbitrarily. if (is_empty()) return y.GetLength() <= 2 * max_error; if (y.is_empty()) return GetLength() <= 2 * max_error; if (is_full()) return y.GetLength() >= 2 * (M_PI - max_error); if (y.is_full()) return GetLength() >= 2 * (M_PI - max_error); // The purpose of the last test below is to verify that moving the endpoints // does not invert the interval, e.g. [-1e20, 1e20] vs. [1e20, -1e20]. return (fabs(remainder(y.lo() - lo(), 2 * M_PI)) <= max_error && fabs(remainder(y.hi() - hi(), 2 * M_PI)) <= max_error && fabs(GetLength() - y.GetLength()) <= 2 * max_error); } src/s2/s1interval.h000066400000000000000000000261201524103652300144340ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_S1INTERVAL_H_ #define S2_S1INTERVAL_H_ #include #include #include #include #include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/util/math/vector.h" // IWYU pragma: export // An S1Interval represents a closed interval on a unit circle (also known // as a 1-dimensional sphere). It is capable of representing the empty // interval (containing no points), the full interval (containing all // points), and zero-length intervals (containing a single point). // // Points are represented by the angle they make with the positive x-axis in // the range [-Pi, Pi]. An interval is represented by its lower and upper // bounds (both inclusive, since the interval is closed). The lower bound may // be greater than the upper bound, in which case the interval is "inverted" // (i.e. it passes through the point (-1, 0)). // // Note that the point (-1, 0) has two valid representations, Pi and -Pi. // The normalized representation of this point internally is Pi, so that // endpoints of normal intervals are in the range (-Pi, Pi]. However, we // take advantage of the point -Pi to construct two special intervals: // the Full() interval is [-Pi, Pi], and the Empty() interval is [Pi, -Pi]. // // This class is intended to be copied by value as desired. It uses // the default copy constructor and assignment operator. class S1Interval { public: // Constructor. Both endpoints must be in the range -Pi to Pi inclusive. // The value -Pi is converted internally to Pi except for the Full() // and Empty() intervals. S1Interval(double lo, double hi); // The default constructor creates an empty interval. // // Note: Don't construct an interval using the default constructor and // set_lo()/set_hi(). If you need to set both endpoints, use the // constructor above: // // lng_bounds_ = S1Interval(lng_lo, lng_hi); S1Interval(); // Returns the empty interval. static S1Interval Empty(); // Returns the full interval. static S1Interval Full(); // Convenience method to construct an interval containing a single point. static S1Interval FromPoint(double p); // Convenience method to construct the minimal interval containing // the two given points. This is equivalent to starting with an empty // interval and calling AddPoint() twice, but it is more efficient. static S1Interval FromPointPair(double p1, double p2); // Accessors methods. double lo() const { return bounds_[0]; } double hi() const { return bounds_[1]; } // Methods that allow the S1Interval to be accessed as a vector. (The // recommended style is to use lo() and hi() whenever possible, but these // methods are useful when the endpoint to be selected is not constant.) // // Only const versions of these methods are provided, since S1Interval // has invariants that must be maintained after each update. double operator[](int i) const { return bounds_[i]; } const Vector2_d& bounds() const { return bounds_; } // An interval is valid if neither bound exceeds Pi in absolute value, // and the value -Pi appears only in the Empty() and Full() intervals. bool is_valid() const; // Return true if the interval contains all points on the unit circle. bool is_full() const { return lo() == -M_PI && hi() == M_PI; } // Return true if the interval is empty, i.e. it contains no points. bool is_empty() const { return lo() == M_PI && hi() == -M_PI; } // Return true if lo() > hi(). (This is true for empty intervals.) bool is_inverted() const { return lo() > hi(); } // Return the midpoint of the interval. For full and empty intervals, // the result is arbitrary. double GetCenter() const; // Return the length of the interval. The length of an empty interval // is negative. double GetLength() const; // Return the complement of the interior of the interval. An interval and // its complement have the same boundary but do not share any interior // values. The complement operator is not a bijection, since the complement // of a singleton interval (containing a single value) is the same as the // complement of an empty interval. S1Interval Complement() const; // Return the midpoint of the complement of the interval. For full and empty // intervals, the result is arbitrary. For a singleton interval (containing a // single point), the result is its antipodal point on S1. double GetComplementCenter() const; // Return true if the interval (which is closed) contains the point 'p'. bool Contains(double p) const; // Return true if the interior of the interval contains the point 'p'. bool InteriorContains(double p) const; // Return true if the interval contains the given interval 'y'. // Works for empty, full, and singleton intervals. bool Contains(const S1Interval& y) const; // Returns true if the interior of this interval contains the entire // interval 'y'. Note that x.InteriorContains(x) is true only when // x is the empty or full interval, and x.InteriorContains(S1Interval(p,p)) // is equivalent to x.InteriorContains(p). bool InteriorContains(const S1Interval& y) const; // Return true if the two intervals contain any points in common. // Note that the point +/-Pi has two representations, so the intervals // [-Pi,-3] and [2,Pi] intersect, for example. bool Intersects(const S1Interval& y) const; // Return true if the interior of this interval contains any point of the // interval 'y' (including its boundary). Works for empty, full, and // singleton intervals. bool InteriorIntersects(const S1Interval& y) const; // Return the Hausdorff distance to the given interval 'y'. For two // S1Intervals x and y, this distance is defined by // h(x, y) = max_{p in x} min_{q in y} d(p, q), // where d(.,.) is measured along S1. double GetDirectedHausdorffDistance(const S1Interval& y) const; // Expand the interval by the minimum amount necessary so that it // contains the given point "p" (an angle in the range [-Pi, Pi]). void AddPoint(double p); // Return the closest point in the interval to the given point "p". // The interval must be non-empty. double Project(double p) const; // Return an interval that has been expanded on each side by the given // distance "margin". If "margin" is negative, then shrink the interval on // each side by "margin" instead. The resulting interval may be empty or // full. Any expansion (positive or negative) of a full interval remains // full, and any expansion of an empty interval remains empty. S1Interval Expanded(double margin) const; // Return the smallest interval that contains this interval and the // given interval "y". S1Interval Union(const S1Interval& y) const; // Return the smallest interval that contains the intersection of this // interval with "y". Note that the region of intersection may // consist of two disjoint intervals. S1Interval Intersection(const S1Interval& y) const; // Return true if two intervals contains the same set of points. bool operator==(const S1Interval& y) const; // Return true if two intervals do not contain the same set of points. bool operator!=(const S1Interval& y) const; // Return true if this interval can be transformed into the given interval by // moving each endpoint by at most "max_error" (and without the endpoints // crossing, which would invert the interval). Empty and full intervals are // considered to start at an arbitrary point on the unit circle, thus any // interval with (length <= 2*max_error) matches the empty interval, and any // interval with (length >= 2*Pi - 2*max_error) matches the full interval. // Note: default value is duplicated in Python bindings (s1interval_bindings.cc) bool ApproxEquals(const S1Interval& y, double max_error = 1e-15) const; // Low-level methods to modify one endpoint of an existing S1Interval. // These methods should really be private because setting just one endpoint // can violate the invariants maintained by S1Interval. In particular: // // - It is not valid to call these methods on an Empty() or Full() // interval, since these intervals do not have any endpoints. // // - It is not allowed to set an endpoint to -Pi. (When these methods are // used internally, values of -Pi have already been normalized to Pi.) // // The preferred way to modify both endpoints of an interval is to use a // constructor, e.g. lng = S1Interval(lng_lo, lng_hi). void set_lo(double p); void set_hi(double p); // Returns true if the given value is a valid S1 point, i.e. it is // in the range [-Pi, Pi]. static bool IsValidPoint(double p) { return std::fabs(p) <= M_PI; } private: enum ArgsChecked { ARGS_CHECKED }; // Internal constructor that assumes that both arguments are in the // correct range, i.e. normalization from -Pi to Pi is already done. S1Interval(double lo, double hi, ArgsChecked dummy); // Return true if the interval (which is closed) contains the point 'p'. // Skips the normalization of 'p' from -Pi to Pi. bool FastContains(double p) const; Vector2_d bounds_; }; inline S1Interval::S1Interval(double lo, double hi) : bounds_(lo, hi) { if (lo == -M_PI && hi != M_PI) set_lo(M_PI); if (hi == -M_PI && lo != M_PI) set_hi(M_PI); ABSL_DCHECK(is_valid()); } inline S1Interval::S1Interval(double lo, double hi, ArgsChecked dummy) : bounds_(lo, hi) { ABSL_DCHECK(is_valid()); } inline S1Interval::S1Interval() : bounds_(M_PI, -M_PI) { } inline S1Interval S1Interval::Empty() { return S1Interval(); } inline S1Interval S1Interval::Full() { return S1Interval(-M_PI, M_PI, ARGS_CHECKED); } inline bool S1Interval::is_valid() const { return (std::fabs(lo()) <= M_PI && std::fabs(hi()) <= M_PI && !(lo() == -M_PI && hi() != M_PI) && !(hi() == -M_PI && lo() != M_PI)); } inline bool S1Interval::operator==(const S1Interval& y) const { return lo() == y.lo() && hi() == y.hi(); } inline bool S1Interval::operator!=(const S1Interval& y) const { return !operator==(y); } inline void S1Interval::set_lo(double p) { bounds_[0] = p; ABSL_DCHECK(is_valid()); } inline void S1Interval::set_hi(double p) { bounds_[1] = p; ABSL_DCHECK(is_valid()); } inline std::ostream& operator<<(std::ostream& os, const S1Interval& x) { return os << "[" << x.lo() << ", " << x.hi() << "]"; } template H AbslHashValue(H h, const S1Interval& interval) { return H::combine(std::move(h), interval.lo(), interval.hi()); } #endif // S2_S1INTERVAL_H_ src/s2/s1interval_test.cc000066400000000000000000000521071524103652300156350ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/s1interval.h" #include #include #include #include #include "absl/hash/hash_testing.h" #include "absl/strings/string_view.h" using absl::string_view; using std::fabs; class S1IntervalTestBase : public testing::Test { public: // Create some standard intervals to use in the tests. These include the // empty and full intervals, intervals containing a single point, and // intervals spanning one or more "quadrants" which are numbered as follows: // quad1 == [0, Pi/2] // quad2 == [Pi/2, Pi] // quad3 == [-Pi, -Pi/2] // quad4 == [-Pi/2, 0] S1IntervalTestBase() : empty(S1Interval::Empty()), full(S1Interval::Full()), // Single-point intervals: zero(0, 0), pi2(M_PI_2, M_PI_2), pi(M_PI, M_PI), mipi(-M_PI, -M_PI), // Same as "pi" after normalization. mipi2(-M_PI_2, -M_PI_2), // Single quadrants: quad1(0, M_PI_2), quad2(M_PI_2, -M_PI), quad3(M_PI, -M_PI_2), quad4(-M_PI_2, 0), // Quadrant pairs: quad12(0, -M_PI), quad23(M_PI_2, -M_PI_2), quad34(-M_PI, 0), quad41(-M_PI_2, M_PI_2), // Quadrant triples: quad123(0, -M_PI_2), quad234(M_PI_2, 0), quad341(M_PI, M_PI_2), quad412(-M_PI_2, -M_PI), // Small intervals around the midpoints between quadrants, such that // the center of each interval is offset slightly CCW from the midpoint. mid12(M_PI_2 - 0.01, M_PI_2 + 0.02), mid23(M_PI - 0.01, -M_PI + 0.02), mid34(-M_PI_2 - 0.01, -M_PI_2 + 0.02), mid41(-0.01, 0.02) { } protected: const S1Interval empty, full; const S1Interval zero, pi2, pi, mipi, mipi2; const S1Interval quad1, quad2, quad3, quad4; const S1Interval quad12, quad23, quad34, quad41; const S1Interval quad123, quad234, quad341, quad412; const S1Interval mid12, mid23, mid34, mid41; }; TEST_F(S1IntervalTestBase, ConstructorsAndAccessors) { // Spot-check the constructors and accessors. EXPECT_EQ(quad12.lo(), 0); EXPECT_EQ(quad12.hi(), M_PI); EXPECT_EQ(quad34[0], M_PI); EXPECT_EQ(quad34[1], 0); EXPECT_EQ(quad34.bounds(), Vector2_d(M_PI, 0)); EXPECT_EQ(pi.lo(), M_PI); EXPECT_EQ(pi.hi(), M_PI); // Check that [-Pi, -Pi] is normalized to [Pi, Pi]. EXPECT_EQ(mipi.lo(), M_PI); EXPECT_EQ(mipi.hi(), M_PI); EXPECT_EQ(quad23.lo(), M_PI_2); EXPECT_EQ(quad23.hi(), -M_PI_2); // Check that the default S1Interval is identical to Empty(). S1Interval default_empty; EXPECT_TRUE(default_empty.is_valid()); EXPECT_TRUE(default_empty.is_empty()); EXPECT_EQ(empty.lo(), default_empty.lo()); EXPECT_EQ(empty.hi(), default_empty.hi()); } TEST_F(S1IntervalTestBase, SimplePredicates) { // is_valid(), is_empty(), is_full(), is_inverted() EXPECT_TRUE(zero.is_valid() && !zero.is_empty() && !zero.is_full()); EXPECT_TRUE(empty.is_valid() && empty.is_empty() && !empty.is_full()); EXPECT_TRUE(empty.is_inverted()); EXPECT_TRUE(full.is_valid() && !full.is_empty() && full.is_full()); EXPECT_TRUE(!quad12.is_empty() && !quad12.is_full() && !quad12.is_inverted()); EXPECT_TRUE(!quad23.is_empty() && !quad23.is_full() && quad23.is_inverted()); EXPECT_TRUE(pi.is_valid() && !pi.is_empty() && !pi.is_inverted()); EXPECT_TRUE(mipi.is_valid() && !mipi.is_empty() && !mipi.is_inverted()); } TEST(S1IntervalTest, IsValidPoint) { // Valid angles: endpoints of the allowed range and interior values. EXPECT_TRUE(S1Interval::IsValidPoint(0)); EXPECT_TRUE(S1Interval::IsValidPoint(M_PI)); EXPECT_TRUE(S1Interval::IsValidPoint(-M_PI)); // Invalid: strictly outside [-Pi, Pi]. EXPECT_FALSE(S1Interval::IsValidPoint(M_PI + 1e-15)); EXPECT_FALSE(S1Interval::IsValidPoint(-M_PI - 1e-15)); EXPECT_FALSE(S1Interval::IsValidPoint(4.0)); EXPECT_FALSE(S1Interval::IsValidPoint(-4.0)); } TEST_F(S1IntervalTestBase, AlmostEmptyOrFull) { // Test that rounding errors don't cause intervals that are almost empty or // full to be considered empty or full. The following value is the greatest // representable value less than Pi. const double kAlmostPi = M_PI - 2 * DBL_EPSILON; EXPECT_FALSE(S1Interval(-kAlmostPi, M_PI).is_full()); EXPECT_FALSE(S1Interval(-M_PI, kAlmostPi).is_full()); EXPECT_FALSE(S1Interval(M_PI, -kAlmostPi).is_empty()); EXPECT_FALSE(S1Interval(kAlmostPi, -M_PI).is_empty()); } TEST_F(S1IntervalTestBase, GetCenter) { EXPECT_EQ(quad12.GetCenter(), M_PI_2); EXPECT_DOUBLE_EQ(S1Interval(3.1, 2.9).GetCenter(), 3.0 - M_PI); EXPECT_DOUBLE_EQ(S1Interval(-2.9, -3.1).GetCenter(), M_PI - 3.0); EXPECT_DOUBLE_EQ(S1Interval(2.1, -2.1).GetCenter(), M_PI); EXPECT_EQ(pi.GetCenter(), M_PI); EXPECT_EQ(mipi.GetCenter(), M_PI); EXPECT_EQ(fabs(quad23.GetCenter()), M_PI); EXPECT_DOUBLE_EQ(quad123.GetCenter(), 0.75 * M_PI); } TEST_F(S1IntervalTestBase, GetLength) { EXPECT_EQ(quad12.GetLength(), M_PI); EXPECT_EQ(pi.GetLength(), 0); EXPECT_EQ(mipi.GetLength(), 0); EXPECT_DOUBLE_EQ(quad123.GetLength(), 1.5 * M_PI); EXPECT_EQ(fabs(quad23.GetLength()), M_PI); EXPECT_EQ(full.GetLength(), 2 * M_PI); EXPECT_LT(empty.GetLength(), 0); } TEST_F(S1IntervalTestBase, Complement) { EXPECT_TRUE(empty.Complement().is_full()); EXPECT_TRUE(full.Complement().is_empty()); EXPECT_TRUE(pi.Complement().is_full()); EXPECT_TRUE(mipi.Complement().is_full()); EXPECT_TRUE(zero.Complement().is_full()); EXPECT_TRUE(quad12.Complement().ApproxEquals(quad34)); EXPECT_TRUE(quad34.Complement().ApproxEquals(quad12)); EXPECT_TRUE(quad123.Complement().ApproxEquals(quad4)); } TEST_F(S1IntervalTestBase, Contains) { // Contains(double), InteriorContains(double) EXPECT_TRUE(!empty.Contains(0) && !empty.Contains(M_PI) && !empty.Contains(-M_PI)); EXPECT_TRUE(!empty.InteriorContains(M_PI) && !empty.InteriorContains(-M_PI)); EXPECT_TRUE(full.Contains(0) && full.Contains(M_PI) && full.Contains(-M_PI)); EXPECT_TRUE(full.InteriorContains(M_PI) && full.InteriorContains(-M_PI)); EXPECT_TRUE(quad12.Contains(0) && quad12.Contains(M_PI) && quad12.Contains(-M_PI)); EXPECT_TRUE(quad12.InteriorContains(M_PI_2) && !quad12.InteriorContains(0)); EXPECT_TRUE(!quad12.InteriorContains(M_PI) && !quad12.InteriorContains(-M_PI)); EXPECT_TRUE(quad23.Contains(M_PI_2) && quad23.Contains(-M_PI_2)); EXPECT_TRUE(quad23.Contains(M_PI) && quad23.Contains(-M_PI)); EXPECT_TRUE(!quad23.Contains(0)); EXPECT_TRUE(!quad23.InteriorContains(M_PI_2) && !quad23.InteriorContains(-M_PI_2)); EXPECT_TRUE(quad23.InteriorContains(M_PI) && quad23.InteriorContains(-M_PI)); EXPECT_TRUE(!quad23.InteriorContains(0)); EXPECT_TRUE(pi.Contains(M_PI) && pi.Contains(-M_PI) && !pi.Contains(0)); EXPECT_TRUE(!pi.InteriorContains(M_PI) && !pi.InteriorContains(-M_PI)); EXPECT_TRUE(mipi.Contains(M_PI) && mipi.Contains(-M_PI) && !mipi.Contains(0)); EXPECT_TRUE(!mipi.InteriorContains(M_PI) && !mipi.InteriorContains(-M_PI)); EXPECT_TRUE(zero.Contains(0) && !zero.InteriorContains(0)); } static void TestIntervalOps(const S1Interval& x, const S1Interval& y, string_view expected_relation, const S1Interval& expected_union, const S1Interval& expected_intersection) { // Test all of the interval operations on the given pair of intervals. // "expected_relation" is a sequence of "T" and "F" characters corresponding // to the expected results of Contains(), InteriorContains(), Intersects(), // and InteriorIntersects() respectively. EXPECT_EQ(x.Contains(y), expected_relation[0] == 'T'); EXPECT_EQ(x.InteriorContains(y), expected_relation[1] == 'T'); EXPECT_EQ(x.Intersects(y), expected_relation[2] == 'T'); EXPECT_EQ(x.InteriorIntersects(y), expected_relation[3] == 'T'); // bounds() returns a const reference to a member variable, so we need to // make a copy when invoking it on a temporary object. EXPECT_EQ(Vector2_d(x.Union(y).bounds()), expected_union.bounds()); EXPECT_EQ(Vector2_d(x.Intersection(y).bounds()), expected_intersection.bounds()); EXPECT_EQ(x.Contains(y), x.Union(y) == x); EXPECT_EQ(x.Intersects(y), !x.Intersection(y).is_empty()); if (y.lo() == y.hi()) { S1Interval r = x; r.AddPoint(y.lo()); EXPECT_EQ(r.bounds(), expected_union.bounds()); } } TEST_F(S1IntervalTestBase, IntervalOps) { // Contains(S1Interval), InteriorContains(S1Interval), // Intersects(), InteriorIntersects(), Union(), Intersection() TestIntervalOps(empty, empty, "TTFF", empty, empty); TestIntervalOps(empty, full, "FFFF", full, empty); TestIntervalOps(empty, zero, "FFFF", zero, empty); TestIntervalOps(empty, pi, "FFFF", pi, empty); TestIntervalOps(empty, mipi, "FFFF", mipi, empty); TestIntervalOps(full, empty, "TTFF", full, empty); TestIntervalOps(full, full, "TTTT", full, full); TestIntervalOps(full, zero, "TTTT", full, zero); TestIntervalOps(full, pi, "TTTT", full, pi); TestIntervalOps(full, mipi, "TTTT", full, mipi); TestIntervalOps(full, quad12, "TTTT", full, quad12); TestIntervalOps(full, quad23, "TTTT", full, quad23); TestIntervalOps(zero, empty, "TTFF", zero, empty); TestIntervalOps(zero, full, "FFTF", full, zero); TestIntervalOps(zero, zero, "TFTF", zero, zero); TestIntervalOps(zero, pi, "FFFF", S1Interval(0, M_PI), empty); TestIntervalOps(zero, pi2, "FFFF", quad1, empty); TestIntervalOps(zero, mipi, "FFFF", quad12, empty); TestIntervalOps(zero, mipi2, "FFFF", quad4, empty); TestIntervalOps(zero, quad12, "FFTF", quad12, zero); TestIntervalOps(zero, quad23, "FFFF", quad123, empty); TestIntervalOps(pi2, empty, "TTFF", pi2, empty); TestIntervalOps(pi2, full, "FFTF", full, pi2); TestIntervalOps(pi2, zero, "FFFF", quad1, empty); TestIntervalOps(pi2, pi, "FFFF", S1Interval(M_PI_2, M_PI), empty); TestIntervalOps(pi2, pi2, "TFTF", pi2, pi2); TestIntervalOps(pi2, mipi, "FFFF", quad2, empty); TestIntervalOps(pi2, mipi2, "FFFF", quad23, empty); TestIntervalOps(pi2, quad12, "FFTF", quad12, pi2); TestIntervalOps(pi2, quad23, "FFTF", quad23, pi2); TestIntervalOps(pi, empty, "TTFF", pi, empty); TestIntervalOps(pi, full, "FFTF", full, pi); TestIntervalOps(pi, zero, "FFFF", S1Interval(M_PI, 0), empty); TestIntervalOps(pi, pi, "TFTF", pi, pi); TestIntervalOps(pi, pi2, "FFFF", S1Interval(M_PI_2, M_PI), empty); TestIntervalOps(pi, mipi, "TFTF", pi, pi); TestIntervalOps(pi, mipi2, "FFFF", quad3, empty); TestIntervalOps(pi, quad12, "FFTF", S1Interval(0, M_PI), pi); TestIntervalOps(pi, quad23, "FFTF", quad23, pi); TestIntervalOps(mipi, empty, "TTFF", mipi, empty); TestIntervalOps(mipi, full, "FFTF", full, mipi); TestIntervalOps(mipi, zero, "FFFF", quad34, empty); TestIntervalOps(mipi, pi, "TFTF", mipi, mipi); TestIntervalOps(mipi, pi2, "FFFF", quad2, empty); TestIntervalOps(mipi, mipi, "TFTF", mipi, mipi); TestIntervalOps(mipi, mipi2, "FFFF", S1Interval(-M_PI, -M_PI_2), empty); TestIntervalOps(mipi, quad12, "FFTF", quad12, mipi); TestIntervalOps(mipi, quad23, "FFTF", quad23, mipi); TestIntervalOps(quad12, empty, "TTFF", quad12, empty); TestIntervalOps(quad12, full, "FFTT", full, quad12); TestIntervalOps(quad12, zero, "TFTF", quad12, zero); TestIntervalOps(quad12, pi, "TFTF", quad12, pi); TestIntervalOps(quad12, mipi, "TFTF", quad12, mipi); TestIntervalOps(quad12, quad12, "TFTT", quad12, quad12); TestIntervalOps(quad12, quad23, "FFTT", quad123, quad2); TestIntervalOps(quad12, quad34, "FFTF", full, quad12); TestIntervalOps(quad23, empty, "TTFF", quad23, empty); TestIntervalOps(quad23, full, "FFTT", full, quad23); TestIntervalOps(quad23, zero, "FFFF", quad234, empty); TestIntervalOps(quad23, pi, "TTTT", quad23, pi); TestIntervalOps(quad23, mipi, "TTTT", quad23, mipi); TestIntervalOps(quad23, quad12, "FFTT", quad123, quad2); TestIntervalOps(quad23, quad23, "TFTT", quad23, quad23); TestIntervalOps(quad23, quad34, "FFTT", quad234, S1Interval(-M_PI, -M_PI_2)); TestIntervalOps(quad1, quad23, "FFTF", quad123, S1Interval(M_PI_2, M_PI_2)); TestIntervalOps(quad2, quad3, "FFTF", quad23, mipi); TestIntervalOps(quad3, quad2, "FFTF", quad23, pi); TestIntervalOps(quad2, pi, "TFTF", quad2, pi); TestIntervalOps(quad2, mipi, "TFTF", quad2, mipi); TestIntervalOps(quad3, pi, "TFTF", quad3, pi); TestIntervalOps(quad3, mipi, "TFTF", quad3, mipi); TestIntervalOps(quad12, mid12, "TTTT", quad12, mid12); TestIntervalOps(mid12, quad12, "FFTT", quad12, mid12); S1Interval quad12eps(quad12.lo(), mid23.hi()); S1Interval quad2hi(mid23.lo(), quad12.hi()); TestIntervalOps(quad12, mid23, "FFTT", quad12eps, quad2hi); TestIntervalOps(mid23, quad12, "FFTT", quad12eps, quad2hi); // This test checks that the union of two disjoint intervals is the smallest // interval that contains both of them. Note that the center of "mid34" is // slightly CCW of -Pi/2 so that there is no ambiguity about the result. S1Interval quad412eps(mid34.lo(), quad12.hi()); TestIntervalOps(quad12, mid34, "FFFF", quad412eps, empty); TestIntervalOps(mid34, quad12, "FFFF", quad412eps, empty); S1Interval quadeps12(mid41.lo(), quad12.hi()); S1Interval quad1lo(quad12.lo(), mid41.hi()); TestIntervalOps(quad12, mid41, "FFTT", quadeps12, quad1lo); TestIntervalOps(mid41, quad12, "FFTT", quadeps12, quad1lo); S1Interval quad2lo(quad23.lo(), mid12.hi()); S1Interval quad3hi(mid34.lo(), quad23.hi()); S1Interval quadeps23(mid12.lo(), quad23.hi()); S1Interval quad23eps(quad23.lo(), mid34.hi()); S1Interval quadeps123(mid41.lo(), quad23.hi()); TestIntervalOps(quad23, mid12, "FFTT", quadeps23, quad2lo); TestIntervalOps(mid12, quad23, "FFTT", quadeps23, quad2lo); TestIntervalOps(quad23, mid23, "TTTT", quad23, mid23); TestIntervalOps(mid23, quad23, "FFTT", quad23, mid23); TestIntervalOps(quad23, mid34, "FFTT", quad23eps, quad3hi); TestIntervalOps(mid34, quad23, "FFTT", quad23eps, quad3hi); TestIntervalOps(quad23, mid41, "FFFF", quadeps123, empty); TestIntervalOps(mid41, quad23, "FFFF", quadeps123, empty); } TEST_F(S1IntervalTestBase, AddPoint) { S1Interval r = empty; r.AddPoint(0); EXPECT_EQ(r, zero); r = empty; r.AddPoint(M_PI); EXPECT_EQ(r, pi); r = empty; r.AddPoint(-M_PI); EXPECT_EQ(r, mipi); r = empty; r.AddPoint(M_PI); r.AddPoint(-M_PI); EXPECT_EQ(r, pi); r = empty; r.AddPoint(-M_PI); r.AddPoint(M_PI); EXPECT_EQ(r, mipi); r = empty; r.AddPoint(mid12.lo()); r.AddPoint(mid12.hi()); EXPECT_EQ(r, mid12); r = empty; r.AddPoint(mid23.lo()); r.AddPoint(mid23.hi()); EXPECT_EQ(r, mid23); r = quad1; r.AddPoint(-0.9*M_PI); r.AddPoint(-M_PI_2); EXPECT_EQ(r, quad123); r = full; r.AddPoint(0); EXPECT_TRUE(r.is_full()); r = full; r.AddPoint(M_PI); EXPECT_TRUE(r.is_full()); r = full; r.AddPoint(-M_PI); EXPECT_TRUE(r.is_full()); } TEST_F(S1IntervalTestBase, Project) { S1Interval r(-M_PI, -M_PI); EXPECT_EQ(M_PI, r.Project(-M_PI)); EXPECT_EQ(M_PI, r.Project(0)); r = S1Interval(0, M_PI); EXPECT_EQ(0.1, r.Project(0.1)); EXPECT_EQ(0, r.Project(-M_PI_2 + 1e-15)); EXPECT_EQ(M_PI, r.Project(-M_PI_2 - 1e-15)); r = S1Interval(M_PI - 0.1, -M_PI + 0.1); EXPECT_EQ(M_PI, r.Project(M_PI)); EXPECT_EQ(M_PI - 0.1, r.Project(1e-15)); EXPECT_EQ(-M_PI + 0.1, r.Project(-1e-15)); EXPECT_EQ(0, S1Interval::Full().Project(0)); EXPECT_EQ(M_PI, S1Interval::Full().Project(M_PI)); EXPECT_EQ(M_PI, S1Interval::Full().Project(-M_PI)); } TEST_F(S1IntervalTestBase, FromPointPair) { EXPECT_EQ(S1Interval::FromPointPair(-M_PI, M_PI), pi); EXPECT_EQ(S1Interval::FromPointPair(M_PI, -M_PI), pi); EXPECT_EQ(S1Interval::FromPointPair(mid34.hi(), mid34.lo()), mid34); EXPECT_EQ(S1Interval::FromPointPair(mid23.lo(), mid23.hi()), mid23); } TEST_F(S1IntervalTestBase, Expanded) { EXPECT_EQ(empty.Expanded(1), empty); EXPECT_EQ(full.Expanded(1), full); EXPECT_EQ(zero.Expanded(1), S1Interval(-1, 1)); EXPECT_EQ(mipi.Expanded(0.01), S1Interval(M_PI - 0.01, -M_PI + 0.01)); EXPECT_EQ(pi.Expanded(27), full); EXPECT_EQ(pi.Expanded(M_PI_2), quad23); EXPECT_EQ(pi2.Expanded(M_PI_2), quad12); EXPECT_EQ(mipi2.Expanded(M_PI_2), quad34); EXPECT_EQ(empty.Expanded(-1), empty); EXPECT_EQ(full.Expanded(-1), full); EXPECT_EQ(quad123.Expanded(-27), empty); EXPECT_EQ(quad234.Expanded(-27), empty); EXPECT_EQ(quad123.Expanded(-M_PI_2), quad2); EXPECT_EQ(quad341.Expanded(-M_PI_2), quad4); EXPECT_EQ(quad412.Expanded(-M_PI_2), quad1); } TEST_F(S1IntervalTestBase, ApproxEquals) { // Choose two values kLo and kHi such that it's okay to shift an endpoint by // kLo (i.e., the resulting interval is equivalent) but not by kHi. static const double kLo = 4 * DBL_EPSILON; // < max_error default static const double kHi = 6 * DBL_EPSILON; // > max_error default // Empty intervals. EXPECT_TRUE(empty.ApproxEquals(empty)); EXPECT_TRUE(zero.ApproxEquals(empty) && empty.ApproxEquals(zero)); EXPECT_TRUE(pi.ApproxEquals(empty) && empty.ApproxEquals(pi)); EXPECT_TRUE(mipi.ApproxEquals(empty) && empty.ApproxEquals(mipi)); EXPECT_FALSE(empty.ApproxEquals(full)); EXPECT_TRUE(empty.ApproxEquals(S1Interval(1, 1 + 2*kLo))); EXPECT_FALSE(empty.ApproxEquals(S1Interval(1, 1 + 2*kHi))); EXPECT_TRUE(S1Interval(M_PI - kLo, -M_PI + kLo).ApproxEquals(empty)); // Full intervals. EXPECT_TRUE(full.ApproxEquals(full)); EXPECT_FALSE(full.ApproxEquals(empty)); EXPECT_FALSE(full.ApproxEquals(zero)); EXPECT_FALSE(full.ApproxEquals(pi)); EXPECT_TRUE(full.ApproxEquals(S1Interval(kLo, -kLo))); EXPECT_FALSE(full.ApproxEquals(S1Interval(2*kHi, 0))); EXPECT_TRUE(S1Interval(-M_PI + kLo, M_PI - kLo).ApproxEquals(full)); EXPECT_FALSE(S1Interval(-M_PI, M_PI - 2*kHi).ApproxEquals(full)); // Singleton intervals. EXPECT_TRUE(pi.ApproxEquals(pi) && mipi.ApproxEquals(pi)); EXPECT_TRUE(pi.ApproxEquals(S1Interval(M_PI - kLo, M_PI - kLo))); EXPECT_FALSE(pi.ApproxEquals(S1Interval(M_PI - kHi, M_PI - kHi))); EXPECT_TRUE(pi.ApproxEquals(S1Interval(M_PI - kLo, -M_PI + kLo))); EXPECT_FALSE(pi.ApproxEquals(S1Interval(M_PI - kHi, -M_PI))); EXPECT_FALSE(zero.ApproxEquals(pi)); EXPECT_TRUE(pi.Union(mid12).Union(zero).ApproxEquals(quad12)); EXPECT_TRUE(quad2.Intersection(quad3).ApproxEquals(pi)); EXPECT_TRUE(quad3.Intersection(quad2).ApproxEquals(pi)); // Intervals whose corresponding endpoints are nearly the same but where the // endpoints are in opposite order (i.e., inverted intervals). EXPECT_FALSE(S1Interval(0, kLo).ApproxEquals(S1Interval(kLo, 0))); EXPECT_FALSE(S1Interval(M_PI - 0.5 * kLo, -M_PI + 0.5 * kLo). ApproxEquals(S1Interval(-M_PI + 0.5 * kLo, M_PI - 0.5 * kLo))); // Other intervals. EXPECT_TRUE(S1Interval(1 - kLo, 2 + kLo).ApproxEquals(S1Interval(1, 2))); EXPECT_TRUE(S1Interval(1 + kLo, 2 - kLo).ApproxEquals(S1Interval(1, 2))); EXPECT_TRUE(S1Interval(2 - kLo, 1 + kLo).ApproxEquals(S1Interval(2, 1))); EXPECT_TRUE(S1Interval(2 + kLo, 1 - kLo).ApproxEquals(S1Interval(2, 1))); EXPECT_FALSE(S1Interval(1 - kHi, 2 + kLo).ApproxEquals(S1Interval(1, 2))); EXPECT_FALSE(S1Interval(1 + kHi, 2 - kLo).ApproxEquals(S1Interval(1, 2))); EXPECT_FALSE(S1Interval(2 - kHi, 1 + kLo).ApproxEquals(S1Interval(2, 1))); EXPECT_FALSE(S1Interval(2 + kHi, 1 - kLo).ApproxEquals(S1Interval(2, 1))); EXPECT_FALSE(S1Interval(1 - kLo, 2 + kHi).ApproxEquals(S1Interval(1, 2))); EXPECT_FALSE(S1Interval(1 + kLo, 2 - kHi).ApproxEquals(S1Interval(1, 2))); EXPECT_FALSE(S1Interval(2 - kLo, 1 + kHi).ApproxEquals(S1Interval(2, 1))); EXPECT_FALSE(S1Interval(2 + kLo, 1 - kHi).ApproxEquals(S1Interval(2, 1))); } TEST_F(S1IntervalTestBase, OperatorEquals) { EXPECT_EQ(empty, empty); EXPECT_EQ(full, full); EXPECT_NE(full, empty); } TEST_F(S1IntervalTestBase, GetDirectedHausdorffDistance) { EXPECT_FLOAT_EQ(0.0, empty.GetDirectedHausdorffDistance(empty)); EXPECT_FLOAT_EQ(0.0, empty.GetDirectedHausdorffDistance(mid12)); EXPECT_FLOAT_EQ(M_PI, mid12.GetDirectedHausdorffDistance(empty)); EXPECT_EQ(0.0, quad12.GetDirectedHausdorffDistance(quad123)); S1Interval in(3.0, -3.0); // an interval whose complement center is 0. EXPECT_FLOAT_EQ(3.0, S1Interval(-0.1, 0.2).GetDirectedHausdorffDistance(in)); EXPECT_FLOAT_EQ(3.0 - 0.1, S1Interval(0.1, 0.2).GetDirectedHausdorffDistance(in)); EXPECT_FLOAT_EQ(3.0 - 0.1, S1Interval(-0.2, -0.1).GetDirectedHausdorffDistance(in)); } TEST(S1Interval, SupportsAbslHash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ S1Interval::Empty(), S1Interval::Full(), S1Interval(0, 1), S1Interval(-1, 1), S1Interval(M_PI / 2, M_PI), S1Interval(-M_PI, -M_PI / 2), S1Interval(M_PI - 0.1, -M_PI + 0.1), // inverted (wraps around) })); } src/s2/s2boolean_operation.cc000066400000000000000000003574431524103652300164650ustar00rootroot00000000000000// Copyright 2017 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) // // Boolean operations are implemented by constructing the boundary of the // result and then using S2Builder to assemble the edges. The boundary is // obtained by clipping each of the two input regions to the interior or // exterior of the other region. For example, to compute the union of A and // B, we clip the boundary of A to the exterior of B and the boundary of B to // the exterior of A; the resulting set of edges defines the union of the two // regions. // // We use exact predicates, but inexact constructions (e.g. computing the // intersection point of two edges). Nevertheless, the following algorithm is // guaranteed to be 100% robust, in that the computed boundary stays within a // small tolerance (snap_radius + S2::kIntersectionError) of the exact // result, and also preserves the correct topology (i.e., no crossing edges). // // Unfortunately this robustness cannot quite be achieved using the strategy // outlined above (clipping the two input regions and assembling the // resulting edges). Since computed intersection points are not exact, the // input geometry passed to S2Builder might contain self-intersections, and // these self-intersections cannot be eliminated reliably by snap rounding. // // So instead, we pass S2Builder the entire set of input edges where at least // some portion of each edge belongs to the output boundary. We allow // S2Builder to compute the intersection points and snap round the edges // (which it does in a way that is guaranteed to preserve the input topology). // Then once this is finished, we remove the portions of each edge that would // have been clipped if we had done the clipping first. This step only // involves deciding whether to keep or discard each edge in the output, since // all intersection points have already been resolved, and therefore there is // no risk of creating new self-intersections. // // This is implemented using the following classes: // // - S2BooleanOperation::Impl: the top-level class that clips each of // the two regions to the other region. // // - CrossingProcessor: a class that processes edge crossings and maintains // the necessary state in order to clip the boundary // of one region to the interior or exterior of the // other region. // // - EdgeClippingLayer: an S2Builder::Layer that removes graph edges that // correspond to clipped portions of input edges, and // passes the result to another layer for assembly. // // - GraphEdgeClipper: a helper class that does the actual work of the // EdgeClippingLayer. #include "s2/s2boolean_operation.h" #include #include #include #include #include #include #include #include #include #include #include "absl/base/nullability.h" #include "absl/cleanup/cleanup.h" #include "absl/container/btree_map.h" #include "absl/container/flat_hash_map.h" #include "absl/container/inlined_vector.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "s2/id_set_lexicon.h" #include "s2/s1angle.h" #include "s2/s2builder.h" #include "s2/s2builder_graph.h" #include "s2/s2builder_layer.h" #include "s2/s2builderutil_snap_functions.h" #include "s2/s2cell_id.h" #include "s2/s2contains_point_query.h" #include "s2/s2crossing_edge_query.h" #include "s2/s2edge_crossings.h" #include "s2/s2error.h" #include "s2/s2measures.h" #include "s2/s2memory_tracker.h" #include "s2/s2point.h" #include "s2/s2predicates.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2shape_index_measures.h" #include "s2/s2shapeutil_shape_edge.h" #include "s2/s2shapeutil_shape_edge_id.h" #include "s2/s2shapeutil_visit_crossing_edge_pairs.h" #include "s2/value_lexicon.h" namespace { // Anonymous namespace for helper classes. using absl::flat_hash_map; using absl::string_view; using std::lower_bound; using std::make_pair; using std::make_unique; using std::max; using std::min; using std::pair; using std::swap; using std::unique_ptr; using std::vector; using EdgeType = S2Builder::EdgeType; using SnapFunction = S2Builder::SnapFunction; using GraphOptions = S2Builder::GraphOptions; using DegenerateEdges = GraphOptions::DegenerateEdges; using DuplicateEdges = GraphOptions::DuplicateEdges; using SiblingPairs = GraphOptions::SiblingPairs; using Graph = S2Builder::Graph; using EdgeId = Graph::EdgeId; using VertexId = Graph::VertexId; using InputEdgeId = Graph::InputEdgeId; using InputEdgeIdSetId = Graph::InputEdgeIdSetId; using PolygonModel = S2BooleanOperation::PolygonModel; using PolylineModel = S2BooleanOperation::PolylineModel; using Precision = S2BooleanOperation::Precision; // A collection of special InputEdgeIds that allow the GraphEdgeClipper state // modifications to be inserted into the list of edge crossings. static const InputEdgeId kSetInside = -1; static const InputEdgeId kSetInvertB = -2; static const InputEdgeId kSetReverseA = -3; // CrossingInputEdge represents an input edge B that crosses some other input // edge A. It stores the input edge id of edge B and also whether it crosses // edge A from left to right (or vice versa). class CrossingInputEdge { public: // Indicates that input edge "input_id" crosses another edge (from left to // right if "left_to_right" is true). CrossingInputEdge(InputEdgeId input_id, bool left_to_right) : left_to_right_(left_to_right), input_id_(input_id) { } InputEdgeId input_id() const { return input_id_; } bool left_to_right() const { return left_to_right_; } bool operator<(const CrossingInputEdge& other) const { return input_id_ < other.input_id_; } bool operator<(const InputEdgeId& other) const { return input_id_ < other; } private: bool left_to_right_ : 1; InputEdgeId input_id_ : 31; }; // InputEdgeCrossings represents all pairs of intersecting input edges and // also certain GraphEdgeClipper state modifications (kSetInside, etc). // It is sorted lexicographically except for entries representing state // modifications, which are sorted by the first InputEdgeId only. using InputEdgeCrossings = vector>; // Given two input edges A and B that intersect, suppose that A maps to a // chain of snapped edges A_0, A_1, ..., A_m and B maps to a chain of snapped // edges B_0, B_1, ..., B_n. CrossingGraphEdge represents an edge from chain // B that shares a vertex with chain A. It is used as a temporary data // representation while processing chain A. The arguments are: // // "id" - the Graph::EdgeId of an edge from chain B. // "a_index" - the index of the vertex (A_i) that is shared with chain A. // "outgoing" - true if the shared vertex is the first vertex of the B edge. // "dst" - the Graph::VertexId of the vertex that is not shared with chain A. // // Note that if an edge from the B chain shares both vertices with the A // chain, there will be two entries: an outgoing edge that treats its first // vertex as being shared, and an incoming edge that treats its second vertex // as being shared. struct CrossingGraphEdge { CrossingGraphEdge(EdgeId _id, int _a_index, bool _outgoing, VertexId _dst) : id(_id), a_index(_a_index), outgoing(_outgoing), dst(_dst) { } EdgeId id; int a_index; bool outgoing; VertexId dst; }; using CrossingGraphEdgeVector = absl::InlinedVector; // Returns a vector of EdgeIds sorted by input edge id. When more than one // output edge has the same input edge id (i.e., the input edge snapped to a // chain of edges), the edges are sorted so that they form a directed edge // chain. // // This function could possibly be moved to S2Builder::Graph, but note that // it has special requirements. Namely, duplicate edges and sibling pairs // must be kept in order to ensure that every output edge corresponds to // exactly one input edge. (See also S2Builder::Graph::GetInputEdgeOrder.) static vector GetInputEdgeChainOrder( const Graph& g, absl::Span input_ids) { ABSL_DCHECK(g.options().edge_type() == EdgeType::DIRECTED); ABSL_DCHECK(g.options().duplicate_edges() == DuplicateEdges::KEEP); ABSL_DCHECK(g.options().sibling_pairs() == SiblingPairs::KEEP); // First, sort the edges so that the edges corresponding to each input edge // are consecutive. (Each input edge was snapped to a chain of output // edges, or two chains in the case of undirected input edges.) vector order = g.GetInputEdgeOrder(input_ids); // Now sort the group of edges corresponding to each input edge in edge // chain order (e.g. AB, BC, CD). vector> vmap; // Map from source vertex to edge id. vector indegree(g.num_vertices()); // Restricted to current input edge. for (size_t end, begin = 0; begin < order.size(); begin = end) { // Gather the edges that came from a single input edge. InputEdgeId input_id = input_ids[order[begin]]; for (end = begin; end < order.size(); ++end) { if (input_ids[order[end]] != input_id) break; } if (end - begin == 1) continue; // Build a map from the source vertex of each edge to its edge id, // and also compute the indegree at each vertex considering only the edges // that came from the current input edge. for (size_t i = begin; i < end; ++i) { EdgeId e = order[i]; vmap.push_back(make_pair(g.edge(e).first, e)); indegree[g.edge(e).second] += 1; } std::sort(vmap.begin(), vmap.end()); // Find the starting edge for building the edge chain. EdgeId next = g.num_edges(); for (size_t i = begin; i < end; ++i) { EdgeId e = order[i]; if (indegree[g.edge(e).first] == 0) next = e; } // Build the edge chain. for (size_t i = begin;;) { order[i] = next; VertexId v = g.edge(next).second; indegree[v] = 0; // Clear as we go along. if (++i == end) break; auto out = lower_bound(vmap.begin(), vmap.end(), make_pair(v, 0)); ABSL_DCHECK_EQ(v, out->first); next = out->second; } vmap.clear(); } return order; } // Given a set of clipping instructions encoded as an InputEdgeCrossings, // GraphEdgeClipper determines which graph edges correspond to clipped // portions of input edges and removes them. // // The clipping model is as follows. The input consists of edge chains. The // clipper maintains an "inside" boolean state as it clips each chain, and // toggles this state whenever an input edge is crossed. Any edges that are // deemed to be "outside" after clipping are removed. // // The "inside" state can be reset when necessary (e.g., when jumping to the // start of a new chain) by adding a special crossing marked kSetInside. // There are also two other special "crossings" that modify the clipping // parameters: kSetInvertB specifies that edges should be clipped to the // exterior of the other region, and kSetReverseA specifies that edges should // be reversed before emitting them (which is needed to implement difference // operations). class GraphEdgeClipper { public: // "input_dimensions" is a vector specifying the dimension of each input // edge (0, 1, or 2). "input_crossings" is the set of all crossings to be // used when clipping the edges of "g", sorted in lexicographic order. // // The clipped set of edges and their corresponding set of input edge ids // are returned in "new_edges" and "new_input_edge_ids". (These can be used // to construct a new S2Builder::Graph.) GraphEdgeClipper(const Graph& g, const vector& input_dimensions, const InputEdgeCrossings& input_crossings, vector* new_edges, vector* new_input_edge_ids); void Run(); private: void AddEdge(Graph::Edge edge, InputEdgeId input_edge_id); void GatherIncidentEdges(absl::Span a, int ai, absl::Span b_input_edges, vector* b_edges) const; int GetCrossedVertexIndex(absl::Span a, const CrossingGraphEdgeVector& b, bool left_to_right) const; int GetVertexRank(const CrossingGraphEdge& e) const; bool EdgeChainOnLeft(absl::Span a, EdgeId b_first, EdgeId b_last) const; const Graph& g_; Graph::VertexInMap in_; Graph::VertexOutMap out_; const vector& input_dimensions_; const InputEdgeCrossings& input_crossings_; vector* new_edges_; vector* new_input_edge_ids_; // Every graph edge is associated with exactly one input edge in our case, // which means that we can declare g_.input_edge_id_set_ids() as a vector of // InputEdgeIds rather than a vector of InputEdgeIdSetIds. (This also takes // advantage of the fact that IdSetLexicon represents a singleton set as the // value of its single element.) const vector& input_ids_; vector order_; // Graph edges sorted in input edge id order. vector rank_; // The rank of each graph edge within order_. }; GraphEdgeClipper::GraphEdgeClipper(const Graph& g, const vector& input_dimensions, const InputEdgeCrossings& input_crossings, vector* new_edges, vector* new_input_edge_ids) : g_(g), in_(g), out_(g), input_dimensions_(input_dimensions), input_crossings_(input_crossings), new_edges_(new_edges), new_input_edge_ids_(new_input_edge_ids), input_ids_(g.input_edge_id_set_ids()), order_(GetInputEdgeChainOrder(g_, input_ids_)), rank_(order_.size()) { for (size_t i = 0; i < order_.size(); ++i) { rank_[order_[i]] = i; } // new_edges_ is obtained by filtering the graph edges and therefore the // number of graph edges is an upper bound on its size. new_edges_->reserve(g_.num_edges()); new_input_edge_ids_->reserve(g_.num_edges()); } inline void GraphEdgeClipper::AddEdge(Graph::Edge edge, InputEdgeId input_edge_id) { new_edges_->push_back(edge); new_input_edge_ids_->push_back(input_edge_id); } void GraphEdgeClipper::Run() { // Declare vectors here and reuse them to avoid reallocation. vector a_vertices; vector a_num_crossings; vector a_isolated; vector b_input_edges; vector b_edges; bool inside = false; bool invert_b = false; bool reverse_a = false; auto next = input_crossings_.begin(); for (size_t i = 0; i < order_.size(); ++i) { // For the current input edge (the "A" input edge), gather all the input // edges that cross it (the "B" input edges). InputEdgeId a_input_id = input_ids_[order_[i]]; const Graph::Edge& edge0 = g_.edge(order_[i]); b_input_edges.clear(); for (; next != input_crossings_.end(); ++next) { if (next->first != a_input_id) break; if (next->second.input_id() >= 0) { b_input_edges.push_back(next->second); } else if (next->second.input_id() == kSetInside) { inside = next->second.left_to_right(); } else if (next->second.input_id() == kSetInvertB) { invert_b = next->second.left_to_right(); } else { ABSL_DCHECK_EQ(next->second.input_id(), kSetReverseA); reverse_a = next->second.left_to_right(); } } // Optimization for degenerate edges. // TODO(ericv): If the output layer for this edge dimension specifies // DegenerateEdges::DISCARD, then remove the edge here. if (edge0.first == edge0.second) { inside ^= (b_input_edges.size() & 1); AddEdge(edge0, a_input_id); continue; } // Optimization for the case where there are no crossings. if (b_input_edges.empty()) { // In general the caller only passes edges that are part of the output // (i.e., we could ABSL_DCHECK(inside) here). The one exception is for // polyline/polygon operations, where the polygon edges are needed to // compute the polyline output but are not emitted themselves. if (inside) { AddEdge(reverse_a ? Graph::reverse(edge0) : edge0, a_input_id); } continue; } // Walk along the chain of snapped edges for input edge A, and at each // vertex collect all the incident edges that belong to one of the // crossing edge chains (the "B" input edges). a_vertices.clear(); a_vertices.push_back(edge0.first); b_edges.clear(); b_edges.resize(b_input_edges.size()); GatherIncidentEdges(a_vertices, 0, b_input_edges, &b_edges); for (; i < order_.size() && input_ids_[order_[i]] == a_input_id; ++i) { a_vertices.push_back(g_.edge(order_[i]).second); GatherIncidentEdges(a_vertices, a_vertices.size() - 1, b_input_edges, &b_edges); } --i; // Now for each B edge chain, decide which vertex of the A chain it // crosses, and keep track of the sum of signed crossings at each A // vertex. The sign of a crossing depends on whether the other edge // crosses from left to right or right to left. // // This would not be necessary if all calculations were done in exact // arithmetic, because crossings would have strictly alternating signs. // But because we have already snapped the result, some crossing locations // are ambiguous, and GetCrossedVertexIndex() handles this by choosing a // candidate vertex arbitrarily. The end result is that rarely, we may // see two crossings in a row with the same sign. We correct for this by // adding extra output edges that essentially link up the crossings in the // correct (alternating sign) order. Compared to the "correct" behavior, // the only difference is that we have added some extra sibling pairs // (consisting of an edge and its corresponding reverse edge) which do not // affect the result. a_num_crossings.clear(); a_num_crossings.resize(a_vertices.size()); a_isolated.clear(); a_isolated.resize(a_vertices.size()); for (size_t bi = 0; bi < b_input_edges.size(); ++bi) { bool left_to_right = b_input_edges[bi].left_to_right(); int a_index = GetCrossedVertexIndex(a_vertices, b_edges[bi], left_to_right); if (a_index >= 0) { // Keep track of the number of signed crossings (see above). bool is_line = input_dimensions_[b_input_edges[bi].input_id()] == 1; int sign = is_line ? 0 : (left_to_right == invert_b) ? -1 : 1; a_num_crossings[a_index] += sign; // Any polyline or polygon vertex that has at least one crossing but no // adjacent emitted edge may be emitted as an isolated vertex. a_isolated[a_index] = true; } else { // TODO(b/112043775): fix this condition. ABSL_LOG(DFATAL) << "Failed to get crossed vertex index."; } } // Finally, we iterate through the A edge chain, keeping track of the // number of signed crossings as we go along. The "multiplicity" is // defined as the cumulative number of signed crossings, and indicates how // many edges should be output (and in which direction) in order to link // up the edge crossings in the correct order. (The multiplicity is // almost always either 0 or 1 except in very rare cases.) int multiplicity = inside + a_num_crossings[0]; for (size_t ai = 1; ai < a_vertices.size(); ++ai) { if (multiplicity != 0) { a_isolated[ai - 1] = a_isolated[ai] = false; } int edge_count = reverse_a ? -multiplicity : multiplicity; // Output any forward edges required. for (int i = 0; i < edge_count; ++i) { AddEdge(Graph::Edge(a_vertices[ai - 1], a_vertices[ai]), a_input_id); } // Output any reverse edges required. for (int i = edge_count; i < 0; ++i) { AddEdge(Graph::Edge(a_vertices[ai], a_vertices[ai - 1]), a_input_id); } multiplicity += a_num_crossings[ai]; } // Multiplicities other than 0 or 1 can only occur in the edge interior. ABSL_DCHECK(multiplicity == 0 || multiplicity == 1); inside = (multiplicity != 0); // Output any isolated polyline vertices. // TODO(ericv): Only do this if an output layer wants degenerate edges. if (input_dimensions_[a_input_id] != 0) { for (size_t ai = 0; ai < a_vertices.size(); ++ai) { if (a_isolated[ai]) { AddEdge(Graph::Edge(a_vertices[ai], a_vertices[ai]), a_input_id); } } } } } // Given the vertices of the snapped edge chain for an input edge A and the // set of input edges B that cross input edge A, this method gathers all of // the snapped edges of B that are incident to a given snapped vertex of A. // The incident edges for each input edge of B are appended to a separate // output vector. (A and B can refer to either the input edge or the // corresponding snapped edge chain.) void GraphEdgeClipper::GatherIncidentEdges( absl::Span a, int ai, absl::Span b_input_edges, vector* b_edges) const { // Examine all of the edges incident to the given vertex of A. If any edge // comes from a B input edge, append it to the appropriate vector. ABSL_DCHECK_EQ(b_input_edges.size(), b_edges->size()); for (EdgeId e : in_.edge_ids(a[ai])) { InputEdgeId id = input_ids_[e]; auto it = lower_bound(b_input_edges.begin(), b_input_edges.end(), id); if (it != b_input_edges.end() && it->input_id() == id) { auto& edges = (*b_edges)[it - b_input_edges.begin()]; edges.push_back(CrossingGraphEdge(e, ai, false, g_.edge(e).first)); } } for (EdgeId e : out_.edge_ids(a[ai])) { InputEdgeId id = input_ids_[e]; auto it = lower_bound(b_input_edges.begin(), b_input_edges.end(), id); if (it != b_input_edges.end() && it->input_id() == id) { auto& edges = (*b_edges)[it - b_input_edges.begin()]; edges.push_back(CrossingGraphEdge(e, ai, true, g_.edge(e).second)); } } } // Returns the "vertex rank" of the shared vertex associated with the given // CrossingGraphEdge. Recall that graph edges are sorted in input edge order, // and that the rank of an edge is its position in this order (rank_[e]). // VertexRank(e) is defined such that VertexRank(e.src) == rank_[e] and // VertexRank(e.dst) == rank_[e] + 1. Note that the concept of "vertex rank" // is only defined within a single edge chain (since different edge chains can // have overlapping vertex ranks). int GraphEdgeClipper::GetVertexRank(const CrossingGraphEdge& e) const { return rank_[e.id] + !e.outgoing; } // Given an edge chain A that is crossed by another edge chain B (where // "left_to_right" indicates whether B crosses A from left to right), this // method decides which vertex of A the crossing takes place at. The // parameters are the vertices of the A chain ("a") and the set of edges in // the B chain ("b") that are incident to vertices of A. The B chain edges // are sorted in increasing order of (a_index, outgoing) tuple. int GraphEdgeClipper::GetCrossedVertexIndex(absl::Span a, const CrossingGraphEdgeVector& b, bool left_to_right) const { if (a.empty() || b.empty()) { ABSL_LOG(DFATAL) << "GraphEdgeClipper::GetCrossedVertexIndex called with " << a.size() << " vertex ids and " << b.size() << " crossing graph edges."; return -1; } // TODO(b/316414071): Rework this algorithm. // The reason this calculation is tricky is that after snapping, the A and B // chains may meet and separate several times. For example, if B crosses A // from left to right, then B may touch A, make an excursion to the left of // A, come back to A, then make an excursion to the right of A and come back // to A again, like this: // // *--B--*-\ /-*-\ // B-\ /-B B-\ 6 7 8 9 // *--A--*--A--*-A,B-*--A--*--A--*-A,B-*--A--*--A--*-A,B-* // 0 1 2 3 4 5 \-B B-/ // \-*-/ // // (where "*" is a vertex, and "A" and "B" are edge labels). Note that B // may also follow A for one or more edges whenever they touch (e.g. between // vertices 2 and 3). In this case the only vertices of A where the // crossing could take place are 5 and 6, i.e. after all excursions of B to // the left of A, and before all excursions of B to the right of A. // // Other factors to consider are that the portion of B before and/or after // the crossing may be degenerate, and some or all of the B edges may be // reversed relative to the A edges. // First, check whether edge A is degenerate. int n = a.size(); if (n == 1) return 0; // If edge chain B is incident to only one vertex of A, we're done. if (b[0].a_index == b.back().a_index) return b[0].a_index; // Determine whether the B chain visits the first and last vertices that it // shares with the A chain in the same order or the reverse order. This is // only needed to implement one special case (see below). bool b_reversed = GetVertexRank(b[0]) > GetVertexRank(b.back()); // Examine each incident B edge and use it to narrow the range of positions // where the crossing could occur in the B chain. Vertex positions are // represented as a range [lo, hi] of vertex ranks in the B chain (see // GetVertexRank). // // Note that if an edge of B is incident to the first or last vertex of A, // we can't test which side of the A chain it is on. (An s2pred::Sign test // doesn't work; e.g. if the B edge is XY and the first edge of A is YZ, // then snapping can change the sign of XYZ while maintaining topological // guarantees.) There can be up to 4 such edges (one incoming and one // outgoing edge at each endpoint of A). Two of these edges logically // extend past the end of the A chain and place no restrictions on the // crossing vertex. The other two edges define the ends of the subchain // where B shares vertices with A. We save these edges in order to handle a // special case (see below). int lo = -1, hi = order_.size(); // Vertex ranks of acceptable crossings EdgeId b_first = -1, b_last = -1; // "b" subchain connecting "a" endpoints for (const auto& e : b) { int ai = e.a_index; if (ai == 0) { if (e.outgoing != b_reversed && e.dst != a[1]) b_first = e.id; } else if (ai == n - 1) { if (e.outgoing == b_reversed && e.dst != a[n - 2]) b_last = e.id; } else { // This B edge is incident to an interior vertex of the A chain. First // check whether this edge is identical (or reversed) to an edge in the // A chain, in which case it does not create any restrictions. if (e.dst == a[ai - 1] || e.dst == a[ai + 1]) continue; // Otherwise we can test which side of the A chain the edge lies on. bool on_left = s2pred::OrderedCCW(g_.vertex(a[ai + 1]), g_.vertex(e.dst), g_.vertex(a[ai - 1]), g_.vertex(a[ai])); // Every B edge that is incident to an interior vertex of the A chain // places some restriction on where the crossing vertex could be. if (left_to_right == on_left) { // This is a pre-crossing edge, so the crossing cannot be before the // destination vertex of this edge. (For example, the input B edge // crosses the input A edge from left to right and this edge of the B // chain is to the left of the A chain.) lo = max(lo, rank_[e.id] + 1); } else { // This is a post-crossing edge, so the crossing cannot be after the // source vertex of this edge. hi = min(hi, rank_[e.id]); } } } // There is one special case. If a subchain of B connects the first and // last vertices of A, then together with the edges of A this forms a loop // whose orientation can be tested to determine whether B is on the left or // right side of A. This is only possible (and only necessary) if the B // subchain does not include any interior vertices of A, since otherwise the // B chain might cross from one side of A to the other. // // Note that it would be possible to avoid this test in some situations by // checking whether either endpoint of the A chain has two incident B edges, // in which case we could check which side of the B chain the A edge is on // and use this to limit the possible crossing locations. if (b_first >= 0 && b_last >= 0) { // Swap the edges if necessary so that they are in B chain order. if (b_reversed) swap(b_first, b_last); // The B subchain connects the first and last vertices of A. We test // whether the chain includes any interior vertices of A by iterating // through the incident B edges again, looking for ones that belong to // the B subchain and are not incident to the first or last vertex of A. bool has_interior_vertex = false; for (const auto& e : b) { if (e.a_index > 0 && e.a_index < n - 1 && rank_[e.id] >= rank_[b_first] && rank_[e.id] <= rank_[b_last]) { has_interior_vertex = true; break; } } if (!has_interior_vertex) { // The B subchain is not incident to any interior vertex of A. bool on_left = EdgeChainOnLeft(a, b_first, b_last); if (left_to_right == on_left) { lo = max(lo, rank_[b_last] + 1); } else { hi = min(hi, rank_[b_first]); } } } // Otherwise we choose the smallest shared VertexId in the acceptable range, // in order to ensure that both chains choose the same crossing vertex. int best = -1; ABSL_DCHECK_LE(lo, hi); for (const auto& e : b) { int ai = e.a_index; int vrank = GetVertexRank(e); if (vrank >= lo && vrank <= hi && (best < 0 || a[ai] < a[best])) { best = ai; } } return best; } // Given edge chains A and B that form a loop (after possibly reversing the // direction of chain B), returns true if chain B is to the left of chain A. // Chain A is given as a sequence of vertices, while chain B is specified as // the first and last edges of the chain. bool GraphEdgeClipper::EdgeChainOnLeft(absl::Span a, EdgeId b_first, EdgeId b_last) const { // TODO(b/317065708): Rather than collecting all the vertices in a list, // accumulate the angle. // Gather all the interior vertices of the B subchain. vector loop; for (int i = rank_[b_first]; i < rank_[b_last]; ++i) { loop.push_back(g_.edge(order_[i]).second); } // Possibly reverse the chain so that it forms a loop when "a" is appended. if (g_.edge(b_last).second != a[0]) std::reverse(loop.begin(), loop.end()); loop.insert(loop.end(), a.begin(), a.end()); // Duplicate the first two vertices to simplify vertex indexing. for (int j = 0; j < 2; j++) { loop.insert(loop.end(), *(loop.begin() + j)); } // Now B is to the left of A if and only if the loop is counterclockwise. double sum = 0; for (size_t i = 2; i < loop.size(); ++i) { sum += S2::TurnAngle(g_.vertex(loop[i - 2]), g_.vertex(loop[i - 1]), g_.vertex(loop[i])); } return sum > 0; } // Given a set of clipping instructions encoded as a set of intersections // between input edges, EdgeClippingLayer determines which graph edges // correspond to clipped portions of input edges and removes them. It // assembles the remaining edges into a new S2Builder::Graph and passes the // result to the given output layer or layers for assembly. class EdgeClippingLayer : public S2Builder::Layer { public: EdgeClippingLayer(const vector>* layers, const vector* input_dimensions, const InputEdgeCrossings* input_crossings, S2MemoryTracker::Client* tracker) : layers_(*layers), input_dimensions_(*input_dimensions), input_crossings_(*input_crossings), tracker_(tracker) {} // Layer interface: GraphOptions graph_options() const override; void Build(const Graph& g, S2Error* absl_nonnull error) override; private: const vector>& layers_; const vector& input_dimensions_; const InputEdgeCrossings& input_crossings_; S2MemoryTracker::Client* tracker_; }; GraphOptions EdgeClippingLayer::graph_options() const { // We keep all edges, including degenerate ones, so that we can figure out // the correspondence between input edge crossings and output edge // crossings. return GraphOptions(EdgeType::DIRECTED, DegenerateEdges::KEEP, DuplicateEdges::KEEP, SiblingPairs::KEEP); } void EdgeClippingLayer::Build(const Graph& g, S2Error* absl_nonnull error) { // Data per graph edge: // vector order_; // vector rank_; // vector new_edges; // vector new_input_edge_ids; // Data per graph vertex: // Graph::VertexInMap in_; // Graph::VertexOutMap out_; // // The first and last two vectors above are freed upon GraphEdgeClipper // destruction. There is also a temporary vector "indegree" in // GetInputEdgeChainOrder() but this does not affect peak memory usage. int64_t tmp_bytes = g.num_edges() * (sizeof(EdgeId) + sizeof(int)) + g.num_vertices() * (2 * sizeof(EdgeId)); int64_t final_bytes = g.num_edges() * (sizeof(Graph::Edge) + sizeof(InputEdgeIdSetId)); // The order of the calls below is important. Note that all memory tracked // through this client is automatically untallied upon object destruction. if (!tracker_->Tally(final_bytes) || !tracker_->TallyTemp(tmp_bytes)) { // We don't need to copy memory tracking errors to "error" because this // is already done for us in S2BooleanOperation::Impl::Build(). return; } // The bulk of the work is handled by GraphEdgeClipper. vector new_edges; vector new_input_edge_ids; // Destroy the GraphEdgeClipper immediately to save memory. GraphEdgeClipper(g, input_dimensions_, input_crossings_, &new_edges, &new_input_edge_ids).Run(); // Construct one or more subgraphs from the clipped edges and pass them to // the given output layer(s). We start with a copy of the input graph's // IdSetLexicon because this is necessary in general, even though in this // case it is guaranteed to be empty because no edges have been merged. IdSetLexicon new_input_edge_id_set_lexicon = g.input_edge_id_set_lexicon(); if (layers_.size() == 1) { Graph new_graph = g.MakeSubgraph( layers_[0]->graph_options(), &new_edges, &new_input_edge_ids, &new_input_edge_id_set_lexicon, g.is_full_polygon_predicate(), error, tracker_); if (tracker_->ok()) layers_[0]->Build(new_graph, error); tracker_->Untally(new_edges); tracker_->Untally(new_input_edge_ids); } else { // The Graph objects must be valid until the last Build() call completes, // so we store all of the graph data in arrays with 3 elements. ABSL_DCHECK_EQ(3, layers_.size()); vector layer_edges[3]; vector layer_input_edge_ids[3]; // Separate the edges according to their dimension. for (size_t i = 0; i < new_edges.size(); ++i) { int d = input_dimensions_[new_input_edge_ids[i]]; if (!tracker_->AddSpace(&layer_edges[d], 1)) return; if (!tracker_->AddSpace(&layer_input_edge_ids[d], 1)) return; layer_edges[d].push_back(new_edges[i]); layer_input_edge_ids[d].push_back(new_input_edge_ids[i]); } // Clear variables to save space. if (!tracker_->Clear(&new_edges)) return; if (!tracker_->Clear(&new_input_edge_ids)) return; vector layer_graphs; // No default constructor. layer_graphs.reserve(3); for (int d = 0; d < 3; ++d) { layer_graphs.push_back(g.MakeSubgraph( layers_[d]->graph_options(), &layer_edges[d], &layer_input_edge_ids[d], &new_input_edge_id_set_lexicon, g.is_full_polygon_predicate(), error, tracker_)); if (tracker_->ok()) layers_[d]->Build(layer_graphs[d], error); } for (int d = 0; d < 3; ++d) { tracker_->Untally(layer_edges[d]); tracker_->Untally(layer_input_edge_ids[d]); } } } } // namespace class S2BooleanOperation::Impl { public: explicit Impl(S2BooleanOperation* op) : op_(op), index_crossings_first_region_id_(-1), tracker_(op->options_.memory_tracker()) { } bool Build(S2Error* absl_nonnull error); private: class CrossingIterator; class CrossingProcessor; using ShapeEdge = s2shapeutil::ShapeEdge; using ShapeEdgeId = s2shapeutil::ShapeEdgeId; // An IndexCrossing represents a pair of intersecting S2ShapeIndex edges // ("a_edge" and "b_edge"). We store all such intersections because the // algorithm needs them twice, once when processing the boundary of region A // and once when processing the boundary of region B. struct IndexCrossing { ShapeEdgeId a, b; // True if S2::CrossingSign(a_edge, b_edge) > 0. uint32_t is_interior_crossing : 1; // True if "a_edge" crosses "b_edge" from left to right. Undefined if // is_interior_crossing is false. uint32_t left_to_right : 1; // Equal to S2::VertexCrossing(a_edge, b_edge). Undefined if "a_edge" and // "b_edge" do not share exactly one vertex or either edge is degenerate. uint32_t is_vertex_crossing : 1; // All flags are "false" by default. IndexCrossing(ShapeEdgeId _a, ShapeEdgeId _b) : a(_a), b(_b), is_interior_crossing(false), left_to_right(false), is_vertex_crossing(false) { } friend bool operator==(const IndexCrossing& x, const IndexCrossing& y) { return x.a == y.a && x.b == y.b; } friend bool operator<(const IndexCrossing& x, const IndexCrossing& y) { // The compiler (2017) doesn't optimize the following as well: // return x.a < y.a || (x.a == y.a && x.b < y.b); if (x.a.shape_id < y.a.shape_id) return true; if (y.a.shape_id < x.a.shape_id) return false; if (x.a.edge_id < y.a.edge_id) return true; if (y.a.edge_id < x.a.edge_id) return false; if (x.b.shape_id < y.b.shape_id) return true; if (y.b.shape_id < x.b.shape_id) return false; return x.b.edge_id < y.b.edge_id; } }; using IndexCrossings = vector; class MemoryTracker : public S2MemoryTracker::Client { public: using S2MemoryTracker::Client::Client; // Used to track memory used by CrossingProcessor::source_id_map_. (The // type is a template parameter so that SourceIdMap can be private.) template bool TallySourceIdMap(int num_entries) { int64_t delta_bytes = num_entries * GetBtreeMinBytesPerEntry(); source_id_map_bytes_ += delta_bytes; return Tally(delta_bytes); } // Used to clear CrossingProcessor::source_id_map_ and update the tracked // memory usage accordingly. template bool ClearSourceIdMap(T* source_id_map) { source_id_map->clear(); Tally(-source_id_map_bytes_); source_id_map_bytes_ = 0; return ok(); } private: // The amount of memory used by CrossingProcessor::source_id_map_. int64_t source_id_map_bytes_ = 0; }; bool is_boolean_output() const { return op_->result_empty_ != nullptr; } // All of the methods below support "early exit" in the case of boolean // results by returning "false" as soon as the result is known to be // non-empty. bool AddBoundary(int a_region_id, bool invert_a, bool invert_b, bool invert_result, absl::Span a_chain_starts, CrossingProcessor* cp); bool GetChainStarts(int a_region_id, bool invert_a, bool invert_b, bool invert_result, CrossingProcessor* cp, vector* chain_starts); bool ProcessIncidentEdges(const ShapeEdge& a, S2ContainsPointQuery* query, CrossingProcessor* cp); static bool HasInterior(const S2ShapeIndex& index); bool AddIndexCrossing(const ShapeEdge& a, const ShapeEdge& b, bool is_interior, IndexCrossings* crossings); bool InitIndexCrossings(int region_id); bool AddBoundaryPair(bool invert_a, bool invert_b, bool invert_result, CrossingProcessor* cp); bool AreRegionsIdentical() const; bool BuildOpType(OpType op_type); bool IsFullPolygonResult(const S2Builder::Graph& g, S2Error* absl_nonnull error) const; bool IsFullPolygonUnion(const S2ShapeIndex& a, const S2ShapeIndex& b) const; bool IsFullPolygonIntersection(const S2ShapeIndex& a, const S2ShapeIndex& b) const; bool IsFullPolygonDifference(const S2ShapeIndex& a, const S2ShapeIndex& b) const; bool IsFullPolygonSymmetricDifference(const S2ShapeIndex& a, const S2ShapeIndex& b) const; void DoBuild(S2Error* absl_nonnull error); // A bit mask representing all six faces of the S2 cube. static constexpr uint8_t kAllFacesMask = 0x3f; S2BooleanOperation* op_; // The S2Builder options used to construct the output. S2Builder::Options builder_options_; // The S2Builder used to construct the output. Note that the S2Builder // object is created only when is_boolean_output() is false. unique_ptr builder_; // A vector specifying the dimension of each edge added to S2Builder. vector input_dimensions_; // The set of all input edge crossings, which is used by EdgeClippingLayer // to construct the clipped output polygon. InputEdgeCrossings input_crossings_; // kSentinel is a sentinel value used to mark the end of vectors. static const ShapeEdgeId kSentinel; // A vector containing all pairs of crossing edges from the two input // regions (including edge pairs that share a common vertex). The first // element of each pair is an edge from "index_crossings_first_region_id_", // while the second element of each pair is an edge from the other region. IndexCrossings index_crossings_; // Indicates that the first element of each crossing edge pair in // "index_crossings_" corresponds to an edge from the given region. // This field is negative if index_crossings_ has not been computed yet. int index_crossings_first_region_id_; // Temporary storage used in GetChainStarts(), declared here to avoid // repeatedly allocating memory. IndexCrossings tmp_crossings_; // An object to track the memory usage of this class. MemoryTracker tracker_; }; const s2shapeutil::ShapeEdgeId S2BooleanOperation::Impl::kSentinel( std::numeric_limits::max(), 0); // A helper class for iterating through the edges from region B that cross a // particular edge from region A. It caches information from the current // shape, chain, and edge so that it doesn't need to be looked up repeatedly. // Typical usage: // // void SomeFunction(ShapeEdgeId a_id, CrossingIterator *it) { // // Iterate through the edges that cross edge "a_id". // for (; !it->Done(a_id); it->Next()) { // ... use it->b_shape(), it->b_edge(), etc ... // } class S2BooleanOperation::Impl::CrossingIterator { public: // Creates an iterator over crossing edge pairs (a, b) where "b" is an edge // from "b_index". "crossings_complete" indicates that "crossings" contains // all edge crossings between the two regions (rather than a subset). CrossingIterator(const S2ShapeIndex* b_index, const IndexCrossings* crossings, bool crossings_complete) : b_index_(*b_index), it_(crossings->begin()), b_shape_id_(-1), crossings_complete_(crossings_complete) { Update(); } void Next() { ++it_; Update(); } bool Done(ShapeEdgeId id) const { return a_id() != id; } // True if all edge crossings are available (see above). bool crossings_complete() const { return crossings_complete_; } // True if this crossing occurs at a point interior to both edges. bool is_interior_crossing() const { return it_->is_interior_crossing; } // Equal to S2::VertexCrossing(a_edge, b_edge), provided that a_edge and // b_edge have exactly one vertex in common and neither edge is degenerate. bool is_vertex_crossing() const { return it_->is_vertex_crossing; } // True if a_edge crosses b_edge from left to right (for interior crossings). bool left_to_right() const { return it_->left_to_right; } ShapeEdgeId a_id() const { return it_->a; } ShapeEdgeId b_id() const { return it_->b; } const S2ShapeIndex& b_index() const { return b_index_; } const S2Shape& b_shape() const { return *b_shape_; } int b_dimension() const { return b_dimension_; } int b_shape_id() const { return b_shape_id_; } int b_edge_id() const { return b_id().edge_id; } S2Shape::Edge b_edge() const { return b_shape_->edge(b_edge_id()); // Opportunity to cache this. } // Information about the chain to which an edge belongs. struct ChainInfo { int chain_id; // chain id int start; // starting edge id int limit; // limit edge id }; // Returns a description of the chain to which the current B edge belongs. const ChainInfo& b_chain_info() const { if (b_info_.chain_id < 0) { b_info_.chain_id = b_shape().chain_position(b_edge_id()).chain_id; auto chain = b_shape().chain(b_info_.chain_id); b_info_.start = chain.start; b_info_.limit = chain.start + chain.length; } return b_info_; } private: // Updates information about the B shape whenever it changes. void Update() { if (a_id() != kSentinel && b_id().shape_id != b_shape_id_) { b_shape_id_ = b_id().shape_id; b_shape_ = b_index_.shape(b_shape_id_); b_dimension_ = b_shape_->dimension(); b_info_.chain_id = -1; // Computed on demand. } } const S2ShapeIndex& b_index_; IndexCrossings::const_iterator it_; const S2Shape* b_shape_; int b_shape_id_; int b_dimension_; mutable ChainInfo b_info_; // Computed on demand. bool crossings_complete_; }; // CrossingProcessor is a helper class that processes all the edges from one // region that cross a specific edge of the other region. It outputs the // appropriate edges to an S2Builder, and outputs other information required // by GraphEdgeClipper to the given vectors. class S2BooleanOperation::Impl::CrossingProcessor { public: // Prepares to build output for the given polygon and polyline boundary // models. Edges are emitted to "builder", while other auxiliary data is // appended to the given vectors. // // If a predicate is being evaluated (i.e., we do not need to construct the // actual result), then "builder" and the various output vectors should all // be nullptr. CrossingProcessor(const PolygonModel& polygon_model, const PolylineModel& polyline_model, bool polyline_loops_have_boundaries, S2Builder* builder, vector* input_dimensions, InputEdgeCrossings* input_crossings, MemoryTracker* tracker) : polygon_model_(polygon_model), polyline_model_(polyline_model), polyline_loops_have_boundaries_(polyline_loops_have_boundaries), builder_(builder), input_dimensions_(input_dimensions), input_crossings_(input_crossings), tracker_(tracker), prev_inside_(false) {} // Starts processing edges from the given region. "invert_a", "invert_b", // and "invert_result" indicate whether region A, region B, and/or the // result should be inverted, which allows operations such as union and // difference to be implemented. For example, union is ~(~A & ~B). // // This method should be called in pairs, once to process the edges from // region A and once to process the edges from region B. void StartBoundary(int a_region_id, bool invert_a, bool invert_b, bool invert_result); // Starts processing edges from the given shape. void StartShape(const S2Shape* a_shape); // Starts processing edges from the given chain. void StartChain(int chain_id, S2Shape::Chain chain, bool inside); // Processes the given edge "a_id". "it" should be positioned to the set of // edges from the other region that cross "a_id" (if any). // // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool ProcessEdge(ShapeEdgeId a_id, CrossingIterator* it); // This method should be called after each pair of calls to StartBoundary. // (The only operation that processes more than one pair of boundaries is // SYMMETRIC_DIFFERENCE, which computes the union of A-B and B-A.) // // Resets the state of the CrossingProcessor. void DoneBoundaryPair(); // Indicates whether the point being processed along the current edge chain // is in the polygonal interior of the opposite region, using semi-open // boundaries. If "invert_b_" is true then this field is inverted. // // This value along with the set of incident edges can be used to compute // whether the opposite region contains this point under any of the // supported boundary models (PolylineModel::CLOSED, etc). bool inside() const { return inside_; } private: // SourceEdgeCrossing represents an input edge that crosses some other // edge; it crosses the edge from left to right iff the second parameter // is "true". using SourceEdgeCrossing = pair; struct EdgeCrossingResult; struct PointCrossingResult; InputEdgeId input_edge_id() const { return input_dimensions_->size(); } // Returns true if the edges on either side of the first vertex of the // current edge have not been emitted. // // REQUIRES: This method is called just after updating "inside_" for "v0". bool is_v0_isolated(ShapeEdgeId a_id) const { return !inside_ && v0_emitted_max_edge_id_ < a_id.edge_id; } // Returns true if "a_id" is the last edge of the current chain, and the // edges on either side of the last vertex have not been emitted (including // the possibility that the chain forms a loop). bool is_chain_last_vertex_isolated(ShapeEdgeId a_id) const { return (a_id.edge_id == chain_limit_ - 1 && !chain_v0_emitted_ && v0_emitted_max_edge_id_ <= a_id.edge_id); } // Returns true if the given polyline edge contains "v0", taking into // account the specified PolylineModel. bool polyline_contains_v0(int edge_id, int chain_start) const { return (polyline_model_ != PolylineModel::OPEN || edge_id > chain_start); } bool is_degenerate(ShapeEdgeId a_id) const { return is_degenerate_hole_.contains(a_id); } void AddCrossing(const SourceEdgeCrossing& crossing) { if (!tracker_->AddSpace(&source_edge_crossings_, 1)) return; source_edge_crossings_.push_back(make_pair(input_edge_id(), crossing)); } void AddInteriorCrossing(const SourceEdgeCrossing& crossing) { // Crossing edges are queued until the S2Builder edge that they are // supposed to be associated with is created (see AddEdge() and // pending_source_edge_crossings_ for details). pending_source_edge_crossings_.push_back(crossing); } void SetClippingState(InputEdgeId parameter, bool state) { AddCrossing(SourceEdgeCrossing(SourceId(parameter), state)); } // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool AddEdge(ShapeEdgeId a_id, const S2Shape::Edge& a, int dimension, int interior_crossings) { if (builder_ == nullptr) return false; // Boolean output. if (interior_crossings > 0) { // Add the edges that cross this edge to the output so that // GraphEdgeClipper can find them. if (!tracker_->AddSpace(&source_edge_crossings_, pending_source_edge_crossings_.size())) { return false; } for (const auto& crossing : pending_source_edge_crossings_) { source_edge_crossings_.push_back(make_pair(input_edge_id(), crossing)); } // Build a map that translates temporary edge ids (SourceId) to // the representation used by EdgeClippingLayer (InputEdgeId). if (!tracker_->TallySourceIdMap(1)) { return false; } SourceId src_id(a_region_id_, a_id.shape_id, a_id.edge_id); source_id_map_[src_id] = input_edge_id(); } // Set the GraphEdgeClipper's "inside" state to match ours. if (inside_ != prev_inside_) SetClippingState(kSetInside, inside_); if (!tracker_->AddSpace(input_dimensions_, 1)) return false; input_dimensions_->push_back(dimension); builder_->AddEdge(a.v0, a.v1); inside_ ^= (interior_crossings & 1); prev_inside_ = inside_; return tracker_->ok(); } // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool AddPointEdge(const S2Point& p, int dimension) { if (builder_ == nullptr) return false; // Boolean output. if (!prev_inside_) SetClippingState(kSetInside, true); if (!tracker_->AddSpace(input_dimensions_, 1)) return false; input_dimensions_->push_back(dimension); builder_->AddEdge(p, p); prev_inside_ = true; return tracker_->ok(); } bool ProcessEdge0(ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it); bool ProcessEdge1(ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it); bool ProcessEdge2(ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it); void SkipCrossings(ShapeEdgeId a_id, CrossingIterator* it); PointCrossingResult ProcessPointCrossings( ShapeEdgeId a_id, const S2Point& a0, CrossingIterator* it) const; EdgeCrossingResult ProcessEdgeCrossings( ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it); bool IsPolylineVertexInside(bool matches_polyline, bool matches_polygon) const; bool IsPolylineEdgeInside(const EdgeCrossingResult& r, bool is_degenerate) const; bool PolylineEdgeContainsVertex(const S2Point& v, const CrossingIterator& it, int dimension) const; // Constructor parameters: PolygonModel polygon_model_; PolylineModel polyline_model_; bool polyline_loops_have_boundaries_; // The output of the CrossingProcessor consists of a subset of the input // edges that are emitted to "builder_", and some auxiliary information // that allows GraphEdgeClipper to determine which segments of those input // edges belong to the output. The auxiliary information consists of the // dimension of each input edge, and set of input edges from the other // region that cross each input edge. S2Builder* builder_; // (nullptr if boolean output was requested) vector* input_dimensions_; InputEdgeCrossings* input_crossings_; MemoryTracker* tracker_; // Fields set by StartBoundary: int a_region_id_, b_region_id_; bool invert_a_, invert_b_, invert_result_; bool is_union_; // True if this is a UNION operation. // Fields set by StartShape: const S2Shape* a_shape_; int a_dimension_; // Fields set by StartChain: int chain_id_; int chain_start_; int chain_limit_; // Fields updated by ProcessEdge: // A temporary representation of input_crossings_ that is used internally // until all necessary edges from *both* polygons have been emitted to the // S2Builder. This field is then converted by DoneBoundaryPair() into // the InputEdgeCrossings format expected by GraphEdgeClipper. // // The reason that we can't construct input_crossings_ directly is that it // uses InputEdgeIds to identify the edges from both polygons, and when we // are processing edges from the first polygon, InputEdgeIds have not yet // been assigned to the second polygon. So instead this field identifies // edges from the first polygon using an InputEdgeId, and edges from the // second polygon using a (region_id, shape_id, edge_id) tuple (i.e., a // SourceId). // // All crossings are represented twice, once to indicate that an edge from // polygon 0 is crossed by an edge from polygon 1, and once to indicate that // an edge from polygon 1 is crossed by an edge from polygon 0. The entries // are sorted lexicographically by their eventual InputEdgeIds except for // GraphEdgeClipper state modifications, which are sorted by the first // InputEdgeId only. using SourceEdgeCrossings = vector>; SourceEdgeCrossings source_edge_crossings_; // A set of edges that cross the current edge being processed by // ProcessEdge() but that have not yet been associated with a particular // S2Builder edge. This is necessary because ProcessEdge can create up to // three S2Builder edges per input edge: one to represent the edge interior, // and up to two more to represent an isolated start and/or end vertex. The // crossing edges must be associated with the S2Builder edge that represents // the edge interior, and they are stored here until that edge is created. vector pending_source_edge_crossings_; // A map that translates from SourceId (the (region_id, shape_id, edge_id) // triple that identifies an S2ShapeIndex edge) to InputEdgeId (the // sequentially increasing numbers assigned to input edges by S2Builder). using SourceIdMap = absl::btree_map; SourceIdMap source_id_map_; // For each edge in region B that defines a degenerate loop (either a point // loop or a sibling pair), indicates whether that loop represents a shell // or a hole. This information is used during the second pass of // AddBoundaryPair() to determine the output for degenerate edges. flat_hash_map is_degenerate_hole_; // Indicates whether the point being processed along the current edge chain // is in the polygonal interior of the opposite region, using semi-open // boundaries. If "invert_b_" is true then this field is inverted. // // Equal to: b_index_.Contains(current point) ^ invert_b_ bool inside_; // The value that "inside_" would have just before the end of the previous // edge added to S2Builder. This value is used to determine whether the // GraphEdgeClipper state needs to be updated when jumping from one edge chain // to another. bool prev_inside_; // The maximum edge id of any edge in the current chain whose v0 vertex has // already been emitted. This is used to determine when an isolated vertex // needs to be emitted, e.g. when two closed polygons share only a vertex. int v0_emitted_max_edge_id_; // True if the first vertex of the current chain has been emitted. This is // used when processing loops in order to determine whether the first/last // vertex of the loop should be emitted as an isolated vertex. bool chain_v0_emitted_; }; // See documentation above. void S2BooleanOperation::Impl::CrossingProcessor::StartBoundary( int a_region_id, bool invert_a, bool invert_b, bool invert_result) { a_region_id_ = a_region_id; b_region_id_ = 1 - a_region_id; invert_a_ = invert_a; invert_b_ = invert_b; invert_result_ = invert_result; is_union_ = invert_b && invert_result; // Specify to GraphEdgeClipper how these edges should be clipped. SetClippingState(kSetReverseA, invert_a != invert_result); SetClippingState(kSetInvertB, invert_b); } // See documentation above. inline void S2BooleanOperation::Impl::CrossingProcessor::StartShape( const S2Shape* a_shape) { a_shape_ = a_shape; a_dimension_ = a_shape->dimension(); } // See documentation above. inline void S2BooleanOperation::Impl::CrossingProcessor::StartChain( int chain_id, S2Shape::Chain chain, bool inside) { chain_id_ = chain_id; chain_start_ = chain.start; chain_limit_ = chain.start + chain.length; inside_ = inside; v0_emitted_max_edge_id_ = chain.start - 1; // No edges emitted yet. chain_v0_emitted_ = false; } // See documentation above. bool S2BooleanOperation::Impl::CrossingProcessor::ProcessEdge( ShapeEdgeId a_id, CrossingIterator* it) { // chain_edge() is faster than edge() when there are multiple chains. auto a = a_shape_->chain_edge(chain_id_, a_id.edge_id - chain_start_); if (a_dimension_ == 0) { return ProcessEdge0(a_id, a, it); } else if (a_dimension_ == 1) { return ProcessEdge1(a_id, a, it); } else { ABSL_DCHECK_EQ(2, a_dimension_); return ProcessEdge2(a_id, a, it); } } // PointCrossingResult describes the relationship between a point from region A // and a set of crossing edges from region B. For example, "matches_polygon" // indicates whether a polygon vertex from region B matches the given point. struct S2BooleanOperation::Impl::CrossingProcessor::PointCrossingResult { PointCrossingResult() : matches_point(false), matches_polyline(false), matches_polygon(false) { } // Note that "matches_polyline" is true only if the point matches a polyline // vertex of B *and* the polyline contains that vertex, whereas // "matches_polygon" is true if the point matches any polygon vertex. bool matches_point; // Matches point. bool matches_polyline; // Matches contained polyline vertex. bool matches_polygon; // Matches polygon vertex. }; // Processes an edge of dimension 0 (i.e., a point) from region A. // // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool S2BooleanOperation::Impl::CrossingProcessor::ProcessEdge0( ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it) { ABSL_DCHECK_EQ(a.v0, a.v1); // When a region is inverted, all points and polylines are discarded. if (invert_a_ != invert_result_) { SkipCrossings(a_id, it); return true; } PointCrossingResult r = ProcessPointCrossings(a_id, a.v0, it); // "contained" indicates whether the current point is inside the polygonal // interior of the opposite region, using semi-open boundaries. bool contained = inside_ ^ invert_b_; if (r.matches_polygon && polygon_model_ != PolygonModel::SEMI_OPEN) { contained = (polygon_model_ == PolygonModel::CLOSED); } if (r.matches_polyline) contained = true; // The output of UNION includes duplicate values, so ensure that points are // not suppressed by other points. if (r.matches_point && !is_union_) contained = true; // Test whether the point is contained after region B is inverted. if (contained == invert_b_) return true; // Don't exit early. return AddPointEdge(a.v0, 0); } // Skip any crossings that were not needed to determine the result. inline void S2BooleanOperation::Impl::CrossingProcessor::SkipCrossings( ShapeEdgeId a_id, CrossingIterator* it) { while (!it->Done(a_id)) it->Next(); } // Returns a summary of the relationship between a point from region A and // a set of crossing edges from region B (see PointCrossingResult). S2BooleanOperation::Impl::CrossingProcessor::PointCrossingResult S2BooleanOperation::Impl::CrossingProcessor::ProcessPointCrossings( ShapeEdgeId a_id, const S2Point& a0, CrossingIterator* it) const { PointCrossingResult r; for (; !it->Done(a_id); it->Next()) { if (it->b_dimension() == 0) { r.matches_point = true; } else if (it->b_dimension() == 1) { if (PolylineEdgeContainsVertex(a0, *it, 0)) { r.matches_polyline = true; } } else { r.matches_polygon = true; } } return r; } // EdgeCrossingResult describes the relationship between an edge (a0, a1) from // region A and a set of crossing edges from region B. For example, // "matches_polygon" indicates whether (a0, a1) matches a polygon edge from // region B. struct S2BooleanOperation::Impl::CrossingProcessor::EdgeCrossingResult { // These fields indicate that (a0, a1) exactly matches an edge of B. bool matches_polyline = false; // Matches polyline edge (either direction). // These fields indicate that a B polyline contains the degenerate polyline // (a0, a0) or (a1, a1). (This is identical to whether the B polyline // contains the point a0 or a1 except when the B polyline is degenerate, // since a degenerate polyline VV contains itself in all boundary models but // contains the point V only in the CLOSED polyline model.) bool a0_matches_polyline = false; // B polyline contains (a0, a0) bool a1_matches_polyline = false; // B polyline contains (a1, a1) // These fields indicate that a vertex of (a0, a1) matches a polygon vertex // of B. (Unlike with polylines, the polygon may not contain that vertex.) bool a0_matches_polygon = false; // a0 matches polygon vertex. bool a1_matches_polygon = false; // a1 matches polygon vertex. // When a0 != a1, the first two fields identify any B polygon edge that // exactly matches (a0, a1) or the sibling edge (a1, a0). The third field // identifies any B polygon edge that exactly matches (a0, a0). ShapeEdgeId polygon_match_id; // B polygon edge that matches (a0, a1). ShapeEdgeId sibling_match_id; // B polygon edge that matches (a1, a0). ShapeEdgeId a0_loop_match_id; // B polygon edge that matches (a0, a0). // Convenience functions to test whether a matching edge was found. bool matches_polygon() const { return polygon_match_id.edge_id >= 0; } bool matches_sibling() const { return sibling_match_id.edge_id >= 0; } bool loop_matches_a0() const { return a0_loop_match_id.edge_id >= 0; } // These fields count the number of edge crossings at a0, a1, and the // interior of (a0, a1). int a0_crossings = 0; // Count of polygon crossings at a0. int a1_crossings = 0; // Count of polygon crossings at a1. int interior_crossings = 0; // Count of polygon crossings in edge interior. }; // Processes an edge of dimension 1 (i.e., a polyline edge) from region A. // // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool S2BooleanOperation::Impl::CrossingProcessor::ProcessEdge1( ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it) { // When a region is inverted, all points and polylines are discarded. if (invert_a_ != invert_result_) { SkipCrossings(a_id, it); return true; } // Evaluate whether the start vertex should belong to the output, in case it // needs to be emitted as an isolated vertex. EdgeCrossingResult r = ProcessEdgeCrossings(a_id, a, it); bool a0_inside = IsPolylineVertexInside(r.a0_matches_polyline, r.a0_matches_polygon); // Test whether the entire polyline edge should be emitted (or not emitted) // because it matches a polyline or polygon edge. bool is_degenerate = (a.v0 == a.v1); inside_ ^= (r.a0_crossings & 1); if (inside_ != IsPolylineEdgeInside(r, is_degenerate)) { inside_ ^= true; // Invert the inside_ state. ++r.a1_crossings; // Restore the correct (semi-open) state later. } // If neither edge adjacent to v0 was emitted, and this polyline contains // v0, and the other region contains v0, then emit an isolated vertex. if (!polyline_loops_have_boundaries_ && a_id.edge_id == chain_start_ && a.v0 == a_shape_->chain_edge(chain_id_, chain_limit_ - chain_start_ - 1).v1) { // This is the first vertex of a polyline loop, so we can't decide if it // is isolated until we process the last polyline edge. chain_v0_emitted_ = inside_; } else if (is_v0_isolated(a_id) && !is_degenerate && polyline_contains_v0(a_id.edge_id, chain_start_) && a0_inside) { if (!AddPointEdge(a.v0, 1)) return false; } // Test whether the entire edge or any part of it belongs to the output. if (inside_ || r.interior_crossings > 0) { // Note: updates "inside_" to correspond to the state just before a1. if (!AddEdge(a_id, a, 1 /*dimension*/, r.interior_crossings)) { return false; } } // Remember whether the edge portion just before "a1" was emitted, so that // we can decide whether "a1" need to be emitted as an isolated vertex. if (inside_) v0_emitted_max_edge_id_ = a_id.edge_id + 1; // Verify that edge crossings are being counted correctly. inside_ ^= (r.a1_crossings & 1); if (it->crossings_complete()) { ABSL_DCHECK_EQ(S2ContainsPointQuery(&it->b_index()).Contains(a.v1), inside_ ^ invert_b_); } // Special case to test whether the last vertex of a polyline should be // emitted as an isolated vertex. if (it->crossings_complete() && !is_degenerate && is_chain_last_vertex_isolated(a_id) && (polyline_model_ == PolylineModel::CLOSED || (!polyline_loops_have_boundaries_ && a.v1 == a_shape_->chain_edge(chain_id_, chain_start_).v0)) && IsPolylineVertexInside(r.a1_matches_polyline, r.a1_matches_polygon)) { if (!AddPointEdge(a.v1, 1)) return false; } return true; } // Returns true if the current point being processed (which must be a polyline // vertex) is contained by the opposite region (after inversion if "invert_b_" // is true). "matches_polyline" and "matches_polygon" indicate whether the // vertex matches a polyline/polygon vertex of the opposite region. bool S2BooleanOperation::Impl::CrossingProcessor::IsPolylineVertexInside( bool matches_polyline, bool matches_polygon) const { // Initially "contained" indicates whether the current point is inside the // polygonal interior of region B using semi-open boundaries. bool contained = inside_ ^ invert_b_; // For UNION the output includes duplicate polylines. The test below // ensures that isolated polyline vertices are not suppressed by other // polyline vertices in the output. if (matches_polyline && !is_union_) { contained = true; } else if (matches_polygon && polygon_model_ != PolygonModel::SEMI_OPEN) { contained = (polygon_model_ == PolygonModel::CLOSED); } // Finally, invert the result if the opposite region should be inverted. return contained ^ invert_b_; } // Returns true if the current polyline edge is contained by the opposite // region (after inversion if "invert_b_" is true). inline bool S2BooleanOperation::Impl::CrossingProcessor::IsPolylineEdgeInside( const EdgeCrossingResult& r, bool is_degenerate) const { // Initially "contained" indicates whether the current point (just past a0) // is inside the polygonal interior of region B using semi-open boundaries. bool contained = inside_ ^ invert_b_; // Note that if r.matches_polyline and is_union_ is true, then "contained" // will be false (unless there is also a matching polygon edge) since // polyline edges are not allowed in the interior of B. In this case we // leave "contained" as false since it causes both matching edges to be // emitted. if (r.matches_polyline && !is_union_) { contained = true; } else if (is_degenerate) { // First allow the polygon boundary model to override the semi-open rules. // Note that a polygon vertex (dimension 2) is considered to completely // contain degenerate OPEN and SEMI_OPEN polylines (dimension 1) even // though the latter do not contain any points. This is because dimension // 2 points are considered to be a strict superset of dimension 1 points. if (polygon_model_ != PolygonModel::SEMI_OPEN && r.a0_matches_polygon) { contained = (polygon_model_ == PolygonModel::CLOSED); } // Note that r.a0_matches_polyline is true if and only if some B polyline // contains the degenerate polyline (a0, a0). if (r.a0_matches_polyline && !is_union_) contained = true; } else if (r.matches_polygon()) { // In the SEMI_OPEN model, polygon sibling pairs cancel each other and // have no effect on point or edge containment. if (!(polygon_model_ == PolygonModel::SEMI_OPEN && r.matches_sibling())) { contained = (polygon_model_ != PolygonModel::OPEN); } } else if (r.matches_sibling()) { contained = (polygon_model_ == PolygonModel::CLOSED); } // Finally, invert the result if the opposite region should be inverted. return contained ^ invert_b_; } // Processes an edge of dimension 2 (i.e., a polygon edge) from region A. // // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool S2BooleanOperation::Impl::CrossingProcessor::ProcessEdge2( ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it) { // Whenever the two regions contain the same edge, or opposite edges of a // sibling pair, or one region contains a point loop while the other // contains a matching vertex, then in general the result depends on whether // one or both sides represent a degenerate shell or hole. // // In each pass it is easy to determine whether edges in region B represent // degenerate geometry, and if so whether they represent a shell or hole, // since this can be determined from the inside_ state and the // matches_polygon() / matches_sibling() methods of EdgeCrossingResult. // However this information is not readily available for region A. // // We handle this by saving the shell/hole status of each degenerate loop in // region B during the first pass, and deferring the processing of any edges // that meet the criteria above until the second pass. (Note that regions // A,B correspond to regions 0,1 respectively in the first pass whereas they // refer to regions 1,0 respectively in the second pass.) // // The first pass ignores: // - degenerate edges of A that are incident to any edge of B // - non-degenerate edges of A that match or are siblings to an edge of B // // The first pass also records the shell/hole status of: // - degenerate edges of B that are incident to any edge of A // - sibling pairs of B where either edge matches an edge of A // // The second pass processes and perhaps outputs: // - degenerate edges of B that are incident to any edge of A // - non-degenerate edges of B that match or are siblings to an edge of A // // The following flag indicates that we are in the second pass described // above, i.e. that we are emitting any necessary edges that were ignored by // the first pass. bool emit_shared = (a_region_id_ == 1); // Degeneracies such as isolated vertices and sibling pairs can only be // created by intersecting CLOSED polygons or unioning OPEN polygons. bool create_degen = (polygon_model_ == PolygonModel::CLOSED && !invert_a_ && !invert_b_) || (polygon_model_ == PolygonModel::OPEN && invert_a_ && invert_b_); // In addition, existing degeneracies are kept when an open boundary is // subtracted. Note that "keep_degen_b" is only defined for completeness. // It is needed to ensure that the "reverse subtraction operator" (B - A) // preserves degeneracies correctly, however in practice this operator is // only used internally to implement symmetric difference, and in that // situation the preserved degeneracy is always removed from the final // result because it overlaps other geometry. bool keep_degen_a = (polygon_model_ == PolygonModel::OPEN && invert_b_); bool keep_degen_b = (polygon_model_ == PolygonModel::OPEN && invert_a_); EdgeCrossingResult r = ProcessEdgeCrossings(a_id, a, it); ABSL_DCHECK(!r.matches_polyline); // If only one region is inverted, matching/sibling relations are reversed. if (invert_a_ != invert_b_) swap(r.polygon_match_id, r.sibling_match_id); bool is_point = (a.v0 == a.v1); if (!emit_shared) { // Remember the shell/hole status of degenerate B edges that are incident // to any edge of A. (We don't need to do this for vertex a1 since it is // the same as vertex a0 of the following A loop edge.) if (r.loop_matches_a0()) { is_degenerate_hole_[r.a0_loop_match_id] = inside_; if (is_point) return true; } // Point loops are handled identically to points in the semi-open model, // and are easier to process in the first pass (since otherwise in the // r.a0_matches_polygon case we would need to remember the containment // status of the matching vertex). Otherwise we defer processing such // loops to the second pass so that we can distinguish whether the // degenerate edge represents a hole or shell. if (polygon_model_ != PolygonModel::SEMI_OPEN) { if (is_point && r.a0_matches_polygon) return true; } } inside_ ^= (r.a0_crossings & 1); if (!emit_shared) { // Defer processing A edges that match or are siblings to an edge of B. if (r.matches_polygon() || r.matches_sibling()) { // For sibling pairs, also remember their shell/hole status. if (r.matches_polygon() && r.matches_sibling()) { is_degenerate_hole_[r.polygon_match_id] = inside_; is_degenerate_hole_[r.sibling_match_id] = inside_; } ABSL_DCHECK_EQ(r.interior_crossings, 0); inside_ ^= (r.a1_crossings & 1); return true; } } // Remember whether the B geometry represents a sibling pair hole. bool is_b_hole = r.matches_polygon() && r.matches_sibling() && inside_; // At this point, "inside_" indicates whether the initial part of the A edge // is contained by the B geometry using semi-open rules. The following code // implements the various other polygon boundary rules by changing the value // of "inside_" when necessary to indicate whether the current A edge should // be emitted to the output or not. "semi_open_inside" remembers the true // value of "inside_" so that it can be restored later. bool semi_open_inside = inside_; if (is_point) { if (r.loop_matches_a0()) { // Both sides are point loops. The edge is kept only: // - for closed intersection, open union, and open difference; // - if A and B are both holes or both shells. inside_ = create_degen || keep_degen_a || (inside_ == is_degenerate_hole_[r.a0_loop_match_id]); } else if (r.a0_matches_polygon) { // A point loop in A matches a polygon vertex in B. Note that this code // can emit an extra isolated vertex if A represents a point hole, but // this doesn't matter (see comments on the call to AddPointEdge below). if (polygon_model_ != PolygonModel::SEMI_OPEN) { inside_ = create_degen || keep_degen_a; } } } else if (r.matches_polygon()) { if (is_degenerate(a_id)) { // The A edge has a sibling. The edge is kept only: // - for closed intersection, open union, and open difference; // - if the A sibling pair is a hole and the B edge has no sibling; or // - if the B geometry is also a sibling pair and A and B are both // holes or both shells. inside_ = create_degen || keep_degen_a || (!r.matches_sibling() || inside_) == is_degenerate_hole_[a_id]; } else { // Matching edges are kept unless the B geometry is a sibling pair, in // which case it is kept only for closed intersection, open union, and // open difference. if (!r.matches_sibling() || create_degen || keep_degen_b) inside_ = true; } } else if (r.matches_sibling()) { if (is_degenerate(a_id)) { // The A edge has a sibling. The edge is kept only if A is a sibling // pair shell and the operation is closed intersection, open union, or // open difference. inside_ = (create_degen || keep_degen_a) && !is_degenerate_hole_[a_id]; } else { inside_ = create_degen; } } if (inside_ != semi_open_inside) { ++r.a1_crossings; // Restores the correct (semi-open) state later. } // Test whether the first vertex of this edge should be emitted as an // isolated degenerate vertex. This is only needed in the second pass when: // - a0 matches a vertex of the B polygon; // - the initial part of the A edge will not be emitted; and // - the operation is closed intersection or open union, or open difference // and the B geometry is a point loop. // // The logic does not attempt to avoid redundant extra vertices (e.g. the // extra code in ProcessEdge1() that checks whether the vertex is the // endpoint of the preceding emitted edge) since these will be removed during // S2Builder::Graph creation by DegenerateEdges::DISCARD or DISCARD_EXCESS // (which are necessary in any case due to snapping). if (emit_shared && r.a0_matches_polygon && !inside_ && (create_degen || (keep_degen_b && r.loop_matches_a0()))) { if (!AddPointEdge(a.v0, 2)) return false; } // Since we skipped edges in the first pass that only had a sibling pair // match in the B geometry, we sometimes need to emit the sibling pair of an // edge in the second pass. This happens only if: // - the operation is closed intersection, open union, or open difference; // - the A geometry is not a sibling pair (since otherwise we will process // that edge as well); and // - the B geometry is not a sibling pair hole (since then only one edge // should be emitted). if (r.matches_sibling() && (create_degen || keep_degen_b) && !is_degenerate(a_id) && !is_b_hole) { S2Shape::Edge sibling(a.v1, a.v0); if (!AddEdge(r.sibling_match_id, sibling, 2 /*dimension*/, 0)) { return false; } } // Test whether the entire edge or any part of it belongs to the output. if (inside_ || r.interior_crossings > 0) { // Note: updates "inside_" to correspond to the state just before a1. if (!AddEdge(a_id, a, 2 /*dimension*/, r.interior_crossings)) { return false; } } inside_ ^= (r.a1_crossings & 1); // Verify that edge crossings are being counted correctly. if (it->crossings_complete()) { ABSL_DCHECK_EQ(S2ContainsPointQuery(&it->b_index()).Contains(a.v1), inside_ ^ invert_b_); } return true; } // Returns a summary of the relationship between a test edge from region A and // a set of crossing edges from region B (see EdgeCrossingResult). // // NOTE(ericv): We could save a bit of work when matching polygon vertices by // passing in a flag saying whether this information is needed. For example // it is only needed in ProcessEdge2 when (emit_shared && create_degenerate). S2BooleanOperation::Impl::CrossingProcessor::EdgeCrossingResult S2BooleanOperation::Impl::CrossingProcessor::ProcessEdgeCrossings( ShapeEdgeId a_id, const S2Shape::Edge& a, CrossingIterator* it) { pending_source_edge_crossings_.clear(); EdgeCrossingResult r; if (it->Done(a_id)) return r; for (; !it->Done(a_id); it->Next()) { // Polyline and polygon "inside" states are not affected by point geometry. if (it->b_dimension() == 0) continue; S2Shape::Edge b = it->b_edge(); if (it->is_interior_crossing()) { // The crossing occurs in the edge interior. The condition below says // that (1) polyline crossings don't affect the polygon "inside" state, // and (2) subtracting a crossing polyline from a polyline does not // affect its "inside" state. (Note that vertices are still created at // the intersection points.) if (a_dimension_ <= it->b_dimension() && !(invert_b_ != invert_result_ && it->b_dimension() == 1)) { SourceId src_id(b_region_id_, it->b_shape_id(), it->b_edge_id()); AddInteriorCrossing(make_pair(src_id, it->left_to_right())); } r.interior_crossings += (it->b_dimension() == 1) ? 2 : 1; } else if (it->b_dimension() == 1) { // The polygon "inside" state is not affected by polyline geometry. if (a_dimension_ == 2) continue; if ((a.v0 == b.v0 && a.v1 == b.v1) || (a.v0 == b.v1 && a.v1 == b.v0)) { r.matches_polyline = true; } if ((a.v0 == b.v0 || a.v0 == b.v1) && PolylineEdgeContainsVertex(a.v0, *it, 1)) { r.a0_matches_polyline = true; } if ((a.v1 == b.v0 || a.v1 == b.v1) && PolylineEdgeContainsVertex(a.v1, *it, 1)) { r.a1_matches_polyline = true; } } else { ABSL_DCHECK_EQ(2, it->b_dimension()); if (a.v0 == a.v1 || b.v0 == b.v1) { // There are no edge crossings since at least one edge is degenerate. if (a.v0 == b.v0 && a.v0 == b.v1) { r.a0_loop_match_id = it->b_id(); } } else if (a.v0 == b.v0 && a.v1 == b.v1) { ++r.a0_crossings; r.polygon_match_id = it->b_id(); } else if (a.v0 == b.v1 && a.v1 == b.v0) { ++r.a0_crossings; r.sibling_match_id = it->b_id(); } else if (it->is_vertex_crossing()) { if (a.v0 == b.v0 || a.v0 == b.v1) { ++r.a0_crossings; } else { ++r.a1_crossings; } } if (a.v0 == b.v0 || a.v0 == b.v1) { r.a0_matches_polygon = true; } if (a.v1 == b.v0 || a.v1 == b.v1) { r.a1_matches_polygon = true; } } } return r; } // Returns true if the vertex "v" is contained by the polyline edge referred // to by the CrossingIterator "it", taking into account the PolylineModel. // "dimension" is 0 or 1 according to whether "v" should be modeled as a point // or as a degenerate polyline. (This only makes a difference when the // containing polyline is degenerate, since the polyline AA contains itself in // all boundary models but contains the point A only in the CLOSED model.) // // REQUIRES: it.b_dimension() == 1 // REQUIRES: "v" is an endpoint of it.b_edge() bool S2BooleanOperation::Impl::CrossingProcessor::PolylineEdgeContainsVertex( const S2Point& v, const CrossingIterator& it, int dimension) const { ABSL_DCHECK_EQ(1, it.b_dimension()); ABSL_DCHECK(it.b_edge().v0 == v || it.b_edge().v1 == v); ABSL_DCHECK(dimension == 0 || dimension == 1); // Closed polylines contain all their vertices. if (polyline_model_ == PolylineModel::CLOSED) return true; // Note that the code below is structured so that it.b_edge() is not usually // needed (since accessing the edge can be relatively expensive). const auto& b_chain = it.b_chain_info(); int b_edge_id = it.b_edge_id(); // A polyline contains its last vertex only when the polyline is degenerate // (v0 == v1) and "v" is modeled as a degenerate polyline (dimension == 1). // This corresponds to the fact that the polyline AA contains itself in all // boundary models, but contains the point A only in the CLOSED model. if (b_edge_id == b_chain.limit - 1 && v == it.b_edge().v1 && (dimension == 0 || b_edge_id > 0 || v != it.b_edge().v0)) { return false; } // Otherwise all interior vertices are contained. The first polyline // vertex is contained if either the polyline model is not OPEN, or the // polyline forms a loop and polyline_loops_have_boundaries_ is false. if (polyline_contains_v0(b_edge_id, b_chain.start)) return true; if (v != it.b_edge().v0) return true; if (polyline_loops_have_boundaries_) return false; return v == it.b_shape().chain_edge(b_chain.chain_id, b_chain.limit - b_chain.start - 1).v1; } // Translates the temporary representation of crossing edges (SourceId) into // the format expected by EdgeClippingLayer (InputEdgeId). void S2BooleanOperation::Impl::CrossingProcessor::DoneBoundaryPair() { tracker_->AddSpaceExact(input_crossings_, source_edge_crossings_.size()); if (!tracker_->TallySourceIdMap(3)) return; // Add entries that translate the "special" crossings. source_id_map_[SourceId(kSetInside)] = kSetInside; source_id_map_[SourceId(kSetInvertB)] = kSetInvertB; source_id_map_[SourceId(kSetReverseA)] = kSetReverseA; for (const auto& tmp : source_edge_crossings_) { auto it = source_id_map_.find(tmp.second.first); ABSL_DCHECK(it != source_id_map_.end()); input_crossings_->push_back(make_pair( tmp.first, CrossingInputEdge(it->second, tmp.second.second))); } tracker_->Clear(&source_edge_crossings_); tracker_->ClearSourceIdMap(&source_id_map_); } // Clips the boundary of A to the interior of the opposite region B and adds // the resulting edges to the output. Optionally, any combination of region // A, region B, and the result may be inverted, which allows operations such // as union and difference to be implemented. // // Note that when an input region is inverted with respect to the output // (e.g., invert_a != invert_result), all polygon edges are reversed and all // points and polylines are discarded, since the complement of such objects // cannot be represented. (If you want to compute the complement of points // or polylines, you can use S2LaxPolygonShape to represent your geometry as // degenerate polygons instead.) // // This method must be called an even number of times (first to clip A to B // and then to clip B to A), calling DoneBoundaryPair() after each pair. // // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool S2BooleanOperation::Impl::AddBoundary( int a_region_id, bool invert_a, bool invert_b, bool invert_result, absl::Span a_chain_starts, CrossingProcessor* cp) { const S2ShapeIndex& a_index = *op_->regions_[a_region_id]; const S2ShapeIndex& b_index = *op_->regions_[1 - a_region_id]; if (!InitIndexCrossings(a_region_id)) return false; cp->StartBoundary(a_region_id, invert_a, invert_b, invert_result); // Walk the boundary of region A and build a list of all edge crossings. // We also keep track of whether the current vertex is inside region B. auto chain_start_iter = a_chain_starts.begin(); CrossingIterator next_crossing_iter(&b_index, &index_crossings_, true /*crossings_complete*/); ShapeEdgeId next_id = min(*chain_start_iter, next_crossing_iter.a_id()); while (next_id != kSentinel) { int a_shape_id = next_id.shape_id; const S2Shape& a_shape = *a_index.shape(a_shape_id); cp->StartShape(&a_shape); while (next_id.shape_id == a_shape_id) { // TODO(ericv): Special handling of dimension 0? Can omit most of this // code, including the loop, since all chains are of length 1. int edge_id = next_id.edge_id; S2Shape::ChainPosition chain_position = a_shape.chain_position(edge_id); int chain_id = chain_position.chain_id; S2Shape::Chain chain = a_shape.chain(chain_id); bool start_inside = (next_id == *chain_start_iter); if (start_inside) ++chain_start_iter; cp->StartChain(chain_id, chain, start_inside); int chain_limit = chain.start + chain.length; while (edge_id < chain_limit) { ShapeEdgeId a_id(a_shape_id, edge_id); ABSL_DCHECK(cp->inside() || next_crossing_iter.a_id() == a_id); if (!cp->ProcessEdge(a_id, &next_crossing_iter)) { return false; } if (cp->inside()) { ++edge_id; } else if (next_crossing_iter.a_id().shape_id == a_shape_id && next_crossing_iter.a_id().edge_id < chain_limit) { edge_id = next_crossing_iter.a_id().edge_id; } else { break; } } next_id = min(*chain_start_iter, next_crossing_iter.a_id()); } } return true; } // Returns the first edge of each edge chain from "a_region_id" whose first // vertex is contained by opposite region's polygons (using the semi-open // boundary model). Each input region and the result region are inverted as // specified (invert_a, invert_b, and invert_result) before testing for // containment. The algorithm uses these "chain starts" in order to clip the // boundary of A to the interior of B in an output-sensitive way. // // This method supports "early exit" in the case where a boolean predicate is // being evaluated and the algorithm discovers that the result region will be // non-empty. bool S2BooleanOperation::Impl::GetChainStarts( int a_region_id, bool invert_a, bool invert_b, bool invert_result, CrossingProcessor* cp, vector* chain_starts) { const S2ShapeIndex& a_index = *op_->regions_[a_region_id]; const S2ShapeIndex& b_index = *op_->regions_[1 - a_region_id]; if (is_boolean_output()) { // If boolean output is requested, then we use the CrossingProcessor to // determine whether the first edge of each chain will be emitted to the // output region. This lets us terminate the operation early in many // cases. cp->StartBoundary(a_region_id, invert_a, invert_b, invert_result); } // If region B has no two-dimensional shapes and is not inverted, then by // definition no chain starts are contained. However if boolean output is // requested then we check for containment anyway, since as a side effect we // may discover that the result region is non-empty and terminate the entire // operation early. bool b_has_interior = HasInterior(b_index); if (b_has_interior || invert_b || is_boolean_output()) { S2ContainsPointQuery query(&b_index); int num_shape_ids = a_index.num_shape_ids(); for (int shape_id = 0; shape_id < num_shape_ids; ++shape_id) { const S2Shape* a_shape = a_index.shape(shape_id); if (a_shape == nullptr) continue; // If region A is being subtracted from region B, points and polylines // in region A can be ignored since these shapes never contribute to the // output (they can only remove edges from region B). if (invert_a != invert_result && a_shape->dimension() < 2) continue; if (is_boolean_output()) cp->StartShape(a_shape); int num_chains = a_shape->num_chains(); for (int chain_id = 0; chain_id < num_chains; ++chain_id) { S2Shape::Chain chain = a_shape->chain(chain_id); if (chain.length == 0) continue; ShapeEdge a(shape_id, chain.start, a_shape->chain_edge(chain_id, 0)); bool inside = (b_has_interior && query.Contains(a.v0())) != invert_b; if (inside) { if (!tracker_.AddSpace(chain_starts, 1)) return false; chain_starts->push_back(ShapeEdgeId(shape_id, chain.start)); } if (is_boolean_output()) { cp->StartChain(chain_id, chain, inside); if (!ProcessIncidentEdges(a, &query, cp)) return false; } } } } if (!tracker_.AddSpace(chain_starts, 1)) return false; chain_starts->push_back(kSentinel); return true; } bool S2BooleanOperation::Impl::ProcessIncidentEdges( const ShapeEdge& a, S2ContainsPointQuery* query, CrossingProcessor* cp) { tmp_crossings_.clear(); query->VisitIncidentEdges(a.v0(), [&a, this](const ShapeEdge& b) { return AddIndexCrossing(a, b, false /*is_interior*/, &tmp_crossings_); }); // Fast path for the common case where there are no incident edges. We // return false (terminating early) if the first chain edge will be emitted. if (tmp_crossings_.empty()) { return !cp->inside(); } // Otherwise we invoke the full CrossingProcessor logic to determine whether // the first chain edge will be emitted. if (tmp_crossings_.size() > 1) { std::sort(tmp_crossings_.begin(), tmp_crossings_.end()); // VisitIncidentEdges() should not generate any duplicate values. ABSL_DCHECK( std::adjacent_find(tmp_crossings_.begin(), tmp_crossings_.end()) == tmp_crossings_.end()); } tmp_crossings_.push_back(IndexCrossing(kSentinel, kSentinel)); CrossingIterator next_crossing(&query->index(), &tmp_crossings_, false /*crossings_complete*/); return cp->ProcessEdge(a.id(), &next_crossing); } bool S2BooleanOperation::Impl::HasInterior(const S2ShapeIndex& index) { for (int s = index.num_shape_ids(); --s >= 0; ) { const S2Shape* shape = index.shape(s); if (shape && shape->dimension() == 2) return true; } return false; } inline bool S2BooleanOperation::Impl::AddIndexCrossing( const ShapeEdge& a, const ShapeEdge& b, bool is_interior, IndexCrossings* crossings) { if (!tracker_.AddSpace(crossings, 1)) return false; crossings->push_back(IndexCrossing(a.id(), b.id())); IndexCrossing* crossing = &crossings->back(); if (is_interior) { crossing->is_interior_crossing = true; if (s2pred::Sign(a.v0(), a.v1(), b.v0()) > 0) { crossing->left_to_right = true; } builder_->AddIntersection( S2::GetIntersection(a.v0(), a.v1(), b.v0(), b.v1())); } else { // TODO(ericv): This field isn't used unless one shape is a polygon and // the other is a polyline or polygon, but we don't have the shape // dimension information readily available here. if (S2::VertexCrossing(a.v0(), a.v1(), b.v0(), b.v1())) { crossing->is_vertex_crossing = true; } } return true; // Continue visiting. } // Initialize index_crossings_ to the set of crossing edge pairs such that the // first element of each pair is an edge from "region_id". // // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool S2BooleanOperation::Impl::InitIndexCrossings(int region_id) { if (region_id == index_crossings_first_region_id_) return true; if (index_crossings_first_region_id_ < 0) { ABSL_DCHECK_EQ(region_id, 0); // For efficiency, not correctness. // TODO(ericv): This would be more efficient if VisitCrossingEdgePairs() // returned the sign (+1 or -1) of the interior crossing, i.e. // "int interior_crossing_sign" rather than "bool is_interior". if (!s2shapeutil::VisitCrossingEdgePairs( *op_->regions_[0], *op_->regions_[1], s2shapeutil::CrossingType::ALL, [this](const ShapeEdge& a, const ShapeEdge& b, bool is_interior) { // For all supported operations (union, intersection, and // difference), if the input edges have an interior crossing // then the output is guaranteed to have at least one edge. if (is_interior && is_boolean_output()) return false; return AddIndexCrossing(a, b, is_interior, &index_crossings_); })) { return false; } if (index_crossings_.size() > 1) { std::sort(index_crossings_.begin(), index_crossings_.end()); index_crossings_.erase( std::unique(index_crossings_.begin(), index_crossings_.end()), index_crossings_.end()); } // Add a sentinel value to simplify the loop logic. tracker_.AddSpace(&index_crossings_, 1); index_crossings_.push_back(IndexCrossing(kSentinel, kSentinel)); index_crossings_first_region_id_ = 0; } if (region_id != index_crossings_first_region_id_) { for (auto& crossing : index_crossings_) { swap(crossing.a, crossing.b); // The following predicates get inverted when the edges are swapped. crossing.left_to_right ^= true; crossing.is_vertex_crossing ^= true; } std::sort(index_crossings_.begin(), index_crossings_.end()); index_crossings_first_region_id_ = region_id; } return tracker_.ok(); } // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool S2BooleanOperation::Impl::AddBoundaryPair( bool invert_a, bool invert_b, bool invert_result, CrossingProcessor* cp) { // Optimization: if the operation is DIFFERENCE or SYMMETRIC_DIFFERENCE, // it is worthwhile checking whether the two regions are identical (in which // case the output is empty). auto type = op_->op_type_; if (type == OpType::DIFFERENCE || type == OpType::SYMMETRIC_DIFFERENCE) { if (AreRegionsIdentical()) return true; } else if (is_boolean_output()) { // TODO(ericv): When boolean output is requested there are other quick // checks that could be done here, such as checking whether a full cell from // one S2ShapeIndex intersects a non-empty cell of the other S2ShapeIndex. } vector a_starts, b_starts; auto _ = absl::MakeCleanup([&]() { tracker_.Untally(a_starts); tracker_.Untally(b_starts); }); if (!GetChainStarts(0, invert_a, invert_b, invert_result, cp, &a_starts) || !GetChainStarts(1, invert_b, invert_a, invert_result, cp, &b_starts) || !AddBoundary(0, invert_a, invert_b, invert_result, a_starts, cp) || !AddBoundary(1, invert_b, invert_a, invert_result, b_starts, cp)) { return false; } if (!is_boolean_output()) cp->DoneBoundaryPair(); return tracker_.ok(); } // Supports "early exit" in the case of boolean results by returning false // as soon as the result is known to be non-empty. bool S2BooleanOperation::Impl::BuildOpType(OpType op_type) { // CrossingProcessor does the real work of emitting the output edges. CrossingProcessor cp(op_->options_.polygon_model(), op_->options_.polyline_model(), op_->options_.polyline_loops_have_boundaries(), builder_.get(), &input_dimensions_, &input_crossings_, &tracker_); switch (op_type) { case OpType::UNION: // A | B == ~(~A & ~B) return AddBoundaryPair(true, true, true, &cp); case OpType::INTERSECTION: // A & B return AddBoundaryPair(false, false, false, &cp); case OpType::DIFFERENCE: // A - B = A & ~B // // Note that degeneracies are implemented such that the symmetric // operation (-B + A) also produces correct results. This can be tested // by swapping op_->regions[0, 1] and calling AddBoundaryPair(true, // false, false), which computes (~B & A). return AddBoundaryPair(false, true, false, &cp); case OpType::SYMMETRIC_DIFFERENCE: // Compute the union of (A - B) and (B - A). return (AddBoundaryPair(false, true, false, &cp) && AddBoundaryPair(true, false, false, &cp)); } ABSL_LOG(FATAL) << "Invalid S2BooleanOperation::OpType"; return false; } // Returns a bit mask indicating which of the 6 S2 cube faces intersect the // index contents. uint8_t GetFaceMask(const S2ShapeIndex& index) { uint8_t mask = 0; S2ShapeIndex::Iterator it(&index, S2ShapeIndex::BEGIN); while (!it.done()) { int face = it.id().face(); mask |= 1 << face; it.Seek(S2CellId::FromFace(face + 1).range_min()); } return mask; } // Given a polygon edge graph containing only degenerate edges and sibling edge // pairs, the purpose of this function is to decide whether the polygon is empty // or full except for the degeneracies, i.e. whether the degeneracies represent // shells or holes. bool S2BooleanOperation::Impl::IsFullPolygonResult( const S2Builder::Graph& g, S2Error* absl_nonnull error) const { // If there are no edges of dimension 2, the result could be either the // empty polygon or the full polygon. Note that this is harder to determine // than you might think due to snapping. For example, the union of two // non-empty polygons can be empty, because both polygons consist of tiny // loops that are eliminated by snapping. Similarly, even if two polygons // both contain a common point their intersection can still be empty. // // We distinguish empty from full results using two heuristics: // // 1. We compute a bit mask representing the subset of the six S2 cube faces // intersected by each input geometry, and use this to determine if only // one of the two results is possible. (This test is very fast.) Note // that snapping will never cause the result to cover an entire extra // cube face because the maximum allowed snap radius is too small. ABSL_DCHECK_LE(S2Builder::SnapFunction::kMaxSnapRadius().degrees(), 70); // // 2. We compute the area of each input geometry, and use this to bound the // minimum and maximum area of the result. If only one of {0, 4*Pi} is // possible then we are done. If neither is possible then we choose the // one that is closest to being possible (since snapping can change the // result area). Both results are possible only when computing the // symmetric difference of two regions of area 2*Pi each, in which case we // must resort to additional heuristics (see below). // // TODO(ericv): Implement a predicate that uses the results of edge snapping // directly, rather than computing areas. This would not only be much faster // but would also allows all cases to be handled 100% robustly. const S2ShapeIndex& a = *op_->regions_[0]; const S2ShapeIndex& b = *op_->regions_[1]; switch (op_->op_type_) { case OpType::UNION: return IsFullPolygonUnion(a, b); case OpType::INTERSECTION: return IsFullPolygonIntersection(a, b); case OpType::DIFFERENCE: return IsFullPolygonDifference(a, b); case OpType::SYMMETRIC_DIFFERENCE: return IsFullPolygonSymmetricDifference(a, b); default: ABSL_LOG(FATAL) << "Invalid S2BooleanOperation::OpType"; return false; } } bool S2BooleanOperation::Impl::IsFullPolygonUnion( const S2ShapeIndex& a, const S2ShapeIndex& b) const { // See comments in IsFullPolygonResult(). The most common case is that // neither input polygon is empty but the result is empty due to snapping. // The result can be full only if the union of the two input geometries // intersects all six faces of the S2 cube. This test is fast. if ((GetFaceMask(a) | GetFaceMask(b)) != kAllFacesMask) return false; // The union area satisfies: // // max(A, B) <= Union(A, B) <= min(4*Pi, A + B) // // where A, B can refer to a polygon or its area. We then choose the result // that assumes the smallest amount of error. double a_area = S2::GetArea(a), b_area = S2::GetArea(b); double min_area = max(a_area, b_area); double max_area = min(4 * M_PI, a_area + b_area); return min_area > 4 * M_PI - max_area; } bool S2BooleanOperation::Impl::IsFullPolygonIntersection( const S2ShapeIndex& a, const S2ShapeIndex& b) const { // See comments in IsFullPolygonResult(). By far the most common case is // that the result is empty. // The result can be full only if each of the two input geometries // intersects all six faces of the S2 cube. This test is fast. if ((GetFaceMask(a) & GetFaceMask(b)) != kAllFacesMask) return false; // The intersection area satisfies: // // max(0, A + B - 4*Pi) <= Intersection(A, B) <= min(A, B) // // where A, B can refer to a polygon or its area. We then choose the result // that assumes the smallest amount of error. double a_area = S2::GetArea(a), b_area = S2::GetArea(b); double min_area = max(0.0, a_area + b_area - 4 * M_PI); double max_area = min(a_area, b_area); return min_area > 4 * M_PI - max_area; } bool S2BooleanOperation::Impl::IsFullPolygonDifference( const S2ShapeIndex& a, const S2ShapeIndex& b) const { // See comments in IsFullPolygonResult(). By far the most common case is // that the result is empty. // The result can be full only if each cube face is intersected by the first // geometry. (The second geometry is irrelevant, since for example it could // consist of a tiny loop on each S2 cube face.) This test is fast. if (GetFaceMask(a) != kAllFacesMask) return false; // The difference area satisfies: // // max(0, A - B) <= Difference(A, B) <= min(A, 4*Pi - B) // // where A, B can refer to a polygon or its area. We then choose the result // that assumes the smallest amount of error. double a_area = S2::GetArea(a), b_area = S2::GetArea(b); double min_area = max(0.0, a_area - b_area); double max_area = min(a_area, 4 * M_PI - b_area); return min_area > 4 * M_PI - max_area; } bool S2BooleanOperation::Impl::IsFullPolygonSymmetricDifference( const S2ShapeIndex& a, const S2ShapeIndex& b) const { // See comments in IsFullPolygonResult(). By far the most common case is // that the result is empty. // The result can be full only if the union of the two input geometries // intersects all six faces of the S2 cube. This test is fast. uint8_t a_mask = GetFaceMask(a); uint8_t b_mask = GetFaceMask(b); if ((a_mask | b_mask) != kAllFacesMask) return false; // The symmetric difference area satisfies: // // |A - B| <= SymmetricDifference(A, B) <= 4*Pi - |4*Pi - (A + B)| // // where A, B can refer to a polygon or its area. double a_area = S2::GetArea(a), b_area = S2::GetArea(b); double min_area = fabs(a_area - b_area); double max_area = 4 * M_PI - fabs(4 * M_PI - (a_area + b_area)); // Now we choose the result that assumes the smallest amount of error // (min_area in the empty case, and (4*Pi - max_area) in the full case). // However in the case of symmetric difference these two errors may be equal, // meaning that the result is ambiguous. This happens when both polygons have // area 2*Pi. Furthermore, this can happen even when the areas are not // exactly 2*Pi due to snapping and area calculation errors. // // To determine whether the result is ambiguous, we compute a rough estimate // of the maximum expected area error (including errors due to snapping), // using the worst-case error bound for a hemisphere defined by 4 vertices. auto edge_snap_radius = builder_options_.edge_snap_radius(); double hemisphere_area_error = 2 * M_PI * edge_snap_radius.radians() + 40 * DBL_EPSILON; // GetCurvatureMaxError // The following sign is the difference between the error needed for an empty // result and the error needed for a full result. It is negative if an // empty result is possible, positive if a full result is possible, and zero // if both results are possible. double error_sign = min_area - (4 * M_PI - max_area); if (fabs(error_sign) <= hemisphere_area_error) { // Handling the ambiguous case correctly requires a more sophisticated // algorithm (see below), but we can at least handle the simple cases by // testing whether both input geometries intersect all 6 cube faces. If // not, then the result is definitely full. if ((a_mask & b_mask) != kAllFacesMask) return true; // Otherwise both regions have area 2*Pi and intersect all 6 cube faces. // We choose "empty" in this case under the assumption that it is more // likely that the user is computing the difference between two nearly // identical polygons. // // TODO(ericv): Implement a robust algorithm based on examining the edge // snapping results directly, or alternatively add another heuristic (such // as testing containment of random points, or using a larger bit mask in // the tests above, e.g. a 24-bit mask representing all level 1 cells). return false; } return error_sign > 0; } // When subtracting regions, we can save a lot of work by detecting the // relatively common case where the two regions are identical. bool S2BooleanOperation::Impl::AreRegionsIdentical() const { const S2ShapeIndex* a = op_->regions_[0]; const S2ShapeIndex* b = op_->regions_[1]; if (a == b) return true; // If the regions are not identical, we would like to detect that fact as // quickly as possible. In particular we would like to avoid fully decoding // both shapes if they are represented as encoded shape types. // // First we test whether the two geometries have the same dimensions and // chain structure. This can be done without decoding any S2Points. int num_shape_ids = a->num_shape_ids(); if (num_shape_ids != b->num_shape_ids()) return false; for (int s = 0; s < num_shape_ids; ++s) { const S2Shape* a_shape = a->shape(s); const S2Shape* b_shape = b->shape(s); int dimension = a_shape->dimension(); if (dimension != b_shape->dimension()) return false; int num_chains = a_shape->num_chains(); if (num_chains != b_shape->num_chains()) return false; int num_edges = a_shape->num_edges(); if (num_edges != b_shape->num_edges()) return false; if (dimension == 0) { ABSL_DCHECK_EQ(num_edges, num_chains); // All chains are of length 1. continue; } for (int c = 0; c < num_chains; ++c) { S2Shape::Chain a_chain = a_shape->chain(c); S2Shape::Chain b_chain = b_shape->chain(c); ABSL_DCHECK_EQ(a_chain.start, b_chain.start); if (a_chain.length != b_chain.length) return false; } } // Next we test whether both geometries have the same vertex positions. for (int s = 0; s < num_shape_ids; ++s) { const S2Shape* a_shape = a->shape(s); const S2Shape* b_shape = b->shape(s); int num_chains = a_shape->num_chains(); for (int c = 0; c < num_chains; ++c) { S2Shape::Chain a_chain = a_shape->chain(c); for (int i = 0; i < a_chain.length; ++i) { S2Shape::Edge a_edge = a_shape->chain_edge(c, i); S2Shape::Edge b_edge = b_shape->chain_edge(c, i); if (a_edge.v0 != b_edge.v0) return false; if (a_edge.v1 != b_edge.v1) return false; } } // Note that we don't need to test whether both shapes have the same // GetReferencePoint(), because S2Shape requires that the full geometry of // the shape (including its interior) must be derivable from its chains // and edges. This is why the "full loop" exists; see s2shape.h. } return true; } void S2BooleanOperation::Impl::DoBuild(S2Error* absl_nonnull error) { if (!tracker_.ok()) return; builder_options_ = S2Builder::Options(op_->options_.snap_function()); builder_options_.set_intersection_tolerance(S2::kIntersectionError); builder_options_.set_memory_tracker(tracker_.tracker()); if (op_->options_.split_all_crossing_polyline_edges()) { builder_options_.set_split_crossing_edges(true); } // TODO(ericv): Ideally idempotent() should be true, but existing clients // expect vertices closer than the full "snap_radius" to be snapped. builder_options_.set_idempotent(false); if (is_boolean_output()) { // BuildOpType() returns true if and only if the result has no edges. S2Builder::Graph g; // Unused by IsFullPolygonResult() implementation. *op_->result_empty_ = BuildOpType(op_->op_type_) && !IsFullPolygonResult(g, error); return; } builder_ = make_unique(builder_options_); builder_->StartLayer(make_unique( &op_->layers_, &input_dimensions_, &input_crossings_, &tracker_)); // Add a predicate that decides whether a result with no polygon edges should // be interpreted as the empty polygon or the full polygon. builder_->AddIsFullPolygonPredicate( [this](const S2Builder::Graph& g, S2Error* absl_nonnull error) { return IsFullPolygonResult(g, error); }); (void) BuildOpType(op_->op_type_); // Release memory that is no longer needed. if (!tracker_.Clear(&index_crossings_)) return; builder_->Build(error); } bool S2BooleanOperation::Impl::Build(S2Error* absl_nonnull error) { // This wrapper ensures that memory tracking errors are reported. *error = S2Error::Ok(); DoBuild(error); if (!tracker_.ok()) *error = tracker_.error(); return error->ok(); } S2BooleanOperation::Options::Options() : snap_function_(make_unique( S1Angle::Zero())) { } S2BooleanOperation::Options::Options(const SnapFunction& snap_function) : snap_function_(snap_function.Clone()) { } S2BooleanOperation::Options::Options(const Options& options) : snap_function_(options.snap_function_->Clone()), polygon_model_(options.polygon_model_), polyline_model_(options.polyline_model_), polyline_loops_have_boundaries_(options.polyline_loops_have_boundaries_), split_all_crossing_polyline_edges_( options.split_all_crossing_polyline_edges_), precision_(options.precision_), conservative_output_(options.conservative_output_), source_id_lexicon_(options.source_id_lexicon_), memory_tracker_(options.memory_tracker_) { } S2BooleanOperation::Options& S2BooleanOperation::Options::operator=( const Options& options) { snap_function_ = options.snap_function_->Clone(); polygon_model_ = options.polygon_model_; polyline_model_ = options.polyline_model_; polyline_loops_have_boundaries_ = options.polyline_loops_have_boundaries_; split_all_crossing_polyline_edges_ = options.split_all_crossing_polyline_edges_; precision_ = options.precision_; conservative_output_ = options.conservative_output_; source_id_lexicon_ = options.source_id_lexicon_; memory_tracker_ = options.memory_tracker_; return *this; } const SnapFunction& S2BooleanOperation::Options::snap_function() const { return *snap_function_; } void S2BooleanOperation::Options::set_snap_function( const SnapFunction& snap_function) { snap_function_ = snap_function.Clone(); } PolygonModel S2BooleanOperation::Options::polygon_model() const { return polygon_model_; } void S2BooleanOperation::Options::set_polygon_model(PolygonModel model) { polygon_model_ = model; } PolylineModel S2BooleanOperation::Options::polyline_model() const { return polyline_model_; } void S2BooleanOperation::Options::set_polyline_model(PolylineModel model) { polyline_model_ = model; } bool S2BooleanOperation::Options::polyline_loops_have_boundaries() const { return polyline_loops_have_boundaries_; } void S2BooleanOperation::Options::set_polyline_loops_have_boundaries( bool value) { polyline_loops_have_boundaries_ = value; } bool S2BooleanOperation::Options::split_all_crossing_polyline_edges() const { return split_all_crossing_polyline_edges_; } void S2BooleanOperation::Options::set_split_all_crossing_polyline_edges( bool value) { split_all_crossing_polyline_edges_ = value; } Precision S2BooleanOperation::Options::precision() const { return precision_; } bool S2BooleanOperation::Options::conservative_output() const { return conservative_output_; } ValueLexicon* S2BooleanOperation::Options::source_id_lexicon() const { return source_id_lexicon_; } S2MemoryTracker* S2BooleanOperation::Options::memory_tracker() const { return memory_tracker_; } void S2BooleanOperation::Options::set_memory_tracker(S2MemoryTracker* tracker) { memory_tracker_ = tracker; } string_view S2BooleanOperation::OpTypeToString(OpType op_type) { switch (op_type) { case OpType::UNION: return "UNION"; case OpType::INTERSECTION: return "INTERSECTION"; case OpType::DIFFERENCE: return "DIFFERENCE"; case OpType::SYMMETRIC_DIFFERENCE: return "SYMMETRIC DIFFERENCE"; default: return "Unknown OpType"; } } string_view S2BooleanOperation::PolygonModelToString(PolygonModel model) { switch (model) { case PolygonModel::OPEN: return "OPEN"; case PolygonModel::SEMI_OPEN: return "SEMI_OPEN"; case PolygonModel::CLOSED: return "CLOSED"; default: return "Unknown PolygonModel"; } } string_view S2BooleanOperation::PolylineModelToString(PolylineModel model) { switch (model) { case PolylineModel::OPEN: return "OPEN"; case PolylineModel::SEMI_OPEN: return "SEMI_OPEN"; case PolylineModel::CLOSED: return "CLOSED"; default: return "Unknown PolylineModel"; } } S2BooleanOperation::S2BooleanOperation(OpType op_type, const Options& options) : options_(options), op_type_(op_type) {} S2BooleanOperation::S2BooleanOperation(OpType op_type, bool* result_empty, const Options& options) : options_(options), op_type_(op_type), result_empty_(result_empty) { } S2BooleanOperation::S2BooleanOperation(OpType op_type, unique_ptr layer, const Options& options) : options_(options), op_type_(op_type) { layers_.push_back(std::move(layer)); } S2BooleanOperation::S2BooleanOperation( OpType op_type, vector> layers, const Options& options) : options_(options), op_type_(op_type), layers_(std::move(layers)) {} bool S2BooleanOperation::Build(const S2ShapeIndex& a, const S2ShapeIndex& b, S2Error* absl_nonnull error) { regions_[0] = &a; regions_[1] = &b; return Impl(this).Build(error); } bool S2BooleanOperation::IsEmpty( OpType op_type, const S2ShapeIndex& a, const S2ShapeIndex& b, const Options& options) { bool result_empty; S2BooleanOperation op(op_type, &result_empty, options); S2Error error; op.Build(a, b, &error); ABSL_DCHECK(error.ok()); return result_empty; } src/s2/s2boolean_operation.h000066400000000000000000000663761524103652300163310ustar00rootroot00000000000000// Copyright 2017 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_S2BOOLEAN_OPERATION_H_ #define S2_S2BOOLEAN_OPERATION_H_ #include #include #include #include #include "absl/base/nullability.h" #include "absl/log/absl_log.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/s2builder.h" #include "s2/s2builder_graph.h" #include "s2/s2builder_layer.h" #include "s2/s2error.h" #include "s2/s2memory_tracker.h" #include "s2/s2shape_index.h" #include "s2/value_lexicon.h" // This class implements boolean operations (intersection, union, difference, // and symmetric difference) for regions whose boundaries are defined by // geodesic edges. // // S2BooleanOperation operates on exactly two input regions at a time. Each // region is represented as an S2ShapeIndex and may contain any number of // points, polylines, and polygons. The region is essentially the union of // these objects, except that polygon interiors must be disjoint from all // other geometry (including other polygon interiors). If the input geometry // for a region does not meet this condition, it can be normalized by // computing its union first. Duplicate polygon edges are not allowed (even // among different polygons), however polylines may have duplicate edges and // may even be self-intersecting. Note that points or polylines are allowed // to coincide with the boundaries of polygons. // // Degeneracies are fully supported. Supported degeneracy types include the // following: // // - Point polylines consisting of a single degenerate edge AA. // // - Point loops consisting of a single vertex A. Such loops may represent // either shells or holes according to whether the loop adds to or // subtracts from the surrounding region of the polygon. // // - Sibling edge pairs of the form {AB, BA}. Such sibling pairs may // represent either shells or holes according to whether they add to or // subtract from the surrounding region. The edges of a sibling pair may // belong to the same polygon loop (e.g. a loop AB) or to different polygon // loops or polygons (e.g. the polygons {ABC, CBD}). // // A big advantage of degeneracy support is that geometry may be simplified // without completely losing small details. For example, if a polygon // representing a land area with many lakes and rivers is simplified using a // tolerance of 1 kilometer, every water feature in the input is guaranteed to // be within 1 kilometer of some water feature in the input (even if some // lakes and rivers are merged and/or reduced to degenerate point or sibling // edge pair holes). Mathematically speaking, degeneracy support allows // geometry to be simplified while guaranteeing that the Hausdorff distance // between the boundaries of the original and simplified geometries is at // most the simplification tolerance. It also allows geometry to be // simplified without changing its dimension, thus preserving boundary // semantics. (Note that the boundary of a polyline ABCD is {A,D}, whereas // the boundary of a degenerate shell ABCDCB is its entire set of vertices and // edges.) // // Points and polyline edges are treated as multisets: if the same point or // polyline edge appears multiple times in the input, it will appear multiple // times in the output. For example, the union of a point with an identical // point consists of two points. This feature is useful for modeling large // sets of points or polylines as a single region while maintaining their // distinct identities, even when the points or polylines intersect each // other. It is also useful for reconstructing polylines that loop back on // themselves (e.g., time series such as GPS tracks). If duplicate geometry // is not desired, it can easily be removed by choosing the appropriate // S2Builder output layer options. // // Self-intersecting polylines can be manipulated without materializing new // vertices at the self-intersection points. This feature is important when // processing polylines with large numbers of self-intersections such as GPS // tracks (e.g., consider the path of a race car in the Indy 500). // // Polylines are always considered to be directed. Polyline edges between the // same pair of vertices are defined to intersect even if the two edges are in // opposite directions. (Undirected polylines can be modeled by specifying // GraphOptions::EdgeType::UNDIRECTED in the S2Builder output layer.) // // The output of each operation is sent to an S2Builder::Layer provided by the // client. This allows clients to build any representation of the geometry // they choose. It also allows the client to do additional postprocessing of // the output before building data structures; for example, the client can // easily discard degeneracies or convert them to another data type. // // The boundaries of polygons and polylines can be modeled as open, semi-open, // or closed. Polyline boundaries are controlled by the PolylineModel class, // whose options are as follows: // // - In the OPEN model, polylines do not contain their first or last vertex // except for one special case: namely, if the polyline forms a loop and // the polyline_loops_have_boundaries() option is set to false, then the // first/last vertex is contained. // // - In the SEMI_OPEN model, polylines contain all vertices except the last. // Therefore if one polyline starts where another polyline stops, the two // polylines do not intersect. // // - In the CLOSED model, polylines contain all of their vertices. // // When multiple polylines are present, they are processed independently and // have no effect on each other. For example, in the OPEN boundary model the // polyline ABC contains the vertex B, while set of polylines {AB, BC} does // not. (If you want to treat the polylines as a union instead, with // boundaries merged according to the "mod 2" rule, this can be achieved by // reassembling the edges into maximal polylines using S2PolylineVectorLayer // with EdgeType::UNDIRECTED, DuplicateEdges::MERGE, and PolylineType::WALK.) // // Polygon boundaries are controlled by the PolygonModel class, which has the // following options: // // - In the OPEN model, polygons do not contain their vertices or edges. // This implies that a polyline that follows the boundary of a polygon will // not intersect it. // // - In the SEMI_OPEN model, polygon point containment is defined such that // if several polygons tile the region around a vertex, then exactly one of // those polygons contains that vertex. Similarly polygons contain all of // their edges, but none of their reversed edges. This implies that a // polyline and polygon edge with the same endpoints intersect if and only // if they are in the same direction. (This rule ensures that if a // polyline is intersected with a polygon and its complement, the two // resulting polylines do not have any edges in common.) // // - In the CLOSED model, polygons contain all their vertices, edges, and // reversed edges. This implies that a polyline that shares an edge (in // either direction) with a polygon is defined to intersect it. Similarly, // this is the only model where polygons that touch at a vertex or along an // edge intersect. // // Note that PolylineModel and PolygonModel are defined as separate classes in // order to allow for possible future extensions. // // Operations between geometry of different dimensions are defined as follows: // // - For UNION, the higher-dimensional shape always wins. For example the // union of a closed polygon A with a polyline B that coincides with the // boundary of A consists only of the polygon A. // // - For INTERSECTION, the lower-dimensional shape always wins. For example, // the intersection of a closed polygon A with a point B that coincides // with a vertex of A consists only of the point B. // // - For DIFFERENCE, higher-dimensional shapes are not affected by // subtracting lower-dimensional shapes. For example, subtracting a point // or polyline from a polygon A yields the original polygon A. This rule // exists because in general, it is impossible to represent the output // using the specified boundary model(s). (Consider subtracting one vertex // from a PolylineModel::CLOSED polyline, or subtracting one edge from a // PolygonModel::CLOSED polygon.) If you want to perform operations like // this, consider representing all boundaries explicitly (topological // boundaries) using OPEN boundary models. Another option for polygons is // to subtract a degenerate loop, which yields a polygon with a degenerate // hole (see S2LaxPolygonShape). // // Note that in the case of Precision::EXACT operations, the above remarks // only apply to the output before snapping. Snapping may cause nearby // distinct edges to become coincident, e.g. a polyline may become coincident // with a polygon boundary. However also note that S2BooleanOperation is // perfectly happy to accept such geometry as input. // // Example usage: // S2ShapeIndex a, b; // Input geometry, e.g. containing polygons. // S2Polygon polygon; // Output geometry. // S2BooleanOperation::Options options; // options.set_snap_function(snap_function); // S2BooleanOperation op(S2BooleanOperation::OpType::INTERSECTION, // std::make_unique(&polygon), // options); // S2Error error; // if (!op.Build(a, b, &error)) { // ABSL_LOG(ERROR) << error; // ... // } // // If the output includes objects of different dimensions, they can be // assembled into different layers with code like this: // // vector points; // vector> polylines; // S2Polygon polygon; // S2BooleanOperation op( // S2BooleanOperation::OpType::UNION, // std::make_unique(&points), // std::make_unique(&polylines), // std::make_unique(&polygon)); class S2BooleanOperation { public: // The supported operation types. enum class OpType : uint8_t { UNION, // Contained by either region. INTERSECTION, // Contained by both regions. DIFFERENCE, // Contained by the first region but not the second. SYMMETRIC_DIFFERENCE // Contained by one region but not the other. }; // Translates OpType to one of the strings above. static absl::string_view OpTypeToString(OpType op_type); // Defines whether polygons are considered to contain their vertices and/or // edges (see definitions above). enum class PolygonModel : uint8_t { OPEN, SEMI_OPEN, CLOSED }; // Translates PolygonModel to one of the strings above. static absl::string_view PolygonModelToString(PolygonModel model); // Defines whether polylines are considered to contain their endpoints // (see definitions above). enum class PolylineModel : uint8_t { OPEN, SEMI_OPEN, CLOSED }; // Translates PolylineModel to one of the strings above. static absl::string_view PolylineModelToString(PolylineModel model); // With Precision::EXACT, the operation is evaluated using the exact input // geometry. Predicates that use this option will produce exact results; // for example, they can distinguish between a polyline that barely // intersects a polygon from one that barely misses it. Constructive // operations (ones that yield new geometry, as opposed to predicates) are // implemented by computing the exact result and then snap rounding it // according to the given snap_function() (see below). This is as close as // it is possible to get to the exact result while requiring that vertex // coordinates have type "double". // // With Precision::SNAPPED, the input regions are snapped together *before* // the operation is evaluated. So for example, two polygons that overlap // slightly will be treated as though they share a common boundary, and // similarly two polygons that are slightly separated from each other will // be treated as though they share a common boundary. Snapped results are // useful for dealing with points, since in S2 the only points that lie // exactly on a polyline or polygon edge are the endpoints of that edge. // // Conceptually, the difference between these two options is that with // Precision::SNAPPED, the inputs are snap rounded (together), whereas with // Precision::EXACT only the result is snap rounded. enum class Precision : uint8_t { EXACT, SNAPPED }; // SourceId identifies an edge from one of the two input S2ShapeIndexes. // It consists of a region id (0 or 1), a shape id within that region's // S2ShapeIndex, and an edge id within that shape. class SourceId { public: SourceId(); SourceId(int region_id, int32_t shape_id, int32_t edge_id); explicit SourceId(int32_t special_edge_id); int region_id() const { return region_id_; } int32_t shape_id() const { return shape_id_; } int32_t edge_id() const { return edge_id_; } // TODO(ericv): Convert to functions, define all 6 comparisons. bool operator==(SourceId other) const; bool operator<(SourceId other) const; private: // TODO(user): Use in-class initializers when C++20 is allowed in // opensource. uint32_t region_id_ : 1; uint32_t shape_id_ : 31; int32_t edge_id_; }; class Options { public: Options(); // Convenience constructor that calls set_snap_function(). explicit Options(const S2Builder::SnapFunction& snap_function); // Specifies the function to be used for snap rounding. // // DEFAULT: s2builderutil::IdentitySnapFunction(S1Angle::Zero()) // - This does no snapping and preserves all input vertices exactly unless // there are crossing edges, in which case the snap radius is increased // to the maximum intersection point error (S2::kIntersectionError). const S2Builder::SnapFunction& snap_function() const; void set_snap_function(const S2Builder::SnapFunction& snap_function); // Defines whether polygons are considered to contain their vertices // and/or edges (see comments above). // // DEFAULT: PolygonModel::SEMI_OPEN PolygonModel polygon_model() const; void set_polygon_model(PolygonModel model); // Defines whether polylines are considered to contain their vertices (see // comments above). // // DEFAULT: PolylineModel::CLOSED PolylineModel polyline_model() const; void set_polyline_model(PolylineModel model); // Specifies whether a polyline loop is considered to have a non-empty // boundary. By default this option is true, meaning that even if the // first and last vertices of a polyline are the same, the polyline is // considered to have a well-defined "start" and "end". For example, if // the polyline boundary model is OPEN then the polyline loop would not // include the start/end vertices. These are the best semantics for most // applications, such as GPS tracks or road network segments. // // If the polyline forms a loop and this option is set to false, then // instead the first and last vertices are considered to represent a // single vertex in the interior of the polyline. In this case the // boundary of the polyline is empty, meaning that the first/last vertex // will be contained by the polyline even if the boundary model is OPEN. // (Note that this option also has a small effect on the CLOSED boundary // model, because the first/last vertices of a polyline loop are // considered to represent one vertex rather than two.) // // The main reason for this option is to implement the "mod 2 union" // boundary semantics of the OpenGIS Simple Features spec. This can be // achieved by making sure that all polylines are constructed using // S2Builder::Graph::PolylineType::WALK (which ensures that all polylines // are as long as possible), and then setting this option to false. // // DEFAULT: true bool polyline_loops_have_boundaries() const; void set_polyline_loops_have_boundaries(bool value); // Specifies that a new vertex should be added whenever a polyline edge // crosses another polyline edge. Note that this can cause the size of // polylines with many self-intersections to increase quadratically. // // If false, new vertices are added only when a polyline from one input // region cross a polyline from the other input region. This allows // self-intersecting input polylines to be modified as little as possible. // // DEFAULT: false bool split_all_crossing_polyline_edges() const; void set_split_all_crossing_polyline_edges(bool value); // Specifies whether the operation should use the exact input geometry // (Precision::EXACT), or whether the two input regions should be snapped // together first (Precision::SNAPPED). // // DEFAULT: Precision::EXACT Precision precision() const; // TODO(b/78590369): Precision.SNAPPED is not yet implemented. // void set_precision(Precision precision); // If true, the input geometry is interpreted as representing nearby // geometry that has been snapped or simplified. It then outputs a // conservative result based on the value of polygon_model() and // polyline_model(). For the most part, this only affects the handling of // degeneracies. // // - If the model is OPEN, the result is as open as possible. For // example, the intersection of two identical degenerate shells is empty // under PolygonModel::OPEN because they could have been disjoint before // snapping. Similarly, two identical degenerate polylines have an // empty intersection under PolylineModel::OPEN. // // - If the model is CLOSED, the result is as closed as possible. In the // case of the DIFFERENCE operation, this is equivalent to evaluating // A - B as Closure(A) - Interior(B). For other operations, it affects // only the handling of degeneracies. For example, the union of two // identical degenerate holes is empty under PolygonModel::CLOSED // (i.e., the hole disappears) because the holes could have been // disjoint before snapping. // // - If the model is SEMI_OPEN, the result is as degenerate as possible. // New degeneracies will not be created, but all degeneracies that // coincide with the opposite region's boundary are retained unless this // would cause a duplicate polygon edge to be created. This model is // is very useful for working with input data that has both positive and // negative degeneracies (i.e., degenerate shells and holes). // // DEFAULT: false bool conservative_output() const; // TODO(b/315152896): Implement support for conservative output. // void set_conservative_output(bool conservative); // If specified, then each output edge will be labelled with one or more // SourceIds indicating which input edge(s) it corresponds to. This // can be useful if your input geometry has additional data that needs to // be propagated from the input to the output (e.g., elevations). // // You can access the labels by using an S2Builder::Layer type that // supports labels, such as S2PolygonLayer. The layer outputs a // "label_set_lexicon" and an "label_set_id" for each edge. You can then // look up the source information for each edge like this: // // for (int32_t label : label_set_lexicon.id_set(label_set_id)) { // const SourceId& src = source_id_lexicon.value(label); // // region_id() specifies which S2ShapeIndex the edge is from (0 or 1). // DoSomething(src.region_id(), src.shape_id(), src.edge_id()); // } // // DEFAULT: nullptr ValueLexicon* source_id_lexicon() const; // TODO(b/314819022): Implement support for source_id_lexicon. // void set_source_id_lexicon(ValueLexicon* source_id_lexicon); // Specifies that internal memory usage should be tracked using the given // S2MemoryTracker. If a memory limit is specified and more more memory // than this is required then an error will be returned. Example usage: // // S2MemoryTracker tracker; // tracker.set_limit(500 << 20); // 500 MB // S2BooleanOperation::Options options; // options.set_memory_tracker(&tracker); // S2BooleanOperation op(..., options); // ... // S2Error error; // if (!op.Build(..., &error)) { // if (error.code() == S2Error::RESOURCE_EXHAUSTED) { // ABSL_LOG(ERROR) << error; // Memory limit exceeded // } // } // // CAVEATS: // // - Memory used by the input S2ShapeIndexes and the output S2Builder // layers is not counted towards the total. // // - While memory tracking is reasonably complete and accurate, it does // not account for every last byte. It is intended only for the // purpose of preventing clients from running out of memory. // // DEFAULT: nullptr (memory tracking disabled) S2MemoryTracker* memory_tracker() const; void set_memory_tracker(S2MemoryTracker* tracker); // Options may be assigned and copied. Options(const Options& options); Options& operator=(const Options& options); private: std::unique_ptr snap_function_; PolygonModel polygon_model_ = PolygonModel::SEMI_OPEN; PolylineModel polyline_model_ = PolylineModel::CLOSED; bool polyline_loops_have_boundaries_ = true; bool split_all_crossing_polyline_edges_ = false; Precision precision_ = Precision::EXACT; bool conservative_output_ = false; ValueLexicon* source_id_lexicon_ = nullptr; S2MemoryTracker* memory_tracker_ = nullptr; }; #ifndef SWIG // Specifies that the output boundary edges should be sent to a single // S2Builder layer. This version can be used when the dimension of the // output geometry is known (e.g., intersecting two polygons to yield a // third polygon). S2BooleanOperation(OpType op_type, std::unique_ptr layer, const Options& options = Options()); // Specifies that the output boundary edges should be sent to three // different layers according to their dimension. Points (represented by // degenerate edges) are sent to layer 0, polyline edges are sent to // layer 1, and polygon edges are sent to layer 2. // // The dimension of an edge is defined as the minimum dimension of the two // input edges that produced it. For example, the intersection of two // crossing polyline edges is a considered to be a degenerate polyline // rather than a point, so it is sent to layer 1. Clients can easily // reclassify such polylines as points if desired, but this rule makes it // easier for clients that want to process point, polyline, and polygon // inputs differently. // // The layers are always built in the order 0, 1, 2, and all arguments to // the Build() calls are guaranteed to be valid until the last call returns. // All Graph objects have the same set of vertices and the same lexicon // objects, in order to make it easier to write classes that process all the // edges in parallel. S2BooleanOperation(OpType op_type, std::vector> layers, const Options& options = Options()); #endif OpType op_type() const { return op_type_; } const Options& options() const { return options_; } // Executes the given operation. Returns true on success, and otherwise // sets "error" appropriately. (This class does not generate any errors // itself, but the S2Builder::Layer might.) bool Build(const S2ShapeIndex& a, const S2ShapeIndex& b, S2Error* absl_nonnull error); // Convenience method that returns true if the result of the given operation // is empty. static bool IsEmpty(OpType op_type, const S2ShapeIndex& a, const S2ShapeIndex& b, const Options& options = Options()); // Convenience method that returns true if A intersects B. static bool Intersects(const S2ShapeIndex& a, const S2ShapeIndex& b, const Options& options = Options()) { return !IsEmpty(OpType::INTERSECTION, b, a, options); } // Convenience method that returns true if A contains B, i.e., if the // difference (B - A) is empty. static bool Contains(const S2ShapeIndex& a, const S2ShapeIndex& b, const Options& options = Options()) { return IsEmpty(OpType::DIFFERENCE, b, a, options); } // Convenience method that returns true if the symmetric difference of A and // B is empty. (Note that A and B may still not be identical, e.g. A may // contain two copies of a polyline while B contains one.) static bool Equals(const S2ShapeIndex& a, const S2ShapeIndex& b, const Options& options = Options()) { return IsEmpty(OpType::SYMMETRIC_DIFFERENCE, b, a, options); } private: class Impl; // The actual implementation. // Internal constructor to reduce code duplication. S2BooleanOperation(OpType op_type, const Options& options); // Specifies that "result_empty" should be set to indicate whether the exact // result of the operation is empty. This constructor is used to efficiently // test boolean relationships (see IsEmpty above). S2BooleanOperation(OpType op_type, bool* result_empty, const Options& options = Options()); Options options_; OpType op_type_; // The input regions. const S2ShapeIndex* regions_[2]; // The output consists either of zero layers, one layer, or three layers. std::vector> layers_; // The following field is set if and only if there are no output layers. bool* result_empty_ = nullptr; }; ////////////////// Implementation details follow //////////////////// inline S2BooleanOperation::SourceId::SourceId() : region_id_(0), shape_id_(0), edge_id_(-1) { } inline S2BooleanOperation::SourceId::SourceId(int region_id, int32_t shape_id, int32_t edge_id) : region_id_(region_id), shape_id_(shape_id), edge_id_(edge_id) {} inline S2BooleanOperation::SourceId::SourceId(int special_edge_id) : region_id_(0), shape_id_(0), edge_id_(special_edge_id) { } inline bool S2BooleanOperation::SourceId::operator==(SourceId other) const { return (region_id_ == other.region_id_ && shape_id_ == other.shape_id_ && edge_id_ == other.edge_id_); } inline bool S2BooleanOperation::SourceId::operator<(SourceId other) const { if (region_id_ < other.region_id_) return true; if (region_id_ > other.region_id_) return false; if (shape_id_ < other.shape_id_) return true; if (shape_id_ > other.shape_id_) return false; return edge_id_ < other.edge_id_; } #endif // S2_S2BOOLEAN_OPERATION_H_ src/s2/s2boolean_operation_test.cc000066400000000000000000003342311524103652300175120ustar00rootroot00000000000000// Copyright 2017 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/s2boolean_operation.h" #include #include #include #include #include #include #include #include "absl/base/nullability.h" #include "absl/flags/declare.h" #include "absl/flags/flag.h" #include "absl/flags/reflection.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/log/log_streamer.h" #include "absl/random/bit_gen_ref.h" #include "absl/random/random.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "s2/mutable_s2shape_index.h" #include "s2/s1angle.h" #include "s2/s2builder.h" #include "s2/s2builder_graph.h" #include "s2/s2builder_layer.h" #include "s2/s2builderutil_lax_polygon_layer.h" #include "s2/s2builderutil_s2point_vector_layer.h" #include "s2/s2builderutil_s2polyline_vector_layer.h" #include "s2/s2builderutil_snap_functions.h" #include "s2/s2builderutil_testing.h" #include "s2/s2edge_crossings.h" #include "s2/s2error.h" #include "s2/s2latlng.h" #include "s2/s2lax_polygon_shape.h" #include "s2/s2lax_polyline_shape.h" #include "s2/s2loop.h" #include "s2/s2memory_tracker.h" #include "s2/s2point.h" #include "s2/s2point_vector_shape.h" #include "s2/s2pointutil.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2random.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2shapeutil_contains_brute_force.h" #include "s2/s2testing.h" #include "s2/s2text_format.h" #include "s2/util/math/matrix3x3.h" ABSL_DECLARE_FLAG(int64_t, s2shape_index_tmp_memory_budget); namespace { using absl::ByAnyChar; using absl::SkipEmpty; using absl::StrCat; using absl::StrContains; using absl::string_view; using absl::StrSplit; using s2builderutil::IndexMatchingLayer; using s2builderutil::LaxPolygonLayer; using s2shapeutil::ContainsBruteForce; using std::make_unique; using std::pair; using std::string; using std::unique_ptr; using std::vector; using EdgeType = S2Builder::EdgeType; using Graph = S2Builder::Graph; using GraphOptions = S2Builder::GraphOptions; using DegenerateEdges = GraphOptions::DegenerateEdges; using DuplicateEdges = GraphOptions::DuplicateEdges; using SiblingPairs = GraphOptions::SiblingPairs; using OpType = S2BooleanOperation::OpType; using PolygonModel = S2BooleanOperation::PolygonModel; using PolylineModel = S2BooleanOperation::PolylineModel; using DegenerateBoundaries = LaxPolygonLayer::Options::DegenerateBoundaries; void ExpectResult(S2BooleanOperation::OpType op_type, const S2BooleanOperation::Options& options, const S2ShapeIndex& a, const S2ShapeIndex& b, const S2ShapeIndex& expected) { vector> layers; for (int dim = 0; dim < 3; ++dim) { // Since all S2Builder polygon layers require DISCARD or DISCARD_EXCESS // for degenerate edges, we intentionally do not require any specific // multiplicity for degenerate edges and sibling pairs of dimension 2. GraphOptions graph_options( EdgeType::DIRECTED, (dim == 2) ? DegenerateEdges::DISCARD_EXCESS : DegenerateEdges::KEEP, DuplicateEdges::KEEP, (dim == 2) ? SiblingPairs::DISCARD_EXCESS : SiblingPairs::KEEP); layers.push_back(make_unique( graph_options, &expected, dim)); } S2BooleanOperation op(op_type, std::move(layers), options); S2Error error; ASSERT_TRUE(op.Build(a, b, &error)) << S2BooleanOperation::OpTypeToString(op_type) << " failed:\n" << "Expected result: " << s2textformat::ToString(expected) << "\n" << error; // Now try the same thing with boolean output. EXPECT_EQ(expected.num_shape_ids() == 0, S2BooleanOperation::IsEmpty(op_type, a, b, options)); } void ExpectResult(S2BooleanOperation::OpType op_type, const S2BooleanOperation::Options& options, string_view a_str, string_view b_str, string_view expected_str) { auto a = s2textformat::MakeIndexOrDie(a_str); auto b = s2textformat::MakeIndexOrDie(b_str); auto expected = s2textformat::MakeIndexOrDie(expected_str); ExpectResult(op_type, options, *a, *b, *expected); } // The intersections in the "expected" data below were computed in lat-lng // space (i.e., the rectangular projection), while the actual intersections // are computed using geodesics. We can compensate for this by rounding the // intersection points to a fixed precision in degrees (e.g., 2 decimals). static S2BooleanOperation::Options RoundToE(int exp) { S2BooleanOperation::Options options; options.set_snap_function(s2builderutil::IntLatLngSnapFunction(exp)); return options; } TEST(S2BooleanOperation, OpTypeAccessor) { vector> layers; const S2BooleanOperation::Options options; S2BooleanOperation op(OpType::UNION, std::move(layers), options); EXPECT_EQ(OpType::UNION, op.op_type()); } // TODO(ericv): Clean up or remove these notes. // // Options to test: // polygon_model: OPEN, SEMI_OPEN, CLOSED // polyline_model: OPEN, SEMI_OPEN, CLOSED // polyline_loops_have_boundaries: true, false // conservative: true, false // // Geometry combinations to test: // // Point/point: // - disjoint, coincident // Point/polyline: // - Start vertex, end vertex, interior vertex, degenerate polyline // - With polyline_loops_have_boundaries: start/end vertex, degenerate polyline // Point/polygon: // - Polygon interior, exterior, vertex // - Vertex of degenerate sibling pair shell, hole // - Vertex of degenerate single point shell, hole // Polyline/polyline: // - Vertex intersection: // - Start, end, interior, degenerate, loop start/end, degenerate loop // - Test cases where vertex is not emitted because an incident edge is. // - Edge/edge: interior crossing, duplicate, reversed, degenerate // - Test that degenerate edges are ignored unless polyline has a single edge. // (For example, AA has one edge but AAA has no edges.) // Polyline/polygon: // - Vertex intersection: polyline vertex cases already covered, but test // polygon normal vertex, sibling pair shell/hole, single vertex shell/hole // - Also test cases where vertex is not emitted because an edge is. // - Edge/edge: interior crossing, duplicate, reversed // - Edge/interior: polyline edge in polygon interior, exterior // Polygon/polygon: // - Vertex intersection: // - normal vertex, sibling pair shell/hole, single vertex shell/hole // - Also test cases where vertex is not emitted because an edge is. // - Test that polygons take priority when there is a polygon vertex and // also isolated polyline vertices. (There should not be any points.) // - Edge/edge: interior crossing, duplicate, reversed // - Interior/interior: polygons in interior/exterior of other polygons TEST(S2BooleanOperation, DegeneratePolylines) { // Verify that degenerate polylines are preserved under all boundary models. S2BooleanOperation::Options options; auto a = "# 0:0, 0:0 #"; auto b = "# #"; options.set_polyline_model(PolylineModel::OPEN); ExpectResult(OpType::UNION, options, a, b, a); options.set_polyline_model(PolylineModel::SEMI_OPEN); ExpectResult(OpType::UNION, options, a, b, a); options.set_polyline_model(PolylineModel::CLOSED); ExpectResult(OpType::UNION, options, a, b, a); } TEST(S2BooleanOperation, DegeneratePolygons) { // Verify that degenerate polygon features (single-vertex and sibling pair // shells and holes) are preserved under all boundary models. S2BooleanOperation::Options options; auto a = "# # 0:0, 0:5, 5:5, 5:0; 1:1; 2:2, 3:3; 6:6; 7:7, 8:8"; auto b = "# #"; options.set_polygon_model(PolygonModel::OPEN); ExpectResult(OpType::UNION, options, a, b, a); options.set_polygon_model(PolygonModel::SEMI_OPEN); ExpectResult(OpType::UNION, options, a, b, a); options.set_polygon_model(PolygonModel::CLOSED); ExpectResult(OpType::UNION, options, a, b, a); } TEST(S2BooleanOperation, PointPoint) { S2BooleanOperation::Options options; auto a = "0:0 | 1:0 # #"; auto b = "0:0 | 2:0 # #"; // Note that these results have duplicates, which is correct. Clients can // eliminate the duplicates with the appropriate GraphOptions. ExpectResult(OpType::UNION, options, a, b, "0:0 | 0:0 | 1:0 | 2:0 # #"); ExpectResult(OpType::INTERSECTION, options, a, b, "0:0 | 0:0 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "1:0 # #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "1:0 | 2:0 # #"); } TEST(S2BooleanOperation, PointOpenPolyline) { // Tests operations between an open polyline and its vertices. // // The polyline "3:0, 3:0" consists of a single degenerate edge and contains // no points (since polyline_model() is OPEN). Since S2BooleanOperation // preserves degeneracies, this means that the union includes *both* the // point 3:0 and the degenerate polyline 3:0, since they do not intersect. // // This test uses Options::polyline_loops_have_boundaries() == true, which // means that the loop "4:0, 5:0, 4:0" does not contain the vertex "4:0". S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::OPEN); auto a = "0:0 | 1:0 | 2:0 | 3:0 | 4:0 | 5:0 # #"; auto b = "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"; ExpectResult(OpType::UNION, options, a, b, "0:0 | 2:0 | 3:0 | 4:0 " "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "1:0 | 5:0 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "0:0 | 2:0 | 3:0 | 4:0 # #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "0:0 | 2:0 | 3:0 | 4:0" "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); } TEST(S2BooleanOperation, PointOpenPolylineLoopBoundariesFalse) { // With Options::polyline_loops_have_boundaries() == false, the loop // "4:0, 5:0, 4:0" has two vertices, both of which are contained. S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::OPEN); options.set_polyline_loops_have_boundaries(false); auto a = "0:0 | 1:0 | 2:0 | 3:0 | 4:0 | 5:0 # #"; auto b = "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"; ExpectResult(OpType::UNION, options, a, b, "0:0 | 2:0 | 3:0 " "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "1:0 | 4:0 | 5:0 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "0:0 | 2:0 | 3:0 # #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "0:0 | 2:0 | 3:0 " "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); } TEST(S2BooleanOperation, PointSemiOpenPolyline) { // Degenerate polylines are defined not contain any points under the // SEMI_OPEN model either, so again the point 3:0 and the degenerate // polyline "3:0, 3:0" do not intersect. // // The result does not depend on Options::polyline_loops_have_boundaries(). S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::SEMI_OPEN); for (bool bool_value : {false, true}) { options.set_polyline_loops_have_boundaries(bool_value); auto a = "0:0 | 1:0 | 2:0 | 3:0 | 4:0 | 5:0 # #"; auto b = "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"; ExpectResult(OpType::UNION, options, a, b, "2:0 | 3:0 # 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "0:0 | 1:0 | 4:0 | 5:0 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "2:0 | 3:0 # #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "2:0 | 3:0 # 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); } } TEST(S2BooleanOperation, PointClosedPolyline) { // Under the CLOSED model, the degenerate polyline 3:0 does contain its // vertex. Since polylines take precedence over points, the union of the // point 3:0 and the polyline 3:0 is the polyline only. Similarly, since // subtracting a point from a polyline has no effect, the symmetric // difference includes only the polyline objects. // // The result does not depend on Options::polyline_loops_have_boundaries(). S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::CLOSED); for (bool bool_value : {false, true}) { options.set_polyline_loops_have_boundaries(bool_value); auto a = "0:0 | 1:0 | 2:0 | 3:0 | 4:0 | 5:0 # #"; auto b = "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "0:0 | 1:0 | 2:0 | 3:0 | 4:0 | 5:0 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0, 4:0 #"); } } TEST(S2BooleanOperation, PointPolygonInterior) { S2BooleanOperation::Options options; // PolygonModel is irrelevant. // One interior point and one exterior point. auto a = "1:1 | 4:4 # #"; auto b = "# # 0:0, 0:3, 3:0"; ExpectResult(OpType::UNION, options, a, b, "4:4 # # 0:0, 0:3, 3:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "1:1 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "4:4 # #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "4:4 # # 0:0, 0:3, 3:0"); } TEST(S2BooleanOperation, PointOpenPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::OPEN); // See notes about the two vertices below. auto a = "0:1 | 1:0 # #"; auto b = "# # 0:0, 0:1, 1:0"; ExpectResult(OpType::UNION, options, a, b, "0:1 | 1:0 # # 0:0, 0:1, 1:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "# #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "0:1 | 1:0 # #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "0:1 | 1:0 # # 0:0, 0:1, 1:0"); } TEST(S2BooleanOperation, PointSemiOpenPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::SEMI_OPEN); // The two vertices are chosen such that the polygon contains one vertex but // not the other under PolygonModel::SEMI_OPEN. (The same vertices are used // for all three PolygonModel options.) auto polygon = s2textformat::MakePolygonOrDie("0:0, 0:1, 1:0"); ASSERT_TRUE(polygon->Contains(s2textformat::MakePointOrDie("0:1"))); ASSERT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("1:0"))); auto a = "0:1 | 1:0 # #"; auto b = "# # 0:0, 0:1, 1:0"; ExpectResult(OpType::UNION, options, a, b, "1:0 # # 0:0, 0:1, 1:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "0:1 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "1:0 # #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "1:0 # # 0:0, 0:1, 1:0"); } TEST(S2BooleanOperation, PointClosedPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::CLOSED); // See notes about the two vertices above. auto a = "0:1 | 1:0 # #"; auto b = "# # 0:0, 0:1, 1:0"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:1, 1:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "0:1 | 1:0 # #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:1, 1:0"); } TEST(S2BooleanOperation, PolylineVertexOpenPolylineVertex) { // Test first, last, and middle vertices of both polylines. Also test // first/last and middle vertices of two polyline loops. // // Degenerate polylines are tested in PolylineEdgePolylineEdgeOverlap below. S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::OPEN); auto a = "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"; auto b = "# 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); // The output consists of the portion of each input polyline that intersects // the opposite region, so the intersection vertex is present twice. This // allows reassembling the individual polylins that intersect, if desired. // (Otherwise duplicates can be removed using DuplicateEdges::MERGE.) ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:1, 0:1 | 0:1, 0:1 #"); // Note that all operations are defined such that subtracting a // lower-dimensional subset of an object has no effect. In this case, // subtracting the middle vertex of a polyline has no effect. ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); } TEST(S2BooleanOperation, PolylineVertexOpenPolylineVertexLoopBoundariesFalse) { // With Options::polyline_loops_have_boundaries() == false, the 3 polyline // loops each have two vertices, both of which are contained. S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::OPEN); options.set_polyline_loops_have_boundaries(false); auto a = "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"; auto b = "# 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); // Note that the polyline "0:3, 0:4, 0:3" only has two vertices, not three. // This means that 0:3 is emitted only once for that polyline, plus once for // the other polyline, for a total of twice. ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:1, 0:1 | 0:1, 0:1 " "| 0:3, 0:3 | 0:3, 0:3 | 0:4, 0:4 | 0:4, 0:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); } TEST(S2BooleanOperation, PolylineVertexSemiOpenPolylineVertex) { // The result does not depend on Options::polyline_loops_have_boundaries(). S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::SEMI_OPEN); for (bool bool_value : {false, true}) { options.set_polyline_loops_have_boundaries(bool_value); auto a = "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"; auto b = "# 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 0:0 | 0:0, 0:0 | 0:1, 0:1 | 0:1, 0:1 " "| 0:3, 0:3 | 0:3, 0:3 | 0:4, 0:4 | 0:4, 0:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); } } TEST(S2BooleanOperation, PolylineVertexClosedPolylineVertex) { S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::CLOSED); auto a = "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"; auto b = "# 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); // Since Options::polyline_loops_have_boundaries() == true, the polyline // "0:3, 0:4, 0:3" has three vertices. Therefore 0:3 is emitted twice for // that polyline, plus once for the other polyline, for a total of thrice. ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 0:0 | 0:0, 0:0 | 0:1, 0:1 | 0:1, 0:1 " "| 0:2, 0:2 | 0:2, 0:2 " "| 0:3, 0:3 | 0:3, 0:3 | 0:3, 0:3 " "| 0:4, 0:4 | 0:4, 0:4 | 0:4, 0:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); } TEST(S2BooleanOperation, PolylineVertexClosedPolylineVertexLoopBoundariesFalse) { S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::CLOSED); options.set_polyline_loops_have_boundaries(false); auto a = "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"; auto b = "# 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); // Since Options::polyline_loops_have_boundaries() == false, the polyline // "0:3, 0:4, 0:3" has two vertices. Therefore 0:3 is emitted once for // that polyline, plus once for the other polyline, for a total of twice. ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 0:0 | 0:0, 0:0 | 0:1, 0:1 | 0:1, 0:1 " "| 0:2, 0:2 | 0:2, 0:2 " "| 0:3, 0:3 | 0:3, 0:3 | 0:4, 0:4 | 0:4, 0:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:3, 0:4, 0:3 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:0, 0:1, 0:2 | 0:0, 1:0 | -1:1, 0:1, 1:1 | -1:2, 0:2 " "| 0:3, 0:4, 0:3 | 1:3, 0:3, 1:3 | 0:4, 1:4, 0:4 #"); } // The polygon used in the polyline/polygon vertex tests below. static string kVertexTestPolygonStr() { return "0:0, 0:1, 0:2, 0:3, 0:4, 0:5, 5:5, 5:4, 5:3, 5:2, 5:1, 5:0"; } TEST(S2BooleanOperation, TestSemiOpenPolygonVerticesContained) { // Verify whether certain vertices of the test polygon are contained under // the semi-open boundary model (for use in the tests below). auto polygon = s2textformat::MakePolygonOrDie(kVertexTestPolygonStr()); EXPECT_TRUE(polygon->Contains(s2textformat::MakePointOrDie("0:1"))); EXPECT_TRUE(polygon->Contains(s2textformat::MakePointOrDie("0:2"))); EXPECT_TRUE(polygon->Contains(s2textformat::MakePointOrDie("0:3"))); EXPECT_TRUE(polygon->Contains(s2textformat::MakePointOrDie("0:4"))); EXPECT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("5:1"))); EXPECT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("5:2"))); EXPECT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("5:3"))); EXPECT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("5:4"))); } // Don't bother testing every PolylineModel with every PolygonModel for vertex // intersection, since we have already tested the PolylineModels individually // above. It is sufficient to use PolylineModel::CLOSED with the various // PolygonModel options. TEST(S2BooleanOperation, PolylineVertexOpenPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::OPEN); // Define some constants to reduce code duplication. // Test all combinations of polylines that start or end on a polygon vertex, // where the polygon vertex is open or closed using semi-open boundaries, // and where the incident edge is inside or outside the polygon. auto a = ("# 1:1, 0:1 | 0:2, 1:2 | -1:3, 0:3 | 0:4, -1:4 " "| 6:1, 5:1 | 5:2, 6:2 | 4:3, 5:3 | 5:4, 4:4 #"); auto b = "# # " + kVertexTestPolygonStr(); const string kDifferenceResult = "# 0:1, 0:1 | 0:2, 0:2 | -1:3, 0:3 | 0:4, -1:4" "| 6:1, 5:1 | 5:2, 6:2 | 5:3, 5:3 | 5:4, 5:4 #"; ExpectResult(OpType::UNION, options, a, b, kDifferenceResult + kVertexTestPolygonStr()); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:1, 0:1 | 0:2, 1:2 | 4:3, 5:3 | 5:4, 4:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, kDifferenceResult); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, kDifferenceResult + kVertexTestPolygonStr()); } // Like the test above, except that every polygon vertex is also incident to a // closed polyline vertex. This tests that when an open vertex and a closed // vertex coincide with each other, the result is considered closed. TEST(S2BooleanOperation, PolylineVertexOpenPolygonClosedPolylineVertex) { const string kTestGeometrySuffix = "-2:0, 0:1 | -2:1, 0:2 | -2:2, 0:3 | -2:3, 0:4 | " "7:0, 5:1 | 7:1, 5:2 | 7:2, 5:3 | 7:3, 5:4 # " + kVertexTestPolygonStr(); S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::OPEN); auto a = ("# 1:1, 0:1 | 0:2, 1:2 | -1:3, 0:3 | 0:4, -1:4 " "| 6:1, 5:1 | 5:2, 6:2 | 4:3, 5:3 | 5:4, 4:4 #"); auto b = ("# " + kTestGeometrySuffix); const string kDifferencePrefix = "# -1:3, 0:3 | 0:4, -1:4 | 6:1, 5:1 | 5:2, 6:2"; ExpectResult(OpType::UNION, options, a, b, kDifferencePrefix + " | 0:1, 0:1 | 0:2, 0:2 | 5:3, 5:3 | 5:4, 5:4 | " + kTestGeometrySuffix); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:1, 0:1 | 0:2, 1:2 | 0:3, 0:3 | 0:4, 0:4" "| 5:1, 5:1 | 5:2, 5:2 | 4:3, 5:3 | 5:4, 4:4" "| 0:1, 0:1 | 0:2, 0:2 | 0:3, 0:3 | 0:4, 0:4" "| 5:1, 5:1 | 5:2, 5:2 | 5:3, 5:3 | 5:4, 5:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, kDifferencePrefix + " #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, kDifferencePrefix + " | " + kTestGeometrySuffix); } TEST(S2BooleanOperation, PolylineVertexSemiOpenPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::SEMI_OPEN); // Test all combinations of polylines that start or end on a polygon vertex, // where the polygon vertex is open or closed using semi-open boundaries, // and where the incident edge is inside or outside the polygon. // // The vertices at latitude 0 used below are all closed while the vertices // at latitude 5 are all open (see TestSemiOpenPolygonVerticesContained). auto a = ("# 1:1, 0:1 | 0:2, 1:2 | -1:3, 0:3 | 0:4, -1:4 " "| 6:1, 5:1 | 5:2, 6:2 | 4:3, 5:3 | 5:4, 4:4 #"); auto b = "# # " + kVertexTestPolygonStr(); const string kDifferenceResult = "# -1:3, 0:3 | 0:4, -1:4 | 6:1, 5:1 | 5:2, 6:2 | 5:3, 5:3 | 5:4, 5:4 #"; ExpectResult(OpType::UNION, options, a, b, kDifferenceResult + kVertexTestPolygonStr()); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:1, 0:1 | 0:2, 1:2 | 0:3, 0:3 | 0:4, 0:4 " "| 4:3, 5:3 | 5:4, 4:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, kDifferenceResult); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, kDifferenceResult + kVertexTestPolygonStr()); } TEST(S2BooleanOperation, PolylineVertexClosedPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::CLOSED); // Test all combinations of polylines that start or end on a polygon vertex, // where the polygon vertex is open or closed using semi-open boundaries, // and where the incident edge is inside or outside the polygon. auto a = ("# 1:1, 0:1 | 0:2, 1:2 | -1:3, 0:3 | 0:4, -1:4 " "| 6:1, 5:1 | 5:2, 6:2 | 4:3, 5:3 | 5:4, 4:4 #"); auto b = "# # " + kVertexTestPolygonStr(); const string kDifferenceResult = "# -1:3, 0:3 | 0:4, -1:4 | 6:1, 5:1 | 5:2, 6:2 #"; ExpectResult(OpType::UNION, options, a, b, kDifferenceResult + kVertexTestPolygonStr()); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:1, 0:1 | 0:2, 1:2 | 0:3, 0:3 | 0:4, 0:4" "| 5:1, 5:1 | 5:2, 5:2 | 4:3, 5:3 | 5:4, 4:4 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, kDifferenceResult); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, kDifferenceResult + kVertexTestPolygonStr()); } TEST(S2BooleanOperation, PolylineEdgePolylineEdgeCrossing) { // Two polyline edges that cross at a point interior to both edges. S2BooleanOperation::Options options = RoundToE(1); auto a = "# 0:0, 2:2 #"; auto b = "# 2:0, 0:2 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 1:1, 2:2 | 2:0, 1:1, 0:2 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:1, 1:1 | 1:1, 1:1 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:0, 1:1, 2:2 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:0, 1:1, 2:2 | 2:0, 1:1, 0:2 #"); } TEST(S2BooleanOperation, PolylineEdgePolylineEdgeOverlap) { // The PolylineModel does not affect this calculation. In particular the // intersection of a degenerate polyline edge with itself is non-empty, even // though the edge contains no points in the OPEN and SEMI_OPEN models. S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::OPEN); // Test edges in the same and reverse directions, and degenerate edges. auto a = "# 0:0, 1:0, 2:0, 2:5 | 3:0, 3:0 | 6:0, 5:0, 4:0 #"; auto b = "# 0:0, 1:0, 2:0 | 3:0, 3:0 | 4:0, 5:0 #"; // As usual, the expected output includes the relevant portions of *both* // input polylines. Duplicates can be removed using GraphOptions. ExpectResult(OpType::UNION, options, a, b, "# 0:0, 1:0, 2:0, 2:5 | 0:0, 1:0, 2:0 | 3:0, 3:0 | 3:0, 3:0 " "| 6:0, 5:0, 4:0 | 4:0, 5:0 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 1:0, 2:0 | 0:0, 1:0, 2:0 | 3:0, 3:0 | 3:0, 3:0 " "| 5:0, 4:0 | 4:0, 5:0 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 2:0, 2:5 | 6:0, 5:0 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 2:0, 2:5 | 6:0, 5:0 #"); } TEST(S2BooleanOperation, PolylineLoopMultipleOpenPolylineEdge) { // Here we test a polyline loop ABCA with the pairs {AA, AB} and {AA, AC}. // This tests not only what happens when degenerate polylines intersect loop // endpoints, but also what happens when polylines intersect a degenerate // and non-degenerate edge that overlap each other. S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::OPEN); auto a = "# 0:0, 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2, 2:2 #"; auto b = "# 0:0, 0:0 | 0:0, 0:1 | 2:2, 2:2 | 2:2, 3:2 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 1:0, 0:0 | 0:0, 0:0 | 0:0, 0:1 " "| 2:2, 2:3, 3:2, 2:2 | 2:2, 2:2 | 2:2, 3:2 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 0:1 | 0:0, 0:1 | 2:2, 3:2 | 3:2, 2:2 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 0:0, 0:0 | 2:2, 2:3, 3:2 | 2:2, 2:2 #"); } TEST(S2BooleanOperation, PolylineLoopMultipleSemiOpenPolylineEdge) { // Like the test above but with SEMI_OPEN boundaries. In this case ABCA // intersected with {AA, AB} is {AA, AB, AB} but ABCA intersected with {AA, // AC} is {AA, AA, AC, CA} since the chain ABCA contains its start vertex // but not its end vertex. S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::SEMI_OPEN); auto a = "# 0:0, 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2, 2:2 #"; auto b = "# 0:0, 0:0 | 0:0, 0:1 | 2:2, 2:2 | 2:2, 3:2 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 1:0, 0:0 | 0:0, 0:0 | 0:0, 0:1 " "| 2:2, 2:3, 3:2, 2:2 | 2:2, 2:2 | 2:2, 3:2 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 0:0 | 0:0, 0:1 | 0:0, 0:1 " "| 2:2, 2:2 | 2:2, 2:2 | 2:2, 3:2 | 3:2, 2:2 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2 #"); } TEST(S2BooleanOperation, PolylineLoopMultipleClosedPolylineEdge) { // Like the test above but with CLOSED boundaries. In this case ABCA // intersected with {AA, AB} is {AA, AA, AB, AB} since the chain ABCA // contains both its start vertex and end vertex. S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::CLOSED); auto a = "# 0:0, 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2, 2:2 #"; auto b = "# 0:0, 0:0 | 0:0, 0:1 | 2:2, 2:2 | 2:2, 3:2 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 1:0, 0:0 | 0:0, 0:0 | 0:0, 0:1 " "| 2:2, 2:3, 3:2, 2:2 | 2:2, 2:2 | 2:2, 3:2 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 0:0 | 0:0, 0:0 | 0:0, 0:1 | 0:0, 0:1 " "| 2:2, 2:2 | 2:2, 2:2 | 2:2, 3:2 | 3:2, 2:2 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2 #"); } TEST(S2BooleanOperation, PolylineLoopMultiplePolylineEdgeLoopBoundariesFalse) { // Like the tests above but with polyline_loops_have_boundaries() == false. // In this case the result does not depend on the polyline model. The // polyline AA intersects ABCA exactly once, and the intersection of ABCA // with {AA, AB} is {AA, AB, AB}. for (auto polyline_model : { PolylineModel::OPEN, PolylineModel::SEMI_OPEN, PolylineModel::CLOSED}) { S2BooleanOperation::Options options; options.set_polyline_model(polyline_model); options.set_polyline_loops_have_boundaries(false); auto a = "# 0:0, 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2, 2:2 #"; auto b = "# 0:0, 0:0 | 0:0, 0:1 | 2:2, 2:2 | 2:2, 3:2 #"; ExpectResult(OpType::UNION, options, a, b, "# 0:0, 0:1, 1:0, 0:0 | 0:0, 0:0 | 0:0, 0:1 " "| 2:2, 2:3, 3:2, 2:2 | 2:2, 2:2 | 2:2, 3:2 #"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 0:0, 0:0 | 0:0, 0:1 | 0:0, 0:1 " "| 2:2, 2:2 | 2:2, 3:2 | 3:2, 2:2 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 0:1, 1:0, 0:0 | 2:2, 2:3, 3:2 #"); } } TEST(S2BooleanOperation, PolylineEdgeOpenPolygonEdgeOverlap) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::OPEN); // A polygon and two polyline edges that coincide with the polygon boundary, // one in the same direction and one in the reverse direction. auto a = "# 1:1, 1:3, 3:3 | 3:3, 1:3 # "; auto b = "# # 1:1, 1:3, 3:3, 3:1"; ExpectResult(OpType::UNION, options, a, b, "# 1:1, 1:3, 3:3 | 3:3, 1:3 # 1:1, 1:3, 3:3, 3:1"); ExpectResult(OpType::INTERSECTION, options, a, b, "# #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 1:1, 1:3, 3:3 | 3:3, 1:3 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 1:1, 1:3, 3:3 | 3:3, 1:3 # 1:1, 1:3, 3:3, 3:1"); } TEST(S2BooleanOperation, PolylineEdgeSemiOpenPolygonEdgeOverlap) { auto polygon = s2textformat::MakePolygonOrDie("1:1, 1:3, 3:3, 3:1"); ASSERT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("1:1"))); ASSERT_TRUE(polygon->Contains(s2textformat::MakePointOrDie("1:3"))); ASSERT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("3:3"))); ASSERT_FALSE(polygon->Contains(s2textformat::MakePointOrDie("3:1"))); S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::SEMI_OPEN); auto a = "# 1:1, 1:3, 3:3 | 3:3, 1:3 # "; auto b = "# # 1:1, 1:3, 3:3, 3:1"; ExpectResult(OpType::UNION, options, a, b, "# 1:1, 1:1 | 3:3, 3:3 | 3:3, 1:3 # 1:1, 1:3, 3:3, 3:1"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:3, 1:3 | 1:1, 1:3, 3:3 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 1:1, 1:1 | 3:3, 3:3 | 3:3, 1:3 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 1:1, 1:1 | 3:3, 3:3 | 3:3, 1:3 # 1:1, 1:3, 3:3, 3:1"); } TEST(S2BooleanOperation, PolylineEdgeClosedPolygonEdgeOverlap) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::CLOSED); auto a = "# 1:1, 1:3, 3:3 | 3:3, 1:3 # "; auto b = "# # 1:1, 1:3, 3:3, 3:1"; ExpectResult(OpType::UNION, options, a, b, "# # 1:1, 1:3, 3:3, 3:1"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:1, 1:3, 3:3 | 3:3, 1:3 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 1:1, 1:3, 3:3, 3:1"); } TEST(S2BooleanOperation, PolygonVertexMatching) { // This test shows that CrossingProcessor::ProcessEdgeCrossings() must set // a0_matches_polygon and a1_matches_polygon correctly even when (a0, a1) // itself is a polygon edge (or its sibling). (It requires degenerate // polygon geometry to demonstrate this.) S2BooleanOperation::Options options; options.set_polyline_model(PolylineModel::CLOSED); options.set_polygon_model(PolygonModel::CLOSED); auto a = "# 0:0, 1:1 # "; auto b = "# # 0:0, 1:1"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 1:1"); } TEST(S2BooleanOperation, PolylineEdgePolygonInterior) { S2BooleanOperation::Options options; // PolygonModel is irrelevant. // One normal and one degenerate polyline edge in the polygon interior, and // similarly for the polygon exterior. auto a = "# 1:1, 2:2 | 3:3, 3:3 | 6:6, 7:7 | 8:8, 8:8 # "; auto b = "# # 0:0, 0:5, 5:5, 5:0"; ExpectResult(OpType::UNION, options, a, b, "# 6:6, 7:7 | 8:8, 8:8 # 0:0, 0:5, 5:5, 5:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "# 1:1, 2:2 | 3:3, 3:3 #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# 6:6, 7:7 | 8:8, 8:8 #"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# 6:6, 7:7 | 8:8, 8:8 # 0:0, 0:5, 5:5, 5:0"); } TEST(S2BooleanOperation, PolylineEdgeIsolatedStartVertexPlusInteriorCrossing) { // Tests a polyline XYZ that when intersected with a polygon results in an // isolated vertex X plus a clipped portion UYV. This case is unusual // because the isolated vertex is handled by creating a separate degenerate // S2Builder input edge XX which is added before the actual edge XY, and the // crossing edge information needs to be associated with XY rather than XX // in order for GraphEdgeClipper to be able to do its work properly. The // test is constructed such that if the crossings are incorrectly associated // with the degenerate edge XX then not only will the output be incorrect, // it will also trigger an internal ABSL_DCHECK. S2BooleanOperation::Options options = RoundToE(1); auto a = "# 0:0, 0:10, 0:4 # "; auto b = "# # 0:0, -5:5, 5:5"; ExpectResult(OpType::DIFFERENCE, options, a, b, "# 0:0, 0:0 | 0:5, 0:10, 0:5 #"); } TEST(S2BooleanOperation, PolygonEdgeIsolatedStartVertexPlusInteriorCrossing) { // Similar to the case above, but tests a polygon XYZ rather than a // polyline. This requires using the CLOSED polygon model and computing the // intersection with a clockwise loop rather than subtracting a CCW loop. // The test is constructed such that if the crossings for the edge 0:0, 0:8 // are incorrectly associated with the degenerate edge 0:0, then not only // will the output be incorrect, it will also trigger an internal ABSL_DCHECK. S2BooleanOperation::Options options = RoundToE(1); options.set_polygon_model(PolygonModel::CLOSED); auto a = "# # 0:0, 5:5, -5:5"; auto b = "# # 1:4, 0:0, 0:8"; ExpectResult(OpType::INTERSECTION, options, a, b, "# # 0:0; 0:5, 0:8, 0.8:5"); } TEST(S2BooleanOperation, PolygonVertexOpenPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::OPEN); auto a = "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5"; auto b = "# # 0:0, 5:3, 5:2"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5, 0:0, 5:3, 5:2"); ExpectResult(OpType::INTERSECTION, options, a, b, "# #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5, 0:0, 5:3, 5:2"); } TEST(S2BooleanOperation, PolygonVertexSemiOpenPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::SEMI_OPEN); auto a = "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5"; auto b = "# # 0:0, 5:3, 5:2"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5, 0:0, 5:3, 5:2"); ExpectResult(OpType::INTERSECTION, options, a, b, "# #"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5, 0:0, 5:3, 5:2"); } TEST(S2BooleanOperation, PolygonVertexClosedPolygonVertex) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::CLOSED); auto a = "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5"; auto b = "# # 0:0, 5:3, 5:2"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5, 0:0, 5:3, 5:2"); ExpectResult(OpType::INTERSECTION, options, a, b, "# # 0:0"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5"); ExpectResult(OpType::DIFFERENCE, options, b, a, "# # 0:0, 5:3, 5:2"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:5, 1:5, 0:0, 2:5, 3:5, 0:0, 5:3, 5:2"); } TEST(S2BooleanOperation, PolygonEdgePolygonEdgeCrossing) { // Two polygons whose edges cross at points interior to both edges. S2BooleanOperation::Options options = RoundToE(2); auto a = "# # 0:0, 0:2, 2:2, 2:0"; auto b = "# # 1:1, 1:3, 3:3, 3:1"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:2, 1:2, 1:3, 3:3, 3:1, 2:1, 2:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "# # 1:1, 1:2, 2:2, 2:1"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:2, 1:2, 1:1, 2:1, 2:0"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:2, 1:2, 1:1, 2:1, 2:0; " "1:2, 1:3, 3:3, 3:1, 2:1, 2:2"); } TEST(S2BooleanOperation, PolygonEdgeOpenPolygonEdgeOverlap) { S2BooleanOperation::Options options; // One shape is a rectangle, the other consists of one triangle inside the // rectangle and one triangle outside the rectangle, where each triangle // shares one edge with the rectangle. This implies that the edges are in // the same direction in one case and opposite directions in the other case. options.set_polygon_model(PolygonModel::OPEN); auto a = "# # 0:0, 0:4, 2:4, 2:0"; auto b = "# # 0:0, 1:1, 2:0; 0:4, 1:5, 2:4"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:4, 2:4, 2:0; 0:4, 1:5, 2:4"); ExpectResult(OpType::INTERSECTION, options, a, b, "# # 0:0, 1:1, 2:0"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:4, 2:4, 2:0, 1:1"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:4, 2:4, 2:0, 1:1; 0:4, 1:5, 2:4"); } TEST(S2BooleanOperation, PolygonEdgeSemiOpenPolygonEdgeOverlap) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::SEMI_OPEN); auto a = "# # 0:0, 0:4, 2:4, 2:0"; auto b = "# # 0:0, 1:1, 2:0; 0:4, 1:5, 2:4"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:4, 1:5, 2:4, 2:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "# # 0:0, 1:1, 2:0"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:4, 2:4, 2:0, 1:1"); // Note that SYMMETRIC_DIFFERENCE does not guarantee that results are // normalized, i.e. the output could contain siblings pairs (which can be // discarded using S2Builder::GraphOptions). ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:4, 2:4, 2:0, 1:1; 0:4, 1:5, 2:4"); } TEST(S2BooleanOperation, PolygonEdgeClosedPolygonEdgeOverlap) { S2BooleanOperation::Options options; options.set_polygon_model(PolygonModel::CLOSED); auto a = "# # 0:0, 0:4, 2:4, 2:0"; auto b = "# # 0:0, 1:1, 2:0; 0:4, 1:5, 2:4"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:4, 1:5, 2:4, 2:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "# # 0:0, 1:1, 2:0; 0:4, 2:4"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:4, 2:4, 2:0, 1:1"); // Note that SYMMETRIC_DIFFERENCE does not guarantee that results are // normalized, i.e. the output could contain siblings pairs. ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:4, 2:4, 2:0, 1:1; 0:4, 1:5, 2:4"); } TEST(S2BooleanOperation, PolygonPolygonInterior) { S2BooleanOperation::Options options; // PolygonModel is irrelevant. // One loop in the interior of another polygon and one loop in the exterior. auto a = "# # 0:0, 0:4, 4:4, 4:0"; auto b = "# # 1:1, 1:2, 2:2, 2:1; 5:5, 5:6, 6:6, 6:5"; ExpectResult(OpType::UNION, options, a, b, "# # 0:0, 0:4, 4:4, 4:0; 5:5, 5:6, 6:6, 6:5"); ExpectResult(OpType::INTERSECTION, options, a, b, "# # 1:1, 1:2, 2:2, 2:1"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:0, 0:4, 4:4, 4:0; 2:1, 2:2, 1:2, 1:1"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:0, 0:4, 4:4, 4:0; 2:1, 2:2, 1:2, 1:1; " "5:5, 5:6, 6:6, 6:5"); } TEST(S2BooleanOperation, PolygonEdgesDegenerateAfterSnapping) { S2BooleanOperation::Options options = RoundToE(0); // Two narrow rectangles forming a plus sign. auto a = "# # 0:-1, 0:1, 0.1:1, 0.1:-1"; auto b = "# # -1:0.1, 1:0.1, 1:0, -1:0"; // When snapping causes an output edge to become degenerate, it is still // emitted (since otherwise loops that contract to a single point would be // lost). If the output layer doesn't want such edges, they can be removed // via DegenerateEdges::DISCARD. ExpectResult(OpType::UNION, options, a, b, "# # 0:-1, 0:0, 0:1, 0:0 | " "-1:0, 0:0, 1:0, 0:0"); ExpectResult(OpType::INTERSECTION, options, a, b, "# # 0:0"); ExpectResult(OpType::DIFFERENCE, options, a, b, "# # 0:-1, 0:0, 0:1, 0:0"); ExpectResult(OpType::SYMMETRIC_DIFFERENCE, options, a, b, "# # 0:-1, 0:0, 0:1, 0:0 | " "-1:0, 0:0, 1:0, 0:0"); } // The following class comprehensively tests the handling of degenerate // geometry. It is used to implement over 4,000 individual test cases encoded // as a series of textual tables. class DegeneracyCoverageTest : public ::testing::Test { public: // Verifies that the S2BooleanOperation results for the given OpType and // PolygonModel match the given set of rules (encoded as described below). void Run(OpType op_type, PolygonModel polygon_model, absl::Span rules); private: // The inputs to the test cases are intended to span all possible types of // degenerate and non-degenerate edge configurations in the vicinity of an // individual input edge. Essentially we are trying to cover all possible // behaviors of S2BooleanOperation::Impl::CrossingProcessor::ProcessEdge(), // which is responsible for determining which parts of each input edge // should be emitted to the output. // // For this purpose it is sufficient to consider two points A and B and the // possible types of degeneracies that involve just these two points. The // actual locations of the points are immaterial, although for descriptive // purposes we suppose that B is located above A so that the edge AB is // considered "up" while the edge BA is considered "down". Only one point // needs to be considered for point degeneracies, so we use A for this // purpose. This means that all inputs consist of some subset of AA, AB, // and BA represented as edges of dimensions 0, 1, or 2. For example, a // polyline edge intersected with a point located at one of its vertices // would be represented as the edge AB of dimension 1 in region 0 and the // edge AA of dimension 0 in region 1. // // Each possibility is represented as a single letter as follows (with the // corresponding edges in braces): // // Special: . = empty {} // * = full sphere {} // // Dimension 0: p = point {AA} // // Dimension 1: P = point polyline {AA} // u = up edge {AB} // d = down edge {BA} // // Dimension 2: s = point shell {AA} // S = sibling pair shell {AB, BA} // U = up edge {AB} // D = down edge {BA} // H = sibling pair hole {AB, BA} // h = point hole {AA} // // Using this encoding, the test case described above would be represented // as 'u' for region 0 and 'p' for region 1. Note that while the test cases // focus only on what happens to the edges AB, BA, and AA, additional edges // are needed in order to construct valid inputs. For example, the test // case U (the "up" polygon edge AB) is represented as a triangle ABC, while // the test case D (the "down" polygon edge BA) is represented as the // triangle AB(-C). // // The expected result of a given operation is then represented as a // sequence of the characters above. In some cases additional symbols are // needed to define the expected results. For example, in the closed // polygon model the union of U and D is the quadrilateral A(-C)BC which // does not appear in the list of symbols above. So the results use the // following additional symbols: // // Q : the union of the "U" and "D" shapes (a quadrilateral) // B : a point polyline consisting only of the vertex B {BB} // // Finally, in some cases the expected result depends on the polyline model, // or on whether one of the two regions contains the vertex A. For example, // the intersection of 'p' and 'U' in the semi-open model depends on whether // the representation of U (the triangle ABC mentioned above) contains its // vertex A. Conditional results of this sort are encoded using the // following operators: // // ~X : the complement of X (where X must be either U or D) // XY : the result is X if region 1 contains point A, otherwise Y. // X|Y|Z : the result is X, Y, or Z depending on whether the polyline // model is OPEN, SEMI_OPEN, or CLOSED. // // The operators above may be combined, e.g. X<>Y means the result is X if // both regions contain point A and Y otherwise. // These are the characters representing possible input regions, in the // order they are used in the rules listed further below. const string kInputChars = ".pPudsSUDHh*"; // Returns an S2ShapeIndex corresponding to the given string of characters. unique_ptr MakeIndex(string_view chars) const; // Verifies that S2BooleanOperation returns the given result for the inputs // represented by the characters 'ch0' and 'ch1'. void TestResult(OpType op_type, const S2BooleanOperation::Options& options, char ch0, char ch1, string_view result) const; }; void DegeneracyCoverageTest::Run(OpType op_type, PolygonModel polygon_model, absl::Span rules) { ABSL_CHECK_EQ(rules.size(), kInputChars.size()); // For the symmetric operators (i.e., all except difference) we only need to // define half of the expected results. const bool symmetric = (op_type != OpType::DIFFERENCE); // Possible values for Options::polyline_model(). const vector kPolylineModels = { PolylineModel::OPEN, PolylineModel::SEMI_OPEN, PolylineModel::CLOSED }; // Possible values for Options::polyline_loops_have_boundaries(). const vector kPolylineLoopOptions = { true, false }; // The set of characters representing polyline inputs. const string kLineChars = "Pud"; // The following nested loops iterate over all combinations of: // - Input character 0 // - Input character 1 // - polyline model (if either input is a polyline) // - whether a closed polyline loop is considered to have a boundary // (if either input is a degenerate polyline) S2BooleanOperation::Options options; options.set_polygon_model(polygon_model); for (int i = 0; i < kInputChars.size(); ++i) { char ch0 = kInputChars[i]; vector row = StrSplit(rules[i], ' ', SkipEmpty()); // Verify and remove the row label. ABSL_CHECK_EQ(row[0], string{ch0}); ABSL_CHECK_EQ(row[1], "|"); row.erase(row.begin(), row.begin() + 2); const int limit = symmetric ? (i + 1) : kInputChars.size(); ABSL_CHECK_EQ(row.size(), limit); for (int j = 0; j < limit; ++j) { char ch1 = kInputChars[j]; // Only iterate over polyline models if at least one input is a polyline. int num_line_models = (StrContains(kLineChars, ch0) || StrContains(kLineChars, ch1)) ? 3 : 1; for (int k = 0; k < num_line_models; ++k) { options.set_polyline_model(kPolylineModels[k]); // Only iterate over polyline loop boundary options if at least one // input is a degenerate polyline. int num_polyline_loop_options = (ch0 == 'P' || ch1 == 'P') ? 2 : 1; for (int m = 0; m < num_polyline_loop_options; ++m) { options.set_polyline_loops_have_boundaries(kPolylineLoopOptions[m]); string_view code = row[j]; // Process any '<' or '>' operators in the result. vector choices = StrSplit(code, ByAnyChar("<>"), SkipEmpty()); string_view result = choices[0]; if (choices.size() > 1) { ABSL_CHECK_EQ(choices.size(), 2); // Test whether each input contains the point A. Note that we // can't use S2ContainsPointQuery because the containment test // must be done using the given S2BooleanOperation options. bool in0 = S2BooleanOperation::Contains(*MakeIndex(string{ch0}), *MakeIndex("p"), options); bool in1 = S2BooleanOperation::Contains(*MakeIndex(string{ch1}), *MakeIndex("p"), options); // If the point containment conditions specified by the operators // '<' and '>' are satisfied then the result is choices[0], // otherwise it is choices[1]. if ((StrContains(code, '<') && !in0) || (StrContains(code, '>') && !in1)) { result = choices[1]; } } // Next process any '|' operators in the result. choices = StrSplit(result, '|'); if (choices.size() > 1) { ABSL_CHECK_EQ(num_line_models, 3) << "No polylines present"; ABSL_CHECK_EQ(choices.size(), 3); result = choices[k]; } TestResult(op_type, options, ch0, ch1, result); if (symmetric && j != i) { TestResult(op_type, options, ch1, ch0, result); } } } } } } void DegeneracyCoverageTest::TestResult( OpType op_type, const S2BooleanOperation::Options& options, char ch0, char ch1, string_view result) const { auto index0 = MakeIndex(string{ch0}); auto index1 = MakeIndex(string{ch1}); auto expected = MakeIndex(result); SCOPED_TRACE(absl::StrCat( "\n Operation: ", S2BooleanOperation::OpTypeToString(op_type), "\n PolygonModel: ", S2BooleanOperation::PolygonModelToString(options.polygon_model()), "\n PolylineModel: ", S2BooleanOperation::PolylineModelToString(options.polyline_model()), "\n polyline_loops_have_boundaries: ", options.polyline_loops_have_boundaries() ? "true" : "false", "\n Inputs: ", string{ch0}, ", ", string{ch1}, "\n Expected: ", result)); ExpectResult(op_type, options, *index0, *index1, *expected); } unique_ptr DegeneracyCoverageTest::MakeIndex( string_view chars) const { // The locations of A, B, C are arbitrary, however some tests are sensitive // as to whether certain polygons contain the points {A, B} or not. If // these points are moved then some test results may need to be changed. S2Point a(1, 0, 0), b(0, 0, 1), c(0, 1, 0); auto index = make_unique(); for (int i = 0; i < chars.size(); ++i) { using Loops = vector>; char ch = chars[i]; if (ch == '.') { // Empty } else if (ch == 'p') { // Point index->Add(make_unique(vector{a})); } else if (ch == 'P') { // Polyline consisting only of the point A index->Add(make_unique(vector{a, a})); } else if (ch == 'B') { // Polyline consisting only of the point B index->Add(make_unique(vector{b, b})); } else if (ch == 'u') { // Upwards polyline edge index->Add(make_unique(vector{a, b})); } else if (ch == 'd') { // Downwards polyline edge index->Add(make_unique(vector{b, a})); } else if (ch == 's') { // Point shell index->Add(make_unique(Loops{{a}})); } else if (ch == 'S') { // Sibling pair shell index->Add(make_unique(Loops{{a, b}})); } else if (ch == 'U') { // Upwards polygon edge int i = index->Add(make_unique(Loops{{a, b, -c}})); // Some test results require that the U polygon contains A but not B. ABSL_CHECK(ContainsBruteForce(*index->shape(i), a)); ABSL_CHECK(!ContainsBruteForce(*index->shape(i), b)); } else if (ch == 'D') { // Downwards polygon edge int i = index->Add(make_unique(Loops{{b, a, c}})); // Some test cases require that the D polygon excludes both A and B. ABSL_CHECK(!ContainsBruteForce(*index->shape(i), a)); ABSL_CHECK(!ContainsBruteForce(*index->shape(i), b)); } else if (ch == '~') { // Complement of following region (U or D) ch = chars[++i]; if (ch == 'U') { index->Add(make_unique(Loops{{-c, b, a}})); } else if (ch == 'D') { index->Add(make_unique(Loops{{c, a, b}})); } else { ABSL_LOG(FATAL) << "Unsupported character for ~ operator: " << string{ch}; } } else if (ch == 'Q') { // Union of 'U' and 'D' shapes index->Add(make_unique(Loops{{a, c, b, -c}})); } else if (ch == 'H') { // Sibling pair hole index->Add(make_unique(Loops{{a, b}, {}})); } else if (ch == 'h') { // Point hole index->Add(make_unique(Loops{{a}, {}})); } else if (ch == '*') { // Full sphere index->Add(make_unique(Loops{{}})); } else { ABSL_LOG(FATAL) << "Unknown degeneracy coverage symbol: " << string{ch}; } } return index; } TEST_F(DegeneracyCoverageTest, OpenIntersection) { const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | . pp", "P | . p<. PP", "u | . p<. PP<. uu", "d | . p<. PP<. ud dd", "s | . . . . . s", "S | . . . . . . S", "U | . . . . . . . U", "D | . . . . . . . . D", "H | . . . . . . . U D H", "h | . . . u d . S U D H h", "* | . p P u d s S U D H h *", }; Run(OpType::INTERSECTION, PolygonModel::OPEN, rules); } TEST_F(DegeneracyCoverageTest, SemiOpenIntersection) { const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | . pp", "P | . p<. PP", "u | . p<. PP<. uu", "d | . p<. PP<. ud dd", "s | . . . . . s", "S | . p<. P<. . . s<. S", "U | . p<. P<. u P<>. s<. . U", "D | . p<. P<. P<>. d s<. . . D", "H | . p<. P<. u d s<. . U D H", "h | . p P u d . S U D H h", "* | . p P u d s S U D H h *", }; Run(OpType::INTERSECTION, PolygonModel::SEMI_OPEN, rules); } TEST_F(DegeneracyCoverageTest, ClosedIntersection) { const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | . pp", "P | . p<. PP", "u | . p<. PP<. uu", "d | . p<. PP<. ud dd", "s | . p P P>. P>. s", "S | . p P u d s S", "U | . p P u d s S U", "D | . p P u d s S S D", "H | . p P u d s S U D H", "h | . p P u d s S U D H h", "* | . p P u d s S U D H h *", }; Run(OpType::INTERSECTION, PolygonModel::CLOSED, rules); } TEST_F(DegeneracyCoverageTest, OpenUnion) { const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | p pp", "P | P Ph Ph>h h h h h h h", "* | * * * * * * * * * * * *", }; Run(OpType::UNION, PolygonModel::OPEN, rules); } TEST_F(DegeneracyCoverageTest, SemiOpenUnion) { // CAVEAT: The results for (U,u) and (D,d) require the U polygon to contain // vertex A but not vertex B, and the D polygon to contain neither vertex. // This differs from most of the other tests, which encode the results // conditionally using the '<' and '>' operators. That was not practical in // this case because (1) no conditional operators are defined for the 'B' // vertex and (2) encoding the full set of possibilities for all 12 cases // (i.e., the 3 polyline models and whether U contains A and/or B) would be // unwieldy. const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | p pp", "P | P Ph *>h *>h *>h h", "* | * * * * * * * * * * * *", }; Run(OpType::UNION, PolygonModel::SEMI_OPEN, rules); } TEST_F(DegeneracyCoverageTest, ClosedUnion) { const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | p pp", "P | P P rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | . . . . . . . . . . . .", "p | p . .>p .>p .>p p p p p p p .", "P | P P . .>P .>P P P P P P P .", "u | u u u . .|P|. u u u u u P<. .", "d | d d d .|B|. . d d d d d P<. .", "s | s s s s s . s s s s s .", "S | S S S S S S . S S S . .", "U | U U U U U U U . U . . .", "D | D D D D D D D D . . . .", "H | H H H H H H H ~U ~D . . .", "h | h h h h h h H ~U ~D S . .", "* | * * * * * h H ~U ~D S s .", }; Run(OpType::DIFFERENCE, PolygonModel::OPEN, rules); } TEST_F(DegeneracyCoverageTest, SemiOpenDifference) { // See SemiOpenUnion notes regarding (u,U) and (d,D). const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | . . . . . . . . . . . .", "p | p . .>p .>p .>p p p .>p .>p . . .", "P | P P . .>P .>P P P .>P .>P . . .", "u | u u u . .|P|. u u .|.|B u . . .", "d | d d d .|B|. . d d d .|B|PB . . .", "s | s s s s s . .>s .>s .>s .>s s .", "S | S S S S S S . . . S s<. .", "U | U U U U U U U . U . s<. .", "D | D D D D D D D D . . s<. .", "H | H H H H H H H ~U ~D . s<. .", "h | h h h h h h H ~U ~D S . .", "* | * * * * * h H ~U ~D S s .", }; Run(OpType::DIFFERENCE, PolygonModel::SEMI_OPEN, rules); } TEST_F(DegeneracyCoverageTest, ClosedDifference) { const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | . . . . . . . . . . . .", "p | p . .>p .>p .>p . . . . . . .", "P | P P . .>P .>P . . . . . . .", "u | u u u . .|P|. u . . . . . .", "d | d d d .|B|. . d . . . . . .", "s | s s s s s . . . . . s .", "S | S S S S S S . . . S . .", "U | U U U U U U U . U . . .", "D | D D D D D D D D . . . .", "H | H H H H H H H ~U ~D . . .", "h | h h h h h h H ~U ~D S . .", "* | * * * * * h H ~U ~D S s .", }; Run(OpType::DIFFERENCE, PolygonModel::CLOSED, rules); } TEST_F(DegeneracyCoverageTest, OpenSymmetricDifference) { const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | p .", "P | P Ph hP>h h H ~U ~D S .", "* | * * * * * h H ~U ~D S s .", }; Run(OpType::SYMMETRIC_DIFFERENCE, PolygonModel::OPEN, rules); } TEST_F(DegeneracyCoverageTest, SemiOpenSymmetricDifference) { // See SemiOpenUnion notes regarding (U,u) and (D,d). const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | p .", "P | P PH, (h,s)->h and (U,D)->UD. In all three cases the // shared boundary is present on both sides and therefore these edges should // not be contained by the result, however this is not possible under the // CLOSED model. The indicated results are the best approximation. const vector rules = { // . p P u d s S U D H h * // |----------------------------------------------------------------------- ". | .", "p | p .", "P | P P> loops{{S2Point(0, 0, -1), S2Point(-1, 0, 0), S2Point(0, 0, 1), S2Point(-1, 0, 0)}}; meridian.Add(make_unique(loops)); MutableS2ShapeIndex output; vector> layers(3); layers[0] = make_unique(&output); // TODO(ericv): Implement s2builderutil::IndexedS2LaxPolylineVectorLayer. layers[1] = make_unique(&output); layers[2] = make_unique(&output); S2BooleanOperation op(OpType::DIFFERENCE, std::move(layers)); S2Error error; ASSERT_TRUE(op.Build(*input, meridian, &error)) << error; EXPECT_EQ(expected_str, s2textformat::ToString(output)); } // This test demonstrates that S2 geometry can easily be transformed such that // no edge crosses the 180 degree meridian, as required by formats such as // GeoJSON, by simply subtracting a degenerate loop that follows the 180 degree // meridian. This not only splits polylines along the meridian, it also inserts // the necessary extra vertices at the north/south poles. (The only extra step // is that the vertices along the 180 degree meridian or at the poles may need // to be "doubled" into two vertices, one at longitude 180 and one at longitude // -180, in order to match the longitudes of the adjacent vertices.) TEST(S2BooleanOperation, MeridianSplitting) { // A line along the equator crossing the 180 degree meridian. TestMeridianSplitting("# 0:-160, 0:170 #", "# 0:-160, 0:180, 0:170 #"); // The northern hemisphere. TestMeridianSplitting("# # 0:0, 0:120, 0:-120", "# # 90:0, 0:180, 0:-120, 0:0, 0:120, 0:180"); // A small square that crosses the 180th meridian. Notice that one input // loop is split into two output loops. TestMeridianSplitting( "# # 9:179, 9:-179, 10:-179, 10:179", "# # 9.00134850712993:180, 9:-179, 10:-179, 10.0014925269841:180; " "10.0014925269841:180, 10:179, 9:179, 9.00134850712993:180"); // An annulus that crosses the 180th meridian. This turns into two shells. TestMeridianSplitting( "# # 8:178, 8:-178, 11:-178, 11:178; 9:179, 10:179, 10:-179, 9:-179", "# # 10.0014925269841:180, 10:-179, 9:-179, 9.00134850712993:180, " "8.00481316618607:180, 8:-178, 11:-178, 11.00654129428:180; " "9.00134850712993:180, 9:179, 10:179, 10.0014925269841:180, " "11.00654129428:180, 11:178, 8:178, 8.00481316618607:180"); // An annulus that crosses the 180th meridian. This turns into two shells. TestMeridianSplitting( "# # 8:178, 8:-178, 11:-178, 11:178; 9:179, 10:179, 10:-179, 9:-179", "# # 10.0014925269841:180, 10:-179, 9:-179, 9.00134850712993:180, " "8.00481316618607:180, 8:-178, 11:-178, 11.00654129428:180; " "9.00134850712993:180, 9:179, 10:179, 10.0014925269841:180, " "11.00654129428:180, 11:178, 8:178, 8.00481316618607:180"); // The whole world except for a small square that crosses the 180th meridian. // This is a single loop that visits both poles. The result is correct // except that (1) +180 or -180 needs to be chosen consistently with the // adjacent points, and (2) each pole needs to be duplicated (once with // longitude -180 and once with longitude 180). TestMeridianSplitting( "# # 9:-179, 9:179, 10:179, 10:-179", "# # 0:180, 9.00134850712993:180, 9:179, 10:179, 10.0014925269841:180, " "90:0, 10.0014925269841:180, 10:-179, 9:-179, 9.00134850712993:180, " "0:180, -90:0"); } void ComputeTestUnion(const vector>& a_loops, const vector>& b_loops, S1Angle snap_radius, S2LaxPolygonShape* result) { MutableS2ShapeIndex a, b; a.Add(make_unique(a_loops)); b.Add(make_unique(b_loops)); S2BooleanOperation op(OpType::UNION, make_unique(result), S2BooleanOperation::Options( s2builderutil::IdentitySnapFunction(snap_radius))); S2Error error; ASSERT_TRUE(op.Build(a, b, &error)) << error; EXPECT_FALSE(result->is_empty()) << "\nS2Polygon: " << s2textformat::ToString(a) << "\nS2Polygon: " << s2textformat::ToString(b); } TEST(S2BooleanOperation, GetCrossedVertexIndexBug1) { // This test exercises a rare special case in GetCrossedVertexIndex where // two crossing edge chains snap to a different permutation of the same // vertices. In this example one input edge crosses another edge from right // to left, the first edge snaps to BCD and the second snaps to ABDC, and // triangle BCD is CCW. Since BCD is to the right of BD, this means that // the first edge has not yet crossed the second at vertex B, leaving C or D // as the possible crossing vertices. vector> a_loops = { { {-0.38306437985388492, -0.74921955334206214, 0.54030708099846292}, {-0.3830643798552798, -0.74921955334134249, 0.5403070809984718}, {-0.38306437985529124, -0.74921955334136414, 0.54030708099843361}, {-0.38306437985389635, -0.74921955334208379, 0.54030708099842473}, }, }; vector> b_loops = { { {-0.38306437985390962, -0.74921955334210588, 0.54030708099838465}, {-0.38306437985527797, -0.74921955334134205, 0.54030708099847369}, {-0.38306437985527941, -0.74921955334134405, 0.54030708099847014}, {-0.38306437985391095, -0.74921955334210777, 0.54030708099838098}, }, }; S2LaxPolygonShape result; ComputeTestUnion(a_loops, b_loops, S2::kIntersectionMergeRadius, &result); } TEST(S2BooleanOperation, GetCrossedVertexIndexBug2) { // This test exercises another rare case where the crossing vertices chosen // by GetCrossedVertexIndex() are not ordered correctly along the edge being // crossed. This is handled by adding extra edges to the output in order to // link up the crossings in the correct order. vector> a_loops = { { {-0.3837392878495085, -0.7477800800281974, 0.5418201831546835}, {-0.38373928785696076, -0.7477800800212292, 0.54182018315902258}, {-0.38373928785701278, -0.74778008002124685, 0.5418201831589613}, {-0.38373928785703426, -0.7477800800212544, 0.54182018315893576}, {-0.38373947205489456, -0.74778014227795497, 0.5418199667802881}, {-0.38373947204434411, -0.74778014228781997, 0.54181996677414512}, {-0.38373947205872994, -0.74778014228185352, 0.54181996677219124}, {-0.38373947218468357, -0.74778014288930306, 0.54181996584462788}, {-0.3837396702525171, -0.74778021044361542, 0.54181973233114322}, {-0.38373967023137123, -0.74778021046333043, 0.54181973231891067}, {-0.38373947216030285, -0.74778014290791484, 0.54181996583620895}, {-0.38373947217087578, -0.74778014289805739, 0.54181996584232528}, {-0.38373947215649007, -0.74778014290402395, 0.54181996584427927}, {-0.3837394720305386, -0.74778014229658485, 0.5418199667718262}, {-0.38373928783585998, -0.74778008004095942, 0.54182018314673686}, {-0.38373928784641037, -0.7477800800310942, 0.54182018315287972}, {-0.38373928783578648, -0.74778008004093421, 0.54182018314682368}, {-0.383739287835765, -0.74778008004092666, 0.54182018314684921}, }, }; vector> b_loops = { { {-0.38373923813692823, -0.7477800632164362, 0.54182024156551456}, {-0.3837392878569364, -0.74778008002122087, 0.54182018315905123}, {-0.38373928784640354, -0.74778008003106944, 0.54182018315291858}, {-0.38373928784638789, -0.74778008003108642, 0.54182018315290648}, {-0.38373928784638023, -0.74778008003109453, 0.54182018315290048}, {-0.38373928783692102, -0.74778008004124585, 0.54182018314559}, {-0.38373928783691913, -0.74778008004124541, 0.54182018314559188}, {-0.38373928784636568, -0.74778008003110774, 0.54182018315289271}, {-0.38373928784637329, -0.74778008003109953, 0.54182018315289848}, {-0.38373928783583561, -0.74778008004095109, 0.5418201831467655}, {-0.38373923811582744, -0.74778006323616641, 0.54182024155322883}, {-0.38373857650312843, -0.74777983961840766, 0.54182101875399913}, {-0.38373857652422921, -0.74777983959867744, 0.54182101876628486}, }, }; S2LaxPolygonShape result; ComputeTestUnion(a_loops, b_loops, S2::kIntersectionMergeRadius, &result); } TEST(S2BooleanOperation, GetCrossedVertexIndexBug3) { // This test exercises the special case in GetCrossedVertexIndex() that // requires checking the orientation of a loop. This is done by adding up the // turning angles at each vertex, which in turn involves computing the edge // normals and measuring the angles between them. However in this test, some // of the edge normals returned by S2::RobustCrossProd() used to be so small // that there were floating-point underflows when computing the angles between // them. This was fixed by implementing the long-standing TODO of making // S2::RobustCrossProd() actually robust. vector> a_loops = { { {1, 0, 2.4678234835261742e-72}, {0.99984769515639127, 0.017452406437283512, 1.8530922845942552e-27}, {0.99740259703611311, 0.069881849826437858, 0.017452406437283512}, }, }; vector> b_loops = { { {0.99999999999999989, 2.4674476220564615e-72, 2.4678234835261742e-72}, {0.99999999999999989, 2.8837981406657438e-169, 2.4678234835261742e-72}, {1, 2.8837981406657432e-169, 2.4678234835261742e-72}, }, }; S2LaxPolygonShape result; ComputeTestUnion(a_loops, b_loops, S1Angle::Zero(), &result); } TEST(S2BooleanOperation, GetCrossedVertexIndexBug4) { // This example tests the "special case" in GetCrossedVertexIndex() in // situations where two edges snap to the same sequence of vertices in // different orders. The first two edges (a0, a1) and (b0, b1) of the // following polygons cross such that after snapping, the corresponding edge // chains are: // // a0 a1 -> a0 b0 b1 x a1 // b0 b1 -> b0 x b1 // // where "x" is the computed intersection point of (a0, a1) and (b0, b1). // Previously there was a bug such that the two edge chains did not choose // the same vertex to represent the point where the two chains cross: the // (a0, a1) chain chose "x" as the crossing point while the (b0, b1) chain // chose "b0". This has been fixed such that both chains now choose "x". // (Both "x" and "b1" happen to be valid choices in this example, but it is // essential that both subchains make the same choice.) // S2LatLng coordinates are not accurate enough to reproduce this example. vector> a_loops{{ // 51.5131559470858:-0.130381523356724 {0.62233331065911901, -0.0014161759526823048, 0.78275107466533156}, // 51.5131892038956:-0.130404244210776 {0.6223328557578689, -0.0014164217071954736, 0.78275143589379825}, s2textformat::MakePointOrDie("51.51317:-0.1306") }}; vector> b_loops{{ // 51.5131559705551:-0.13038153939079 {0.62233331033809591, -0.001416176126110953, 0.78275107492024998}, // 51.5131559705551:-0.130381539390786 {0.62233331033809591, -0.0014161761261109063, 0.78275107492025009}, s2textformat::MakePointOrDie("51.52:-0.12"), s2textformat::MakePointOrDie("51.52:-0.14") }}; S2LaxPolygonShape result; ComputeTestUnion(a_loops, b_loops, S1Angle::Zero(), &result); } TEST(S2BooleanOperation, GetCrossedVertexIndexBug5) { // Yet another bizarre situation where two crossing edges snap (correctly) to // a sequence of vertices in different orders. Using the internal vertex // numbers assigned by S2Builder, input edges 3 and 12 snap to the following // vertex sequences: // // Input edge 3: 14, 8, 4, 9, 2, 5 // Input edge 12: 2, 7, 8, 9 // // Furthermore input edge 3 crosses input edge 12 from left to right. // Schematically, here is what edge 12 crossing edge 3 looks like: // // 14-->--8-->--4-->--9-->--2-->--5 // |\ / / // \ \--->---/ / // \ / // \--<--7--<--/ // // And here is what edge 3 crossing edge 12 looks like: // // 14-->--\ /---4->-\ // \ / \ // 2-->--7-->--8----->-----9 // / \ / // 5--<--/ \---------<---------/ // // In both cases, the only possible choice of crossing vertex consistent with // the fact that edge 3 crosses edge 12 from left to right is vertex 9. // Determining this requires knowing that loop (9, 2, 7, 8) is clockwise // (the "special case" in GetCrossedVertexIndex). The code previously didn't // have quite the correct test to decide when this was necessary. vector> a_loops = { { {0.99984769515639127, 0, 0.017452406437283512}, {0.99923861495548261, 0.017441774902830158, 0.034899496702500969}, {0.99847743863945992, 0.052327985223313139, 0.017452406437283512}, {0.99802119662406841, 0.034851668155187324, 0.052335956242943835}, }, }; vector> b_loops = { { {0.99802119662406841, 0.034851668155187324, 0.052335956242943835}, {0.99619692339885657, 0.052208468483931986, 0.069756473744125302}, {0.99802098681615425, 0.034839714972148959, 0.052347914334467859}, {0.99741208276778681, 0.017411821260589495, 0.069756473744125302}, {0.99741219210106513, 0.017411340538768819, 0.069755030419252628}, {0.99741211642315963, 0.017409893252357169, 0.069756473744125302}, {0.99984769515639116, 4.9500424645560228e-16, 0.017452406437284993}, {0.99984769515639127, 3.7368529835165677e-16, 0.017452406437284632}, {0.99984769515639116, 3.3065924905014365e-16, 0.017452406437284504}, {0.99984769515639127, 9.9060035932242025e-16, 0.017452406437284504}, {0.99969541350954794, 0.017449748351250485, 0.017452406437283512}, }, { {0.99984769515639116, 3.3065924905014365e-16, 0.017452406437284504}, {0.99984769515639116, 3.3006856770496304e-16, 0.017452406437284504}, {0.99984769515639127, 0, 0.017452406437284504}, {0.99984769515639127, 0, 0.017452406437283512}, }, }; S2LaxPolygonShape result; ComputeTestUnion(a_loops, b_loops, S1Angle::Zero(), &result); } TEST(S2BooleanOperation, GetCrossedVertexIndexBug6) { // This is another test of the code in GetCrossedVertexIndex() that checks // whether the B subchain contains an interior vertex of the A edge. vector> a_loops = { { {0.99870488823558456, 0.026138065586168355, 0.043650289137205818}, {0.99876259434149239, 0.030513215246694664, 0.0392711578586665}, {0.99984769515639127, 0.017452406437283512, 0}, {0.998782023517925, 0.034862286684437908, 0.034915476003791211}, {0.99878202512991221, 0.034878236872062651, 0.034899496702500969}, {0.9975640502598242, 0.069756473744125302, 0}, {0.99877979583714305, 0.034883478425067296, 0.034958008531414335}, {0.99619692339885657, 0.052208468483931986, 0.069756473744125302}, {0.99847581234813876, 0.017465633646566288, 0.052354596713645812}, {0.9975640502598242, 0, 0.069756473744125302}, {0.99847674250410212, 0.017444393356200013, 0.052343937746706169}, {0.99847743863945992, 0.017428488520812163, 0.052335956242943835}, {0.99984769515639127, 0, 0.017452406437283512}, }, { {0.99619692339885657, 0.052208468483931986, 0.069756473744125302}, {0.99802119661969568, 0.034851668280404598, 0.052335956242943835}, {0.9987605225894034, 0.030527121154938986, 0.039313018084772409}, {0.99870321796526884, 0.026161932439896601, 0.043674199670139441}, }, { {0.99619692339885657, 0.052208468483931986, 0.069756473744125302}, {0.99619692339885657, 0.06966087492121549, 0.052335956242943835}, {0.99513403437078507, 0.069586550480032719, 0.069756473744125302}, }, }; vector> b_loops = { { {0.99802200429988497, 0.034828499898458924, 0.052335977377554299}, {0.99862953475457383, 0, 0.052335956242943835}, {0.99923793061512223, 0.017455729388178846, 0.034912111530741322}, {0.99923859085845868, 0.017443155365764275, 0.034899496702500969}, {0.99923793076147094, 0.017455737780810811, 0.034912103145779166}, {0.9992865072388355, 0.020934110218524152, 0.0314362764933699}, {1, 0, 0}, {0.99929987808789411, 0.022418034384064717, 0.029953053064335624}, {0.99931406232431441, 0.02616995393092059, 0.026201876881811362}, {0.99984769515639127, 0.017452406437283512, 0}, {0.99930573320200933, 0.029072747464899757, 0.023298646837028814}, {0.99862953475457383, 0.052335956242943835, 1.700986599320836e-73}, {0.99838518277004218, 0.038347188759395717, 0.041910857059723181}, {0.99619692339885668, 0.052208468483931979, 0.069756473744125289}, }, { {0.99802119662406841, 0.052304074592470849, 0.034899496702500969}, {0.99847743834686298, 0.052327990806397578, 0.017452406437283512}, {0.99619645281505653, 0.052208443821680058, 0.069763212314351342}, {0.99619692339885657, 0.052208468483932, 0.069756473744125316}, {0.99619692339885657, 0.052208468483931986, 0.069756473744125302}, {0.99619692339885679, 0.052208468483931993, 0.069756473744125316}, {0.99619692339885679, 0.052208468483931986, 0.069756473744125302}, {0.99619692339885668, 0.052208468483931979, 0.069756473744125289}, }, }; S2LaxPolygonShape result; ComputeTestUnion(a_loops, b_loops, S1Angle::Zero(), &result); } // Performs the given operation and compares the result to "expected_str". All // arguments are in s2textformat::MakeLaxPolygonOrDie() format. void ExpectPolygon(S2BooleanOperation::OpType op_type, string_view a_str, string_view b_str, string_view expected_str) { auto a = s2textformat::MakeIndexOrDie(StrCat("# # ", a_str)); auto b = s2textformat::MakeIndexOrDie(StrCat("# # ", b_str)); s2builderutil::LaxPolygonLayer::Options polygon_options; polygon_options.set_degenerate_boundaries(DegenerateBoundaries::DISCARD); S2LaxPolygonShape output; S2BooleanOperation op( op_type, make_unique(&output, polygon_options), S2BooleanOperation::Options{s2builderutil::IdentitySnapFunction{ S1Angle::Degrees(1.1)}}); S2Error error; ASSERT_TRUE(op.Build(*a, *b, &error)) << error; EXPECT_EQ(expected_str, s2textformat::ToString(output)); } TEST(S2BooleanOperation, FullAndEmptyResults) { // The following constants are all in s2textformat::MakeLaxPolygonOrDie() // format. string kEmpty = ""; string kFull = "full"; // Two complementary shell/hole pairs, together with alternative shells that // are slightly smaller or larger than the original. string kShell1 = "10:0, 10:10, 20:10"; string kHole1 = "10:0, 20:10, 10:10"; string kShell1Minus = "11:2, 11:9, 18:9"; string kShell1Plus = "9:-2, 9:11, 22:11"; string kShell2 = "10:20, 10:30, 20:30"; string kHole2 = "10:20, 20:30, 10:30"; // The northern and southern hemispheres. string kNorthHemi = "0:0, 0:120, 0:-120"; string kSouthHemi = "0:0, 0:-120, 0:120"; // These edges deviate from kSouthHemi by slightly more than 1 degree. string kSouthHemiPlus = "0.5:0, 0.5:-120, 0.5:120"; // A shell and hole that cover complementary hemispheres, such that each // hemisphere intersects all six S2 cube faces. There are also alternative // shells that are slightly smaller or larger than the original. string k6FaceShell1 = "0:-45, 45:0, 45:90, 0:135, -45:180, -45:-90"; string k6FaceHole1 = "0:-45, -45:-90, -45:180, 0:135, 45:90, 45:0"; string k6FaceShell1Minus = "-1:-45, 44:0, 44:90, -1:135, -46:180, -46:-90"; string k6FaceShell1Plus = "1:-45, 46:0, 46:90, 1:135, -44:180, -44:-90"; // Two complementary shell/hole pairs that are small enough so that they will // disappear when the snap radius chosen above is used. string kAlmostEmpty1 = "2:0, 2:10, 3:0"; string kAlmostFull1 = "2:0, 3:0, 2:10"; string kAlmostEmpty2 = "4:0, 4:10, 5:0"; string kAlmostFull2 = "4:0, 5:0, 4:10"; // A polygon that intersects all 6 faces such but snaps to an empty polygon. string k6FaceAlmostEmpty1 = k6FaceShell1Minus + "; " + k6FaceHole1; // Test empty UNION results. // - Exact result, no input edges. ExpectPolygon(OpType::UNION, kEmpty, kEmpty, kEmpty); // - Empty due to snapping, union does not intersect all 6 cube faces. ExpectPolygon(OpType::UNION, kAlmostEmpty1, kAlmostEmpty2, kEmpty); // - Empty due to snapping, union intersects all 6 cube faces. ExpectPolygon(OpType::UNION, k6FaceAlmostEmpty1, k6FaceAlmostEmpty1, kEmpty); // Test full UNION results. // - Exact result, no input edges. ExpectPolygon(OpType::UNION, kEmpty, kFull, kFull); ExpectPolygon(OpType::UNION, kEmpty, kFull, kFull); ExpectPolygon(OpType::UNION, kFull, kFull, kFull); // - Exact result, some input edges. ExpectPolygon(OpType::UNION, kFull, kShell1, kFull); ExpectPolygon(OpType::UNION, kHole1, kHole2, kFull); ExpectPolygon(OpType::UNION, kHole1, kShell1, kFull); // - Full due to snapping, almost complementary polygons. ExpectPolygon(OpType::UNION, kHole1, kShell1Minus, kFull); ExpectPolygon(OpType::UNION, k6FaceHole1, k6FaceShell1Minus, kFull); // Test empty INTERSECTION results. // - Exact result, no input edges. ExpectPolygon(OpType::INTERSECTION, kEmpty, kEmpty, kEmpty); ExpectPolygon(OpType::INTERSECTION, kEmpty, kFull, kEmpty); ExpectPolygon(OpType::INTERSECTION, kFull, kEmpty, kEmpty); // - Exact result, inputs do not both intersect all 6 cube faces. ExpectPolygon(OpType::INTERSECTION, kEmpty, kHole1, kEmpty); ExpectPolygon(OpType::INTERSECTION, kShell1, kShell2, kEmpty); ExpectPolygon(OpType::INTERSECTION, kShell1, kHole1, kEmpty); // - Exact result, inputs both intersect all 6 cube faces. ExpectPolygon(OpType::INTERSECTION, k6FaceShell1, k6FaceHole1, kEmpty); // - Empty due to snapping, inputs do not both intersect all 6 cube faces. ExpectPolygon(OpType::INTERSECTION, kShell1Plus, kHole1, kEmpty); // - Empty due to snapping, inputs both intersect all 6 cube faces. ExpectPolygon(OpType::INTERSECTION, k6FaceShell1Plus, k6FaceHole1, kEmpty); // Test full INTERSECTION results. // - Exact result, no input edges. ExpectPolygon(OpType::INTERSECTION, kFull, kFull, kFull); // - Full due to snapping, almost full input polygons. ExpectPolygon(OpType::INTERSECTION, kAlmostFull1, kAlmostFull2, kFull); // Test empty DIFFERENCE results. // - Exact result, no input edges. ExpectPolygon(OpType::DIFFERENCE, kEmpty, kEmpty, kEmpty); ExpectPolygon(OpType::DIFFERENCE, kEmpty, kFull, kEmpty); ExpectPolygon(OpType::DIFFERENCE, kFull, kFull, kEmpty); // - Exact result, first input does not intersect all 6 cube faces. ExpectPolygon(OpType::DIFFERENCE, kEmpty, kShell1, kEmpty); ExpectPolygon(OpType::DIFFERENCE, kShell1, kFull, kEmpty); ExpectPolygon(OpType::DIFFERENCE, kShell1, kShell1, kEmpty); ExpectPolygon(OpType::DIFFERENCE, kShell1, kHole2, kEmpty); // - Exact result, first input intersects all 6 cube faces. ExpectPolygon(OpType::DIFFERENCE, k6FaceShell1, k6FaceShell1Plus, kEmpty); // - Empty due to snapping, first input does not intersect all 6 cube faces. ExpectPolygon(OpType::DIFFERENCE, kShell1Plus, kShell1, kEmpty); // - Empty due to snapping, first input intersect all 6 cube faces. ExpectPolygon(OpType::DIFFERENCE, k6FaceShell1Plus, k6FaceShell1, kEmpty); // Test full DIFFERENCE results. // - Exact result, no input edges. ExpectPolygon(OpType::DIFFERENCE, kFull, kEmpty, kFull); // - Full due to snapping, almost full/empty input polygons. ExpectPolygon(OpType::DIFFERENCE, kAlmostFull1, kAlmostEmpty2, kFull); // Test empty SYMMETRIC_DIFFERENCE results. // - Exact result, no input edges. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kEmpty, kEmpty, kEmpty); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kFull, kFull, kEmpty); // - Exact result, union does not intersect all 6 cube faces. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kShell1, kShell1, kEmpty); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kNorthHemi, kNorthHemi, kEmpty); // - Exact result, union intersects all 6 cube faces. This case is only // handled correctly due to the kBiasTowardsEmpty heuristic. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, k6FaceShell1, k6FaceShell1, kEmpty); // - Empty due to snapping, union does not intersect all 6 cube faces. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kShell1Plus, kShell1, kEmpty); // - Empty due to snapping, union intersects all 6 cube faces. This case is // only handled correctly due to the kBiasTowardsEmpty heuristic. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, k6FaceShell1Plus, k6FaceShell1, kEmpty); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, k6FaceShell1Minus, k6FaceShell1, kEmpty); // Test full SYMMETRIC_DIFFERENCE results. // - Exact result, no input edges. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kFull, kEmpty, kFull); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kEmpty, kFull, kFull); // - Exact result, complementary input polygons. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kShell1, kHole1, kFull); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kAlmostEmpty1, kAlmostFull1, kFull); // - Full due to snapping, almost complementary input polygons. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kShell1Plus, kHole1, kFull); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kAlmostFull1, kAlmostEmpty2, kFull); // - Exact result, complementary hemispheres, at least one input does not // intersect all 6 cube faces. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kNorthHemi, kSouthHemi, kFull); // - Exact result, almost complementary hemispheres, at least one input does // not intersect all 6 cube faces. ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, kNorthHemi, kSouthHemiPlus, kFull); // TODO(ericv): The following case is not currently implemented. // - Full result, complementary (to within the snap radius) input polygons // each with an area of approximately 2*Pi, and both polygons intersect all // 6 cube faces. #if 0 ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, k6FaceShell1, k6FaceHole1, kFull); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, k6FaceShell1Plus, k6FaceHole1, kFull); ExpectPolygon(OpType::SYMMETRIC_DIFFERENCE, k6FaceShell1Minus, k6FaceHole1, kFull); #endif } // Tests whether the two S2ShapeIndexes are equal according to // S2BooleanOperation::Equals(). bool TestEqual(string_view a_str, string_view b_str) { auto a = s2textformat::MakeIndexOrDie(a_str); auto b = s2textformat::MakeIndexOrDie(b_str); return S2BooleanOperation::Equals(*a, *b); } // Tests S2BooleanOperation::Equals, which computes the symmetric difference // between two geometries and tests whether the result is empty. // // This also indirectly tests IsEmpty(), which is used to implement Contains() // and Intersects(). TEST(S2BooleanOperation, Equals) { EXPECT_TRUE(TestEqual("# #", "# #")); EXPECT_TRUE(TestEqual("# # full", "# # full")); EXPECT_FALSE(TestEqual("# #", "# # full")); EXPECT_FALSE(TestEqual("0:0 # #", "# #")); EXPECT_FALSE(TestEqual("0:0 # #", "# # full")); EXPECT_FALSE(TestEqual("# 0:0, 1:1 #", "# #")); EXPECT_FALSE(TestEqual("# 0:0, 1:1 #", "# # full")); EXPECT_FALSE(TestEqual("# # 0:0, 0:1, 1:0 ", "# #")); EXPECT_FALSE(TestEqual("# # 0:0, 0:1, 1:0 ", "# # full")); } // Tests Contains() on empty and full geometries. TEST(S2BooleanOperation, ContainsEmptyAndFull) { auto empty = s2textformat::MakeIndexOrDie("# #"); auto full = s2textformat::MakeIndexOrDie("# # full"); EXPECT_TRUE(S2BooleanOperation::Contains(*empty, *empty)); EXPECT_FALSE(S2BooleanOperation::Contains(*empty, *full)); EXPECT_TRUE(S2BooleanOperation::Contains(*full, *empty)); EXPECT_TRUE(S2BooleanOperation::Contains(*full, *full)); } // Tests Intersects() on empty and full geometries. TEST(S2BooleanOperation, IntersectsEmptyAndFull) { auto empty = s2textformat::MakeIndexOrDie("# #"); auto full = s2textformat::MakeIndexOrDie("# # full"); EXPECT_FALSE(S2BooleanOperation::Intersects(*empty, *empty)); EXPECT_FALSE(S2BooleanOperation::Intersects(*empty, *full)); EXPECT_FALSE(S2BooleanOperation::Intersects(*full, *empty)); EXPECT_TRUE(S2BooleanOperation::Intersects(*full, *full)); } TEST(S2BooleanOperation, OptionsFieldsCopied) { S2BooleanOperation::Options options; // Just test one field. options.set_polyline_loops_have_boundaries(false); S2BooleanOperation no_boundary_op(S2BooleanOperation::OpType::UNION, vector>(), options); EXPECT_FALSE(no_boundary_op.options().polyline_loops_have_boundaries()); options.set_polyline_loops_have_boundaries(true); S2BooleanOperation boundary_op(S2BooleanOperation::OpType::UNION, vector>(), options); EXPECT_TRUE(boundary_op.options().polyline_loops_have_boundaries()); } TEST(S2BooleanOperationSourceIdTest, Accessors) { // region_id may only be 0 or 1. S2BooleanOperation::SourceId id(/*region_id=*/1, /*shape_id=*/2, /*edge_id=*/3); EXPECT_EQ(1, id.region_id()); EXPECT_EQ(2, id.shape_id()); EXPECT_EQ(3, id.edge_id()); } TEST(S2BooleanOperationSourceIdTest, Equality) { using Id = S2BooleanOperation::SourceId; EXPECT_EQ(Id(1, 2, 3), Id(1, 2, 3)); // `operator!=` is not defined, so use `==` instead of `EXPECT_NE`. EXPECT_FALSE(Id(1, 2, 3) == Id(0, 2, 3)); EXPECT_FALSE(Id(1, 2, 3) == Id(1, 0, 3)); EXPECT_FALSE(Id(1, 2, 3) == Id(1, 2, 0)); } TEST(S2BooleanOperationSourceIdTest, LessThan) { using Id = S2BooleanOperation::SourceId; EXPECT_FALSE(Id(1, 2, 3) < Id(1, 2, 3)); EXPECT_LT(Id(0, 2, 3), Id(1, 2, 3)); EXPECT_LT(Id(1, 2, 3), Id(1, 20, 3)); EXPECT_LT(Id(1, 2, 3), Id(1, 2, 30)); } } // namespace src/s2/s2buffer_operation.cc000066400000000000000000000761341524103652300163120ustar00rootroot00000000000000// Copyright 2020 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) // // The algorithm below essentially computes the offset curve of the original // boundary, and uses this curve to divide the sphere into regions of constant // winding number. Since winding numbers on the sphere are relative rather // than absolute (see s2winding_operation.h), we also need to keep track of // the desired winding number at a fixed reference point. The initial winding // number for this point is the number of input shapes that contain it. We // then update it during the buffering process by imagining a "sweep edge" // that extends from the current point A on the input boundary to the // corresponding point B on the offset curve. As we process an input loop and // generate the corresponding offset curve, the sweep edge moves continuously // and covers the entire buffer region (i.e., the region added to or // subtracted from the input geometry). We increase the winding number of the // reference point by one whenever it crosses the sweep edge from left to // right, and we decrease the winding number by one whenever it crosses the // sweep edge from right to left. // // Concave vertices require special handling, because the corresponding offset // curve can leave behind regions whose winding number is zero or negative. // We handle this by splicing the concave vertex into the offset curve itself; // this effectively terminates the current buffer region and starts a new one, // such that the region of overlap is counted twice (i.e., its winding number // increases by two). The end result is the same as though we had computed // the union of a sequence of buffered convex boundary segments. This trick // is described in the following paper: "Polygon Offsetting by Computing // Winding Numbers" (Chen and McMains, Proceedings of IDETC/CIE 2005). // // TODO(ericv): The algorithm below is much faster than, say, computing the // union of many buffered edges. However further improvements are possible. // In particular, there is an unimplemented optimization that would make it // much faster to buffer concave boundaries when the buffer radius is large. #include "s2/s2buffer_operation.h" #include #include #include #include #include #include #include "absl/base/nullability.h" #include "absl/log/absl_check.h" #include "absl/types/span.h" #include "s2/s1angle.h" #include "s2/s1chord_angle.h" #include "s2/s2builder.h" #include "s2/s2builder_layer.h" #include "s2/s2builderutil_snap_functions.h" #include "s2/s2contains_point_query.h" #include "s2/s2edge_crosser.h" #include "s2/s2edge_crossings.h" #include "s2/s2edge_distances.h" #include "s2/s2error.h" #include "s2/s2lax_loop_shape.h" #include "s2/s2memory_tracker.h" #include "s2/s2point.h" #include "s2/s2point_span.h" #include "s2/s2pointutil.h" #include "s2/s2predicates.h" #include "s2/s2predicates_internal.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2shape_measures.h" #include "s2/s2shapeutil_contains_brute_force.h" #include "s2/s2winding_operation.h" #include "s2/util/math/mathutil.h" using s2pred::DBL_ERR; using std::ceil; using std::make_unique; using std::max; using std::min; using std::unique_ptr; using std::vector; // The errors due to buffering can be categorized as follows: // // 1. Requested error. This represents the error due to approximating the // buffered boundary as a sequence of line segments rather than a sequence // of circular arcs. It is largely controlled by options.error_fraction(), // and can be bounded as // // max(kMinRequestedError, error_fraction * buffer_radius) // // where kMinRequestedError reflects the fact that S2Points do not have // infinite precision. (For example, it makes no sense to attempt to // buffer geometry by 1e-100 radians because the spacing between // representable S2Points is only about 2e-16 radians in general.) // // 2. Relative interpolation errors. These are numerical errors whose // magnitude is proportional to the buffer radius. For such errors the // worst-case coefficient of proportionality turns out to be so tiny // compared to the smallest allowable error fraction (kMinErrorFraction) // that we simply ignore such errors. // // 3. Absolute interpolation errors. These are numerical errors that are not // proportional to the buffer radius. The main sources of such errors are // (1) calling S2::RobustCrossProd() to compute edge normals, and (2) calls // to S2::GetPointOnRay() to interpolate points along the buffered // boundary. It is possible to show that this error is at most // kMaxAbsoluteInterpolationError as defined below. // // Putting these together, the final error bound looks like this: // // max_error = kMaxAbsoluteInterpolationError + // max(kMinRequestedError, // max(kMinErrorFraction, options.error_fraction()) * // options.buffer_radius()) // The maximum angular spacing between representable S2Points on the unit // sphere is roughly 2 * DBL_ERR. We require the requested absolute error to // be at least this large because attempting to achieve a smaller error does // not increase the precision of the result and can increase the running time // and space requirements considerably. static constexpr S1Angle kMinRequestedError = S1Angle::Radians(2 * DBL_ERR); // The maximum absolute error due to interpolating points on the buffered // boundary. The following constant bounds the maximum additional error // perpendicular to the buffered boundary due to all steps of the calculation // (S2::RobustCrossProd, the two calls to GetPointOnRay, etc). // // This distance represents about 10 nanometers on the Earth's surface. Note // that this is a conservative upper bound and that it is difficult to // construct inputs where the error is anywhere close to this large. static constexpr S1Angle kMaxAbsoluteInterpolationError = S2::kGetPointOnLineError + S2::kGetPointOnRayPerpendicularError; S2BufferOperation::Options::Options() : snap_function_( make_unique(S1Angle::Zero())) { } S2BufferOperation::Options::Options(S1Angle buffer_radius) : Options() { buffer_radius_ = buffer_radius; } S2BufferOperation::Options::Options(const Options& options) : buffer_radius_(options.buffer_radius_), error_fraction_(options.error_fraction_), end_cap_style_(options.end_cap_style_), polyline_side_(options.polyline_side_), snap_function_(options.snap_function_->Clone()), memory_tracker_(options.memory_tracker_) { } S2BufferOperation::Options& S2BufferOperation::Options::operator=( const Options& options) { buffer_radius_ = options.buffer_radius_; error_fraction_ = options.error_fraction_; end_cap_style_ = options.end_cap_style_; polyline_side_ = options.polyline_side_; snap_function_ = options.snap_function_->Clone(); memory_tracker_ = options.memory_tracker_; return *this; } S1Angle S2BufferOperation::Options::buffer_radius() const { return buffer_radius_; } void S2BufferOperation::Options::set_buffer_radius(S1Angle buffer_radius) { buffer_radius_ = buffer_radius; } double S2BufferOperation::Options::error_fraction() const { return error_fraction_; } void S2BufferOperation::Options::set_error_fraction(double error_fraction) { ABSL_DCHECK_GE(error_fraction, kMinErrorFraction); ABSL_DCHECK_LE(error_fraction, 1.0); error_fraction_ = max(kMinErrorFraction, min(1.0, error_fraction)); } S1Angle S2BufferOperation::Options::max_error() const { // See comments for kMinRequestedError above. S2Builder::Options builder_options(*snap_function_); builder_options.set_split_crossing_edges(true); return max(kMinRequestedError, error_fraction_ * abs(buffer_radius_)) + kMaxAbsoluteInterpolationError + builder_options.max_edge_deviation(); } double S2BufferOperation::Options::circle_segments() const { #if 0 // This formula assumes that vertices can be placed anywhere. TODO(ericv). return M_PI / acos((1 - error_fraction_) / (1 + error_fraction_)); #else // This formula assumes that all vertices are placed on the midline. return M_PI / acos(1 - error_fraction_); #endif } void S2BufferOperation::Options::set_circle_segments(double circle_segments) { ABSL_DCHECK_GE(circle_segments, 2.0); ABSL_DCHECK_LE(circle_segments, kMaxCircleSegments); circle_segments = max(2.0, min(kMaxCircleSegments, circle_segments)); // We convert circle_segments to error_fraction using planar geometry, // because the number of segments required to approximate a circle on the // sphere to within a given tolerance is not constant. Unlike in the plane, // the total curvature of a circle on the sphere decreases as the area // enclosed by the circle increases; great circles have no curvature at all. // We round up when converting to ensure that we won't generate any tiny // extra edges. // #if 0 // Note that we take advantage of both positive and negative errors when // approximating circles (i.e., vertices are not necessarily on the midline) // and thus the relationships between circle_segments and error_fraction are // e = (1 - cos(Pi/n)) / (1 + cos(Pi/n)) // n = Pi / acos((1 - e) / (1 + e)) double r = cos(M_PI / circle_segments); set_error_fraction((1 - r) / (1 + r) + 1e-15); #else // When all vertices are on the midline, the relationships are // e = 1 - cos(Pi/n) // n = Pi / acos(1 - e) set_error_fraction(1 - cos(M_PI / circle_segments) + 1e-15); #endif } S2BufferOperation::EndCapStyle S2BufferOperation::Options::end_cap_style() const { return end_cap_style_; } void S2BufferOperation::Options::set_end_cap_style(EndCapStyle end_cap_style) { end_cap_style_ = end_cap_style; } S2BufferOperation::PolylineSide S2BufferOperation::Options::polyline_side() const { return polyline_side_; } void S2BufferOperation::Options::set_polyline_side( PolylineSide polyline_side) { polyline_side_ = polyline_side; } const S2Builder::SnapFunction& S2BufferOperation::Options::snap_function() const { return *snap_function_; } void S2BufferOperation::Options::set_snap_function( const S2Builder::SnapFunction& snap_function) { snap_function_ = snap_function.Clone(); } S2MemoryTracker* S2BufferOperation::Options::memory_tracker() const { return memory_tracker_; } void S2BufferOperation::Options::set_memory_tracker(S2MemoryTracker* tracker) { memory_tracker_ = tracker; } S2BufferOperation::S2BufferOperation() = default; S2BufferOperation::S2BufferOperation(unique_ptr result_layer, const Options& options) { Init(std::move(result_layer), options); } void S2BufferOperation::Init(unique_ptr result_layer, const Options& options) { options_ = options; ref_point_ = S2::Origin(); ref_winding_ = 0; have_input_start_ = false; have_offset_start_ = false; buffer_sign_ = sgn(options_.buffer_radius().radians()); S1Angle abs_radius = abs(options_.buffer_radius()); S1Angle requested_error = max(kMinRequestedError, options_.error_fraction() * abs_radius); S1Angle max_error = kMaxAbsoluteInterpolationError + requested_error; if (abs_radius <= max_error) { // If the requested radius is smaller than the maximum error, buffering // could yield points on the wrong side of the original input boundary // (e.g., shrinking geometry slightly rather than expanding it). Rather // than taking that risk, we set the buffer radius to zero when this // happens (which causes the original geometry to be returned). abs_radius_ = S1ChordAngle::Zero(); buffer_sign_ = 0; } else if (abs_radius + max_error >= S1Angle::Radians(M_PI)) { // If the permissible range of buffer angles includes Pi then we might // as well take advantage of that. abs_radius_ = S1ChordAngle::Straight(); } else { abs_radius_ = S1ChordAngle(abs_radius); S1Angle vertex_step = GetMaxEdgeSpan(abs_radius, requested_error); vertex_step_ = S1ChordAngle(vertex_step); // We take extra care to ensure that points are buffered as regular // polygons. The step angle is adjusted up slightly to ensure that we // don't wind up with a tiny extra edge. point_step_ = S1ChordAngle::Radians( 2 * M_PI / ceil(2 * M_PI / vertex_step.radians()) + 1e-15); // Edges are buffered only if the buffer radius (including permissible // error) is less than 90 degrees. S1Angle edge_radius = S1Angle::Radians(M_PI_2) - abs_radius; if (edge_radius > max_error) { edge_step_ = S1ChordAngle(GetMaxEdgeSpan(edge_radius, requested_error)); } } // The buffered output should include degeneracies (i.e., isolated points // and/or sibling edge pairs) only if (1) the user specified a non-negative // buffer radius, and (2) the adjusted buffer radius is zero. The only // purpose of keeping degeneracies is to allow points/polylines in the input // geometry to be converted back to points/polylines in the output if the // client so desires. S2WindingOperation::Options winding_options{options.snap_function()}; winding_options.set_include_degeneracies( buffer_sign_ == 0 && options_.buffer_radius() >= S1Angle::Zero()); winding_options.set_memory_tracker(options.memory_tracker()); op_.Init(std::move(result_layer), winding_options); tracker_.Init(options.memory_tracker()); } const S2BufferOperation::Options& S2BufferOperation::options() const { return options_; } S1Angle S2BufferOperation::GetMaxEdgeSpan(S1Angle radius, S1Angle requested_error) const { // If the allowable radius range spans Pi/2 then we can use edges as long as // we like, however we always use at least 3 edges to approximate a circle. S1Angle step = S1Angle::Radians(2 * M_PI / 3 + 1e-15); S1Angle min_radius = radius - requested_error; ABSL_DCHECK_GE(min_radius, S1Angle::Zero()); if (radius.radians() < M_PI_2) { step = min(step, S1Angle::Radians(2 * acos(tan(min_radius) / tan(radius)))); } else if (min_radius.radians() > M_PI_2) { step = min(step, S1Angle::Radians(2 * acos(tan(radius) / tan(min_radius)))); } return step; } // The sweep edge AB (see introduction) consists of one point on the input // boundary (A) and one point on the offset curve (B). This function advances // the sweep edge by moving its first vertex A to "new_a" and updating the // winding number of the reference point if necessary. void S2BufferOperation::SetInputVertex(const S2Point& new_a) { if (have_input_start_) { ABSL_DCHECK(have_offset_start_); UpdateRefWinding(sweep_a_, sweep_b_, new_a); } else { input_start_ = new_a; have_input_start_ = true; } sweep_a_ = new_a; } // Adds the point "new_b" to the offset path. Also advances the sweep edge AB // by moving its second vertex B to "new_b" and updating the winding number of // the reference point if necessary (see introduction). void S2BufferOperation::AddOffsetVertex(const S2Point& new_b) { if (!tracker_.AddSpace(&path_, 1)) return; path_.push_back(new_b); if (have_offset_start_) { ABSL_DCHECK(have_input_start_); UpdateRefWinding(sweep_a_, sweep_b_, new_b); } else { offset_start_ = new_b; have_offset_start_ = true; } sweep_b_ = new_b; } // Finishes buffering the current loop by advancing the sweep edge back to its // starting location, updating the winding number of the reference point if // necessary. void S2BufferOperation::CloseBufferRegion() { if (have_offset_start_ && have_input_start_) { UpdateRefWinding(sweep_a_, sweep_b_, input_start_); UpdateRefWinding(input_start_, sweep_b_, offset_start_); } } // Outputs the current buffered path (which is assumed to be a loop), and // resets the state to prepare for buffering a new loop. void S2BufferOperation::OutputPath() { op_.AddLoop(path_); path_.clear(); // Does not change capacity. have_input_start_ = false; have_offset_start_ = false; } // Given a triangle ABC that has just been covered by the sweep edge AB, // updates the winding number of the reference point if necessary. void S2BufferOperation::UpdateRefWinding( const S2Point& a, const S2Point& b, const S2Point& c) { // TODO(ericv): This code could be made much faster by maintaining a // bounding plane that separates the current sweep edge from the reference // point. Whenever the sweep_a_ or sweep_b_ is updated we would just need // to check that the new vertex is still on the opposite side of the // bounding plane (i.e., one dot product). If not, we test the current // triangle using the code below and then compute a new bounding plane. // // Another optimization would be to choose the reference point to be 90 // degrees away from the first input vertex, since then triangle tests would // not be needed unless the input geometry spans more than 90 degrees. This // would involve adding a new flag have_ref_point_ rather than always // choosing the reference point to be S2::Origin(). // // According to profiling these optimizations are not currently worthwhile, // but this is worth revisiting if and when other improvements are made. int sign = s2pred::Sign(a, b, c); if (sign == 0) return; bool inside = S2::AngleContainsVertex(a, b, c) == (sign > 0); S2EdgeCrosser crosser(&b, &ref_point_); inside ^= crosser.EdgeOrVertexCrossing(&a, &b); inside ^= crosser.EdgeOrVertexCrossing(&b, &c); inside ^= crosser.EdgeOrVertexCrossing(&c, &a); if (inside) ref_winding_ += sign; } // Ensures that the output will be the full polygon. void S2BufferOperation::AddFullPolygon() { ref_winding_ += 1; } void S2BufferOperation::AddPoint(const S2Point& point) { // If buffer_radius < 0, points are discarded. if (buffer_sign_ < 0) return; // Buffering by 180 degrees or more always yields the full polygon. // (We don't need to worry about buffering by 180 degrees yielding // a degenerate hole because error_fraction_ is always positive. if (abs_radius_ >= S1ChordAngle::Straight()) { return AddFullPolygon(); } // If buffer_radius == 0, points are converted into degenerate loops. if (buffer_sign_ == 0) { if (!tracker_.AddSpace(&path_, 1)) return; path_.push_back(point); } else { // Since S1ChordAngle can only represent angles between 0 and 180 degrees, // we generate the circle in four 90 degree increments. SetInputVertex(point); S2Point start = S2::Ortho(point); S1ChordAngle angle = S1ChordAngle::Zero(); for (int quadrant = 0; quadrant < 4; ++quadrant) { // Generate 90 degrees of the circular arc. Normalize "rotate_dir" at // each iteration to avoid magnifying normalization errors in "point". S2Point rotate_dir = point.CrossProd(start).Normalize(); for (; angle < S1ChordAngle::Right(); angle += point_step_) { S2Point dir = S2::GetPointOnRay(start, rotate_dir, angle); AddOffsetVertex(S2::GetPointOnRay(point, dir, abs_radius_)); } angle -= S1ChordAngle::Right(); start = rotate_dir; } CloseBufferRegion(); } OutputPath(); } // Returns the edge normal for the given edge AB. The sign is chosen such // that the normal is on the right of AB if buffer_sign_ > 0, and on the left // of AB if buffer_sign_ < 0. inline S2Point S2BufferOperation::GetEdgeAxis(const S2Point& a, const S2Point& b) const { ABSL_DCHECK_NE(buffer_sign_, 0); return buffer_sign_ * S2::RobustCrossProd(b, a).Normalize(); } // Adds a semi-open offset arc around vertex V. The arc proceeds CCW from // "start" to "end" (both of which must be perpendicular to V). void S2BufferOperation::AddVertexArc(const S2Point& v, const S2Point& start, const S2Point& end) { // Make sure that we output at least one point even when span == 0. S2Point rotate_dir = buffer_sign_ * v.CrossProd(start).Normalize(); S1ChordAngle angle, span(start, end); do { S2Point dir = S2::GetPointOnRay(start, rotate_dir, angle); AddOffsetVertex(S2::GetPointOnRay(v, dir, abs_radius_)); } while ((angle += vertex_step_) < span); } // Closes the semi-open arc generated by AddVertexArc(). void S2BufferOperation::CloseVertexArc(const S2Point& v, const S2Point& end) { AddOffsetVertex(S2::GetPointOnRay(v, end, abs_radius_)); } // Adds a semi-open offset arc for the given edge AB. void S2BufferOperation::AddEdgeArc(const S2Point& a, const S2Point& b) { S2Point ab_axis = GetEdgeAxis(a, b); if (edge_step_ == S1ChordAngle::Zero()) { // If the buffer radius is more than 90 degrees, edges do not contribute to // the buffered boundary. Instead we force the offset path to pass // through a vertex located at the edge normal. This is similar to the // case of concave vertices (below) where it is necessary to route the // offset path through the concave vertex to ensure that the winding // numbers in all output regions have the correct sign. AddOffsetVertex(ab_axis); } else { // Make sure that we output at least one point even when span == 0. S2Point rotate_dir = buffer_sign_ * a.CrossProd(ab_axis).Normalize(); S1ChordAngle angle, span(a, b); do { S2Point p = S2::GetPointOnRay(a, rotate_dir, angle); AddOffsetVertex(S2::GetPointOnRay(p, ab_axis, abs_radius_)); } while ((angle += edge_step_) < span); } SetInputVertex(b); } // Closes the semi-open arc generated by AddEdgeArc(). void S2BufferOperation::CloseEdgeArc(const S2Point& a, const S2Point& b) { if (edge_step_ != S1ChordAngle::Zero()) { AddOffsetVertex(S2::GetPointOnRay(b, GetEdgeAxis(a, b), abs_radius_)); } } // Buffers the edge AB and the vertex B. (The vertex C is used to determine // the range of angles that should be buffered at B.) // // TODO(ericv): Let A* denote the possible offset points of A with respect to // the edge AB for buffer radii in the range specified by "radius" and // "error_fraction". Rather than requiring that the path so far terminates at // a point in A*, as you might expect, instead we only require that the path // terminates at a point X such that for any point Y in A*, the edge XY does // not leave the valid buffer zone of the previous edge and vertex. void S2BufferOperation::BufferEdgeAndVertex(const S2Point& a, const S2Point& b, const S2Point& c) { ABSL_DCHECK_NE(a, b); ABSL_DCHECK_NE(b, c); ABSL_DCHECK_NE(buffer_sign_, 0); if (!tracker_.ok()) return; // For left (convex) turns we need to add an offset arc. For right // (concave) turns we connect the end of the current offset path to the // vertex itself and then to the start of the offset path for the next edge. // Note that A == C is considered to represent a convex (left) turn. AddEdgeArc(a, b); if (buffer_sign_ * s2pred::Sign(a, b, c) >= 0) { // The boundary makes a convex turn. If there is no following edge arc // then we need to generate a closed vertex arc. S2Point start = GetEdgeAxis(a, b); S2Point end = GetEdgeAxis(b, c); AddVertexArc(b, start, end); if (edge_step_ == S1ChordAngle::Zero()) CloseVertexArc(b, end); } else { // The boundary makes a concave turn. It is tempting to simply connect // the end of the current offset path to the start of the offset path for // the next edge, however this can create output regions where the winding // number is incorrect. A solution that always works is to terminate the // current offset path and start a new one by connecting the two offset // paths through the input vertex whenever it is concave. We first need // to close the previous semi-open edge arc if necessary. CloseEdgeArc(a, b); AddOffsetVertex(b); // Connect through the input vertex. } } // Given a polyline that starts with the edge AB, adds an end cap (as // specified by end_cap_style() and polyline_side()) for the vertex A. void S2BufferOperation::AddStartCap(const S2Point& a, const S2Point& b) { S2Point axis = GetEdgeAxis(a, b); if (options_.end_cap_style() == EndCapStyle::FLAT) { // One-sided flat end caps require no additional vertices since the // "offset curve" for the opposite side is simply the reversed polyline. if (options_.polyline_side() == PolylineSide::BOTH) { AddOffsetVertex(S2::GetPointOnRay(a, -axis, abs_radius_)); } } else { ABSL_DCHECK(options_.end_cap_style() == EndCapStyle::ROUND); if (options_.polyline_side() == PolylineSide::BOTH) { // The end cap consists of a semicircle. AddVertexArc(a, -axis, axis); } else { // The end cap consists of a quarter circle. Note that for // PolylineSide::LEFT, the polyline direction has been reversed. AddVertexArc(a, axis.CrossProd(a).Normalize(), axis); } } } // Given a polyline that ends with the edge AB, adds an end cap (as specified // by end_cap_style() and polyline_side()) for the vertex B. void S2BufferOperation::AddEndCap(const S2Point& a, const S2Point& b) { S2Point axis = GetEdgeAxis(a, b); if (options_.end_cap_style() == EndCapStyle::FLAT) { CloseEdgeArc(a, b); // Close the previous semi-open edge arc if necessary. } else { ABSL_DCHECK(options_.end_cap_style() == EndCapStyle::ROUND); if (options_.polyline_side() == PolylineSide::BOTH) { // The end cap consists of a semicircle. AddVertexArc(b, axis, -axis); } else { // The end cap consists of a quarter circle. We close the arc since it // will be followed by the reversed polyline vertices. Note that for // PolylineSide::LEFT, the polyline direction has been reversed. S2Point end = b.CrossProd(axis).Normalize(); AddVertexArc(b, axis, end); CloseVertexArc(b, end); } } } // Helper function that buffers the given loop. void S2BufferOperation::BufferLoop(S2PointLoopSpan loop) { // Empty loops always yield an empty path. if (loop.empty() || !tracker_.ok()) return; // Loops with one degenerate edge are treated as points. if (loop.size() == 1) return AddPoint(loop[0]); // Buffering by 180 degrees or more always yields the full polygon. // Buffering by -180 degrees or more always yields the empty polygon. if (abs_radius_ >= S1ChordAngle::Straight()) { if (buffer_sign_ > 0) AddFullPolygon(); return; } // If buffer_radius == 0, the loop is passed through unchanged. if (buffer_sign_ == 0) { if (!tracker_.AddSpace(&path_, loop.size())) return; path_.assign(loop.begin(), loop.end()); } else { SetInputVertex(loop[0]); for (size_t i = 0; i < loop.size(); ++i) { BufferEdgeAndVertex(loop[i], loop[i + 1], loop[i + 2]); } CloseBufferRegion(); } OutputPath(); } void S2BufferOperation::AddPolyline(S2PointSpan polyline) { // Left-sided buffering is supported by reversing the polyline and then // buffering on the right. vector reversed; if (options_.polyline_side() == PolylineSide::LEFT) { reversed.reserve(polyline.size()); std::reverse_copy(polyline.begin(), polyline.end(), std::back_inserter(reversed)); polyline = reversed; } // If buffer_radius < 0, polylines are discarded. if (buffer_sign_ < 0 || !tracker_.ok()) return; // Polylines with 0 or 1 vertices are defined to have no edges. int n = polyline.size(); if (n <= 1) return; // Polylines with one degenerate edge are treated as points. if (n == 2 && polyline[0] == polyline[1]) { return AddPoint(polyline[0]); } // Buffering by 180 degrees or more always yields the full polygon. if (abs_radius_ >= S1ChordAngle::Straight()) { return AddFullPolygon(); } // If buffer_radius == 0, polylines are converted into degenerate loops. if (buffer_sign_ == 0) { if (!tracker_.AddSpace(&path_, 2 * (n - 1))) return; path_.assign(polyline.begin(), polyline.end() - 1); path_.insert(path_.end(), polyline.rbegin(), polyline.rend() - 1); } else { // Otherwise we buffer each side of the polyline separately. SetInputVertex(polyline[0]); AddStartCap(polyline[0], polyline[1]); for (int i = 0; i < n - 2; ++i) { BufferEdgeAndVertex(polyline[i], polyline[i + 1], polyline[i + 2]); } AddEdgeArc(polyline[n - 2], polyline[n - 1]); AddEndCap(polyline[n - 2], polyline[n - 1]); if (options_.polyline_side() == PolylineSide::BOTH) { for (int i = n - 3; i >= 0; --i) { BufferEdgeAndVertex(polyline[i + 2], polyline[i + 1], polyline[i]); } AddEdgeArc(polyline[1], polyline[0]); CloseBufferRegion(); } else { // The other side of the polyline is not buffered. Note that for // PolylineSide::LEFT, the polyline direction has been reversed. if (!tracker_.AddSpace(&path_, n)) return; path_.insert(path_.end(), polyline.rbegin(), polyline.rend()); // Don't call CloseBufferRegion() since the path has already been closed. } } OutputPath(); } void S2BufferOperation::AddLoop(S2PointLoopSpan loop) { if (loop.empty()) return; BufferLoop(loop); // The vertex copying below could be avoided by adding a version of // S2LaxLoopShape that doesn't own its vertices. if (!tracker_.ok()) return; ref_winding_ += s2shapeutil::ContainsBruteForce(S2LaxLoopShape(loop), ref_point_); num_polygon_layers_ += 1; } void S2BufferOperation::BufferShape(const S2Shape& shape) { int dimension = shape.dimension(); int num_chains = shape.num_chains(); for (int c = 0; c < num_chains; ++c) { S2Shape::Chain chain = shape.chain(c); if (chain.length == 0) continue; if (dimension == 0) { AddPoint(shape.edge(c).v0); } else { S2::GetChainVertices(shape, c, &tmp_vertices_); if (dimension == 1) { AddPolyline(S2PointSpan(tmp_vertices_)); } else { BufferLoop(S2PointLoopSpan(tmp_vertices_)); } } } } void S2BufferOperation::AddShape(const S2Shape& shape) { BufferShape(shape); ref_winding_ += s2shapeutil::ContainsBruteForce(shape, ref_point_); num_polygon_layers_ += (shape.dimension() == 2); } void S2BufferOperation::AddShapeIndex(const S2ShapeIndex& index) { int max_dimension = -1; for (const S2Shape* shape : index) { if (shape == nullptr) continue; max_dimension = max(max_dimension, shape->dimension()); BufferShape(*shape); } ref_winding_ += S2ContainsPointQuery(&index).Contains(ref_point_); num_polygon_layers_ += (max_dimension == 2); } bool S2BufferOperation::Build(S2Error* absl_nonnull error) { if (buffer_sign_ < 0 && num_polygon_layers_ > 1) { *error = S2Error::FailedPrecondition( "Negative buffer radius requires at most one polygon layer"); return false; } return op_.Build(ref_point_, ref_winding_, S2WindingOperation::WindingRule::POSITIVE, error); } src/s2/s2buffer_operation.h000066400000000000000000000365711524103652300161550ustar00rootroot00000000000000// Copyright 2020 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #ifndef S2_S2BUFFER_OPERATION_H_ #define S2_S2BUFFER_OPERATION_H_ #include #include #include "absl/base/nullability.h" #include "absl/log/absl_log.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/s1angle.h" #include "s2/s1chord_angle.h" #include "s2/s2builder.h" #include "s2/s2error.h" #include "s2/s2memory_tracker.h" #include "s2/s2point.h" #include "s2/s2point_span.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/s2winding_operation.h" // This class provides a way to expand an arbitrary collection of geometry by // a fixed radius (an operation variously known as "buffering", "offsetting", // or "Minkowski sum with a disc"). The output consists of a polygon // (possibly with multiple shells) that contains all points within the given // radius of the original geometry. // // The radius can also be negative, in which case the geometry is contracted. // This causes the boundaries of polygons to shrink or disappear, and removes // all points and polylines. // // The input consists of a sequence of layers. Each layer may consist of any // combination of points, polylines, and polygons, with the restriction that // polygon interiors within each layer may not intersect any other geometry // (including other polygon interiors). The output is the union of the // buffered input layers. Note that only a single layer is allowed if the // buffer radius is negative. // // This class may be used to compute polygon unions by setting the buffer // radius to zero. The union is computed using a single snapping operation. // // Note that if you only want to compute an S2CellId covering of the buffered // geometry, it is much faster to use S2ShapeIndexBufferedRegion instead. // // Keywords: buffer, buffering, expand, expanding, offset, offsetting, // widen, contract, shrink, Minkowski sum class S2BufferOperation { public: // For polylines, specifies whether the end caps should be round or flat. // See Options::set_end_cap_style() below. enum class EndCapStyle : uint8_t { ROUND, FLAT }; // Specifies whether polylines should be buffered only on the left, only on // the right, or on both sides. enum class PolylineSide : uint8_t { LEFT, RIGHT, BOTH }; class Options { public: Options(); // Convenience constructor that calls set_buffer_radius(). explicit Options(S1Angle buffer_radius); // If positive, specifies that all points within the given radius of the // input geometry should be added to the output. If negative, specifies // that all points within the given radius of complement of the input // geometry should be subtracted from the output. If the buffer radius // is zero then the input geometry is passed through to the output layer // after first converting points and polylines into degenerate loops. // // DEFAULT: S1Angle::Zero() S1Angle buffer_radius() const; void set_buffer_radius(S1Angle buffer_radius); // Specifies the allowable error when buffering, expressed as a fraction // of buffer_radius(). The actual buffer distance will be in the range // [(1-f) * r - C, (1 + f) * r + C] where "f" is the error fraction, "r" // is the buffer radius, and "C" is S2BufferOperation::kAbsError. // // Be aware that the number of output edges increases proportionally to // (1 / sqrt(error_fraction)), so setting a small value may increase the // size of the output considerably. // // REQUIRES: error_fraction() >= kMinErrorFraction // REQUIRES: error_fraction() <= 1.0 // // DEFAULT: 0.01 (i.e., maximum error of 1%) static constexpr double kMinErrorFraction = 1e-6; double error_fraction() const; void set_error_fraction(double error_fraction); // Returns the maximum error in the buffered result for the current // buffer_radius(), error_fraction(), and snap_function(). Note that the // error due to buffering consists of both relative errors (those // proportional to the buffer radius) and absolute errors. The maximum // relative error is controlled by error_fraction(), while the maximum // absolute error is about 10 nanometers on the Earth's surface and is // defined internally. The error due to snapping is defined by the // specified snap_function(). S1Angle max_error() const; // Alternatively, error_fraction() may be specified as the number of // polyline segments used to approximate a planar circle. These two // values are related according to the formula // // error_fraction = (1 - cos(theta)) / (1 + cos(theta)) // ~= 0.25 * (theta ** 2) // // where (theta == Pi / circle_segments), i.e. error decreases // quadratically with the number of circle segments. // // REQUIRES: circle_segments() >= 2.0 // REQUIRES: circle_segments() <= kMaxCircleSegments // (about 1570; corresponds to kMinErrorFraction) // // DEFAULT: about 15.76 (corresponding to error_fraction() default value) static constexpr double kMaxCircleSegments = 1570.7968503979573; double circle_segments() const; void set_circle_segments(double circle_segments); // For polylines, specifies whether the end caps should be round or flat. // // Note that with flat end caps, there is no buffering beyond the polyline // endpoints (unlike "square" end caps, which are not implemented). // // DEFAULT: EndCapStyle::ROUND EndCapStyle end_cap_style() const; void set_end_cap_style(EndCapStyle end_cap_style); // Specifies whether polylines should be buffered only on the left, only // on the right, or on both sides. For one-sided buffering please note // the following: // // - EndCapStyle::ROUND yields two quarter-circles, one at each end. // // - To buffer by a different radius on each side of the polyline, you // can use two S2BufferOperations and compute their union. (Note that // round end caps will yield two quarter-circles at each end of the // polyline with different radii.) // // - Polylines consisting of a single degenerate edge are always buffered // identically to points, i.e. this option has no effect. // // - When the polyline turns right by more than 90 degrees, buffering may // or may not extend to the non-buffered side of the polyline. For // example if ABC makes a 170 degree right turn at B, it is unspecified // whether the buffering of AB extends across edge BC and vice versa. // Similarly if ABCD represents two right turns of 90 degrees where AB // and CD are separated by less than the buffer radius, it is // unspecified whether buffering of AB extends across CD and vice versa. // // DEFAULT: PolylineSide::BOTH PolylineSide polyline_side() const; void set_polyline_side(PolylineSide polyline_side); // Specifies the function used for snap rounding the output during the // call to Build(). Note that any errors due to snapping are in addition // to those specified by error_fraction(). // // DEFAULT: s2builderutil::IdentitySnapFunction(S1Angle::Zero()) const S2Builder::SnapFunction& snap_function() const; void set_snap_function(const S2Builder::SnapFunction& snap_function); // Specifies that internal memory usage should be tracked using the given // S2MemoryTracker. If a memory limit is specified and more more memory // than this is required then an error will be returned. Example usage: // // S2MemoryTracker tracker; // tracker.set_limit(500 << 20); // 500 MB // S2BufferOperation::Options options; // options.set_buffer_radius(S1Angle::Degrees(1e-5)); // options.set_memory_tracker(&tracker); // S2BufferOperation op{options}; // ... // S2Error error; // if (!op.Build(&error)) { // if (error.code() == S2Error::RESOURCE_EXHAUSTED) { // ABSL_LOG(ERROR) << error; // Memory limit exceeded // } // } // // CAVEATS: // // - Memory allocated by the output S2Builder layer is not tracked. // // - While memory tracking is reasonably complete and accurate, it does // not account for every last byte. It is intended only for the // purpose of preventing clients from running out of memory. // // DEFAULT: nullptr (memory tracking disabled) S2MemoryTracker* memory_tracker() const; void set_memory_tracker(S2MemoryTracker* tracker); // Options may be assigned and copied. Options(const Options& options); Options& operator=(const Options& options); private: S1Angle buffer_radius_ = S1Angle::Zero(); // double error_fraction_ = 0.01; double error_fraction_ = 0.02; EndCapStyle end_cap_style_ = EndCapStyle::ROUND; PolylineSide polyline_side_ = PolylineSide::BOTH; std::unique_ptr snap_function_; S2MemoryTracker* memory_tracker_ = nullptr; }; // Default constructor; requires Init() to be called. S2BufferOperation(); #ifndef SWIG // Convenience constructor that calls Init(). explicit S2BufferOperation(std::unique_ptr result_layer, const Options& options = Options{}); #endif // Starts a buffer operation that sends the output polygon to the given // S2Builder layer. This method may be called more than once. // // Note that buffering always yields a polygon, even if the input includes // polylines and points. If the buffer radius is zero, points and polylines // will be converted into degenerate polygon loops; if the buffer radius is // negative, points and polylines will be removed. void Init(std::unique_ptr result_layer, const Options& options = Options()); const Options& options() const; // Each call below represents a different input layer. Note that if the // buffer radius is negative, then at most one input layer is allowed // (ignoring any layers that contain only points and polylines). // Adds an input layer containing a single point. void AddPoint(const S2Point& point); // Adds an input layer containing a polyline. Note the following: // // - Polylines with 0 or 1 vertices are considered to be empty. // - A polyline with 2 identical vertices is equivalent to a point. // - Polylines have end caps (see Options::end_cap_style). // - One-sided polyline buffering is supported (see Options::polyline_side). void AddPolyline(S2PointSpan polyline); // Adds an input layer containing a loop. Note the following: // // - A loop with no vertices is empty. // - A loop with 1 vertex is equivalent to a point. // - The interior of the loop is on its left. // - Buffering a self-intersecting loop produces undefined results. void AddLoop(S2PointLoopSpan loop); // Adds an input layer containing the given shape. Shapes are handled as // points, polylines, or polygons according to the rules above. In addition // note the following: // // - Polygons holes may be degenerate (e.g., consisting of a // single vertex or entirely of sibling pairs such as ABCBDB). // - Full polygons are supported. Note that since full polygons do // not have a boundary, they are not affected by buffering. void AddShape(const S2Shape& shape); // Adds an input layer containing all of the shapes in the given index. // // REQUIRES: The interiors of polygons must be disjoint from all other // indexed geometry, including other polygon interiors. // (S2BooleanOperation also requires this.) void AddShapeIndex(const S2ShapeIndex& index); // Computes the union of the buffered input shapes and sends the output // polygon to the S2Builder layer specified in the constructor. Returns // true on success and otherwise sets "error" appropriately. // // Note that if the buffer radius is negative, only a single input layer is // allowed (ignoring any layers that contain only points and polylines). bool Build(S2Error* absl_nonnull error); private: S1Angle GetMaxEdgeSpan(S1Angle radius, S1Angle requested_error) const; void SetInputVertex(const S2Point& new_a); void AddOffsetVertex(const S2Point& new_b); void CloseBufferRegion(); void OutputPath(); void UpdateRefWinding(const S2Point& a, const S2Point& b, const S2Point& c); void AddFullPolygon(); S2Point GetEdgeAxis(const S2Point& a, const S2Point& b) const; void AddVertexArc(const S2Point& v, const S2Point& start, const S2Point& end); void CloseVertexArc(const S2Point& v, const S2Point& end); void AddEdgeArc(const S2Point& a, const S2Point& b); void CloseEdgeArc(const S2Point& a, const S2Point& b); void BufferEdgeAndVertex(const S2Point& a, const S2Point& b, const S2Point& c); void AddStartCap(const S2Point& a, const S2Point& b); void AddEndCap(const S2Point& a, const S2Point& b); void BufferLoop(S2PointLoopSpan loop); void BufferShape(const S2Shape& shape); Options options_; // The number of layers containing two-dimension geometry that have been // added so far. This is used to enforce the requirement that negative // buffer radii allow only a single such layer. int num_polygon_layers_ = 0; // Parameters for buffering vertices and edges. int buffer_sign_; // The sign of buffer_radius (-1, 0, or +1). S1ChordAngle abs_radius_; S1ChordAngle vertex_step_, edge_step_; // We go to extra effort to ensure that points are transformed into regular // polygons. (We don't do this for arcs in general because we would rather // use the allowable error to reduce the complexity of the output rather // than increase its symmetry.) S1ChordAngle point_step_; // Contains the buffered loops that have been accumulated so far. S2WindingOperation op_; // The current offset path. When each path is completed into a loop it is // added to op_ (the S2WindingOperation). std::vector path_; // As buffered loops are added we keep track of the winding number of a // fixed reference point. This is used to derive the winding numbers of // every region in the spherical partition induced by the buffered loops. S2Point ref_point_; // The winding number associated with ref_point_. int ref_winding_; // The endpoints of the current sweep edge. sweep_a_ is a vertex of the // original geometry and sweep_b_ is a vertex of the current offset path. S2Point sweep_a_, sweep_b_; // The starting vertices of the current input loop and offset curve. These // are used to close the buffer region when a loop is completed. S2Point input_start_, offset_start_; bool have_input_start_, have_offset_start_; // Used internally as a temporary to avoid excessive memory allocation. std::vector tmp_vertices_; S2MemoryTracker::Client tracker_; }; #endif // S2_S2BUFFER_OPERATION_H_ src/s2/s2buffer_operation_test.cc000066400000000000000000001000371524103652300173370ustar00rootroot00000000000000// Copyright 2020 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/s2buffer_operation.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "absl/base/call_once.h" #include "absl/base/nullability.h" #include "absl/flags/flag.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/log/absl_vlog_is_on.h" #include "absl/log/log_streamer.h" #include "absl/random/random.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "s2/base/malloc_extension.h" #include "s2/mutable_s2shape_index.h" #include "s2/s1angle.h" #include "s2/s1chord_angle.h" #include "s2/s2boolean_operation.h" #include "s2/s2builder_layer.h" #include "s2/s2builderutil_lax_polygon_layer.h" #include "s2/s2builderutil_snap_functions.h" #include "s2/s2cell_id.h" #include "s2/s2closest_edge_query.h" #include "s2/s2closest_edge_query_base.h" #include "s2/s2contains_point_query.h" #include "s2/s2edge_crossings.h" #include "s2/s2edge_distances.h" #include "s2/s2error.h" #include "s2/s2fractal.h" #include "s2/s2lax_loop_shape.h" #include "s2/s2lax_polygon_shape.h" #include "s2/s2lax_polyline_shape.h" #include "s2/s2loop.h" #include "s2/s2memory_tracker.h" #include "s2/s2metrics.h" #include "s2/s2point.h" #include "s2/s2point_span.h" #include "s2/s2point_vector_shape.h" #include "s2/s2pointutil.h" #include "s2/s2polygon.h" #include "s2/s2predicates.h" #include "s2/s2random.h" #include "s2/s2shape.h" #include "s2/s2testing.h" #include "s2/s2text_format.h" using absl::StrCat; using absl::string_view; using std::make_unique; using std::max; using std::string; using std::unique_ptr; using std::vector; using EndCapStyle = S2BufferOperation::EndCapStyle; using PolylineSide = S2BufferOperation::PolylineSide; namespace { // A callback that allows adding input to an S2BufferOperation. This is // convenient for testing the various input methods (AddPoint, AddShape, etc). using InputCallback = std::function; // Convenience function that calls the given lambda expression to add input to // an S2BufferOperation and returns the buffered result. unique_ptr DoBuffer( InputCallback input_callback, const S2BufferOperation::Options& options) { auto output = make_unique(); S2BufferOperation op( make_unique(output.get()), options); input_callback(&op); S2Error error; EXPECT_TRUE(op.Build(&error)) << error; if (ABSL_VLOG_IS_ON(1) && output->num_vertices() < 1000) { std::cerr << "\nS2Polygon: " << s2textformat::ToString(*output) << "\n"; } return output; } // Simpler version that accepts a buffer radius and error fraction. unique_ptr DoBuffer( InputCallback input_callback, S1Angle buffer_radius, double error_fraction) { S2BufferOperation::Options options; options.set_buffer_radius(buffer_radius); options.set_error_fraction(error_fraction); return DoBuffer(std::move(input_callback), options); } // Given a callback that adds empty geometry to the S2BufferOperation, // verifies that the result is empty after buffering. void TestBufferEmpty(InputCallback input) { // Test code paths that involve buffering by negative, zero, and positive // values, and also values where the result is usually empty or full. EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(-200), 0.1)->is_empty()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(-1), 0.1)->is_empty()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(0), 0.1)->is_empty()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(1), 0.1)->is_empty()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(200), 0.1)->is_empty()); } TEST(S2BufferOperation, NoInput) { TestBufferEmpty([](S2BufferOperation* op) {}); } TEST(S2BufferOperation, EmptyPolyline) { // Note that polylines with 1 vertex are defined to have no edges. TestBufferEmpty([](S2BufferOperation* op) { op->AddPolyline(vector{S2Point(1, 0, 0)}); }); } TEST(S2BufferOperation, EmptyLoop) { TestBufferEmpty([](S2BufferOperation* op) { op->AddLoop(vector{}); }); } TEST(S2BufferOperation, EmptyPointShape) { TestBufferEmpty([](S2BufferOperation* op) { op->AddShape(S2PointVectorShape{}); }); } TEST(S2BufferOperation, EmptyPolylineShape) { TestBufferEmpty([](S2BufferOperation* op) { op->AddShape(*s2textformat::MakeLaxPolylineOrDie("")); }); } TEST(S2BufferOperation, EmptyPolygonShape) { TestBufferEmpty([](S2BufferOperation* op) { op->AddShape(*s2textformat::MakeLaxPolygonOrDie("")); }); } TEST(S2BufferOperation, EmptyShapeIndex) { TestBufferEmpty([](S2BufferOperation* op) { op->AddShapeIndex(*s2textformat::MakeIndexOrDie("# #")); }); } TEST(S2BufferOperation, Options) { // Provide test coverage for `options()`. S2BufferOperation::Options options(S1Angle::Radians(1e-12)); S2LaxPolygonShape output; S2BufferOperation op( make_unique(&output), options); EXPECT_EQ(options.buffer_radius(), op.options().buffer_radius()); } TEST(S2BufferOperation, PoorlyNormalizedPoint) { // Verify that debugging assertions are not triggered when an input point is // not unit length (but within the limits guaranteed by S2Point::Normalize). // // The purpose of this test is not to check that the result is correct // (which is done elsewhere), simply that no assertions occur. DoBuffer([](S2BufferOperation* op) { S2Point p(1 - 2 * DBL_EPSILON, 0, 0); // Maximum error allowed. ABSL_CHECK(S2::IsUnitLength(p)); op->AddPoint(p); }, S1Angle::Degrees(1), 0.01); } // Given a callback that adds the full polygon to the S2BufferOperation, // verifies that the result is full after buffering. void TestBufferFull(InputCallback input) { // Test code paths that involve buffering by negative, zero, and positive // values, and also values where the result is usually empty or full. EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(-200), 0.1)->is_full()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(-1), 0.1)->is_full()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(0), 0.1)->is_full()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(1), 0.1)->is_full()); EXPECT_TRUE(DoBuffer(input, S1Angle::Degrees(200), 0.1)->is_full()); } TEST(S2BufferOperation, FullPolygonShape) { TestBufferFull([](S2BufferOperation* op) { op->AddShape(*s2textformat::MakeLaxPolygonOrDie("full")); }); } TEST(S2BufferOperation, FullShapeIndex) { TestBufferFull([](S2BufferOperation* op) { op->AddShapeIndex(*s2textformat::MakeIndexOrDie("# # full")); }); } TEST(S2BufferOperation, PointsAndPolylinesAreRemoved) { // Test that points and polylines are removed with a negative buffer radius. auto output = DoBuffer([](S2BufferOperation* op) { op->AddShapeIndex(*s2textformat::MakeIndexOrDie("0:0 # 2:2, 2:3#")); }, S1Angle::Degrees(-1), 0.1); EXPECT_TRUE(output->is_empty()); } TEST(S2BufferOperation, BufferedPointsAreSymmetric) { // Test that points are buffered into regular polygons. (This is not // guaranteed by the API but makes the output nicer to look at. :) auto output = DoBuffer([](S2BufferOperation* op) { op->AddPoint(S2Point(1, 0, 0)); }, S1Angle::Degrees(5), 0.001234567); // We use the length of the last edge as our reference length. int n = output->num_vertices(); S1Angle edge_len(output->loop_vertex(0, 0), output->loop_vertex(0, n - 1)); for (int i = 1; i < n; ++i) { EXPECT_LE(abs(edge_len - S1Angle(output->loop_vertex(0, i - 1), output->loop_vertex(0, i))), S1Angle::Radians(1e-14)); } } TEST(S2BufferOperation, SetCircleSegments) { // Test that when a point is buffered with a small radius the number of // edges matches options.circle_segments(). (This is not true for large // radii because large circles on the sphere curve less than 360 degrees.) // Using a tiny radius helps to catch rounding problems. S2BufferOperation::Options options(S1Angle::Radians(1e-12)); for (int circle_segments = 3; circle_segments <= 20; ++circle_segments) { options.set_circle_segments(circle_segments); EXPECT_FLOAT_EQ(circle_segments, options.circle_segments()); auto output = DoBuffer([](S2BufferOperation* op) { op->AddPoint(S2Point(1, 0, 0)); }, options); EXPECT_EQ(output->num_vertices(), circle_segments); } } TEST(S2BufferOperation, SetSnapFunction) { // Verify that the snap function is passed through to S2Builder. // We use a buffer radius of zero to make the test simpler. S2BufferOperation::Options options; options.set_snap_function(s2builderutil::IntLatLngSnapFunction(0)); auto output = DoBuffer([](S2BufferOperation* op) { op->AddPoint(s2textformat::MakePointOrDie("0.1:-0.4")); }, options); EXPECT_EQ(output->num_vertices(), 1); EXPECT_EQ(output->loop_vertex(0, 0), s2textformat::MakePointOrDie("0:0")); } TEST(S2BufferOperation, NegativeBufferRadiusMultipleLayers) { // Verify that with a negative buffer radius, at most one polygon layer is // allowed. S2LaxPolygonShape output; S2BufferOperation op( make_unique(&output), S2BufferOperation::Options(S1Angle::Radians(-1))); op.AddLoop(S2PointLoopSpan(s2textformat::ParsePointsOrDie("0:0, 0:1, 1:0"))); op.AddShapeIndex(*s2textformat::MakeIndexOrDie("# # 2:2, 2:3, 3:2")); S2Error error; EXPECT_FALSE(op.Build(&error)); EXPECT_EQ(error.code(), S2Error::FAILED_PRECONDITION); } // If buffer_radius > max_error, tests that "output" contains "input". // If buffer_radius < -max_error tests that "input" contains "output". // Otherwise does nothing. void TestContainment(const MutableS2ShapeIndex& input, const MutableS2ShapeIndex& output, S1Angle buffer_radius, S1Angle max_error) { S2BooleanOperation::Options options; options.set_polygon_model(S2BooleanOperation::PolygonModel::CLOSED); options.set_polyline_model(S2BooleanOperation::PolylineModel::CLOSED); if (buffer_radius > max_error) { // For positive buffer radii, the output should contain the input. EXPECT_TRUE(S2BooleanOperation::Contains(output, input, options)); } else if (buffer_radius < -max_error) { // For negative buffer radii, the input should contain the output. EXPECT_TRUE(S2BooleanOperation::Contains(input, output, options)); } } // Tests that the minimum distance from the boundary of "output" to the // boundary of "input" is at least "min_dist" using exact predicates. void TestMinimumDistance(const MutableS2ShapeIndex& input, const MutableS2ShapeIndex& output, S1ChordAngle min_dist) { if (min_dist == S1ChordAngle::Zero()) return; // We do one query to find the edges of "input" that might be too close to // "output", then for each such edge we do another query to find the edges // of "output" that might be too close to it. Then we check the distance // between each edge pair (A, B) using exact predicates. // We make the distance limit big enough to find all edges whose true // distance might be less than "min_dist". S2ClosestEdgeQuery::Options query_options; query_options.set_include_interiors(false); query_options.set_max_distance( min_dist.PlusError(S2::GetUpdateMinDistanceMaxError(min_dist))); S2ClosestEdgeQuery in_query(&input, query_options); S2ClosestEdgeQuery::ShapeIndexTarget out_target(&output); out_target.set_include_interiors(false); S2ClosestEdgeQuery out_query(&output, query_options); for (const auto& in_result : in_query.FindClosestEdges(&out_target)) { auto a = input.shape(in_result.shape_id())->edge(in_result.edge_id()); S2ClosestEdgeQuery::EdgeTarget in_target(a.v0, a.v1); for (const auto& out_result : out_query.FindClosestEdges(&in_target)) { auto b = output.shape(out_result.shape_id())->edge(out_result.edge_id()); ASSERT_GE( s2pred::CompareEdgePairDistance(a.v0, a.v1, b.v0, b.v1, min_dist), 0); } } } // Tests that the Hausdorff distance from the boundary of "output" to the // boundary of "input" is at most (1 + error_fraction) * buffer_radius. The // implementation approximates this by measuring the distance at a set of // points along the boundary of "output". void TestHausdorffDistance(const MutableS2ShapeIndex& input, const MutableS2ShapeIndex& output, S1ChordAngle max_dist) { S2ClosestEdgeQuery::Options query_options; query_options.set_include_interiors(false); query_options.set_max_distance( max_dist.PlusError(S2::GetUpdateMinDistanceMaxError(max_dist))); S2ClosestEdgeQuery in_query(&input, query_options); for (const S2Shape* out_shape : output) { for (int i = 0; i < out_shape->num_edges(); ++i) { S2Shape::Edge e = out_shape->edge(i); // Measure the distance at 5 points along the edge. for (double t = 0; t <= 1.0; t += 0.25) { S2Point b = S2::Interpolate(e.v0, e.v1, t); S2ClosestEdgeQuery::PointTarget out_target(b); // We check the distance bound using exact predicates. for (const auto& in_result : in_query.FindClosestEdges(&out_target)) { auto a = input.shape(in_result.shape_id())->edge(in_result.edge_id()); ASSERT_LE(s2pred::CompareEdgeDistance(b, a.v0, a.v1, max_dist), 0); } } } } } // Buffers the given input with the given buffer_radius and error_fraction and // verifies that the output is correct. void TestBuffer(const MutableS2ShapeIndex& input, S1Angle buffer_radius, double error_fraction) { ABSL_LOG(INFO) << "TestBuffer: " << s2textformat::ToString(input) << " buffer_radius: " << buffer_radius.radians() << " error_fraction: " << error_fraction; // Ideally we would verify the correctness of buffering as follows. Suppose // that B = Buffer(A, r) and let ~X denote the complement of region X. Then // if r > 0, we would verify: // // 1a. Minimum distance between ~B and A >= r_min // 1b. Directed Hausdorff distance from B to A <= r_max // // Buffering A by r < 0 is equivalent to buffering ~A by |r|, so instead we // would verify the following (where r_min and r_max are based on |r|): // // 2a. Minimum distance between B and ~A >= r_min // 2b. Directed Hausdorff distance from ~B to ~A <= r_max // // Conditions 1a and 2a can be implemented as follows: // // 1a*: B.Contains(A) && minimum distance between @B and @A >= r_min // 2a*: A.Contains(B) && minimum distance between @B and @A >= r_min // // Note that if r_min <= 0 then there is nothing to be tested, since the // containment condition may not hold. (Note that even when the specified // buffer radius is zero, edges can move slightly when crossing edges are // split during the snapping step.) The correct approach would be to test // instead that the directed Hausdorff distance from A to ~B is at most // -r_min, but Hausdorff distance is not yet implemented. // // Similarly, conditions 1b and 2b need to be approximated because Hausdorff // distance is not yet implemented. We do this by measuring the distance at // a set of points on the boundary of B: // // 1b*: Minimum distance from P to @A <= r_max for a set of points P on @B // 2b*: Minimum distance from P to @A <= r_max for a set of points P on @B // // This is not perfect (e.g., it won't detect cases where an entire boundary // loop of B is missing, such as returning a disc in the place of an // annulus) but it is sufficient to detect many types of errors. S2BufferOperation::Options options; options.set_buffer_radius(buffer_radius); options.set_error_fraction(error_fraction); MutableS2ShapeIndex output; output.Add(DoBuffer( [&input](S2BufferOperation* op) { op->AddShapeIndex(input); }, options)); SCOPED_TRACE(absl::StrFormat( "\nradius = %.17g, error_fraction = %.17g\ninput = %s\noutput = %s", buffer_radius.radians(), error_fraction, s2textformat::ToString(input), s2textformat::ToString(output))); // Check the 1a*/1b* condition above. S1Angle max_error = options.max_error(); TestContainment(input, output, buffer_radius, max_error); S1ChordAngle min_dist(max(S1Angle::Zero(), abs(buffer_radius) - max_error)); TestMinimumDistance(input, output, min_dist); // Check the 2a*/2b* condition (i.e., directed Hausdorff distance). S1ChordAngle max_dist(abs(buffer_radius) + max_error); TestHausdorffDistance(input, output, max_dist); } // Convenience function that takes an S2ShapeIndex in s2textformat format. void TestBuffer(string_view index_str, S1Angle buffer_radius, double error_fraction) { TestBuffer(*s2textformat::MakeIndexOrDie(index_str), buffer_radius, error_fraction); } // Convenience function that tests buffering using +/- the given radius. void TestSignedBuffer(string_view index_str, S1Angle buffer_radius, double error_fraction) { TestBuffer(index_str, buffer_radius, error_fraction); TestBuffer(index_str, -buffer_radius, error_fraction); } TEST(S2BufferOperation, PointShell) { TestSignedBuffer("# # 0:0", S1Angle::Radians(M_PI_2), 0.01); } TEST(S2BufferOperation, SiblingPairShell) { TestSignedBuffer("# # 0:0, 0:5", S1Angle::Radians(M_PI_2), 0.01); } TEST(S2BufferOperation, SiblingPairHole) { TestSignedBuffer("# # 0:0, 0:10, 7:7; 3:4, 3:6", S1Angle::Degrees(1), 0.01); } TEST(S2BufferOperation, Square) { TestSignedBuffer("# # -3:-3, -3:3, 3:3, 3:-3", S1Angle::Degrees(1), 0.01); TestSignedBuffer("# # -3:-3, -3:3, 3:3, 3:-3", S1Angle::Degrees(170), 1e-4); } TEST(S2BufferOperation, HollowSquare) { TestSignedBuffer("# # -3:-3, -3:3, 3:3, 3:-3; 2:2, -2:2, -2:-2, 2:-2", S1Angle::Degrees(1), 0.01); } TEST(S2BufferOperation, ZigZagLoop) { TestSignedBuffer("# # 0:0, 0:7, 5:3, 5:10, 6:10, 6:1, 1:5, 1:0", S1Angle::Degrees(0.2), 0.01); } TEST(S2BufferOperation, Fractals) { absl::BitGen bitgen( S2Testing::MakeTaggedSeedSeq("FRACTALS", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); for (double dimension : {1.02, 1.8}) { S2Fractal fractal(bitgen); fractal.SetLevelForApproxMaxEdges(3 * 64); fractal.set_fractal_dimension(dimension); auto loop = fractal.MakeLoop(S2::GetFrame(S2Point(1, 0, 0)), S1Angle::Degrees(10)); MutableS2ShapeIndex input; input.Add(make_unique(loop.get())); TestBuffer(input, S1Angle::Degrees(0.4), 0.01); } } TEST(S2BufferOperation, S2Curve) { // Tests buffering the S2 curve by an amount that yields the full polygon. constexpr int kLevel = 2; // Number of input edges == 6 * (4 ** kLevel) vector points; for (S2CellId id = S2CellId::Begin(kLevel); id != S2CellId::End(kLevel); id = id.next()) { points.push_back(id.ToPoint()); } // Buffering by this amount or more is guaranteed to yield the full polygon. // (Note that the bound is not tight for S2CellIds at low levels.) S1Angle full_radius = S1Angle::Radians(0.5 * S2::kMaxDiag.GetValue(kLevel)); EXPECT_TRUE(DoBuffer([&points](S2BufferOperation* op) { op->AddShape(S2LaxClosedPolylineShape(points)); }, full_radius, 0.1)->is_full()); } // Tests buffering the given S2ShapeIndex with a variety of radii and error // fractions. This method is intended to be used with relatively simple // shapes since calling it is quite expensive. void TestRadiiAndErrorFractions(string_view index_str) { // Try the full range of radii with a representative error fraction. constexpr double kFrac = 0.01; vector kTestRadiiRadians = { 0, 1e-300, 1e-15, 2e-15, 3e-15, 1e-5, 0.01, 0.1, 1.0, (1 - kFrac) * M_PI_2, M_PI_2 - 1e-15, M_PI_2, M_PI_2 + 1e-15, (1 - kFrac) * M_PI, M_PI - 1e-6, M_PI, 1e300 }; for (double radius : kTestRadiiRadians) { TestSignedBuffer(index_str, S1Angle::Radians(radius), kFrac); } // Now try the full range of error fractions with a few selected radii. vector kTestErrorFractions = {S2BufferOperation::Options::kMinErrorFraction, 0.001, 0.01, 0.1, 1.0}; for (double error_fraction : kTestErrorFractions) { TestBuffer(index_str, S1Angle::Radians(-1e-6), error_fraction); TestBuffer(index_str, S1Angle::Radians(1e-14), error_fraction); TestBuffer(index_str, S1Angle::Radians(1e-2), error_fraction); TestBuffer(index_str, S1Angle::Radians(M_PI - 1e-3), error_fraction); } } // Test buffering simple shapes with a wide range of different buffer radii // and error fractions. TEST(S2BufferOperation, RadiiAndErrorFractionCoverageSinglePoint) { TestRadiiAndErrorFractions("1:1 # #"); } TEST(S2BufferOperation, RadiiAndErrorFractionCoverageZigZagPolyline) { TestRadiiAndErrorFractions("# 0:0, 0:30, 30:30, 30:60 #"); } TEST(S2BufferOperation, RadiiAndErrorFractionCoverageTriangleWithHole) { // A triangular polygon with a triangular hole. (The hole is clockwise.) TestRadiiAndErrorFractions("# # 0:0, 0:100, 70:50; 10:20, 50:50, 10:80"); } TEST(S2BufferOperation, RadiiAndErrorFractionCoverageTriangleTwoLongEdges) { // A triangle with one very short and two very long edges. TestRadiiAndErrorFractions("# # 0:0, 0:179.99999999999, 1e-300:0"); } class TestBufferPolyline { public: TestBufferPolyline(string_view input_str, const S2BufferOperation::Options& options); private: static constexpr double kArcLo = 0.001; static constexpr double kArcHi = 0.999; static constexpr int kArcSamples = 7; S2Point GetEdgeAxis(const S2Point& a, const S2Point& b) { return S2::RobustCrossProd(a, b).Normalize(); } bool PointBufferingUncertain(const S2Point& p, bool expect_contained) { // The only case where a point might be excluded from the buffered output is // if it is on the unbuffered side of the polyline. if (expect_contained && two_sided_) return false; int n = polyline_.size(); for (int i = 0; i < n - 1; ++i) { const S2Point& a = polyline_[i]; const S2Point& b = polyline_[i + 1]; if (!two_sided_) { // Ignore points on the buffered side if expect_contained is true, // and on the unbuffered side if expect_contained is false. if ((s2pred::Sign(a, b, p) < 0) == expect_contained) continue; } // TODO(ericv): Depending on how the erasing optimization is implemented, // it might be possible to add "&& expect_contained" to the test below. if (round_) { if (S2::IsDistanceLess(p, a, b, max_dist_)) return true; } else { if (S2::IsInteriorDistanceLess(p, a, b, max_dist_)) return true; if (i > 0 && S1ChordAngle(p, a) < max_dist_) return true; if (i == n - 2 && S1ChordAngle(p, b) < max_dist_) return true; } } return false; } void TestPoint(const S2Point& p, const S2Point& dir, bool expect_contained) { S2Point x = S2::GetPointOnRay( p, dir, expect_contained ? buffer_radius_ - max_error_ : max_error_); if (!PointBufferingUncertain(x, expect_contained)) { EXPECT_EQ(S2ContainsPointQuery(&output_).Contains(x), expect_contained); } } void TestVertexArc(const S2Point& p, const S2Point& start, const S2Point& end, bool expect_contained) { for (double t = kArcLo; t < 1; t += (kArcHi - kArcLo) / kArcSamples) { S2Point dir = S2::Interpolate(start, end, t); TestPoint(p, dir, expect_contained); } } void TestEdgeArc(const S2Point& ba_axis, const S2Point& a, const S2Point& b, bool expect_contained) { for (double t = kArcLo; t < 1; t += (kArcHi - kArcLo) / kArcSamples) { S2Point p = S2::Interpolate(a, b, t); TestPoint(p, ba_axis, expect_contained); } } void TestEdgeAndVertex(const S2Point& a, const S2Point& b, const S2Point& c, bool expect_contained) { S2Point ba_axis = GetEdgeAxis(b, a); S2Point cb_axis = GetEdgeAxis(c, b); TestEdgeArc(ba_axis, a, b, expect_contained); TestVertexArc(b, ba_axis, cb_axis, expect_contained); } vector polyline_; MutableS2ShapeIndex output_; S1Angle buffer_radius_, max_error_; S1ChordAngle min_dist_, max_dist_; bool round_, two_sided_; }; // Tests buffering a polyline with the given options. This method is intended // only for testing Options::EndCapStyle and Options::PolylineSide; if these // options have their default values then TestBuffer() should be used // instead. Similarly TestBuffer should be used to test negative buffer radii // and polylines with 0 or 1 vertices. TestBufferPolyline::TestBufferPolyline( string_view input_str, const S2BufferOperation::Options& options) : polyline_(s2textformat::ParsePointsOrDie(input_str)), buffer_radius_(options.buffer_radius()), max_error_(options.max_error()), min_dist_(max(S1Angle::Zero(), buffer_radius_ - max_error_)), max_dist_(buffer_radius_ + max_error_), round_(options.end_cap_style() == EndCapStyle::ROUND), two_sided_(options.polyline_side() == PolylineSide::BOTH) { ABSL_DCHECK_GE(polyline_.size(), 2); ABSL_DCHECK(buffer_radius_ > S1Angle::Zero()); MutableS2ShapeIndex input; input.Add(s2textformat::MakeLaxPolylineOrDie(input_str)); output_.Add(DoBuffer( [&input](S2BufferOperation* op) { op->AddShapeIndex(input); }, options)); // Even with one-sided buffering and flat end caps the Hausdorff distance // criterion should still be true. (This checks that the buffered result // is never further than (buffer_radius + max_error) from the input.) TestHausdorffDistance(input, output_, max_dist_); // However the minimum distance criterion is different; it only applies to // the portions of the boundary that are buffered using the given radius. // We check this approximately by walking along the polyline and checking // that (1) on portions of the polyline that should be buffered, the output // contains the offset point at distance (buffer_radius - max_error) and (2) // on portions of the polyline that should not be buffered, the output does // not contain the offset point at distance max_error. The tricky part is // that both of these conditions have exceptions: (1) may not hold if the // test point is closest to the non-buffered side of the polyline (see the // last caveat in the documentation for Options::polyline_side), and (2) // may not hold if the test point is within (buffer_radius + max_error) of // the buffered side of any portion of the polyline. if (min_dist_ == S1ChordAngle::Zero()) return; // Left-sided buffering is tested by reversing the polyline and then testing // whether it has been buffered correctly on the right. if (options.polyline_side() == PolylineSide::LEFT) { std::reverse(polyline_.begin(), polyline_.end()); } int n = polyline_.size(); S2Point start0 = polyline_[0], start1 = polyline_[1]; S2Point start_begin = GetEdgeAxis(start0, start1); S2Point start_mid = start0.CrossProd(start_begin); TestVertexArc(start0, start_begin, start_mid, round_ && two_sided_); TestVertexArc(start0, start_mid, -start_begin, round_); for (int i = 0; i < n - 2; ++i) { TestEdgeAndVertex(polyline_[i], polyline_[i + 1], polyline_[i + 2], true); } S2Point end0 = polyline_[n - 1], end1 = polyline_[n - 2]; S2Point end_begin = GetEdgeAxis(end0, end1); S2Point end_mid = end0.CrossProd(end_begin); TestEdgeArc(end_begin, end1, end0, true); TestVertexArc(end0, end_begin, end_mid, round_); TestVertexArc(end0, end_mid, -end_begin, round_ && two_sided_); for (int i = n - 3; i >= 0; --i) { TestEdgeAndVertex(polyline_[i + 2], polyline_[i + 1], polyline_[i], two_sided_); } TestEdgeArc(start_begin, start1, start0, two_sided_); } TEST(S2BufferOperation, ZigZagPolyline) { S2BufferOperation::Options options(S1Angle::Degrees(1)); for (PolylineSide polyline_side : { PolylineSide::LEFT, PolylineSide::RIGHT, PolylineSide::BOTH}) { for (EndCapStyle end_cap_style : { EndCapStyle::ROUND, EndCapStyle::FLAT}) { SCOPED_TRACE(absl::StrFormat( "two_sided = %d, round = %d", polyline_side == PolylineSide::BOTH, end_cap_style == EndCapStyle::ROUND)); options.set_polyline_side(polyline_side); options.set_end_cap_style(end_cap_style); TestBufferPolyline("0:0, 0:7, 5:3, 5:10", options); // NOLINT TestBufferPolyline("10:0, 0:0, 5:1", options); // NOLINT } } } void BM_BufferPoints(benchmark::State& state) { const string seed_str = StrCat("BUFFER_POINTS", absl::GetFlag(FLAGS_s2_random_seed)); std::seed_seq seed(seed_str.begin(), seed_str.end()); std::mt19937_64 bitgen(seed); int num_points = state.range(0); S1Angle buffer_radius = S2Testing::MetersToAngle(100); for (auto _ : state) { S2LaxPolygonShape output; S2BufferOperation op(make_unique(&output), S2BufferOperation::Options{buffer_radius}); for (int i = 0; i < num_points; ++i) { op.AddPoint(s2random::Point(bitgen)); } S2Error error; ABSL_CHECK(op.Build(&error)) << error; } } BENCHMARK(BM_BufferPoints)->Arg(1)->Arg(10)->Arg(1000); void BenchmarkBufferLoop(benchmark::State& state, S2PointLoopSpan loop, S1Angle buffer_radius) { for (auto _ : state) { S2LaxPolygonShape output; S2BufferOperation op(make_unique(&output), S2BufferOperation::Options{buffer_radius}); op.AddLoop(loop); S2Error error; ABSL_CHECK(op.Build(&error)) << error; } } void BM_BufferConvexLoop(benchmark::State& state) { auto loop = S2Testing::MakeRegularPoints( S2Point(1, 0, 0), S2Testing::MetersToAngle(1000), state.range(0)); S1Angle buffer_radius = S2Testing::MetersToAngle(state.range(1)); BenchmarkBufferLoop(state, loop, buffer_radius); } BENCHMARK(BM_BufferConvexLoop) ->ArgPair(10, 10)->ArgPair(1000, 10)->ArgPair(1000, 1000); void BM_BufferConcaveLoop(benchmark::State& state) { auto loop = S2Testing::MakeRegularPoints( S2Point(1, 0, 0), S2Testing::MetersToAngle(1000), state.range(0)); std::reverse(loop.begin(), loop.end()); S1Angle buffer_radius = S2Testing::MetersToAngle(state.range(1)); BenchmarkBufferLoop(state, loop, buffer_radius); } BENCHMARK(BM_BufferConcaveLoop) ->ArgPair(10, 10)->ArgPair(1000, 10)->ArgPair(1000, 100); void BenchmarkBufferFractal( benchmark::State& state, int num_edges, S1Angle nominal_radius, double dimension, S1Angle buffer_radius) { const string seed_str = StrCat("BUFFER_FRACTAL", absl::GetFlag(FLAGS_s2_random_seed)); std::seed_seq seed(seed_str.begin(), seed_str.end()); std::mt19937_64 bitgen(seed); S2Fractal fractal(bitgen); fractal.SetLevelForApproxMaxEdges(num_edges); fractal.set_fractal_dimension(dimension); auto loop = fractal.MakeLoop(s2random::Frame(bitgen), nominal_radius); S2PointLoopSpan loop_span(&loop->vertex(0), loop->num_vertices()); BenchmarkBufferLoop(state, loop_span, buffer_radius); } void BM_BufferLoDimFractal(benchmark::State& state) { BenchmarkBufferFractal( state, state.range(0), S1Angle::Degrees(10), 1.05, S1Angle::Degrees(0.1)); } BENCHMARK(BM_BufferLoDimFractal) ->Arg(3 * 16)->Arg(3 * 1024); void BM_BufferHiDimFractal(benchmark::State& state) { BenchmarkBufferFractal( state, state.range(0), S1Angle::Degrees(10), 1.5, S1Angle::Degrees(0.1)); } BENCHMARK(BM_BufferHiDimFractal) ->Arg(3 * 16)->Arg(3 * 1024); } // namespace src/s2/s2builder.cc000066400000000000000000003000311524103652300143710ustar00rootroot00000000000000// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) // // The algorithm is based on the idea of choosing a set of sites and computing // their "limited radius Voronoi diagram", which is obtained by intersecting // each Voronoi region with a disc of fixed radius (the "snap radius") // centered around the corresponding site. // // For each input edge, we then determine the sequence of Voronoi regions // crossed by that edge, and snap the edge to the corresponding sequence of // sites. (In other words, each input edge is replaced by an edge chain.) // // The sites are chosen by starting with the set of input vertices, optionally // snapping them to discrete point set (such as S2CellId centers or lat/lng E7 // coordinates), and then choosing a subset such that no two sites are closer // than the given "snap_radius". Note that the sites do not need to be spaced // regularly -- their positions are completely arbitrary. // // Rather than computing the full limited radius Voronoi diagram, instead we // compute on demand the sequence of Voronoi regions intersected by each edge. // We do this by first finding all the sites that are within "snap_radius" of // the edge, sorting them by distance from the edge origin, and then using an // incremental algorithm. // // We implement the minimum edge-vertex separation property by snapping all // the input edges and checking whether any site (the "site to avoid") would // then be too close to the edge. If so we add another site (the "separation // site") along the input edge, positioned so that the new snapped edge is // guaranteed to be far enough away from the site to avoid. We then find all // the input edges that are within "snap_radius" of the new site, and resnap // those edges. (It is very rare that we need to add a separation site, even // when sites are densely spaced.) // // Idempotency is implemented by explicitly checking whether the input // geometry already meets the output criteria. This is not as sophisticated // as Stable Snap Rounding (Hershberger); I have worked out the details and it // is possible to adapt those ideas here, but it would make the implementation // significantly more complex. // // The only way that different output layers interact is in the choice of // Voronoi sites: // // - Vertices from all layers contribute to the initial selection of sites. // // - Edges in any layer that pass too close to a site can cause new sites to // be added (which affects snapping in all layers). // // - Simplification can be thought of as removing sites. A site can be // removed only if the snapped edges stay within the error bounds of the // corresponding input edges in all layers. // // Otherwise all layers are processed independently. For example, sibling // edge pairs can only cancel each other within a single layer (if desired). #include "s2/s2builder.h" #include #include #include #include #include #include #include #include #include #include "absl/base/nullability.h" #include "absl/cleanup/cleanup.h" #include "absl/container/btree_map.h" #include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_format.h" #include "absl/types/span.h" #include "s2/base/casts.h" #include "s2/base/log_severity.h" #include "s2/id_set_lexicon.h" #include "s2/mutable_s2shape_index.h" #include "s2/s1angle.h" #include "s2/s1chord_angle.h" #include "s2/s2builder_graph.h" #include "s2/s2builder_layer.h" #include "s2/s2builderutil_snap_functions.h" #include "s2/s2cell_id.h" #include "s2/s2closest_edge_query.h" #include "s2/s2closest_edge_query_base.h" #include "s2/s2closest_point_query.h" #include "s2/s2closest_point_query_base.h" #include "s2/s2crossing_edge_query.h" #include "s2/s2edge_crossings.h" #include "s2/s2edge_distances.h" #include "s2/s2error.h" #include "s2/s2loop.h" #include "s2/s2point.h" #include "s2/s2point_index.h" #include "s2/s2point_span.h" #include "s2/s2polygon.h" #include "s2/s2polyline.h" #include "s2/s2polyline_simplifier.h" #include "s2/s2predicates.h" #include "s2/s2shape.h" #include "s2/s2shapeutil_shape_edge.h" #include "s2/s2shapeutil_visit_crossing_edge_pairs.h" #include "s2/s2text_format.h" #include "s2/util/gtl/compact_array.h" using absl::flat_hash_set; using gtl::compact_array; using std::make_unique; using std::max; using std::pair; using std::unique_ptr; using std::vector; S2Builder::Options::Options() : snap_function_( make_unique(S1Angle::Zero())) { } S2Builder::Options::Options(const SnapFunction& snap_function) : snap_function_(snap_function.Clone()) { } S2Builder::Options::Options(const Options& options) : snap_function_(options.snap_function_->Clone()), split_crossing_edges_(options.split_crossing_edges_), intersection_tolerance_(options.intersection_tolerance_), simplify_edge_chains_(options.simplify_edge_chains_), idempotent_(options.idempotent_), memory_tracker_(options.memory_tracker_) { } S2Builder::Options& S2Builder::Options::operator=(const Options& options) { snap_function_ = options.snap_function_->Clone(); split_crossing_edges_ = options.split_crossing_edges_; intersection_tolerance_ = options.intersection_tolerance_; simplify_edge_chains_ = options.simplify_edge_chains_; idempotent_ = options.idempotent_; memory_tracker_ = options.memory_tracker_; return *this; } S1Angle S2Builder::Options::edge_snap_radius() const { return snap_function().snap_radius() + intersection_tolerance(); } S1Angle S2Builder::Options::max_edge_deviation() const { // We want max_edge_deviation() to be large enough compared to snap_radius() // such that edge splitting is rare. // // Using spherical trigonometry, if the endpoints of an edge of length L // move by at most a distance R, the center of the edge moves by at most // asin(sin(R) / cos(L / 2)). Thus the (max_edge_deviation / snap_radius) // ratio increases with both the snap radius R and the edge length L. // // We arbitrarily limit the edge deviation to be at most 10% more than the // snap radius. With the maximum allowed snap radius of 70 degrees, this // means that edges up to 30.6 degrees long are never split. For smaller // snap radii, edges up to 49 degrees long are never split. (Edges of any // length are not split unless their endpoints move far enough so that the // actual edge deviation exceeds the limit; in practice, splitting is rare // even with long edges.) Note that it is always possible to split edges // when max_edge_deviation() is exceeded; see MaybeAddExtraSites(). ABSL_DCHECK_LE(snap_function().snap_radius(), SnapFunction::kMaxSnapRadius()); const double kMaxEdgeDeviationRatio = 1.1; return kMaxEdgeDeviationRatio * edge_snap_radius(); } bool operator==(const S2Builder::GraphOptions& x, const S2Builder::GraphOptions& y) { return (x.edge_type() == y.edge_type() && x.degenerate_edges() == y.degenerate_edges() && x.duplicate_edges() == y.duplicate_edges() && x.sibling_pairs() == y.sibling_pairs() && x.allow_vertex_filtering() == y.allow_vertex_filtering()); } // Helper functions for computing error bounds: static S1ChordAngle RoundUp(S1Angle a) { S1ChordAngle ca(a); return ca.PlusError(ca.GetS1AngleConstructorMaxError()); } static S1ChordAngle AddPointToPointError(S1ChordAngle ca) { return ca.PlusError(ca.GetS2PointConstructorMaxError()); } static S1ChordAngle AddPointToEdgeError(S1ChordAngle ca) { return ca.PlusError(S2::GetUpdateMinDistanceMaxError(ca)); } S2Builder::S2Builder() = default; S2Builder::S2Builder(const Options& options) { Init(options); } void S2Builder::Init(const Options& options) { options_ = options; const SnapFunction& snap_function = options.snap_function(); S1Angle snap_radius = snap_function.snap_radius(); ABSL_DCHECK_LE(snap_radius, SnapFunction::kMaxSnapRadius()); // Convert the snap radius to an S1ChordAngle. This is the "true snap // radius" used when evaluating exact predicates (s2predicates.h). site_snap_radius_ca_ = S1ChordAngle(snap_radius); // When intersection_tolerance() is non-zero we need to use a larger snap // radius for edges than for vertices to ensure that both edges are snapped // to the edge intersection location. This is because the computed // intersection point is not exact; it may be up to intersection_tolerance() // away from its true position. The computed intersection point might then // be snapped to some other vertex up to snap_radius away. So to ensure // that both edges are snapped to a common vertex, we need to increase the // snap radius for edges to at least the sum of these two values (calculated // conservatively). S1Angle edge_snap_radius = options.edge_snap_radius(); edge_snap_radius_ca_ = RoundUp(edge_snap_radius); snapping_requested_ = (edge_snap_radius > S1Angle::Zero()); // Compute the maximum distance that a vertex can be separated from an // edge while still affecting how that edge is snapped. max_edge_deviation_ = options.max_edge_deviation(); edge_site_query_radius_ca_ = S1ChordAngle( max_edge_deviation_ + snap_function.min_edge_vertex_separation()); // Compute the maximum edge length such that even if both endpoints move by // the maximum distance allowed (i.e., edge_snap_radius), the center of the // edge will still move by less than max_edge_deviation(). This saves us a // lot of work since then we don't need to check the actual deviation. if (!snapping_requested_) { min_edge_length_to_split_ca_ = S1ChordAngle::Infinity(); } else { // This value varies between 30 and 50 degrees depending on the snap radius. min_edge_length_to_split_ca_ = S1ChordAngle::Radians( 2 * acos(sin(edge_snap_radius) / sin(max_edge_deviation_))); } // In rare cases we may need to explicitly check that the input topology is // preserved, i.e. that edges do not cross vertices when snapped. This is // only necessary (1) for vertices added using ForceVertex(), and (2) when the // snap radius is smaller than intersection_tolerance() (which is typically // either zero or S2::kIntersectionError, about 9e-16 radians). This // condition arises because when a geodesic edge is snapped, the edge center // can move further than its endpoints. This can cause an edge to pass on the // wrong side of an input vertex. (Note that this could not happen in a // planar version of this algorithm.) Usually we don't need to consider this // possibility explicitly, because if the snapped edge passes on the wrong // side of a vertex then it is also closer than min_edge_vertex_separation() // to that vertex, which will cause a separation site to be added. // // If the condition below is true then we need to check all sites (i.e., // snapped input vertices) for topology changes. However this is almost never // the case because // // max_edge_deviation() == 1.1 * edge_snap_radius() // and min_edge_vertex_separation() >= 0.219 * snap_radius() // // for all currently implemented snap functions. The condition below is // only true when intersection_tolerance() is non-zero (which causes // edge_snap_radius() to exceed snap_radius() by S2::kIntersectionError) and // snap_radius() is very small (at most S2::kIntersectionError / 1.19). check_all_site_crossings_ = (options.max_edge_deviation() > options.edge_snap_radius() + snap_function.min_edge_vertex_separation()); if (options.intersection_tolerance() <= S1Angle::Zero()) { ABSL_DCHECK(!check_all_site_crossings_); } // To implement idempotency, we check whether the input geometry could // possibly be the output of a previous S2Builder invocation. This involves // testing whether any site/site or edge/site pairs are too close together. // This is done using exact predicates, which require converting the minimum // separation values to an S1ChordAngle. min_site_separation_ = snap_function.min_vertex_separation(); min_site_separation_ca_ = S1ChordAngle(min_site_separation_); min_edge_site_separation_ca_ = S1ChordAngle(snap_function.min_edge_vertex_separation()); // This is an upper bound on the distance computed by S2ClosestPointQuery // where the true distance might be less than min_edge_site_separation_ca_. min_edge_site_separation_ca_limit_ = AddPointToEdgeError(min_edge_site_separation_ca_); // Compute the maximum possible distance between two sites whose Voronoi // regions touch. (The maximum radius of each Voronoi region is // edge_snap_radius_.) Then increase this bound to account for errors. max_adjacent_site_separation_ca_ = AddPointToPointError(RoundUp(2 * edge_snap_radius)); // Finally, we also precompute sin^2(edge_snap_radius), which is simply the // squared distance between a vertex and an edge measured perpendicular to // the plane containing the edge, and increase this value by the maximum // error in the calculation to compare this distance against the bound. double d = sin(edge_snap_radius); edge_snap_radius_sin2_ = d * d; edge_snap_radius_sin2_ += ((9.5 * d + 2.5 + 2 * sqrt(3)) * d + 9 * DBL_EPSILON) * DBL_EPSILON; // Initialize the current label set. label_set_id_ = label_set_lexicon_.EmptySetId(); label_set_modified_ = false; // If snapping was requested, we try to determine whether the input geometry // already meets the output requirements. This is necessary for // idempotency, and can also save work. If we discover any reason that the // input geometry needs to be modified, snapping_needed_ is set to true. snapping_needed_ = false; tracker_.Init(options.memory_tracker()); } void S2Builder::clear_labels() { label_set_.clear(); label_set_modified_ = true; } void S2Builder::push_label(Label label) { ABSL_DCHECK_GE(label, 0); label_set_.push_back(label); label_set_modified_ = true; } void S2Builder::pop_label() { label_set_.pop_back(); label_set_modified_ = true; } void S2Builder::set_label(Label label) { ABSL_DCHECK_GE(label, 0); label_set_.resize(1); label_set_[0] = label; label_set_modified_ = true; } bool S2Builder::IsFullPolygonUnspecified(const S2Builder::Graph& g, S2Error* absl_nonnull error) { *error = S2Error(S2Error::BUILDER_IS_FULL_PREDICATE_NOT_SPECIFIED, "A degenerate polygon was found, but no predicate was specified " "to determine whether the polygon is empty or full. Call " "S2Builder::AddIsFullPolygonPredicate() to fix this problem."); return false; // Assumes the polygon is empty. } S2Builder::IsFullPolygonPredicate S2Builder::IsFullPolygon(bool is_full) { return [is_full](const S2Builder::Graph& g, S2Error* absl_nonnull error) { return is_full; }; } void S2Builder::StartLayer(unique_ptr layer) { layer_options_.push_back(layer->graph_options()); layer_begins_.push_back(input_edges_.size()); layer_is_full_polygon_predicates_.push_back(IsFullPolygon(false)); layers_.push_back(std::move(layer)); } // Input vertices are stored in a vector, with some removal of duplicates. // Edges are represented as (VertexId, VertexId) pairs. All edges are stored // in a single vector; each layer corresponds to a contiguous range. S2Builder::InputVertexId S2Builder::AddVertex(const S2Point& v) { // Remove duplicate vertices that follow the pattern AB, BC, CD. If we want // to do anything more sophisticated, either use a ValueLexicon, or sort the // vertices once they have all been added, remove duplicates, and update the // edges. if (input_vertices_.empty() || v != input_vertices_.back()) { if (!tracker_.AddSpace(&input_vertices_, 1)) return -1; input_vertices_.push_back(v); } return input_vertices_.size() - 1; } void S2Builder::AddIntersection(const S2Point& vertex) { // It is an error to call this method without first setting // intersection_tolerance() to a non-zero value. ABSL_DCHECK_GT(options_.intersection_tolerance(), S1Angle::Zero()); // Calling this method also overrides the idempotent() option. snapping_needed_ = true; AddVertex(vertex); } void S2Builder::AddEdge(const S2Point& v0, const S2Point& v1) { ABSL_DCHECK(!layers_.empty()) << "Call StartLayer before adding any edges"; if (v0 == v1 && (layer_options_.back().degenerate_edges() == GraphOptions::DegenerateEdges::DISCARD)) { return; } InputVertexId j0 = AddVertex(v0); InputVertexId j1 = AddVertex(v1); if (!tracker_.AddSpace(&input_edges_, 1)) return; input_edges_.push_back(InputEdge(j0, j1)); // If there are any labels, then attach them to this input edge. if (label_set_modified_) { if (label_set_ids_.empty()) { // Populate the missing entries with empty label sets. label_set_ids_.assign(input_edges_.size() - 1, label_set_id_); } label_set_id_ = label_set_lexicon_.Add(label_set_); label_set_ids_.push_back(label_set_id_); label_set_modified_ = false; } else if (!label_set_ids_.empty()) { label_set_ids_.push_back(label_set_id_); } } void S2Builder::AddPolyline(S2PointSpan polyline) { for (size_t i = 1; i < polyline.size(); ++i) { AddEdge(polyline[i - 1], polyline[i]); } } void S2Builder::AddPolyline(const S2Polyline& polyline) { const int n = polyline.num_vertices(); for (int i = 1; i < n; ++i) { AddEdge(polyline.vertex(i - 1), polyline.vertex(i)); } } void S2Builder::AddLoop(S2PointLoopSpan loop) { for (size_t i = 0; i < loop.size(); ++i) { AddEdge(loop[i], loop[i + 1]); } } void S2Builder::AddLoop(const S2Loop& loop) { // Ignore loops with a single vertex, as they do not have a boundary. if (loop.is_empty_or_full()) return; // For loops that represent holes, we add the edge from vertex n-1 to vertex // n-2 first. This is because these edges will be assembled into a // clockwise loop, which will eventually be normalized in S2Polygon by // calling S2Loop::Invert(). S2Loop::Invert() reverses the order of the // vertices, so to end up with the original vertex order (0, 1, ..., n-1) we // need to build a clockwise loop with vertex order (n-1, n-2, ..., 0). // This is done by adding the edge (n-1, n-2) first, and then ensuring that // Build() assembles loops starting from edges in the order they were added. const int n = loop.num_vertices(); for (int i = 0; i < n; ++i) { AddEdge(loop.oriented_vertex(i), loop.oriented_vertex(i + 1)); } } void S2Builder::AddPolygon(const S2Polygon& polygon) { for (int i = 0; i < polygon.num_loops(); ++i) { AddLoop(*polygon.loop(i)); } } void S2Builder::AddShape(const S2Shape& shape) { for (int e = 0, n = shape.num_edges(); e < n; ++e) { S2Shape::Edge edge = shape.edge(e); AddEdge(edge.v0, edge.v1); } } void S2Builder::AddIsFullPolygonPredicate(IsFullPolygonPredicate predicate) { layer_is_full_polygon_predicates_.back() = std::move(predicate); } void S2Builder::ForceVertex(const S2Point& vertex) { if (!tracker_.AddSpace(&sites_, 1)) return; sites_.push_back(vertex); } // An S2Shape used to represent the entire collection of S2Builder input edges. // Vertices are specified as indices into a vertex vector to save space. namespace { class VertexIdEdgeVectorShape final : public S2Shape { public: // Requires that "edges" is constant for the lifetime of this object. VertexIdEdgeVectorShape(const vector>& edges, const vector& vertices) : edges_(edges), vertices_(vertices) {} const S2Point& vertex0(int e) const { return vertex(edges_[e].first); } const S2Point& vertex1(int e) const { return vertex(edges_[e].second); } // S2Shape interface: int num_edges() const override { return edges_.size(); } Edge edge(int e) const override { return Edge(vertices_[edges_[e].first], vertices_[edges_[e].second]); } int dimension() const override { return 1; } ReferencePoint GetReferencePoint() const override { return ReferencePoint::Contained(false); } int num_chains() const override { return edges_.size(); } Chain chain(int i) const override { return Chain(i, 1); } Edge chain_edge(int i, int j) const override { return edge(i); } ChainPosition chain_position(int e) const override { return ChainPosition(e, 0); } private: const S2Point& vertex(int i) const { return vertices_[i]; } const vector>& edges_; const vector& vertices_; }; } // namespace bool S2Builder::Build(S2Error* absl_nonnull error) { error_ = error; *error_ = S2Error::Ok(); // Mark the end of the last layer. layer_begins_.push_back(input_edges_.size()); // See the algorithm overview at the top of this file. if (snapping_requested_ && !options_.idempotent()) { snapping_needed_ = true; } ChooseSites(); BuildLayers(); Reset(); if (!tracker_.ok()) *error_ = tracker_.error(); return error_->ok(); } void S2Builder::Reset() { // Note that these calls do not change vector capacities. input_vertices_.clear(); input_edges_.clear(); layers_.clear(); layer_options_.clear(); layer_begins_.clear(); layer_is_full_polygon_predicates_.clear(); label_set_ids_.clear(); label_set_lexicon_.Clear(); label_set_.clear(); label_set_modified_ = false; sites_.clear(); edge_sites_.clear(); snapping_needed_ = false; } void S2Builder::ChooseSites() { if (!tracker_.ok() || input_vertices_.empty()) return; // Note that although we always create an S2ShapeIndex, often it is not // actually built (because this happens lazily). Therefore we only test // its memory usage at the places where it is used. MutableS2ShapeIndex input_edge_index; input_edge_index.set_memory_tracker(tracker_.tracker()); input_edge_index.Add(make_unique(input_edges_, input_vertices_)); if (options_.split_crossing_edges()) { AddEdgeCrossings(input_edge_index); } if (snapping_requested_) { S2PointIndex site_index; auto _ = absl::MakeCleanup([&]() { tracker_.DoneSiteIndex(site_index); }); AddForcedSites(&site_index); ChooseInitialSites(&site_index); if (!tracker_.FixSiteIndexTally(site_index)) return; CollectSiteEdges(site_index); } if (snapping_needed_) { AddExtraSites(input_edge_index); } else { ChooseAllVerticesAsSites(); } } void S2Builder::ChooseAllVerticesAsSites() { // Sort the input vertices, discard duplicates, and use the result as the // list of sites. (We sort in the same order used by ChooseInitialSites() // to avoid inconsistencies in tests.) We also copy the result back to // input_vertices_ and update the input edges to use the new vertex // numbering (so that InputVertexId == SiteId). This simplifies the // implementation of SnapEdge() for this case. sites_.clear(); if (!tracker_.AddSpaceExact(&sites_, input_vertices_.size())) return; const int64_t kTempPerVertex = sizeof(InputVertexKey) + sizeof(InputVertexId); if (!tracker_.TallyTemp(input_vertices_.size() * kTempPerVertex)) return; vector sorted = SortInputVertices(); vector vmap(input_vertices_.size()); for (size_t in = 0; in < sorted.size();) { const S2Point& site = input_vertices_[sorted[in].second]; vmap[sorted[in].second] = sites_.size(); while (++in < sorted.size() && input_vertices_[sorted[in].second] == site) { vmap[sorted[in].second] = sites_.size(); } sites_.push_back(site); } input_vertices_ = sites_; // Does not change allocated size. for (InputEdge& e : input_edges_) { e.first = vmap[e.first]; e.second = vmap[e.second]; } } vector S2Builder::SortInputVertices() { // Sort all the input vertices in the order that we wish to consider them as // candidate Voronoi sites. ChooseAllVerticesAsSites() requires duplicate // points be adjacent in the sorted output for deduplication. Otherwise, any // sort order will produce correct output, so we have complete flexibility in // choosing the sort key. We could even leave them unsorted, although this // would have the disadvantage that changing the order of the input edges // could cause S2Builder to snap to a different set of Voronoi sites. // // We have chosen to sort them primarily by S2CellId since this improves the // performance of many S2Builder phases (due to better spatial locality). It // also allows the possibility of replacing the current S2PointIndex approach // with a more efficient recursive divide-and-conquer algorithm. Ties are // broken by comparing the S2Point values of vertices lexicographically. // // However, sorting by leaf S2CellId alone has two small disadvantages in // the case where the candidate sites are densely spaced relative to the // snap radius (e.g., when using the IdentitySnapFunction, or when snapping // to E6/E7 near the poles, or snapping to S2CellId/E6/E7 using a snap // radius larger than the minimum value required): // // - First, it tends to bias the Voronoi site locations towards points that // are earlier on the S2CellId Hilbert curve. For example, suppose that // there are two parallel rows of input vertices on opposite sides of the // edge between two large S2Cells, and the rows are separated by less // than the snap radius. Then only vertices from the cell with the // smaller S2CellId are selected, because they are considered first and // prevent us from selecting the sites from the other cell (because they // are closer than "snap_radius" to an existing site). // // - Second, it tends to choose more Voronoi sites than necessary, because // at each step we choose the first site along the Hilbert curve that is // at least "snap_radius" away from all previously selected sites. This // tends to yield sites whose "coverage discs" overlap quite a bit, // whereas it would be better to cover all the input vertices with a // smaller set of coverage discs that don't overlap as much. (This is // the "geometric set cover problem", which is NP-hard.) // // It is not worth going to much trouble to fix these problems, because they // really aren't that important (and don't affect the guarantees made by the // algorithm), but here are a couple of heuristics that might help: // // 1. Sort the input vertices by S2CellId at a coarse level (down to cells // that are O(snap_radius) in size), and then sort by a fingerprint of the // S2Point coordinates (i.e., quasi-randomly). This would retain most of // the advantages of S2CellId sorting, but makes it more likely that we will // select sites that are further apart. // // 2. Rather than choosing the first uncovered input vertex and snapping it // to obtain the next Voronoi site, instead look ahead through following // candidates in S2CellId order and choose the furthest candidate whose // snapped location covers all previous uncovered input vertices. // // TODO(ericv): Experiment with these approaches. vector keys; keys.reserve(input_vertices_.size()); for (InputVertexId i = 0; static_cast(i) < input_vertices_.size(); ++i) { keys.push_back(InputVertexKey(S2CellId(input_vertices_[i]), i)); } std::sort(keys.begin(), keys.end(), [this](const InputVertexKey& a, const InputVertexKey& b) { if (a.first < b.first) return true; if (b.first < a.first) return false; if (input_vertices_[a.second] < input_vertices_[b.second]) return true; if (input_vertices_[b.second] < input_vertices_[a.second]) return false; return a.second < b.second; // Tie-break to ensure deterministic result. }); return keys; } // Check all edge pairs for crossings, and add the corresponding intersection // points to input_vertices_. (The intersection points will be snapped and // merged with the other vertices during site selection.) void S2Builder::AddEdgeCrossings(const MutableS2ShapeIndex& input_edge_index) { input_edge_index.ForceBuild(); if (!tracker_.ok()) return; // We need to build a list of intersections and add them afterwards so that // we don't reallocate vertices_ during the VisitCrossings() call. vector new_vertices; auto _ = absl::MakeCleanup([&]() { tracker_.Untally(new_vertices); }); s2shapeutil::VisitCrossingEdgePairs( input_edge_index, s2shapeutil::CrossingType::INTERIOR, [this, &new_vertices](const s2shapeutil::ShapeEdge& a, const s2shapeutil::ShapeEdge& b, bool) { if (!tracker_.AddSpace(&new_vertices, 1)) return false; new_vertices.push_back( S2::GetIntersection(a.v0(), a.v1(), b.v0(), b.v1())); return true; }); if (new_vertices.empty()) return; snapping_needed_ = true; if (!tracker_.AddSpaceExact(&input_vertices_, new_vertices.size())) return; input_vertices_.insert(input_vertices_.end(), new_vertices.begin(), new_vertices.end()); } void S2Builder::AddForcedSites(S2PointIndex* site_index) { // Sort the forced sites and remove duplicates. std::sort(sites_.begin(), sites_.end()); sites_.erase(std::unique(sites_.begin(), sites_.end()), sites_.end()); // Add the forced sites to the index. for (SiteId id = 0; static_cast(id) < sites_.size(); ++id) { if (!tracker_.TallyIndexedSite()) return; site_index->Add(sites_[id], id); } num_forced_sites_ = sites_.size(); } void S2Builder::ChooseInitialSites(S2PointIndex* site_index) { // Prepare to find all points whose distance is <= min_site_separation_ca_. S2ClosestPointQueryOptions options; options.set_conservative_max_distance(min_site_separation_ca_); S2ClosestPointQuery site_query(site_index, options); vector::Result> results; // Apply the snap_function() to each input vertex, then check whether any // existing site is closer than min_vertex_separation(). If not, then add a // new site. // // NOTE(ericv): There are actually two reasonable algorithms, which we call // "snap first" (the one above) and "snap last". The latter checks for each // input vertex whether any existing site is closer than snap_radius(), and // only then applies the snap_function() and adds a new site. "Snap last" // can yield slightly fewer sites in some cases, but it is also more // expensive and can produce surprising results. For example, if you snap // the polyline "0:0, 0:0.7" using IntLatLngSnapFunction(0), the result is // "0:0, 0:0" rather than the expected "0:0, 0:1", because the snap radius // is approximately sqrt(2) degrees and therefore it is legal to snap both // input points to "0:0". "Snap first" produces "0:0, 0:1" as expected. // // Track the memory used by SortInputVertices() before calling it. if (!tracker_.Tally(input_vertices_.size() * sizeof(InputVertexKey))) return; vector sorted_keys = SortInputVertices(); auto _ = absl::MakeCleanup([&]() { tracker_.Untally(sorted_keys); }); for (const InputVertexKey& key : sorted_keys) { const S2Point& vertex = input_vertices_[key.second]; S2Point site = SnapSite(vertex); // If any vertex moves when snapped, the output cannot be idempotent. snapping_needed_ = snapping_needed_ || site != vertex; bool add_site = true; if (site_snap_radius_ca_ == S1ChordAngle::Zero()) { add_site = sites_.empty() || site != sites_.back(); } else { // FindClosestPoints() measures distances conservatively, so we need to // recheck the distances using exact predicates. // // NOTE(ericv): When the snap radius is large compared to the average // vertex spacing, we could possibly avoid the call the FindClosestPoints // by checking whether sites_.back() is close enough. S2ClosestPointQueryPointTarget target(site); site_query.FindClosestPoints(&target, &results); for (const auto& result : results) { if (s2pred::CompareDistance(site, result.point(), min_site_separation_ca_) <= 0) { add_site = false; // This pair of sites is too close. If the sites are distinct, then // the output cannot be idempotent. snapping_needed_ = snapping_needed_ || site != result.point(); } } } if (add_site) { if (!tracker_.TallyIndexedSite()) return; site_index->Add(site, sites_.size()); if (!tracker_.AddSpace(&sites_, 1)) return; sites_.push_back(site); site_query.ReInit(); } } } S2Point S2Builder::SnapSite(const S2Point& point) const { if (!snapping_requested_) return point; S2Point site = options_.snap_function().SnapPoint(point); S1ChordAngle dist_moved(site, point); if (dist_moved > site_snap_radius_ca_) { *error_ = S2Error( S2Error::BUILDER_SNAP_RADIUS_TOO_SMALL, absl::StrFormat("Snap function moved vertex (%.15g, %.15g, %.15g) " "by %.15g, which is more than the specified snap " "radius of %.15g", point.x(), point.y(), point.z(), dist_moved.ToAngle().radians(), site_snap_radius_ca_.ToAngle().radians())); } return site; } // For each edge, find all sites within edge_site_query_radius_ca_ and // store them in edge_sites_. Also, to implement idempotency this method also // checks whether the input vertices and edges may already satisfy the output // criteria. If any problems are found then snapping_needed_ is set to true. void S2Builder::CollectSiteEdges(const S2PointIndex& site_index) { // Find all points whose distance is <= edge_site_query_radius_ca_. // // Memory used by S2ClosestPointQuery is not tracked, but it is temporary, // typically insignificant, and does not affect the high water mark. S2ClosestPointQueryOptions options; options.set_conservative_max_distance(edge_site_query_radius_ca_); S2ClosestPointQuery site_query(&site_index, options); vector::Result> results; if (!tracker_.AddSpaceExact(&edge_sites_, input_edges_.size())) return; edge_sites_.resize(input_edges_.size()); // Construct all elements. for (InputEdgeId e = 0; static_cast(e) < input_edges_.size(); ++e) { const InputEdge& edge = input_edges_[e]; const S2Point& v0 = input_vertices_[edge.first]; const S2Point& v1 = input_vertices_[edge.second]; S2ClosestPointQueryEdgeTarget target(v0, v1); site_query.FindClosestPoints(&target, &results); auto* sites = &edge_sites_[e]; sites->reserve(results.size()); for (const auto& result : results) { sites->push_back(result.data()); if (!snapping_needed_ && result.distance() < min_edge_site_separation_ca_limit_ && result.point() != v0 && result.point() != v1 && s2pred::CompareEdgeDistance(result.point(), v0, v1, min_edge_site_separation_ca_) < 0) { snapping_needed_ = true; } } SortSitesByDistance(v0, sites); if (!tracker_.TallyEdgeSites(*sites)) return; } } // Sorts the sites in increasing order of distance to X. void S2Builder::SortSitesByDistance(const S2Point& x, compact_array* sites) const { std::sort(sites->begin(), sites->end(), [&x, this](SiteId i, SiteId j) { if (i == j) return false; int diff = s2pred::CompareDistances(x, sites_[i], sites_[j]); if (diff < 0) return true; if (diff > 0) return false; return i < j; // Tie-break to ensure deterministic result. }); } // Like the above, but inserts "new_site_id" into an already-sorted list. void S2Builder::InsertSiteByDistance(SiteId new_site_id, const S2Point& x, compact_array* sites) { if (!tracker_.ReserveEdgeSite(sites)) return; sites->insert(std::lower_bound( sites->begin(), sites->end(), new_site_id, [&x, this](SiteId i, SiteId j) { return s2pred::CompareDistances(x, sites_[i], sites_[j]) < 0; }), new_site_id); } // There are two situations where we need to add extra Voronoi sites in order to // ensure that the snapped edges meet the output requirements: // // (1) If a snapped edge deviates from its input edge by more than // max_edge_deviation(), we add a new site on the input edge near the // middle of the snapped edge. This causes the snapped edge to split // into two pieces, so that it follows the input edge more closely. // // (2) If a snapped edge is closer than min_edge_vertex_separation() to any // nearby site (the "site to avoid") or passes on the wrong side of it // relative to the input edge, then we add a new site (the "separation // site") along the input edge near the site to avoid. This causes the // snapped edge to follow the input edge more closely, so that it is // guaranteed to pass on the correct side of the site to avoid with a // separation of at least the required distance. // // We check these conditions by snapping all the input edges to a chain of // Voronoi sites and then testing each edge in the chain. If a site needs to // be added, we mark all nearby edges for re-snapping. void S2Builder::AddExtraSites(const MutableS2ShapeIndex& input_edge_index) { // Note that we could save some work in AddSnappedEdges() by saving the // snapped edge chains in a vector, but currently this is not worthwhile // since SnapEdge() accounts for less than 5% of the runtime. // Using 18 buckets is equivalent to `reserve(16)`, which was the // `expected_max_elements` used by the old `dense_hash_set` version. // This will actually get us 31 buckets since it gets rounded up. // We could experiment with different values here. flat_hash_set edges_to_resnap(/*bucket_count=*/18); vector chain; // Temporary storage. int num_edges_after_snapping = 0; // CheckEdge() defines the body of the loops below. const auto CheckEdge = [&](InputEdgeId e) -> bool { if (!tracker_.ok()) return false; SnapEdge(e, &chain); edges_to_resnap.erase(e); num_edges_after_snapping += chain.size(); MaybeAddExtraSites(e, chain, input_edge_index, &edges_to_resnap); return true; }; // The first pass is different because we snap every edge. In the following // passes we only snap edges that are near the extra sites that were added. ABSL_VLOG(1) << "Before pass 0: sites=" << sites_.size(); for (InputEdgeId e = 0; static_cast(e) < input_edges_.size(); ++e) { if (!CheckEdge(e)) return; } ABSL_VLOG(1) << "Pass 0: edges snapped=" << input_edges_.size() << ", output edges=" << num_edges_after_snapping << ", sites=" << sites_.size(); for (int num_passes = 1; !edges_to_resnap.empty(); ++num_passes) { auto edges_to_snap = edges_to_resnap; edges_to_resnap.clear(); num_edges_after_snapping = 0; for (InputEdgeId e : edges_to_snap) { if (!CheckEdge(e)) return; } ABSL_VLOG(1) << "Pass " << num_passes << ": edges snapped=" << edges_to_snap.size() << ", output edges=" << num_edges_after_snapping << ", sites=" << sites_.size(); } } void S2Builder::MaybeAddExtraSites( InputEdgeId edge_id, absl::Span chain, const MutableS2ShapeIndex& input_edge_index, flat_hash_set* edges_to_resnap) { // If the memory tracker has a periodic callback function, tally an amount // of memory proportional to the work being done so that the caller has an // opportunity to cancel the operation if necessary. if (!tracker_.TallyTemp(chain.size() * sizeof(chain[0]))) return; // If the input includes NaN vertices, snapping can produce an empty chain. if (chain.empty()) return; // The snapped edge chain is always a subsequence of the nearby sites // (edge_sites_), so we walk through the two arrays in parallel looking for // sites that weren't snapped. These are the "sites to avoid". We also keep // track of the current snapped edge, since it is the only edge that can be // too close or pass on the wrong side of a site to avoid. Vertices beyond // the chain endpoints in either direction can be ignored because only the // interiors of chain edges can be too close to a site to avoid. const InputEdge& edge = input_edges_[edge_id]; const S2Point& a0 = input_vertices_[edge.first]; const S2Point& a1 = input_vertices_[edge.second]; const auto& nearby_sites = edge_sites_[edge_id]; for (size_t i = 0, j = 0; j < nearby_sites.size(); ++j) { SiteId id = nearby_sites[j]; if (id == chain[i]) { // This site is a vertex of the snapped edge chain. if (++i == chain.size()) { break; // Sites beyond the end of the snapped chain can be ignored. } // Check whether this snapped edge deviates too far from its original // position. If so, we split the edge by adding an extra site. const S2Point& v0 = sites_[chain[i - 1]]; const S2Point& v1 = sites_[chain[i]]; if (S1ChordAngle(v0, v1) < min_edge_length_to_split_ca_) continue; if (!S2::IsEdgeBNearEdgeA(a0, a1, v0, v1, max_edge_deviation_)) { // Add a new site on the input edge, positioned so that it splits the // snapped edge into two approximately equal pieces. Then we find all // the edges near the new site (including this one) and add them to // the snap queue. // // Note that with large snap radii, it is possible that the snapped // edge wraps around the sphere the "wrong way". To handle this we // find the preferred split location by projecting both endpoints onto // the input edge and taking their midpoint. S2Point mid = (S2::Project(v0, a0, a1) + S2::Project(v1, a0, a1)).Normalize(); S2Point new_site = GetSeparationSite(mid, v0, v1, edge_id); AddExtraSite(new_site, input_edge_index, edges_to_resnap); // In the case where the edge wrapped around the sphere the "wrong // way", it is not safe to continue checking this edge. It will be // marked for resnapping and we will come back to it in the next pass. return; } } else { // This site is near the input edge but is not part of the snapped chain. if (i == 0) { continue; // Sites before the start of the chain can be ignored. } // We need to ensure that non-forced sites are separated by at least // min_edge_vertex_separation() from the snapped chain. This happens // automatically as part of the algorithm except where there are portions // of the input edge that are not within edge_snap_radius() of any site. // These portions of the original edge are called "coverage gaps". // Therefore if we find that a site to avoid that is too close to the // snapped edge chain, we can fix the problem by adding a new site (the // "separation site") in the corresponding coverage gap located as closely // as possible to the site to avoid. This technique is is guaranteed to // produce the required minimum separation, and the entire process of // adding separation sites is guaranteed to terminate. const S2Point& site_to_avoid = sites_[id]; const S2Point& v0 = sites_[chain[i - 1]]; const S2Point& v1 = sites_[chain[i]]; bool add_separation_site = false; if (!is_forced(id) && min_edge_site_separation_ca_ > S1ChordAngle::Zero() && s2pred::CompareEdgeDistance( site_to_avoid, v0, v1, min_edge_site_separation_ca_) < 0) { add_separation_site = true; } // Similarly, we also add a separation site whenever a snapped edge passes // on the wrong side of a site to avoid. Normally we don't need to worry // about this, since if an edge passes on the wrong side of a nearby site // then it is also too close to it. However if the snap radius is very // small and intersection_tolerance() is non-zero then we need to check // this condition explicitly (see the "check_all_site_crossings_" flag for // details). We also need to check this condition explicitly for forced // vertices. Again, we can solve this problem by adding a "separation // site" in the corresponding coverage gap located as closely as possible // to the site to avoid. // // It is possible to show that when all points are projected onto the // great circle through (a0, a1), no improper crossing occurs unless the // the site to avoid is located between a0 and a1, and also between v0 // and v1. TODO(ericv): Verify whether all these checks are necessary. if (!add_separation_site && (is_forced(id) || check_all_site_crossings_) && (s2pred::Sign(a0, a1, site_to_avoid) != s2pred::Sign(v0, v1, site_to_avoid))&& s2pred::CompareEdgeDirections(a0, a1, a0, site_to_avoid) > 0 && s2pred::CompareEdgeDirections(a0, a1, site_to_avoid, a1) > 0 && s2pred::CompareEdgeDirections(a0, a1, v0, site_to_avoid) > 0 && s2pred::CompareEdgeDirections(a0, a1, site_to_avoid, v1) > 0) { add_separation_site = true; } if (add_separation_site) { // We add a new site (the separation site) in the coverage gap along the // input edge, located as closely as possible to the site to avoid. // Then we find all the edges near the new site (including this one) and // add them to the snap queue. S2Point new_site = GetSeparationSite(site_to_avoid, v0, v1, edge_id); ABSL_DCHECK_NE(site_to_avoid, new_site); AddExtraSite(new_site, input_edge_index, edges_to_resnap); // Skip the remaining sites near this chain edge, and then continue // scanning this chain. Note that this is safe even though the call // to AddExtraSite() above added a new site to "nearby_sites". for (; nearby_sites[j + 1] != chain[i]; ++j) {} } } } } // Adds a new site, then updates "edge_sites_" for all edges near the new site // and adds them to "edges_to_resnap" for resnapping. void S2Builder::AddExtraSite(const S2Point& new_site, const MutableS2ShapeIndex& input_edge_index, flat_hash_set* edges_to_resnap) { if (!sites_.empty()) ABSL_DCHECK_NE(new_site, sites_.back()); if (!tracker_.AddSpace(&sites_, 1)) return; SiteId new_site_id = sites_.size(); sites_.push_back(new_site); // Find all edges whose distance is <= edge_site_query_radius_ca_. S2ClosestEdgeQuery::Options options; options.set_conservative_max_distance(edge_site_query_radius_ca_); options.set_include_interiors(false); if (!input_edge_index.is_fresh()) input_edge_index.ForceBuild(); if (!tracker_.ok()) return; // Memory used by S2ClosestEdgeQuery is not tracked, but it is temporary, // typically insignificant, and does not affect the high water mark. S2ClosestEdgeQuery query(&input_edge_index, options); S2ClosestEdgeQuery::PointTarget target(new_site); for (const auto& result : query.FindClosestEdges(&target)) { InputEdgeId e = result.edge_id(); const S2Point& v0 = input_vertices_[input_edges_[e].first]; InsertSiteByDistance(new_site_id, v0, &edge_sites_[e]); edges_to_resnap->insert(e); } } S2Point S2Builder::GetSeparationSite(const S2Point& site_to_avoid, const S2Point& v0, const S2Point& v1, InputEdgeId input_edge_id) const { // Define the "coverage disc" of a site S to be the disc centered at S with // radius "snap_radius". Similarly, define the "coverage interval" of S for // an edge XY to be the intersection of XY with the coverage disc of S. The // SnapFunction implementations guarantee that the only way that a snapped // edge can be closer than min_edge_vertex_separation() to a non-snapped // site (i.e., site_to_avoid) if is there is a gap in the coverage of XY // near this site. We can fix this problem simply by adding a new site to // fill this gap, located as closely as possible to the site to avoid. // // To calculate the coverage gap, we look at the two snapped sites on // either side of site_to_avoid, and find the endpoints of their coverage // intervals. The we place a new site in the gap, located as closely as // possible to the site to avoid. Note that the new site may move when it // is snapped by the snap_function, but it is guaranteed not to move by // more than snap_radius and therefore its coverage interval will still // intersect the gap. const InputEdge& edge = input_edges_[input_edge_id]; const S2Point& x = input_vertices_[edge.first]; const S2Point& y = input_vertices_[edge.second]; Vector3_d xy_dir = y - x; S2Point n = S2::RobustCrossProd(x, y); S2Point new_site = S2::Project(site_to_avoid, x, y, n); S2Point gap_min = GetCoverageEndpoint(v0, n); S2Point gap_max = GetCoverageEndpoint(v1, -n); if ((new_site - gap_min).DotProd(xy_dir) < 0) { new_site = gap_min; } else if ((gap_max - new_site).DotProd(xy_dir) < 0) { new_site = gap_max; } new_site = SnapSite(new_site); ABSL_DCHECK_NE(v0, new_site); ABSL_DCHECK_NE(v1, new_site); return new_site; } // Given a site P and an edge XY with normal N, intersect XY with the disc of // radius snap_radius() around P, and return the intersection point that is // further along the edge XY toward Y. S2Point S2Builder::GetCoverageEndpoint(const S2Point& p, const S2Point& n) const { // Consider the plane perpendicular to P that cuts off a spherical cap of // radius snap_radius(). This plane intersects the plane through the edge // XY (perpendicular to N) along a line, and that line intersects the unit // sphere at two points Q and R, and we want to return the point R that is // further along the edge XY toward Y. // // Let M be the midpoint of QR. This is the point along QR that is closest // to P. We can now express R as the sum of two perpendicular vectors OM // and MR in the plane XY. Vector MR is in the direction N x P, while // vector OM is in the direction (N x P) x N, where N = X x Y. // // The length of OM can be found using the Pythagorean theorem on triangle // OPM, and the length of MR can be found using the Pythagorean theorem on // triangle OMR. // // In the calculations below, we save some work by scaling all the vectors // by n.CrossProd(p).Norm2(), and normalizing at the end. double n2 = n.Norm2(); double nDp = n.DotProd(p); S2Point nXp = n.CrossProd(p); S2Point nXpXn = n2 * p - nDp * n; Vector3_d om = sqrt(1 - edge_snap_radius_sin2_) * nXpXn; double mr2 = edge_snap_radius_sin2_ * n2 - nDp * nDp; // MR is constructed so that it points toward Y (rather than X). Vector3_d mr = sqrt(max(0.0, mr2)) * nXp; return (om + mr).Normalize(); } void S2Builder::SnapEdge(InputEdgeId e, vector* chain) const { chain->clear(); const InputEdge& edge = input_edges_[e]; if (!snapping_needed_) { // Note that the input vertices have been renumbered such that // InputVertexId and SiteId are the same (see ChooseAllVerticesAsSites). chain->push_back(edge.first); chain->push_back(edge.second); return; } const S2Point& x = input_vertices_[edge.first]; const S2Point& y = input_vertices_[edge.second]; // Optimization: if there is only one nearby site, return. // Optimization: if there are exactly two nearby sites, and one is close // enough to each vertex, then return. // Now iterate through the sites. We keep track of the sequence of sites // that are visited. const auto& candidates = edge_sites_[e]; for (SiteId site_id : candidates) { const S2Point& c = sites_[site_id]; // Skip any sites that are too far away. (There will be some of these, // because we also keep track of "sites to avoid".) Note that some sites // may be close enough to the line containing the edge, but not to the // edge itself, so we can just use the dot product with the edge normal. if (s2pred::CompareEdgeDistance(c, x, y, edge_snap_radius_ca_) > 0) { continue; } // Check whether the new site C excludes the previous site B. If so, // repeat with the previous site, and so on. bool add_site_c = true; for (; !chain->empty(); chain->pop_back()) { S2Point b = sites_[chain->back()]; // First, check whether B and C are so far apart that their clipped // Voronoi regions can't intersect. S1ChordAngle bc(b, c); if (bc >= max_adjacent_site_separation_ca_) break; // Otherwise, we want to check whether site C prevents the Voronoi // region of B from intersecting XY, or vice versa. This can be // determined by computing the "coverage interval" (the segment of XY // intersected by the coverage disc of radius snap_radius) for each // site. If the coverage interval of one site contains the coverage // interval of the other, then the contained site can be excluded. s2pred::Excluded result = s2pred::GetVoronoiSiteExclusion( b, c, x, y, edge_snap_radius_ca_); if (result == s2pred::Excluded::FIRST) continue; // Site B excluded by C if (result == s2pred::Excluded::SECOND) { add_site_c = false; // Site C is excluded by B. break; } ABSL_DCHECK_EQ(s2pred::Excluded::NEITHER, result); // Otherwise check whether the previous site A is close enough to B and // C that it might further clip the Voronoi region of B. if (chain->size() < 2) break; S2Point a = sites_[chain->end()[-2]]; S1ChordAngle ac(a, c); if (ac >= max_adjacent_site_separation_ca_) break; // If triangles ABC and XYB have the same orientation, the circumcenter // Z of ABC is guaranteed to be on the same side of XY as B. int xyb = s2pred::Sign(x, y, b); if (s2pred::Sign(a, b, c) == xyb) { break; // The circumcenter is on the same side as B but further away. } // Other possible optimizations: // - if AB > max_adjacent_site_separation_ca_ then keep B. // - if d(B, XY) < 0.5 * min(AB, BC) then keep B. // If the circumcenter of ABC is on the same side of XY as B, then B is // excluded by A and C combined. Otherwise B is needed and we can exit. if (s2pred::EdgeCircumcenterSign(x, y, a, b, c) != xyb) break; } if (add_site_c) { chain->push_back(site_id); } } ABSL_DCHECK(!chain->empty()); if (S2_DEBUG_MODE) { for (SiteId site_id : candidates) { if (s2pred::CompareDistances(y, sites_[chain->back()], sites_[site_id]) > 0) { ABSL_LOG(ERROR) << "Snapping invariant broken!"; } } } } void S2Builder::BuildLayers() { if (!tracker_.ok()) return; // Each output edge has an "input edge id set id" (an int32_t) representing // the set of input edge ids that were snapped to this edge. The actual // InputEdgeIds can be retrieved using "input_edge_id_set_lexicon". vector> layer_edges; vector> layer_input_edge_ids; IdSetLexicon input_edge_id_set_lexicon; vector> layer_vertices; BuildLayerEdges(&layer_edges, &layer_input_edge_ids, &input_edge_id_set_lexicon); auto _ = absl::MakeCleanup([&]() { for (size_t i = 0; i < layers_.size(); ++i) { tracker_.Untally(layer_edges[i]); tracker_.Untally(layer_input_edge_ids[i]); if (!layer_vertices.empty()) tracker_.Untally(layer_vertices[i]); } }); // If there are a large number of layers, then we build a minimal subset of // vertices for each layer. This ensures that layer types that iterate over // vertices will run in time proportional to the size of that layer rather // than the size of all layers combined. static const int kMinLayersForVertexFiltering = 10; if (layers_.size() >= kMinLayersForVertexFiltering) { // Disable vertex filtering if it is disallowed by any layer. (This could // be optimized, but in current applications either all layers allow // filtering or none of them do.) bool allow_vertex_filtering = true; for (const auto& options : layer_options_) { allow_vertex_filtering &= options.allow_vertex_filtering(); } if (allow_vertex_filtering) { // Track the temporary memory used by FilterVertices(). Note that // although vertex filtering can increase the number of vertices stored // (i.e., if the same vertex is referred to by multiple layers), it // never increases storage quadratically because there can be at most // two filtered vertices per edge. if (!tracker_.TallyFilterVertices(sites_.size(), layer_edges)) return; auto _ = absl::MakeCleanup([this]() { tracker_.DoneFilterVertices(); }); layer_vertices.resize(layers_.size()); vector filter_tmp; // Temporary used by FilterVertices. for (size_t i = 0; i < layers_.size(); ++i) { layer_vertices[i] = Graph::FilterVertices(sites_, &layer_edges[i], &filter_tmp); if (!tracker_.Tally(layer_vertices[i])) return; } tracker_.Clear(&sites_); // Releases memory. } } if (!tracker_.ok()) return; for (size_t i = 0; i < layers_.size(); ++i) { const vector& vertices = (layer_vertices.empty() ? sites_ : layer_vertices[i]); Graph graph(layer_options_[i], &vertices, &layer_edges[i], &layer_input_edge_ids[i], &input_edge_id_set_lexicon, &label_set_ids_, &label_set_lexicon_, layer_is_full_polygon_predicates_[i]); layers_[i]->Build(graph, error_); // Don't free the layer data until all layers have been built, in order to // support building multiple layers at once (e.g. ClosedSetNormalizer). } } // Snaps and possibly simplifies the edges for each layer, populating the // given output arguments. The resulting edges can be used to construct an // S2Builder::Graph directly (no further processing is necessary). // // This method is not "const" because Graph::ProcessEdges can modify // layer_options_ in some cases (changing undirected edges to directed ones). void S2Builder::BuildLayerEdges( vector>* layer_edges, vector>* layer_input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon) { // Edge chains are simplified only when a non-zero snap radius is specified. // If so, we build a map from each site to the set of input vertices that // snapped to that site. (Note that site_vertices is relatively small and // that its memory tracking is deferred until TallySimplifyEdgeChains.) vector> site_vertices; bool simplify = snapping_needed_ && options_.simplify_edge_chains(); if (simplify) site_vertices.resize(sites_.size()); layer_edges->resize(layers_.size()); layer_input_edge_ids->resize(layers_.size()); for (size_t i = 0; i < layers_.size(); ++i) { AddSnappedEdges(layer_begins_[i], layer_begins_[i+1], layer_options_[i], &(*layer_edges)[i], &(*layer_input_edge_ids)[i], input_edge_id_set_lexicon, &site_vertices); } // We simplify edge chains before processing the per-layer GraphOptions // because simplification can create duplicate edges and/or sibling edge // pairs which may need to be removed. if (simplify) { SimplifyEdgeChains(site_vertices, layer_edges, layer_input_edge_ids, input_edge_id_set_lexicon); vector>().swap(site_vertices); } // At this point we have no further need for nearby site data, so we clear // it to save space. We keep input_vertices_ and input_edges_ so that // S2Builder::Layer implementations can access them if desired. (This is // useful for determining how snapping has changed the input geometry.) tracker_.ClearEdgeSites(&edge_sites_); for (size_t i = 0; i < layers_.size(); ++i) { // The errors generated by ProcessEdges are really warnings, so we simply // record them and continue. Graph::ProcessEdges(&layer_options_[i], &(*layer_edges)[i], &(*layer_input_edge_ids)[i], input_edge_id_set_lexicon, error_, &tracker_); if (!tracker_.ok()) return; } } // Snaps all the input edges for a given layer, populating the given output // arguments. If (*site_vertices) is non-empty then it is updated so that // (*site_vertices)[site] contains a list of all input vertices that were // snapped to that site. void S2Builder::AddSnappedEdges( InputEdgeId begin, InputEdgeId end, const GraphOptions& options, vector* edges, vector* input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon, vector>* site_vertices) { bool discard_degenerate_edges = (options.degenerate_edges() == GraphOptions::DegenerateEdges::DISCARD); vector chain; for (InputEdgeId e = begin; e < end; ++e) { InputEdgeIdSetId id = input_edge_id_set_lexicon->AddSingleton(e); SnapEdge(e, &chain); if (chain.empty()) { continue; } int num_snapped_edges = max(1, chain.size() - 1); if (options.edge_type() == EdgeType::UNDIRECTED) num_snapped_edges *= 2; if (!tracker_.AddSpace(edges, num_snapped_edges)) return; if (!tracker_.AddSpace(input_edge_ids, num_snapped_edges)) return; MaybeAddInputVertex(input_edges_[e].first, chain[0], site_vertices); if (chain.size() == 1) { if (discard_degenerate_edges) continue; AddSnappedEdge(chain[0], chain[0], id, options.edge_type(), edges, input_edge_ids); } else { MaybeAddInputVertex(input_edges_[e].second, chain.back(), site_vertices); for (size_t i = 1; i < chain.size(); ++i) { AddSnappedEdge(chain[i-1], chain[i], id, options.edge_type(), edges, input_edge_ids); } } } } // If "site_vertices" is non-empty, ensures that (*site_vertices)[id] contains // "v". Duplicate entries are allowed. The purpose of this function is to // build a map so that SimplifyEdgeChains() can quickly find all the input // vertices that snapped to a particular site. inline void S2Builder::MaybeAddInputVertex( InputVertexId v, SiteId id, vector>* site_vertices) const { if (site_vertices->empty()) return; // Optimization: check if we just added this vertex. This is worthwhile // because the input edges usually form a continuous chain, i.e. the // destination of one edge is the same as the source of the next edge. auto& vertices = (*site_vertices)[id]; if (vertices.empty() || vertices.back() != v) { // Memory tracking is deferred until SimplifyEdgeChains. vertices.push_back(v); } } // Adds the given edge to "edges" and "input_edge_ids". If undirected edges // are being used, also adds an edge in the opposite direction. inline void S2Builder::AddSnappedEdge( SiteId src, SiteId dst, InputEdgeIdSetId id, EdgeType edge_type, vector* edges, vector* input_edge_ids) const { edges->push_back(Edge(src, dst)); input_edge_ids->push_back(id); if (edge_type == EdgeType::UNDIRECTED) { edges->push_back(Edge(dst, src)); // Automatically created edges do not have input edge ids or labels. This // can be used to distinguish the original direction of the undirected edge. input_edge_ids->push_back(IdSetLexicon::EmptySetId()); } } // A class that encapsulates the state needed for simplifying edge chains. class S2Builder::EdgeChainSimplifier { public: // The graph "g" contains all edges from all layers. "edge_layers" // indicates the original layer for each edge. "site_vertices" is a map // from SiteId to the set of InputVertexIds that were snapped to that site. // "layer_edges" and "layer_input_edge_ids" are output arguments where the // simplified edge chains will be placed. The input and output edges are // not sorted. EdgeChainSimplifier( const S2Builder& builder, const Graph& g, const vector& edge_layers, const vector>& site_vertices, vector>* layer_edges, vector>* layer_input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon); void Run(); private: using VertexId = Graph::VertexId; class InteriorVertexMatcher; void OutputEdge(EdgeId e); int graph_edge_layer(EdgeId e) const; int input_edge_layer(InputEdgeId id) const; bool IsInterior(VertexId v); void SimplifyChain(VertexId v0, VertexId v1); Graph::VertexId FollowChain(VertexId v0, VertexId v1) const; void OutputAllEdges(VertexId v0, VertexId v1); bool TargetInputVertices(VertexId v, S2PolylineSimplifier* simplifier) const; bool AvoidSites(VertexId v0, VertexId v1, VertexId v2, flat_hash_set* used_vertices, S2PolylineSimplifier* simplifier) const; void MergeChain(absl::Span vertices); void AssignDegenerateEdges(absl::Span degenerate_ids, vector>* merged_ids) const; // LINT.IfChange const S2Builder& builder_; const Graph& g_; Graph::VertexInMap in_; Graph::VertexOutMap out_; const vector& edge_layers_; const vector>& site_vertices_; vector>* layer_edges_; vector>* layer_input_edge_ids_; IdSetLexicon* input_edge_id_set_lexicon_; // Convenience member copied from builder_. const vector& layer_begins_; // is_interior_[v] indicates that VertexId "v" is eligible to be an interior // vertex of a simplified edge chain. You can think of it as vertex whose // indegree and outdegree are both 1 (although the actual definition is a // bit more complicated because of duplicate edges and layers). vector is_interior_; // used_[e] indicates that EdgeId "e" has already been processed. vector used_; // Temporary objects declared here to avoid repeated allocation. vector tmp_vertices_; vector tmp_edges_; flat_hash_set tmp_vertex_set_; // The output edges after simplification. vector new_edges_; vector new_input_edge_ids_; vector new_edge_layers_; }; // Simplifies edge chains, updating its input/output arguments as necessary. void S2Builder::SimplifyEdgeChains( const vector>& site_vertices, vector>* layer_edges, vector>* layer_input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon) { if (layers_.empty()) return; if (!tracker_.TallySimplifyEdgeChains(site_vertices, *layer_edges)) return; // Merge the edges from all layers (in order to build a single graph). vector merged_edges; vector merged_input_edge_ids; vector merged_edge_layers; MergeLayerEdges(*layer_edges, *layer_input_edge_ids, &merged_edges, &merged_input_edge_ids, &merged_edge_layers); // The following fields will be reconstructed by EdgeChainSimplifier. for (auto& edges : *layer_edges) edges.clear(); for (auto& input_edge_ids : *layer_input_edge_ids) input_edge_ids.clear(); // The graph options are irrelevant for edge chain simplification, but we // try to set them appropriately anyway. S2Builder::GraphOptions graph_options(EdgeType::DIRECTED, GraphOptions::DegenerateEdges::KEEP, GraphOptions::DuplicateEdges::KEEP, GraphOptions::SiblingPairs::KEEP); Graph graph(graph_options, &sites_, &merged_edges, &merged_input_edge_ids, input_edge_id_set_lexicon, nullptr, nullptr, IsFullPolygonPredicate()); EdgeChainSimplifier simplifier( *this, graph, merged_edge_layers, site_vertices, layer_edges, layer_input_edge_ids, input_edge_id_set_lexicon); simplifier.Run(); } // LINT.ThenChange(:TallySimplifyEdgeChains) // Merges the edges from all layers and sorts them in lexicographic order so // that we can construct a single graph. The sort is stable, which means that // any duplicate edges within each layer will still be sorted by InputEdgeId. void S2Builder::MergeLayerEdges( absl::Span> layer_edges, absl::Span> layer_input_edge_ids, vector* edges, vector* input_edge_ids, vector* edge_layers) const { vector order; for (size_t i = 0; i < layer_edges.size(); ++i) { for (size_t e = 0; e < layer_edges[i].size(); ++e) { order.push_back(LayerEdgeId(i, e)); } } std::sort(order.begin(), order.end(), [layer_edges](const LayerEdgeId& ai, const LayerEdgeId& bi) { return StableLessThan(layer_edges[ai.first][ai.second], layer_edges[bi.first][bi.second], ai, bi); }); edges->reserve(order.size()); input_edge_ids->reserve(order.size()); edge_layers->reserve(order.size()); for (const LayerEdgeId& id : order) { edges->push_back(layer_edges[id.first][id.second]); input_edge_ids->push_back(layer_input_edge_ids[id.first][id.second]); edge_layers->push_back(id.first); } } // A comparison function that allows stable sorting with std::sort (which is // fast but not stable). It breaks ties between equal edges by comparing // their LayerEdgeIds. inline bool S2Builder::StableLessThan( const Edge& a, const Edge& b, const LayerEdgeId& ai, const LayerEdgeId& bi) { // The compiler doesn't optimize this as well as it should: // return std::make_pair(a, ai) < std::make_pair(b, bi); if (a.first < b.first) return true; if (b.first < a.first) return false; if (a.second < b.second) return true; if (b.second < a.second) return false; return ai < bi; // Stable sort. } S2Builder::EdgeChainSimplifier::EdgeChainSimplifier( const S2Builder& builder, const Graph& g, const vector& edge_layers, const vector>& site_vertices, vector>* layer_edges, vector>* layer_input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon) : builder_(builder), g_(g), in_(g), out_(g), edge_layers_(edge_layers), site_vertices_(site_vertices), layer_edges_(layer_edges), layer_input_edge_ids_(layer_input_edge_ids), input_edge_id_set_lexicon_(input_edge_id_set_lexicon), layer_begins_(builder_.layer_begins_), is_interior_(g.num_vertices()), used_(g.num_edges()), // See `AddExtraSites` for explanation of `bucket_count`. tmp_vertex_set_(/*bucket_count=*/18) { new_edges_.reserve(g.num_edges()); new_input_edge_ids_.reserve(g.num_edges()); new_edge_layers_.reserve(g.num_edges()); } void S2Builder::EdgeChainSimplifier::Run() { // Determine which vertices can be interior vertices of an edge chain. for (VertexId v = 0; v < g_.num_vertices(); ++v) { is_interior_[v] = IsInterior(v); } // Attempt to simplify all edge chains that start from a non-interior // vertex. (This takes care of all chains except loops.) for (EdgeId e = 0; e < g_.num_edges(); ++e) { if (used_[e]) continue; Edge edge = g_.edge(e); if (is_interior_[edge.first]) continue; if (!is_interior_[edge.second]) { OutputEdge(e); // An edge between two non-interior vertices. } else { SimplifyChain(edge.first, edge.second); } } // If there are any edges left, they form one or more disjoint loops where // all vertices are interior vertices. // // TODO(ericv): It would be better to start from the edge with the smallest // min_input_edge_id(), since that would make the output more predictable // for testing purposes. It also means that we won't create an edge that // spans the start and end of a polyline if the polyline is snapped into a // loop. (Unfortunately there are pathological examples that prevent us // from guaranteeing this in general, e.g. there could be two polylines in // different layers that snap to the same loop but start at different // positions. In general we only consider input edge ids to be a hint // towards the preferred output ordering.) for (EdgeId e = 0; e < g_.num_edges(); ++e) { if (used_[e]) continue; Edge edge = g_.edge(e); if (edge.first == edge.second) { // Note that it is safe to output degenerate edges as we go along, // because this vertex has at least one non-degenerate outgoing edge and // therefore we will (or just did) start an edge chain here. OutputEdge(e); } else { SimplifyChain(edge.first, edge.second); } } // TODO(ericv): The graph is not needed past here, so we could save some // memory by clearing the underlying Edge and InputEdgeIdSetId vectors. // Finally, copy the output edges into the appropriate layers. They don't // need to be sorted because the input edges were also unsorted. for (size_t e = 0; e < new_edges_.size(); ++e) { int layer = new_edge_layers_[e]; (*layer_edges_)[layer].push_back(new_edges_[e]); (*layer_input_edge_ids_)[layer].push_back(new_input_edge_ids_[e]); } } // Copies the given edge to the output and marks it as used. inline void S2Builder::EdgeChainSimplifier::OutputEdge(EdgeId e) { new_edges_.push_back(g_.edge(e)); new_input_edge_ids_.push_back(g_.input_edge_id_set_id(e)); new_edge_layers_.push_back(edge_layers_[e]); used_[e] = true; } // Returns the layer that a given graph edge belongs to. inline int S2Builder::EdgeChainSimplifier::graph_edge_layer(EdgeId e) const { return edge_layers_[e]; } // Returns the layer than a given input edge belongs to. int S2Builder::EdgeChainSimplifier::input_edge_layer(InputEdgeId id) const { // NOTE(ericv): If this method shows up in profiling, the result could be // stored with each edge (i.e., edge_layers_ and new_edge_layers_). ABSL_DCHECK_GE(id, 0); return (std::upper_bound(layer_begins_.begin(), layer_begins_.end(), id) - (layer_begins_.begin() + 1)); } // A helper class for determining whether a vertex can be an interior vertex // of a simplified edge chain. Such a vertex must be adjacent to exactly two // vertices (across all layers combined), and in each layer the number of // incoming edges from one vertex must equal the number of outgoing edges to // the other vertex (in both directions). Furthermore the vertex cannot have // any degenerate edges in a given layer unless it has at least one // non-degenerate edge in that layer as well. (Note that usually there will // not be any degenerate edges at all, since most layer types discard them.) // // The last condition is necessary to prevent the following: suppose that one // layer has a chain ABC and another layer has a degenerate edge BB (with no // other edges incident to B). Then we can't simplify ABC to AC because there // would be no suitable replacement for the edge BB (since the input edge that // mapped to BB can't be replaced by any of the edges AA, AC, or CC without // moving further than snap_radius). class S2Builder::EdgeChainSimplifier::InteriorVertexMatcher { public: // Checks whether "v0" can be an interior vertex of an edge chain. explicit InteriorVertexMatcher(VertexId v0) : v0_(v0) {} // Starts analyzing the edges of a new layer. void StartLayer() { excess_out_ = n0_ = n1_ = n2_ = 0; } // This method should be called for each edge incident to "v0" in a given // layer. (For degenerate edges, it should be called twice.) void Tally(VertexId v, bool outgoing) { excess_out_ += outgoing ? 1 : -1; // outdegree - indegree if (v == v0_) { ++n0_; // Counts both endpoints of each degenerate edge. } else { // We keep track of the total number of edges (incoming or outgoing) // connecting v0 to up to two adjacent vertices. if (v1_ < 0) v1_ = v; if (v1_ == v) { ++n1_; } else { if (v2_ < 0) v2_ = v; if (v2_ == v) { ++n2_; } else { too_many_endpoints_ = true; } } } } // This method should be called after processing the edges for each layer. // It returns true if "v0" is an interior vertex based on the edges so far. bool Matches() const { // We check that there are the same number of incoming and outgoing edges // in each direction by verifying that (1) indegree(v0) == outdegree(v0) // and (2) the total number of edges (incoming and outgoing) to "v1" and // "v2" are equal. We also check the condition on degenerate edges that // is documented above. return (!too_many_endpoints_ && excess_out_ == 0 && n1_ == n2_ && (n0_ == 0 || n1_ > 0)); } private: VertexId v0_ = -1, v1_ = -1, v2_ = -1; int n0_ = 0, n1_ = 0, n2_ = 0; int excess_out_ = 0; // outdegree(v0) - indegree(v0) // Have we seen more than two adjacent vertices? bool too_many_endpoints_ = false; }; // Returns true if VertexId "v" can be an interior vertex of a simplified edge // chain. (See the InteriorVertexMatcher class for what this implies.) bool S2Builder::EdgeChainSimplifier::IsInterior(VertexId v) { // Check a few simple prerequisites. if (out_.degree(v) == 0) return false; if (out_.degree(v) != in_.degree(v)) return false; if (builder_.is_forced(v)) return false; // Keep forced vertices. // Sort the edges so that they are grouped by layer. vector& edges = tmp_edges_; // Avoid allocating each time. edges.clear(); for (EdgeId e : out_.edge_ids(v)) edges.push_back(e); for (EdgeId e : in_.edge_ids(v)) edges.push_back(e); std::sort(edges.begin(), edges.end(), [this](EdgeId x, EdgeId y) { return graph_edge_layer(x) < graph_edge_layer(y); }); // Now feed the edges in each layer to the InteriorVertexMatcher. InteriorVertexMatcher matcher(v); for (auto e = edges.begin(); e != edges.end(); ) { int layer = graph_edge_layer(*e); matcher.StartLayer(); for (; e != edges.end() && graph_edge_layer(*e) == layer; ++e) { Edge edge = g_.edge(*e); if (edge.first == v) matcher.Tally(edge.second, true /*outgoing*/); if (edge.second == v) matcher.Tally(edge.first, false /*outgoing*/); } if (!matcher.Matches()) return false; } return true; } // Follows the edge chain starting with (v0, v1) until either we find a // non-interior vertex or we return to the original vertex v0. At each vertex // we simplify a subchain of edges that is as long as possible. void S2Builder::EdgeChainSimplifier::SimplifyChain(VertexId v0, VertexId v1) { // Avoid allocating "chain" each time by reusing it. vector& chain = tmp_vertices_; // Contains the set of vertices that have either been avoided or added to // the chain so far. This is necessary so that AvoidSites() doesn't try to // avoid vertices that have already been added to the chain. flat_hash_set& used_vertices = tmp_vertex_set_; S2PolylineSimplifier simplifier; VertexId vstart = v0; bool done = false; do { // Simplify a subchain of edges starting with (v0, v1). chain.push_back(v0); used_vertices.insert(v0); simplifier.Init(g_.vertex(v0)); // Note that if the first edge (v0, v1) is longer than the maximum length // allowed for simplification, then AvoidSites() will return false and we // exit the loop below after the first iteration. const bool simplify = AvoidSites(v0, v0, v1, &used_vertices, &simplifier); do { chain.push_back(v1); used_vertices.insert(v1); done = !is_interior_[v1] || v1 == vstart; if (done) break; // Attempt to extend the chain to the next vertex. VertexId vprev = v0; v0 = v1; v1 = FollowChain(vprev, v0); } while (simplify && TargetInputVertices(v0, &simplifier) && AvoidSites(chain[0], v0, v1, &used_vertices, &simplifier) && simplifier.Extend(g_.vertex(v1))); if (chain.size() == 2) { OutputAllEdges(chain[0], chain[1]); // Could not simplify. } else { MergeChain(chain); } // Note that any degenerate edges that were not merged into a chain are // output by EdgeChainSimplifier::Run(). chain.clear(); used_vertices.clear(); } while (!done); } // Given an edge (v0, v1) where v1 is an interior vertex, returns the (unique) // next vertex in the edge chain. S2Builder::Graph::VertexId S2Builder::EdgeChainSimplifier::FollowChain( VertexId v0, VertexId v1) const { ABSL_DCHECK(is_interior_[v1]); for (EdgeId e : out_.edge_ids(v1)) { VertexId v = g_.edge(e).second; if (v != v0 && v != v1) return v; } ABSL_LOG(FATAL) << "Could not find next edge in edge chain"; } // Copies all input edges between v0 and v1 (in both directions) to the output. void S2Builder::EdgeChainSimplifier::OutputAllEdges(VertexId v0, VertexId v1) { for (EdgeId e : out_.edge_ids(v0, v1)) OutputEdge(e); for (EdgeId e : out_.edge_ids(v1, v0)) OutputEdge(e); } // Ensures that the simplified edge passes within "edge_snap_radius" of all // the *input* vertices that snapped to the given vertex "v". bool S2Builder::EdgeChainSimplifier::TargetInputVertices( VertexId v, S2PolylineSimplifier* simplifier) const { for (InputVertexId i : site_vertices_[v]) { if (!simplifier->TargetDisc(builder_.input_vertices_[i], builder_.edge_snap_radius_ca_)) { return false; } } return true; } // Given the starting vertex v0 and last edge (v1, v2) of an edge chain, // restricts the allowable range of angles in order to ensure that all sites // near the edge (v1, v2) are avoided by at least min_edge_vertex_separation. bool S2Builder::EdgeChainSimplifier::AvoidSites( VertexId v0, VertexId v1, VertexId v2, flat_hash_set* used_vertices, S2PolylineSimplifier* simplifier) const { const S2Point& p0 = g_.vertex(v0); const S2Point& p1 = g_.vertex(v1); const S2Point& p2 = g_.vertex(v2); S1ChordAngle r1(p0, p1); S1ChordAngle r2(p0, p2); // The distance from the start of the edge chain must increase monotonically // for each vertex, since we don't want to simplify chains that backtrack on // themselves (we want a parametric approximation, not a geometric one). if (r2 < r1) return false; // We also limit the maximum edge length in order to guarantee that the // simplified edge stays with max_edge_deviation() of all the input edges // that snap to it. if (r2 >= builder_.min_edge_length_to_split_ca_) return false; // Otherwise it is sufficient to consider the nearby sites (edge_sites_) for // a single input edge that snapped to (v1, v2) or (v2, v1). This is // because each edge has a list of all sites within (max_edge_deviation + // min_edge_vertex_separation), and since the output edge is within // max_edge_deviation of all input edges, this list includes all sites // within min_edge_vertex_separation of the output edge. // // Usually there is only one edge to choose from, but it's not much more // effort to choose the edge with the shortest list of edge_sites_. InputEdgeId best = -1; const auto& edge_sites = builder_.edge_sites_; for (EdgeId e : out_.edge_ids(v1, v2)) { for (InputEdgeId id : g_.input_edge_ids(e)) { if (best < 0 || edge_sites[id].size() < edge_sites[best].size()) best = id; } } for (EdgeId e : out_.edge_ids(v2, v1)) { for (InputEdgeId id : g_.input_edge_ids(e)) { if (best < 0 || edge_sites[id].size() < edge_sites[best].size()) best = id; } } ABSL_DCHECK_GE(best, 0); // Because there is at least one outgoing edge. for (VertexId v : edge_sites[best]) { // Sites whose distance from "p0" is at least "r2" are not relevant yet. const S2Point& p = g_.vertex(v); S1ChordAngle r(p0, p); if (r >= r2) continue; // The following test prevents us from avoiding previous vertices of the // edge chain that also happen to be nearby the current edge. (It also // happens to ensure that each vertex is avoided at most once, but this is // just an optimization.) if (!used_vertices->insert(v).second) continue; // We need to figure out whether this site is to the left or right of the // edge chain. For the first edge this is easy. Otherwise, since we are // only considering sites in the radius range (r1, r2), we can do this by // checking whether the site is to the left of the wedge (p0, p1, p2). bool disc_on_left = (v1 == v0) ? (s2pred::Sign(p1, p2, p) > 0) : s2pred::OrderedCCW(p0, p2, p, p1); if (!simplifier->AvoidDisc(p, builder_.min_edge_site_separation_ca_, disc_on_left)) { return false; } } return true; } // Given the vertices in a simplified edge chain, adds the corresponding // simplified edge(s) to the output. Note that (1) the edge chain may exist // in multiple layers, (2) the edge chain may exist in both directions, (3) // there may be more than one copy of an edge chain (in either direction) // within a single layer. void S2Builder::EdgeChainSimplifier::MergeChain( absl::Span vertices) { // Suppose that all interior vertices have M outgoing edges and N incoming // edges. Our goal is to group the edges into M outgoing chains and N // incoming chains, and then replace each chain by a single edge. vector> merged_input_ids; vector degenerate_ids; int num_out; // Edge count in the outgoing direction. for (size_t i = 1; i < vertices.size(); ++i) { VertexId v0 = vertices[i-1]; VertexId v1 = vertices[i]; auto out_edges = out_.edge_ids(v0, v1); auto in_edges = out_.edge_ids(v1, v0); if (i == 1) { // Allocate space to store the input edge ids associated with each edge. num_out = out_edges.size(); merged_input_ids.resize(num_out + in_edges.size()); for (vector& ids : merged_input_ids) { ids.reserve(vertices.size() - 1); } } else { // For each interior vertex, we build a list of input edge ids // associated with degenerate edges. Each input edge ids will be // assigned to one of the output edges later. (Normally there are no // degenerate edges at all since most layer types don't want them.) ABSL_DCHECK(is_interior_[v0]); for (EdgeId e : out_.edge_ids(v0, v0)) { for (InputEdgeId id : g_.input_edge_ids(e)) { degenerate_ids.push_back(id); } used_[e] = true; } } // Because the edges were created in layer order, and all sorts used are // stable, the edges are still in layer order. Therefore we can simply // merge together all the edges in the same relative position. int j = 0; for (EdgeId e : out_edges) { for (InputEdgeId id : g_.input_edge_ids(e)) { merged_input_ids[j].push_back(id); } used_[e] = true; ++j; } for (EdgeId e : in_edges) { for (InputEdgeId id : g_.input_edge_ids(e)) { merged_input_ids[j].push_back(id); } used_[e] = true; ++j; } ABSL_DCHECK_EQ(merged_input_ids.size(), j); } if (!degenerate_ids.empty()) { std::sort(degenerate_ids.begin(), degenerate_ids.end()); AssignDegenerateEdges(degenerate_ids, &merged_input_ids); } // Output the merged edges. VertexId v0 = vertices[0], v1 = vertices[1], vb = vertices.back(); for (EdgeId e : out_.edge_ids(v0, v1)) { new_edges_.push_back(Edge(v0, vb)); new_edge_layers_.push_back(graph_edge_layer(e)); } for (EdgeId e : out_.edge_ids(v1, v0)) { new_edges_.push_back(Edge(vb, v0)); new_edge_layers_.push_back(graph_edge_layer(e)); } for (const auto& ids : merged_input_ids) { new_input_edge_ids_.push_back(input_edge_id_set_lexicon_->Add(ids)); } } // Given a list of the input edge ids associated with degenerate edges in the // interior of an edge chain, assigns each input edge id to one of the output // edges. void S2Builder::EdgeChainSimplifier::AssignDegenerateEdges( absl::Span degenerate_ids, vector>* merged_ids) const { // Each degenerate edge is assigned to an output edge in the appropriate // layer. If there is more than one candidate, we use heuristics so that if // the input consists of a chain of edges provided in consecutive order // (some of which became degenerate), then all those input edges are // assigned to the same output edge. For example, suppose that one output // edge is labeled with input edges 3,4,7,8, while another output edge is // labeled with input edges 50,51,54,57. Then if we encounter degenerate // edges labeled with input edges 5 and 6, we would prefer to assign them to // the first edge (yielding the continuous range 3,4,5,6,7,8). // // The heuristic below is only smart enough to handle the case where the // candidate output edges have non-overlapping ranges of input edges. // (Otherwise there is probably not a good heuristic for assigning the // degenerate edges in any case.) // Duplicate edge ids don't affect the heuristic below, so we don't bother // removing them. (They will be removed by IdSetLexicon::Add.) for (auto& ids : *merged_ids) std::sort(ids.begin(), ids.end()); // Sort the output edges by their minimum input edge id. This is sufficient // for the purpose of determining which layer they belong to. With // EdgeType::UNDIRECTED, some edges might not have any input edge ids (i.e., // if they consist entirely of siblings of input edges). We simply remove // such edges from the lists of candidates. vector order; order.reserve(merged_ids->size()); for (size_t i = 0; i < merged_ids->size(); ++i) { if (!(*merged_ids)[i].empty()) order.push_back(i); } std::sort(order.begin(), order.end(), [&merged_ids](int i, int j) { return (*merged_ids)[i][0] < (*merged_ids)[j][0]; }); // Now determine where each degenerate edge should be assigned. for (InputEdgeId degenerate_id : degenerate_ids) { int layer = input_edge_layer(degenerate_id); // Find the first output edge whose range of input edge ids starts after // "degenerate_id". If the previous edge belongs to the correct layer, // then we assign the degenerate edge to it. auto it = std::upper_bound(order.begin(), order.end(), degenerate_id, [&merged_ids](InputEdgeId x, unsigned y) { return x < (*merged_ids)[y][0]; }); if (it != order.begin()) { if ((*merged_ids)[it[-1]][0] >= layer_begins_[layer]) --it; } ABSL_DCHECK_EQ(layer, input_edge_layer((*merged_ids)[it[0]][0])); (*merged_ids)[it[0]].push_back(degenerate_id); } } /////////////////////// S2Builder::MemoryTracker ///////////////////////// // Called to track memory used to store the set of sites near a given edge. bool S2Builder::MemoryTracker::TallyEdgeSites( const compact_array& sites) { int64_t size = GetCompactArrayAllocBytes(sites); edge_sites_bytes_ += size; return Tally(size); } // Ensures that "sites" contains space for at least one more edge site. bool S2Builder::MemoryTracker::ReserveEdgeSite(compact_array* sites) { int64_t new_size = sites->size() + 1; if (new_size <= sites->capacity()) return true; int64_t old_bytes = GetCompactArrayAllocBytes(*sites); sites->reserve(new_size); int64_t added_bytes = GetCompactArrayAllocBytes(*sites) - old_bytes; edge_sites_bytes_ += added_bytes; return Tally(added_bytes); } // Releases and tracks the memory used to store nearby edge sites. bool S2Builder::MemoryTracker::ClearEdgeSites( vector>* edge_sites) { Tally(-edge_sites_bytes_); edge_sites_bytes_ = 0; return Clear(edge_sites); } // Called when a site is added to the S2PointIndex. bool S2Builder::MemoryTracker::TallyIndexedSite() { // S2PointIndex stores its data in a btree. In general btree nodes are only // guaranteed to be half full, but in our case all nodes are full except for // the rightmost node at each btree level because the values are added in // sorted order. int64_t delta_bytes = GetBtreeMinBytesPerEntry< absl::btree_multimap::PointData>>(); site_index_bytes_ += delta_bytes; return Tally(delta_bytes); } // Corrects the approximate S2PointIndex memory tracking done above. bool S2Builder::MemoryTracker::FixSiteIndexTally( const S2PointIndex& index) { int64_t delta_bytes = index.SpaceUsed() - site_index_bytes_; site_index_bytes_ += delta_bytes; return Tally(delta_bytes); } // Tracks memory due to destroying the site index. bool S2Builder::MemoryTracker::DoneSiteIndex( const S2PointIndex& index) { Tally(-site_index_bytes_); site_index_bytes_ = 0; return ok(); } // Called to indicate that edge simplification was requested. // LINT.IfChange(TallySimplifyEdgeChains) bool S2Builder::MemoryTracker::TallySimplifyEdgeChains( absl::Span> site_vertices, absl::Span> layer_edges) { if (!is_active()) return true; // The simplify_edge_chains() option uses temporary memory per site // (output vertex) and per output edge, as outlined below. // // Per site: // vector> site_vertices; // BuildLayerEdges // - compact_array non-inlined space is tallied separately // vector is_interior_; // EdgeChainSimplifier // Graph::VertexInMap in_; // EdgeChainSimplifier // Graph::VertexOutMap out_; // EdgeChainSimplifier const int64_t kTempPerSite = sizeof(compact_array) + sizeof(bool) + 2 * sizeof(EdgeId); // Per output edge: // vector used_; // EdgeChainSimplifier // Graph::VertexInMap in_; // EdgeChainSimplifier // vector merged_edges; // SimplifyEdgeChains // vector merged_input_edge_ids; // SimplifyEdgeChains // vector merged_edge_layers; // SimplifyEdgeChains // vector new_edges_; // EdgeChainSimplifier // vector new_input_edge_ids_; // EdgeChainSimplifier // vector new_edge_layers_; // EdgeChainSimplifier // // Note that the temporary vector in MergeLayerEdges() does not // affect peak usage. const int64_t kTempPerEdge = sizeof(bool) + sizeof(EdgeId) + 2 * sizeof(Edge) + 2 * sizeof(InputEdgeIdSetId) + 2 * sizeof(int); int64_t simplify_bytes = site_vertices.size() * kTempPerSite; for (const auto& array : site_vertices) { simplify_bytes += GetCompactArrayAllocBytes(array); } for (const auto& edges : layer_edges) { simplify_bytes += edges.size() * kTempPerEdge; } return TallyTemp(simplify_bytes); } // LINT.ThenChange() // Tracks the temporary memory used by Graph::FilterVertices. // LINT.IfChange(TallyFilterVertices) bool S2Builder::MemoryTracker::TallyFilterVertices( int num_sites, absl::Span> layer_edges) { if (!is_active()) return true; // Vertex filtering (see BuildLayers) uses temporary space of one VertexId // per Voronoi site plus 2 VertexIds per layer edge, plus space for all the // vertices after filtering. // // vector *tmp; // Graph::FilterVertices // vector used; // Graph::FilterVertices const int64_t kTempPerSite = sizeof(Graph::VertexId); const int64_t kTempPerEdge = 2 * sizeof(Graph::VertexId); size_t max_layer_edges = 0; for (const auto& edges : layer_edges) { max_layer_edges = max(max_layer_edges, edges.size()); } filter_vertices_bytes_ = (num_sites * kTempPerSite + max_layer_edges * kTempPerEdge); return Tally(filter_vertices_bytes_); } // LINT.ThenChange() bool S2Builder::MemoryTracker::DoneFilterVertices() { Tally(-filter_vertices_bytes_); filter_vertices_bytes_ = 0; return ok(); } src/s2/s2builder.h000066400000000000000000001665661524103652300142620ustar00rootroot00000000000000// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) // // This class is a replacement for S2PolygonBuilder. Once all clients have // been updated to use this class, S2PolygonBuilder will be removed. #ifndef S2_S2BUILDER_H_ #define S2_S2BUILDER_H_ #include #include #include #include #include #include #include "absl/base/macros.h" #include "absl/base/nullability.h" #include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/types/span.h" #include "s2/_fp_contract_off.h" // IWYU pragma: keep #include "s2/id_set_lexicon.h" #include "s2/mutable_s2shape_index.h" #include "s2/s1angle.h" #include "s2/s1chord_angle.h" #include "s2/s2cell_id.h" #include "s2/s2edge_crossings.h" #include "s2/s2edge_distances.h" #include "s2/s2error.h" #include "s2/s2memory_tracker.h" #include "s2/s2point.h" #include "s2/s2point_index.h" #include "s2/s2point_span.h" #include "s2/s2shape.h" #include "s2/s2shape_index.h" #include "s2/util/gtl/compact_array.h" class S2Loop; class S2Polygon; class S2Polyline; // S2Builder is a tool for assembling polygonal geometry from edges. Here are // some of the things it is designed for: // // 1. Building polygons, polylines, and polygon meshes from unsorted // collections of edges. // // 2. Snapping geometry to discrete representations (such as S2CellId centers // or E7 lat/lng coordinates) while preserving the input topology and with // guaranteed error bounds. // // 3. Simplifying geometry (e.g. for indexing, display, or storage). // // 4. Importing geometry from other formats, including repairing geometry // that has errors. // // 5. As a tool for implementing more complex operations such as polygon // intersections and unions. // // The implementation is based on the framework of "snap rounding". Unlike // most snap rounding implementations, S2Builder defines edges as geodesics on // the sphere (straight lines) and uses the topology of the sphere (i.e., // there are no "seams" at the poles or 180th meridian). The algorithm is // designed to be 100% robust for arbitrary input geometry. It offers the // following properties: // // - Guaranteed bounds on how far input vertices and edges can move during // the snapping process (i.e., at most the given "snap_radius"). // // - Guaranteed minimum separation between edges and vertices other than // their endpoints (similar to the goals of Iterated Snap Rounding). In // other words, edges that do not intersect in the output are guaranteed // to have a minimum separation between them. // // - Idempotency (similar to the goals of Stable Snap Rounding), i.e. if the // input already meets the output criteria then it will not be modified. // // - Preservation of the input topology (up to the creation of // degeneracies). This means that there exists a continuous deformation // from the input to the output such that no vertex crosses an edge. In // other words, self-intersections won't be created, loops won't change // orientation, etc. // // - The ability to snap to arbitrary discrete point sets (such as S2CellId // centers, E7 lat/lng points on the sphere, or simply a subset of the // input vertices), rather than being limited to an integer grid. // // Here are some of its other features: // // - It can handle both directed and undirected edges. Undirected edges can // be useful for importing data from other formats, e.g. where loops have // unspecified orientations. // // - It can eliminate self-intersections by finding all edge pairs that cross // and adding a new vertex at each intersection point. // // - It can simplify polygons to within a specified tolerance. For example, // if two vertices are close enough they will be merged, and if an edge // passes nearby a vertex then it will be rerouted through that vertex. // Optionally, it can also detect nearly straight chains of short edges and // replace them with a single long edge, while maintaining the same // accuracy, separation, and topology guarantees ("simplify_edge_chains"). // // - It supports many different output types through the concept of "layers" // (polylines, polygons, polygon meshes, etc). You can build multiple // layers at once in order to ensure that snapping does not create // intersections between different objects (for example, you can simplify a // set of contour lines without the risk of having them cross each other). // // - It supports edge labels, which allow you to attach arbitrary information // to edges and have it preserved during the snapping process. (This can // also be achieved using layers, at a coarser level of granularity.) // // Caveats: // // - Because S2Builder only works with edges, it cannot distinguish between // the empty and full polygons. If your application can generate both the // empty and full polygons, you must implement logic outside of this class. // // Example showing how to snap a polygon to E7 coordinates: // // using s2builderutil::IntLatLngSnapFunction; // S2Builder builder(S2Builder::Options(IntLatLngSnapFunction(7))); // S2Polygon output; // builder.StartLayer(std::make_unique(&output)); // builder.AddPolygon(input); // S2Error error; // if (!builder.Build(&error)) { // ABSL_LOG(ERROR) << error; // ... // } class S2Builder { public: // Indicates whether the input edges are undirected. Typically this is // specified for each output layer (e.g., s2builderutil::S2PolygonLayer). // // Directed edges are preferred, since otherwise the output is ambiguous. // For example, output polygons may be the *inverse* of the intended result // (e.g., a polygon intended to represent the world's oceans may instead // represent the world's land masses). Directed edges are also somewhat // more efficient. // // However even with undirected edges, most S2Builder layer types try to // preserve the input edge direction whenever possible. Generally, edges // are reversed only when it would yield a simpler output. For example, // S2PolygonLayer assumes that polygons created from undirected edges should // cover at most half of the sphere. Similarly, S2PolylineVectorLayer // assembles edges into as few polylines as possible, even if this means // reversing some of the "undirected" input edges. // // For shapes with interiors, directed edges should be oriented so that the // interior is to the left of all edges. This means that for a polygon with // holes, the outer loops ("shells") should be directed counter-clockwise // while the inner loops ("holes") should be directed clockwise. Note that // S2Builder::AddPolygon() follows this convention automatically. enum class EdgeType : uint8_t { DIRECTED, UNDIRECTED }; // A SnapFunction restricts the locations of the output vertices. For // example, there are predefined snap functions that require vertices to be // located at S2CellId centers or at E5/E6/E7 coordinates. The SnapFunction // can also specify a minimum spacing between vertices (the "snap radius"). // // A SnapFunction defines the following methods: // // 1. The SnapPoint() method, which snaps a point P to a nearby point (the // "candidate snap site"). Any point may be returned, including P // itself (this is the "identity snap function"). // // 2. "snap_radius", the maximum distance that vertices can move when // snapped. The snap_radius must be at least as large as the maximum // distance between P and SnapPoint(P) for any point P. // // Note that the maximum distance that edge interiors can move when // snapped is slightly larger than "snap_radius", and is returned by the // function S2Builder::Options::max_edge_deviation() (see there for // details). // // 3. "min_vertex_separation", the guaranteed minimum distance between // vertices in the output. This is generally a fraction of // "snap_radius" where the fraction depends on the snap function. // // 4. "min_edge_vertex_separation", the guaranteed minimum distance between // edges and non-incident vertices in the output. This is generally a // fraction of "snap_radius" where the fraction depends on the snap // function. // // It is important to note that SnapPoint() does not define the actual // mapping from input vertices to output vertices, since the points it // returns (the candidate snap sites) are further filtered to ensure that // they are separated by at least the snap radius. For example, if you // specify E7 coordinates (2cm resolution) and a snap radius of 10m, then a // subset of points returned by SnapPoint will be chosen (the "snap sites"), // and each input vertex will be mapped to the closest site. Therefore you // cannot assume that P is necessarily snapped to SnapPoint(P). // // S2Builder makes the following guarantees: // // 1. Every vertex is at a location returned by SnapPoint(). // // 2. Vertices are within "snap_radius" of the corresponding input vertex. // // 3. Edges are within "max_edge_deviation" of the corresponding input edge // (a distance slightly larger than "snap_radius"). // // 4. Vertices are separated by at least "min_vertex_separation" // (a fraction of "snap_radius" that depends on the snap function). // // 5. Edges and non-incident vertices are separated by at least // "min_edge_vertex_separation" (a fraction of "snap_radius"). // // 6. Vertex and edge locations do not change unless one of the conditions // above is not already met (idempotency / stability). // // 7. The topology of the input geometry is preserved (up to the creation // of degeneracies). This means that there exists a continuous // deformation from the input to the output such that no vertex // crosses an edge. class SnapFunction { public: virtual ~SnapFunction() = default; // The maximum distance that vertices can move when snapped. The snap // radius can be any value between zero and SnapFunction::kMaxSnapRadius(). // // If the snap radius is zero, then vertices are snapped together only if // they are identical. Edges will not be snapped to any vertices other // than their endpoints, even if there are vertices whose distance to the // edge is zero, unless split_crossing_edges() is true (see below). // // REQUIRES: snap_radius() <= kMaxSnapRadius virtual S1Angle snap_radius() const = 0; // The maximum supported snap radius (equivalent to about 7800km). static S1Angle kMaxSnapRadius(); // The guaranteed minimum distance between vertices in the output. // This is generally some fraction of "snap_radius". virtual S1Angle min_vertex_separation() const = 0; // The guaranteed minimum spacing between edges and non-incident vertices // in the output. This is generally some fraction of "snap_radius". virtual S1Angle min_edge_vertex_separation() const = 0; // Returns a candidate snap site for the given point. The final vertex // locations are a subset of the snap sites returned by this function // (spaced at least "min_vertex_separation" apart). // // The only requirement is that SnapPoint(x) must return a point whose // distance from "x" is no greater than "snap_radius". virtual S2Point SnapPoint(const S2Point& point) const = 0; // Returns a deep copy of this SnapFunction. virtual std::unique_ptr Clone() const = 0; }; class Options { public: Options(); // Convenience constructor that calls set_snap_function(). explicit Options(const SnapFunction& snap_function); // Sets the desired snap function. The snap function is copied // internally, so you can safely pass a temporary object. // // Note that if your input data includes vertices that were created using // S2::GetIntersection(), then you should use a "snap_radius" of // at least S2::kIntersectionMergeRadius, e.g. by calling // // options.set_snap_function(s2builderutil::IdentitySnapFunction( // S2::kIntersectionMergeRadius)); // // DEFAULT: s2builderutil::IdentitySnapFunction(S1Angle::Zero()) // [This does no snapping and preserves all input vertices exactly.] const SnapFunction& snap_function() const; void set_snap_function(const SnapFunction& snap_function); // The maximum distance from snapped edge vertices to the original edge. // This is the same as snap_function().snap_radius() except when // split_crossing_edges() is true (see below), in which case the edge snap // radius is increased by S2::kIntersectionError. S1Angle edge_snap_radius() const; // The maximum distance that any point along an edge can move when snapped. // It is slightly larger than edge_snap_radius() because when a geodesic // edge is snapped, the edge center moves further than its endpoints. // S2Builder ensures that this distance is at most 10% larger than // edge_snap_radius(). S1Angle max_edge_deviation() const; // If true, then detect all pairs of crossing edges and eliminate them by // adding a new vertex at their intersection point. See also the // AddIntersection() method which allows intersection points to be added // selectively. // // When this option is true, intersection_tolerance() is automatically set // to a minimum of S2::kIntersectionError (see intersection_tolerance() // for why this is necessary). Note that this means that edges can move // by up to S2::kIntersectionError even when the specified snap radius is // zero. The exact distance that edges can move is always given by // max_edge_deviation() defined above. // // Undirected edges should always be used when the output is a polygon, // since splitting a directed loop at a self-intersection converts it into // two loops that don't define a consistent interior according to the // "interior is on the left" rule. (On the other hand, it is fine to use // directed edges when defining a polygon *mesh* because in that case the // input consists of sibling edge pairs.) // // Self-intersections can also arise when importing data from a 2D // projection. You can minimize this problem by subdividing the input // edges so that the S2 edges (which are geodesics) stay close to the // original projected edges (which are curves on the sphere). This can // be done using S2EdgeTessellator, for example. // // DEFAULT: false bool split_crossing_edges() const; void set_split_crossing_edges(bool split_crossing_edges); // Specifies the maximum allowable distance between a vertex added by // AddIntersection() and the edge(s) that it is intended to snap to. This // method must be called before AddIntersection() can be used. It has the // effect of increasing the snap radius for edges (but not vertices) by // the given distance. // // The intersection tolerance should be set to the maximum error in the // intersection calculation used. For example, if S2::GetIntersection() // is used then the error should be set to S2::kIntersectionError. If // S2::GetPointOnLine() is used then the error should be set to // S2::kGetPointOnLineError. If S2::Project() is used then the error // should be set to S2::kProjectPerpendicularError. If more than one // method is used then the intersection tolerance should be set to the // maximum such error. // // The reason this option is necessary is that computed intersection // points are not exact. For example, S2::GetIntersection(a, b, c, d) // returns a point up to S2::kIntersectionError away from the true // mathematical intersection of the edges AB and CD. Furthermore such // intersection points are subject to further snapping in order to ensure // that no pair of vertices is closer than the specified snap radius. For // example, suppose the computed intersection point X of edges AB and CD // is 1 nanonmeter away from both edges, and the snap radius is 1 meter. // In that case X might snap to another vertex Y exactly 1 meter away, // which would leave us with a vertex Y that could be up to 1.000000001 // meters from the edges AB and/or CD. This means that AB and/or CD might // not snap to Y leaving us with two edges that still cross each other. // // However if the intersection tolerance is set to 1 nanometer then the // snap radius for edges is increased to 1.000000001 meters ensuring that // both edges snap to a common vertex even in this worst case. (This // technique does not work if the vertex snap radius is increased as well; // it requires edges and vertices to be handled differently.) // // Note that this option allows edges to move by up to the given // intersection tolerance even when the snap radius is zero. The exact // distance that edges can move is always given by max_edge_deviation() // defined above. // // When split_crossing_edges() is true, the intersection tolerance is // automatically set to a minimum of S2::kIntersectionError. A larger // value can be specified by calling this method explicitly. // // DEFAULT: S1Angle::Zero() S1Angle intersection_tolerance() const; void set_intersection_tolerance(S1Angle intersection_tolerance); // If true, then simplify the output geometry by replacing nearly straight // chains of short edges with a single long edge. // // The combined effect of snapping and simplifying will not change the // input by more than the guaranteed tolerances (see the list documented // with the SnapFunction class). For example, simplified edges are // guaranteed to pass within snap_radius() of the *original* positions of // all vertices that were removed from that edge. This is a much tighter // guarantee than can be achieved by snapping and simplifying separately. // // However, note that this option does not guarantee idempotency. In // other words, simplifying geometry that has already been simplified once // may simplify it further. (This is unavoidable, since tolerances are // measured with respect to the original geometry, which is no longer // available when the geometry is simplified a second time.) // // When the output consists of multiple layers, simplification is // guaranteed to be consistent: for example, edge chains are simplified in // the same way across layers, and simplification preserves topological // relationships between layers (e.g., no crossing edges will be created). // Note that edge chains in different layers do not need to be identical // (or even have the same number of vertices, etc) in order to be // simplified together. All that is required is that they are close // enough together so that the same simplified edge can meet all of their // individual snapping guarantees. // // Note that edge chains are approximated as parametric curves rather than // point sets. This means that if an edge chain backtracks on itself (for // example, ABCDEFEDCDEFGH) then such backtracking will be preserved to // within snap_radius() (for example, if the preceding point were all in a // straight line then the edge chain would be simplified to ACFCFH, noting // that C and F have degree > 2 and therefore can't be simplified away). // // Simplified edges are assigned all labels associated with the edges of // the simplified chain. // // For this option to have any effect, a SnapFunction with a non-zero // snap_radius() must be specified. Also note that vertices specified // using ForceVertex are never simplified away. // // DEFAULT: false bool simplify_edge_chains() const; void set_simplify_edge_chains(bool simplify_edge_chains); // If true, then snapping occurs only when the input geometry does not // already meet the S2Builder output guarantees (see the SnapFunction // class description for details). This means that if all input vertices // are at snapped locations, all vertex pairs are separated by at least // min_vertex_separation(), and all edge-vertex pairs are separated by at // least min_edge_vertex_separation(), then no snapping is done. // // If false, then all vertex pairs and edge-vertex pairs closer than // "snap_radius" will be considered for snapping. This can be useful, for // example, if you know that your geometry contains errors and you want to // make sure that features closer together than "snap_radius" are merged. // // This option is automatically turned off by simplify_edge_chains(), // since simplifying edge chains is never guaranteed to be idempotent. // // DEFAULT: true bool idempotent() const; void set_idempotent(bool idempotent); // Specifies that internal memory usage should be tracked using the given // S2MemoryTracker. If a memory limit is specified and more more memory // than this is required then an error will be returned. Example usage: // // S2MemoryTracker tracker; // tracker.set_limit(500 << 20); // 500 MB // S2Builder::Options options; // options.set_memory_tracker(&tracker); // S2Builder builder{options}; // ... // S2Error error; // if (!builder.Build(&error)) { // if (error.code() == S2Error::RESOURCE_EXHAUSTED) { // ABSL_LOG(ERROR) << error; // Memory limit exceeded // } // } // // CAVEATS: // // - Memory allocated by the output S2Builder layers is not tracked. // // - While memory tracking is reasonably complete and accurate, it does // not account for every last byte. It is intended only for the // purpose of preventing clients from running out of memory. // // DEFAULT: nullptr (memory tracking disabled) S2MemoryTracker* memory_tracker() const; void set_memory_tracker(S2MemoryTracker* tracker); // Options may be assigned and copied. Options(const Options& options); Options& operator=(const Options& options); private: std::unique_ptr snap_function_; bool split_crossing_edges_ = false; S1Angle intersection_tolerance_ = S1Angle::Zero(); bool simplify_edge_chains_ = false; bool idempotent_ = true; S2MemoryTracker* memory_tracker_ = nullptr; }; class Graph; // The following classes are only needed by Layer implementations. class GraphOptions; // For output layers that represent polygons, there is an ambiguity inherent // in spherical geometry that does not exist in planar geometry. Namely, if // a polygon has no edges, does it represent the empty polygon (containing // no points) or the full polygon (containing all points)? This ambiguity // also occurs for polygons that consist only of degeneracies, e.g. a // degenerate loop with only two edges could be either a degenerate shell in // the empty polygon or a degenerate hole in the full polygon. // // To resolve this ambiguity, an IsFullPolygonPredicate may be specified for // each output layer (see AddIsFullPolygonPredicate below). If the output // after snapping consists only of degenerate edges and/or sibling pairs // (including the case where there are no edges at all), then the layer // implementation calls the given predicate to determine whether the polygon // is empty or full except for those degeneracies. The predicate is given // an S2Builder::Graph containing the output edges, but note that in general // the predicate must also have knowledge of the input geometry in order to // determine the correct result. // // This predicate is only needed by layers that are assembled into polygons. // It is not used by other layer types. using IsFullPolygonPredicate = std::function; // Default constructor; requires Init() to be called. S2Builder(); // Convenience constructor that calls Init(). Note that to use the default // options, C++ syntax requires an extra layer of parentheses: // // S2Builder builder{S2Builder::Options()}; explicit S2Builder(const Options& options); // Initializes an S2Builder with the given options. void Init(const Options& options); const Options& options() const { return options_; } // Starts a new output layer. This method must be called before adding any // edges to the S2Builder. You may call this method multiple times to build // multiple geometric objects that are snapped to the same set of sites. // // For example, if you have a set of contour lines, then you could put each // contour line in a separate layer. This keeps the contour lines separate // from each other, while also ensuring that no crossing edges are created // when they are snapped and/or simplified. (This is not true if the // contour lines are snapped or simplified independently.) // // Similarly, if you have a set of polygons that share common boundaries // (e.g., countries), you can snap and/or simplify them at the same time by // putting them in different layers, while ensuring that their boundaries // remain consistent (i.e., no crossing edges or T-vertices are introduced). // // Ownership of the layer is transferred to the S2Builder. Example usage: // // S2Polyline line1, line2; // builder.StartLayer(make_unique(&line1))); // ... Add edges using builder.AddEdge(), etc ... // builder.StartLayer(make_unique(&line2))); // ... Add edges using builder.AddEdge(), etc ... // S2Error error; // ABSL_CHECK(builder.Build(&error)) << error; // Builds "line1" & "line2" class Layer; void StartLayer(std::unique_ptr layer); // Adds a degenerate edge (representing a point) to the current layer. void AddPoint(const S2Point& v); // Adds the given edge to the current layer. void AddEdge(const S2Point& v0, const S2Point& v1); // Adds the edges in the given polyline to the current layer. Note that // polylines with 0 or 1 vertices are defined to have no edges. void AddPolyline(S2PointSpan polyline); void AddPolyline(const S2Polyline& polyline); // Adds the edges in the given loop to the current layer. Note that a loop // consisting of one vertex adds a single degenerate edge. void AddLoop(S2PointLoopSpan loop); // Adds the edges in the given loop to the current layer. Loops with a single // vertex are ignored. // // If the sign() of an S2Loop is negative (i.e. the loop represents a hole // within a polygon), the edge directions are automatically reversed to // ensure that the polygon interior is always to the left of every edge. void AddLoop(const S2Loop& loop); // Adds the loops in the given polygon to the current layer. Loops // representing holes have their edge directions automatically reversed as // described for AddLoop(). Note that this method does not distinguish // between the empty and full polygons, i.e. adding a full polygon has the // same effect as adding an empty one. void AddPolygon(const S2Polygon& polygon); // Adds the edges of the given shape to the current layer. void AddShape(const S2Shape& shape); // If "vertex" is the intersection point of two edges AB and CD (as computed // by S2::GetIntersection()), this method ensures that AB and CD snap to a // common vertex. (Note that the common vertex may be different than // "vertex" in order to ensure that no pair of vertices is closer than the // given snap radius.) Unlike Options::split_crossing_edges(), this method // may be used to split crossing edge pairs selectively. // // This method can also be used to tessellate edges using S2::GetPointOnLine() // or S2::Project() provided that a suitable intersection tolerance is // specified (see intersection_tolerance() for details). // // This method implicitly overrides the idempotent() option, since adding an // intersection point implies a desire to have nearby edges snapped to it // even if these edges already satisfy the S2Builder output guarantees. // (Otherwise for example edges would never be snapped to nearby // intersection points when the snap radius is zero.) // // Note that unlike ForceVertex(), this method maintains all S2Builder // guarantees regarding minimum vertex-vertex separation, minimum // edge-vertex separation, and edge chain simplification. // // REQUIRES: options().intersection_tolerance() > S1Angle::Zero() // REQUIRES: "vertex" was computed by S2::GetIntersection() (in order to // guarantee that both edges snap to a common vertex) void AddIntersection(const S2Point& vertex); // For layers that are assembled into polygons, this method specifies a // predicate that is called when the output consists entirely of degenerate // edges and/or sibling pairs. The predicate is given an S2Builder::Graph // containing the output edges (if any) and is responsible for deciding // whether this graph represents the empty polygon (possibly with degenerate // shells) or the full polygon (possibly with degenerate holes). Note that // this cannot be determined from the output edges alone; it also requires // knowledge of the input geometry. (Also see IsFullPolygonPredicate above.) // // This method should be called at most once per layer; additional calls // simply overwrite the previous value for the current layer. // // The default predicate simply returns false (i.e., degenerate polygons are // assumed to be empty). Arguably it would better to return an error in // this case, but the fact is that relatively few clients need to be able to // construct full polygons, and it is unreasonable to expect all such // clients to supply an appropriate predicate. // // The reason for having a predicate rather than a boolean value is that the // predicate is responsible for determining whether the output polygon is // empty or full. In general the input geometry is not degenerate, but // rather collapses into a degenerate configuration due to snapping and/or // simplification. // // TODO(ericv): Provide standard predicates to handle common cases, // e.g. valid input geometry that becomes degenerate due to snapping. void AddIsFullPolygonPredicate(IsFullPolygonPredicate predicate); // A predicate that returns an error indicating that no polygon predicate // has been specified. static bool IsFullPolygonUnspecified(const S2Builder::Graph& g, S2Error* absl_nonnull error); // Returns a predicate that returns a constant value (true or false); static IsFullPolygonPredicate IsFullPolygon(bool is_full); // Forces a vertex to be located at the given position. This can be used to // prevent certain input vertices from moving. However if you are trying to // preserve input edges, be aware that this option does not prevent edges from // being split by new vertices. // // Forced vertices are subject to the following limitations: // // - Forced vertices are never snapped. This is true even when the given // position is not allowed by the given snap function (e.g. you can force // a vertex at a non-S2CellId center when using S2CellIdSnapFunction). // If you want to ensure that forced vertices obey the snap function // restrictions, you must call snap_function().SnapPoint() explicitly. // // - There is no guaranteed minimum separation between pairs of forced // vertices, i.e. snap_function().min_vertex_separation() does not apply. // (This must be true because forced vertices can be placed arbitrarily.) // // - There is no guaranteed minimum separation between forced vertices and // non-incident edges, i.e. snap_function().min_edge_vertex_separation() // does not apply. // // - Forced vertices are never simplified away (i.e. when simplification is // requested using options().simplify_edge_chains()). // // All other guarantees continue to hold, e.g. the input topology will always // be preserved. void ForceVertex(const S2Point& vertex); // Every edge can have a set of non-negative integer labels attached to it. // When used with an appropriate layer type, you can then retrieve the // labels associated with each output edge. This can be useful when merging // or combining data from several sources. (Note that in many cases it is // easier to use separate output layers rather than labels.) // // Labels are 32-bit non-negative integers. To support other label types, // you can use ValueLexicon to store the set of unique labels seen so far: // // ValueLexicon my_label_lexicon; // builder.set_label(my_label_lexicon.Add(label)); // // The current set of labels is represented as a stack. This makes it easy // to add and remove labels hierarchically (e.g., polygon 5, loop 2). Use // set_label() and clear_labels() if you need at most one label per edge. // using Label = int32_t; // Clear the stack of labels. void clear_labels(); // Add a label to the stack. // REQUIRES: label >= 0. void push_label(Label label); // Remove a label from the stack. void pop_label(); // Convenience function that clears the stack and adds a single label. // REQUIRES: label >= 0. void set_label(Label label); // Performs the requested edge splitting, snapping, simplification, etc, and // then assembles the resulting edges into the requested output layers. // // Returns true if all edges were assembled; otherwise sets "error" // appropriately. Depending on the error, some or all output layers may // have been created. Automatically resets the S2Builder state so that it // can be reused. // // REQUIRES: error != nullptr. bool Build(S2Error* absl_nonnull error); // Clears all input data and resets the builder state. Any options // specified are preserved. void Reset(); /////////////////////////////////////////////////////////////////////////// // The following methods may be called at any time, including from // S2Builder::Layer implementations. // Returns the number of input edges. int num_input_edges() const; // Returns the endpoints of the given input edge. // // REQUIRES: 0 <= input_edge_id < num_input_edges() S2Shape::Edge input_edge(int input_edge_id) const; private: ////////////////////// Input Types ///////////////////////// // All types associated with the S2Builder inputs are prefixed with "Input". // Identifies an input vertex. using InputVertexId = int32_t; // Defines an input edge. using InputEdge = std::pair; // Identifies an input edge. using InputEdgeId = int32_t; // Identifies the set of input edge ids that were snapped to a given edge. using InputEdgeIdSetId = int32_t; // Sort key for prioritizing input vertices. (Note that keys are *not* // compared using std::less; see SortInputVertices for details.) using InputVertexKey = std::pair; ////////////////////// Output Types ///////////////////////// // These types define the output vertices and edges. // Identifies a snapped vertex ("snap site"). If there is only one layer, // than SiteId is the same as Graph::VertexId, but if there are many layers // then each Graph may contain only a subset of the sites. Also see // GraphOptions::allow_vertex_filtering(). using SiteId = int32_t; // Defines an output edge. using Edge = std::pair; // Identifies an output edge. using EdgeId = int32_t; // Identifies an output edge in a particular layer. using LayerEdgeId = std::pair; ////////////////////// Internal Types ///////////////////////// class EdgeChainSimplifier; // MemoryTracker is a helper class to measure S2Builder memory usage. It is // based on a detailed analysis of the data structures used. This approach // is fragile because the memory tracking code needs to be updated whenever // S2Builder is modified, however S2Builder has been quite stable and this // approach allows the memory usage to be measured quite accurately. // // CAVEATS: // // - Does not track memory used by edge labels. (It is tricky to do this // accurately because they are stored in an IdSetLexicon, and labels // are typically a tiny fraction of the total space used.) // // - Does not track memory used to represent layers internally. (The // number of layers is typically small compared to the numbers of // vertices and edges, and the amount of memory used by the Layer and // IsFullPolygonPredicate objects is difficult to measure.) // // - Does not track memory used by the output layer Build() methods. (This // includes both temporary space, e.g. due to calling S2Builder::Graph // methods, and also any geometric objects created by these layers.) class MemoryTracker : public S2MemoryTracker::Client { public: bool TallyEdgeSites(const gtl::compact_array& sites); bool ReserveEdgeSite(gtl::compact_array* sites); bool ClearEdgeSites(std::vector>* edge_sites); bool TallyIndexedSite(); bool FixSiteIndexTally(const S2PointIndex& index); bool DoneSiteIndex(const S2PointIndex& index); bool TallySimplifyEdgeChains( absl::Span> site_vertices, absl::Span> layer_edges); bool TallyFilterVertices(int num_sites, absl::Span> layer_edges); bool DoneFilterVertices(); private: // The amount of non-inline memory used to store edge sites. int64_t edge_sites_bytes_ = 0; // The amount of memory used by the S2PointIndex for sites. int64_t site_index_bytes_ = 0; // The amount of temporary memory used by Graph::FilterVertices(). int64_t filter_vertices_bytes_ = 0; }; InputVertexId AddVertex(const S2Point& v); void ChooseSites(); void ChooseAllVerticesAsSites(); std::vector SortInputVertices(); void AddEdgeCrossings(const MutableS2ShapeIndex& input_edge_index); void AddForcedSites(S2PointIndex* site_index); bool is_forced(SiteId v) const; void ChooseInitialSites(S2PointIndex* site_index); S2Point SnapSite(const S2Point& point) const; void CollectSiteEdges(const S2PointIndex& site_index); void SortSitesByDistance(const S2Point& x, gtl::compact_array* sites) const; void InsertSiteByDistance(SiteId new_site_id, const S2Point& x, gtl::compact_array* sites); void AddExtraSites(const MutableS2ShapeIndex& input_edge_index); void MaybeAddExtraSites(InputEdgeId edge_id, absl::Span chain, const MutableS2ShapeIndex& input_edge_index, absl::flat_hash_set* edges_to_resnap); void AddExtraSite(const S2Point& new_site, const MutableS2ShapeIndex& input_edge_index, absl::flat_hash_set* edges_to_resnap); S2Point GetSeparationSite(const S2Point& site_to_avoid, const S2Point& v0, const S2Point& v1, InputEdgeId input_edge_id) const; S2Point GetCoverageEndpoint(const S2Point& p, const S2Point& n) const; void SnapEdge(InputEdgeId e, std::vector* chain) const; void BuildLayers(); void BuildLayerEdges( std::vector>* layer_edges, std::vector>* layer_input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon); void AddSnappedEdges( InputEdgeId begin, InputEdgeId end, const GraphOptions& options, std::vector* edges, std::vector* input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon, std::vector>* site_vertices); void MaybeAddInputVertex( InputVertexId v, SiteId id, std::vector>* site_vertices) const; void AddSnappedEdge(SiteId src, SiteId dst, InputEdgeIdSetId id, EdgeType edge_type, std::vector* edges, std::vector* input_edge_ids) const; void SimplifyEdgeChains( const std::vector>& site_vertices, std::vector>* layer_edges, std::vector>* layer_input_edge_ids, IdSetLexicon* input_edge_id_set_lexicon); void MergeLayerEdges( absl::Span> layer_edges, absl::Span> layer_input_edge_ids, std::vector* edges, std::vector* input_edge_ids, std::vector* edge_layers) const; static bool StableLessThan(const Edge& a, const Edge& b, const LayerEdgeId& ai, const LayerEdgeId& bi); //////////// Parameters ///////////// // S2Builder options. Options options_; // The maximum distance (inclusive) that a vertex can move when snapped, // equal to S1ChordAngle(options_.snap_function().snap_radius()). S1ChordAngle site_snap_radius_ca_; // The maximum distance (inclusive) that an edge can move when snapping to a // snap site. It can be slightly larger than the site snap radius when // edges are being split at crossings. S1ChordAngle edge_snap_radius_ca_; // True if we need to check that snapping has not changed the input topology // around any vertex (i.e. Voronoi site). Normally this is only necessary for // forced vertices, but if the snap radius is very small (e.g., zero) and // split_crossing_edges() is true then we need to do this for all vertices. // In all other situations, any snapped edge that crosses a vertex will also // be closer than min_edge_vertex_separation() to that vertex, which will // cause us to add a separation site anyway. bool check_all_site_crossings_; S1Angle max_edge_deviation_; S1ChordAngle edge_site_query_radius_ca_; S1ChordAngle min_edge_length_to_split_ca_; S1Angle min_site_separation_; S1ChordAngle min_site_separation_ca_; S1ChordAngle min_edge_site_separation_ca_; S1ChordAngle min_edge_site_separation_ca_limit_; S1ChordAngle max_adjacent_site_separation_ca_; // The squared sine of the edge snap radius. This is equivalent to the snap // radius (squared) for distances measured through the interior of the // sphere to the plane containing an edge. This value is used only when // interpolating new points along edges (see GetSeparationSite). double edge_snap_radius_sin2_; // A copy of the argument to Build(). S2Error* absl_nonnull error_; // True if snapping was requested. This is true if either snap_radius() is // positive, or split_crossing_edges() is true (which implicitly requests // snapping to ensure that both crossing edges are snapped to the // intersection point). bool snapping_requested_; // Initially false, and set to true when it is discovered that at least one // input vertex or edge does not meet the output guarantees (e.g., that // vertices are separated by at least snap_function.min_vertex_separation). bool snapping_needed_; //////////// Input Data ///////////// // A flag indicating whether label_set_ has been modified since the last // time label_set_id_ was computed. bool label_set_modified_; std::vector input_vertices_; std::vector input_edges_; std::vector> layers_; std::vector layer_options_; std::vector layer_begins_; std::vector layer_is_full_polygon_predicates_; // Each input edge has "label set id" (an int32_t) representing the set of // labels attached to that edge. This vector is populated only if at least // one label is used. using LabelSetId = int32_t; std::vector label_set_ids_; IdSetLexicon label_set_lexicon_; // The current set of labels (represented as a stack). std::vector::template rebind_alloc; public: typedef T value_type; typedef A allocator_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef uint32_t size_type; typedef ptrdiff_t difference_type; typedef value_type* iterator; typedef const value_type* const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; // Init() replace the default constructors; so it can be used in "union". // This means Init() must be called for every new compact_array_base void Init() noexcept { memset(this, 0, sizeof(*this)); } // Construct an array of size n and initialize the values to v. // Any old contents, if heap-allocated, will be leaked. void Construct(size_type n, const value_type& v = value_type()) { Init(); value_init(n, v); } // See 23.1.1/9 in the C++ standard for an explanation. template void Copy(Iterator first, Iterator last) { Init(); typedef typename std::is_integral::type Int; initialize(first, last, Int()); } void CopyFrom(const compact_array_base& v) { Init(); initialize(v.begin(), v.end(), std::false_type()); } compact_array_base& AssignFrom(const compact_array_base& v) { // Safe for self-assignment, which is rare. // Optimized to use existing allocated space. // Also to use assignment instead of copying where possible. if (size() < v.size()) { // grow reserve(v.size()); std::copy(v.begin(), v.begin() + size(), begin()); insert(end(), v.begin() + size(), v.end()); } else { // maybe shrink erase(begin() + v.size(), end()); std::copy(v.begin(), v.end(), begin()); } return *this; } // Deallocate the whole array. void Destruct() { if (!MayBeInlined() || Array() != InlinedSpace()) { value_allocator_type allocator; allocator.deallocate(Array(), capacity()); } Init(); } // Safe against self-swapping. // copying/destruction of compact_array_base is fairly trivial as the type // was designed to be usable in a C++98 union. void swap(compact_array_base& v) noexcept { compact_array_base tmp = *this; *this = v; v = tmp; } // The number of active items in the array. size_type size() const { return size_; } bool empty() const { return size() == 0; } // Maximum size that this data structure can hold. static constexpr size_type max_size() { return kMaxSize; } static constexpr bool MayBeInlined() { return kInlined > 0; } public: // Container interface (tables 65,66). iterator begin() { return Array(); } iterator end() { return Array() + size(); } const_iterator begin() const { return ConstArray(); } const_iterator end() const { return ConstArray() + size(); } reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(Array()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(ConstArray()); } private: // This Insert() is private because it might return the end(). iterator Insert(const_iterator p, const value_type& v) { if (ABSL_PREDICT_FALSE(size() >= kMaxSize)) { absl::ThrowStdLengthError("compact_array size exceeded"); } iterator r = make_hole(p, 1); *r = v; return r; } public: // Sequence operations, table 67. iterator insert(const_iterator p, const value_type& v) { return Insert(p, v); } void insert(const_iterator p, size_type n, const value_type& v) { if (ABSL_PREDICT_FALSE(n > kMaxSize - size())) { absl::ThrowStdLengthError("compact_array size exceeded"); } value_insert(p, n, v); } // See 23.1.1/9 in the C++ standard for an explanation. template void insert(const_iterator p, Iterator first, Iterator last) { typedef typename std::is_integral::type Int; insert(p, first, last, Int()); } template reference emplace_back(Args&&... args) { return *Insert(end(), value_type(std::forward(args)...)); } template iterator emplace(const_iterator p, Args&&... args) { return Insert(p, value_type(std::forward(args)...)); } iterator erase(const_iterator p) { size_type index = p - begin(); erase_aux(p, 1); return begin() + index; } iterator erase(const_iterator first, const_iterator last) { size_type index = first - begin(); erase_aux(first, last - first); return begin() + index; } // clear just resets the size to 0, without deallocating the storage. // To deallocate the array, use Destruct(). void clear() { set_size(0); } reference front() { return begin()[0]; } const_reference front() const { return begin()[0]; } reference back() { return end()[-1]; } const_reference back() const { return end()[-1]; } void push_back(const value_type& v) { iterator p = make_hole(end(), 1); *p = v; } void pop_back() { erase_aux(end() - 1, 1); } reference operator[](size_type n) { ABSL_HARDENING_ASSERT(n < size_); return Array()[n]; } const_reference operator[](size_type n) const { ABSL_HARDENING_ASSERT(n < size_); return ConstArray()[n]; } reference at(size_type n) { if (ABSL_PREDICT_FALSE(n >= size_)) { absl::ThrowStdOutOfRange("compact_array_base::at"); } return Array()[n]; } const_reference at(size_type n) const { if (ABSL_PREDICT_FALSE(n >= size_)) { absl::ThrowStdOutOfRange("compact_array_base::at"); } return ConstArray()[n]; } // Preallocate the array of size n. Only changes the capacity, not size. void reserve(int n) { reallocate(n); } size_type capacity() const { return is_exponent_ ? (1 << capacity_) : capacity_; } void resize(size_type n) { if (n > capacity()) reserve(n); // resize(n) is the only place in the class that exposes uninitialized // memory as live elements, so call a constructor for each element if // needed. // Destroying elements on shrinking resize isn't a concern, since the // value_type must be trivially destructible. if (n > size() && !absl::is_trivially_default_constructible::value) { // Increasing size would expose unconstructed elements. value_type* new_end = Array() + n; for (value_type* p = Array() + size(); p != new_end; ++p) new (p) value_type(); } set_size(n); } template friend H AbslHashValue(H h, const compact_array_base& v) { return H::combine( H::combine_contiguous(std::move(h), v.ConstArray(), v.size()), v.size()); } private: // Low-level helper functions. void set_size(size_type n) { ABSL_DCHECK_LE(n, capacity()); size_ = n; } void set_capacity(size_type n) { ABSL_DCHECK_LE(size(), n); is_exponent_ = (n >= kExponentStart); capacity_ = is_exponent_ ? absl::bit_width(n - 1) : n; // A tiny optimization here would be to set capacity_ to kInlined if // it's currently less. We don't bother, because doing so would require // changing the existing comments and unittests that say that, for small n, // capacity() will be exactly n if one calls reserve(n). ABSL_DCHECK(n == capacity() || n > kInlined); } // Make capacity n or more. Reallocate and copy data as necessary. void reallocate(size_type n) { size_type old_capacity = capacity(); if (n <= old_capacity) return; size_type new_n = n; if (new_n > kInlined) { new_n = nallocx(n * sizeof(T), 0) / sizeof(T); } set_capacity(new_n); if constexpr (MayBeInlined()) { if (!IsInlined() && n <= kInlined) { SetInlined(); return; } else if (IsInlined()) { if (n > kInlined) { value_allocator_type allocator; value_type* new_array = allocator.allocate(capacity()); memcpy(new_array, InlinedSpace(), size() * sizeof(T)); SetArray(new_array); } return; } } value_allocator_type allocator; T* new_ptr = allocator.allocate(capacity()); if (old_capacity != 0) { memcpy(new_ptr, Array(), old_capacity * sizeof(T)); allocator.deallocate(Array(), old_capacity); } SetArray(new_ptr); } value_type* lastp() { return Array() + size(); } void move(const value_type* first, const value_type* last, value_type* out) { memmove(out, first, (last - first) * sizeof(value_type)); } iterator make_hole(const_iterator p, size_type n) { iterator q = const_cast(p); if (n != 0) { size_type new_size = size() + n; size_type index = q - Array(); reallocate(new_size); q = Array() + index; move(q, Array() + new_size - n, q + n); set_size(new_size); } return q; } void erase_aux(const_iterator p, size_type n) { iterator q = const_cast(p); size_type new_size = size() - n; move(q + n, lastp(), q); reallocate(new_size); set_size(new_size); } private: // Helper functions for range/value. void value_init(size_type n, const value_type& v) { reserve(n); set_size(n); std::fill(Array(), lastp(), v); } template void range_init(InputIter first, InputIter last, std::input_iterator_tag) { for (; first != last; ++first) push_back(*first); } template void range_init(ForwIter first, ForwIter last, std::forward_iterator_tag) { size_type n = std::distance(first, last); reserve(n); set_size(n); std::copy(first, last, Array()); } template void initialize(Integer n, Integer v, std::true_type) { value_init(n, v); } template void initialize(Iterator first, Iterator last, std::false_type) { typedef typename std::iterator_traits::iterator_category Cat; range_init(first, last, Cat()); } void value_insert(const_iterator p, size_type n, const value_type& v) { if (ABSL_PREDICT_FALSE(n > kMaxSize - size())) { absl::ThrowStdLengthError("compact_array size exceeded"); } iterator hole = make_hole(p, n); std::fill(hole, hole + n, v); } template void range_insert(const_iterator p, InputIter first, InputIter last, std::input_iterator_tag) { size_type pos = p - begin(); size_type old_size = size(); for (; first != last; ++first) push_back(*first); std::rotate(begin() + pos, begin() + old_size, end()); } template void range_insert(const_iterator p, ForwIter first, ForwIter last, std::forward_iterator_tag) { size_type n = std::distance(first, last); if (ABSL_PREDICT_FALSE(n > kMaxSize - size())) { absl::ThrowStdLengthError("compact_array size exceeded"); } std::copy(first, last, make_hole(p, n)); } template void insert(const_iterator p, Integer n, Integer v, std::true_type) { value_insert(p, n, v); } template void insert(const_iterator p, Iterator first, Iterator last, std::false_type) { typedef typename std::iterator_traits::iterator_category Cat; range_insert(p, first, last, Cat()); } static_assert(absl::is_trivially_copy_constructible::value && absl::is_trivially_copy_assignable::value && absl::is_trivially_destructible::value, "Requires trivial copy, assignment, and destructor."); }; // Allocates storage for constants in compact_array_base template const int compact_array_base::kSizeNumBits; template const int compact_array_base::kCapacityNumBits; template const int compact_array_base::kMaxSize; template const int compact_array_base::kExponentStart; // compact_array: Wrapper for compact_array_base that provides the // constructors and destructor. template > class compact_array : public compact_array_base { private: typedef compact_array_base Base; public: typedef typename Base::value_type value_type; typedef typename Base::allocator_type allocator_type; typedef typename Base::pointer pointer; typedef typename Base::const_pointer const_pointer; typedef typename Base::reference reference; typedef typename Base::const_reference const_reference; typedef typename Base::size_type size_type; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; compact_array() noexcept(noexcept(std::declval().Init())) { Base::Init(); } explicit compact_array(size_type n) { Base::Construct(n, value_type()); } compact_array(size_type n, const value_type& v) { Base::Construct(n, v); } // See 23.1.1/9 in the C++ standard for an explanation. template compact_array(Iterator first, Iterator last) { Base::Copy(first, last); } compact_array(const compact_array& v) { Base::CopyFrom(v); } compact_array(compact_array&& v) noexcept( noexcept(compact_array()) && noexcept(std::declval().swap(v))) : compact_array() { Base::swap(v); } compact_array& operator=(const compact_array& v) { Base::AssignFrom(v); return *this; } compact_array& operator=(compact_array&& v) noexcept { // swap is only right here because the objects are trivially destructible // and thus there are no side effects on their destructor. // Otherwise we must destroy the objects on `this`. Base::swap(v); return *this; } ~compact_array() { Base::Destruct(); } }; // Comparison operators template bool operator==(const compact_array& x, const compact_array& y) { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } template bool operator!=(const compact_array& x, const compact_array& y) { return !(x == y); } template bool operator<(const compact_array& x, const compact_array& y) { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } template bool operator>(const compact_array& x, const compact_array& y) { return y < x; } template bool operator<=(const compact_array& x, const compact_array& y) { return !(y < x); } template bool operator>=(const compact_array& x, const compact_array& y) { return !(x < y); } // Swap template inline void swap(compact_array& x, compact_array& y) noexcept { x.swap(y); } namespace compact_array_internal { struct LogArray : public gtl::LogLegacyUpTo100 { template void Log(std::ostream& out, const ElementT& element) const { // NOLINT out << element; } void Log(std::ostream& out, int8_t c) const { // NOLINT out << static_cast(c); } void Log(std::ostream& out, uint8_t c) const { // NOLINT out << static_cast(c); } void LogOpening(std::ostream& out) const { out << "["; } // NOLINT void LogClosing(std::ostream& out) const { out << "]"; } // NOLINT }; } // namespace compact_array_internal // Output operator for compact_array. Requires that T has an // operator<< for std::ostream. Note that // compact_array_internal::LogArray ensures that "signed char" and // "unsigned char" types print as integers. template std::ostream& operator<<(std::ostream& out, const compact_array& array) { gtl::LogRangeToStream(out, array.begin(), array.end(), compact_array_internal::LogArray()); return out; } } // namespace gtl #endif // S2_UTIL_GTL_COMPACT_ARRAY_H_ src/s2/util/gtl/container_logging.h000066400000000000000000000243201524103652300175770ustar00rootroot00000000000000// Copyright 2013 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // All Rights Reserved. // // Utilities for container logging. // TODO(user): Broaden the scope and rename to "stream_util.h" // // // The typical use looks like this: // // ABSL_LOG(INFO) << gtl::LogContainer(container); // // By default, LogContainer() uses the LogShortUpTo100 policy: comma-space // separation, no newlines, and with limit of 100 items. // // Policies can be specified: // // ABSL_LOG(INFO) << gtl::LogContainer(container, gtl::LogMultiline()); // // The above example will print the container using newlines between // elements, enclosed in [] braces. // // See below for further details on policies. #ifndef S2_UTIL_GTL_CONTAINER_LOGGING_H_ #define S2_UTIL_GTL_CONTAINER_LOGGING_H_ #include #include #include #include #include #include #include "absl/strings/str_cat.h" #include "s2/util/gtl/requires.h" namespace gtl { // Several policy classes below determine how LogRangeToStream will // format a range of items. A Policy class should have these methods: // // Called to print an individual container element. // void Log(ostream &out, const ElementT &element) const; // // Called before printing the set of elements: // void LogOpening(ostream &out) const; // // Called after printing the set of elements: // void LogClosing(ostream &out) const; // // Called before printing the first element: // void LogFirstSeparator(ostream &out) const; // // Called before printing the remaining elements: // void LogSeparator(ostream &out) const; // // Returns the maximum number of elements to print: // int64 MaxElements() const; // // Called to print an indication that MaximumElements() was reached: // void LogEllipsis(ostream &out) const; namespace internal { struct LogBase { template void Log(std::ostream &out, const ElementT &element) const { // NOLINT // Fallback to `AbslStringify` if the type does not have `operator<<`. if constexpr (Requires( [](auto &&x, auto &&y) -> decltype(x << y) {})) { out << element; } else { out << absl::StrCat(element); } } void LogEllipsis(std::ostream &out) const { // NOLINT out << "..."; } }; struct LogShortBase : public LogBase { void LogOpening(std::ostream &out) const { out << "["; } // NOLINT void LogClosing(std::ostream &out) const { out << "]"; } // NOLINT void LogFirstSeparator(std::ostream &out) const { out << ""; } // NOLINT void LogSeparator(std::ostream &out) const { out << ", "; } // NOLINT }; struct LogMultilineBase : public LogBase { void LogOpening(std::ostream &out) const { out << "["; } // NOLINT void LogClosing(std::ostream &out) const { out << "\n]"; } // NOLINT void LogFirstSeparator(std::ostream &out) const { out << "\n"; } // NOLINT void LogSeparator(std::ostream &out) const { out << "\n"; } // NOLINT }; struct LogLegacyBase : public LogBase { void LogOpening(std::ostream &out) const { out << ""; } // NOLINT void LogClosing(std::ostream &out) const { out << ""; } // NOLINT void LogFirstSeparator(std::ostream &out) const { out << ""; } // NOLINT void LogSeparator(std::ostream &out) const { out << " "; } // NOLINT }; } // namespace internal // LogShort uses [] braces and separates items with comma-spaces. For // example "[1, 2, 3]". struct LogShort : public internal::LogShortBase { int64_t MaxElements() const { return std::numeric_limits::max(); } }; // LogShortUpToN(max_elements) formats the same as LogShort but prints no more // than the max_elements elements. class LogShortUpToN : public internal::LogShortBase { public: explicit LogShortUpToN(int64_t max_elements) : max_elements_(max_elements) {} int64_t MaxElements() const { return max_elements_; } private: int64_t max_elements_; }; // LogShortUpTo100 formats the same as LogShort but prints no more // than 100 elements. struct LogShortUpTo100 : public LogShortUpToN { LogShortUpTo100() : LogShortUpToN(100) {} }; // LogMultiline uses [] braces and separates items with // newlines. For example "[ // 1 // 2 // 3 // ]". struct LogMultiline : public internal::LogMultilineBase { int64_t MaxElements() const { return std::numeric_limits::max(); } }; // LogMultilineUpToN(max_elements) formats the same as LogMultiline but // prints no more than max_elements elements. class LogMultilineUpToN : public internal::LogMultilineBase { public: explicit LogMultilineUpToN(int64_t max_elements) : max_elements_(max_elements) {} int64_t MaxElements() const { return max_elements_; } private: int64_t max_elements_; }; // LogMultilineUpTo100 formats the same as LogMultiline but // prints no more than 100 elements. struct LogMultilineUpTo100 : public LogMultilineUpToN { LogMultilineUpTo100() : LogMultilineUpToN(100) {} }; // The legacy behavior of LogSequence() does not use braces and // separates items with spaces. For example "1 2 3". struct LogLegacyUpTo100 : public internal::LogLegacyBase { int64_t MaxElements() const { return 100; } }; struct LogLegacy : public internal::LogLegacyBase { int64_t MaxElements() const { return std::numeric_limits::max(); } }; // The default policy for new code. typedef LogShortUpTo100 LogDefault; // LogRangeToStream should be used to define operator<< for // STL and STL-like containers. For example, see stl_logging.h. template inline void LogRangeToStream(std::ostream &out, // NOLINT IteratorT begin, IteratorT end, const PolicyT &policy) { policy.LogOpening(out); for (int64_t i = 0; begin != end && i < policy.MaxElements(); ++i, ++begin) { if (i == 0) { policy.LogFirstSeparator(out); } else { policy.LogSeparator(out); } policy.Log(out, *begin); } if (begin != end) { policy.LogSeparator(out); policy.LogEllipsis(out); } policy.LogClosing(out); } namespace detail { // RangeLogger is a helper class for gtl::LogRange and // gtl::LogContainer; do not use it directly. This object // captures iterators into the argument of the LogRange and // LogContainer functions, so its lifetime should be confined to a // single logging statement. Objects of this type should not be // assigned to local variables. template class RangeLogger { public: RangeLogger(const IteratorT &begin, const IteratorT &end, const PolicyT &policy) : begin_(begin), end_(end), policy_(policy) {} friend std::ostream &operator<<(std::ostream &out, const RangeLogger &range) { gtl::LogRangeToStream(out, range.begin_, range.end_, range.policy_); return out; } // operator<< above is generally recommended. However, some situations may // require a string, so a convenience str() method is provided as well. std::string str() const { std::stringstream ss; ss << *this; return ss.str(); } private: IteratorT begin_; IteratorT end_; PolicyT policy_; }; template class EnumLogger { public: explicit EnumLogger(E e) : e_(e) {} friend std::ostream &operator<<(std::ostream &out, const EnumLogger &v) { using I = typename std::underlying_type::type; return out << static_cast(v.e_); } private: E e_; }; } // namespace detail // Log a range using "policy". For example: // // ABSL_LOG(INFO) << gtl::LogRange(start_pos, end_pos, gtl::LogMultiline()); // // The above example will print the range using newlines between // elements, enclosed in [] braces. template detail::RangeLogger LogRange(const IteratorT &begin, const IteratorT &end, const PolicyT &policy) { return gtl::detail::RangeLogger(begin, end, policy); } // Log a range. For example: // // ABSL_LOG(INFO) << gtl::LogRange(start_pos, end_pos); // // By default, Range() uses the LogShortUpTo100 policy: comma-space // separation, no newlines, and with limit of 100 items. template detail::RangeLogger LogRange(const IteratorT &begin, const IteratorT &end) { return gtl::LogRange(begin, end, LogDefault()); } // Log a container using "policy". For example: // // ABSL_LOG(INFO) << gtl::LogContainer(container, gtl::LogMultiline()); // // The above example will print the container using newlines between // elements, enclosed in [] braces. template auto LogContainer(const ContainerT &container, const PolicyT &policy) -> decltype(gtl::LogRange(container.begin(), container.end(), policy)) { return gtl::LogRange(container.begin(), container.end(), policy); } // Log a container. For example: // // ABSL_LOG(INFO) << gtl::LogContainer(container); // // By default, Container() uses the LogShortUpTo100 policy: comma-space // separation, no newlines, and with limit of 100 items. template auto LogContainer(const ContainerT &container) -> decltype(gtl::LogContainer(container, LogDefault())) { return gtl::LogContainer(container, LogDefault()); } // Log a (possibly scoped) enum. For example: // // enum class Color { kRed, kGreen, kBlue }; // ABSL_LOG(INFO) << gtl::LogEnum(kRed); template detail::EnumLogger LogEnum(E e) { static_assert(std::is_enum::value, "must be an enum"); return detail::EnumLogger(e); } } // namespace gtl #endif // S2_UTIL_GTL_CONTAINER_LOGGING_H_ src/s2/util/gtl/dense_hash_set.h000066400000000000000000000321741524103652300170710ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // 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 Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. // --- // // This is just a very thin wrapper over densehashtable.h, just // like sgi stl's stl_hash_set is a very thin wrapper over // stl_hashtable. // // This is more different from dense_hash_map than you might think, // because all iterators for sets are const (you obviously can't // change the key, and for sets there is no value). // // NOTE: this is exactly like sparse_hash_set.h, with the word // "sparse" replaced by "dense", except for the addition of // set_empty_key(). // // YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION. // // Otherwise your program will die in mysterious ways. (Note if you // use the constructor that takes an InputIterator range, you pass in // the empty key in the constructor, rather than after. As a result, // this constructor differs from the standard STL version.) // // In other respects, we adhere mostly to the STL semantics for // hash-map. One important exception is that insert() may invalidate // iterators entirely -- STL semantics are that insert() may reorder // iterators, but they all still refer to something valid in the // hashtable. Not so for us. Likewise, insert() may invalidate // pointers into the hashtable. (Whether insert invalidates iterators // and pointers depends on whether it results in a hashtable resize, // but that's an implementation detail that may change in the future.) // On the plus side, delete() doesn't invalidate iterators or pointers // at all, or even change the ordering of elements. // // Also please note: // // 1) set_deleted_key(): // If you want to use erase() you must call set_deleted_key(), // in addition to set_empty_key(), after construction. // The deleted and empty keys must differ. // // 2) Keys equal to the empty key or deleted key (if any) cannot be // used as keys for find(), count(), insert(), etc. // // 3) min_load_factor(): // Setting the minimum load factor controls how aggressively the // table is shrunk when keys are erased. Setting it to 0.0 // guarantees that the hash table will never shrink. // // 4) resize(0): // When an item is deleted, its memory isn't freed right // away. This allows you to iterate over a hashtable, // and call erase(), without invalidating the iterator. // To force the memory to be freed, call resize(0). // For tr1 compatibility, this can also be called as rehash(0). // Roughly speaking: // (1) dense_hash_set: fastest, uses the most memory unless entries are small // (2) sparse_hash_set: slowest, uses the least memory // (3) hash_set / unordered_set (STL): in the middle // // Typically I use sparse_hash_set when I care about space and/or when // I need to save the hashtable on disk. I use hash_set otherwise. I // don't personally use dense_hash_set ever; some people use it for // small sets with lots of lookups. // // - dense_hash_set has, typically, about 78% memory overhead (if your // data takes up X bytes, the hash_set uses .78X more bytes in overhead). // - sparse_hash_set has about 4 bits overhead per entry. // - sparse_hash_set can be 3-7 times slower than the others for lookup and, // especially, inserts. See time_hash_map.cc for details. // // See /usr/(local/)?doc/sparsehash-*/dense_hash_set.html // for information about how to use this class. #ifndef S2_UTIL_GTL_DENSE_HASH_SET_H_ #define S2_UTIL_GTL_DENSE_HASH_SET_H_ #include #include #include #include #include #include #include "absl/base/macros.h" #include "s2/util/gtl/densehashtable.h" // IWYU pragma: export // Some files test for this symbol. #define S2__DENSE_HASH_SET_H_ namespace gtl { template , class EqualKey = std::equal_to, class Alloc = std::allocator> class dense_hash_set { private: // Apparently identity is not stl-standard, so we define our own struct Identity { typedef const Value& result_type; const Value& operator()(const Value& v) const { return v; } }; struct SetKey { void operator()(Value* value, const Value& new_key) const { *value = new_key; } }; // The actual data typedef dense_hashtable ht; ht rep; public: typedef typename ht::key_type key_type; typedef typename ht::value_type value_type; typedef typename ht::hasher hasher; typedef typename ht::key_equal key_equal; typedef Alloc allocator_type; typedef typename ht::size_type size_type; typedef typename ht::difference_type difference_type; typedef typename ht::const_pointer pointer; typedef typename ht::const_pointer const_pointer; typedef typename ht::const_reference reference; typedef typename ht::const_reference const_reference; typedef typename ht::const_iterator iterator; typedef typename ht::const_iterator const_iterator; typedef typename ht::const_local_iterator local_iterator; typedef typename ht::const_local_iterator const_local_iterator; // Iterator functions -- recall all iterators are const iterator begin() const { return rep.begin(); } iterator end() const { return rep.end(); } // These come from tr1's unordered_set. For us, a bucket has 0 or 1 elements. ABSL_DEPRECATED( "This method is slated for removal. Please migrate to " "absl::flat_hash_set.") local_iterator begin(size_type i) const { return rep.begin(i); } // Accessor functions allocator_type get_allocator() const { return rep.get_allocator(); } hasher hash_funct() const { return rep.hash_funct(); } hasher hash_function() const { return hash_funct(); } // tr1 name key_equal key_eq() const { return rep.key_eq(); } // Constructors dense_hash_set() = default; explicit dense_hash_set(size_type expected_max_items_in_table, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& alloc = allocator_type()) : rep(expected_max_items_in_table, hf, eql, Identity(), SetKey(), alloc) { } template dense_hash_set(InputIterator f, InputIterator l, const key_type& empty_key_val, size_type expected_max_items_in_table = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& alloc = allocator_type()) : rep(expected_max_items_in_table, hf, eql, Identity(), SetKey(), alloc) { set_empty_key(empty_key_val); rep.insert(f, l); } // We use the default copy constructor // We use the default operator=() // We use the default destructor void clear() { rep.clear(); } // This clears the hash set without resizing it down to the minimum // bucket count, but rather keeps the number of buckets constant void clear_no_resize() { rep.clear_no_resize(); } void swap(dense_hash_set& hs) noexcept { rep.swap(hs.rep); } // Functions concerning size size_type size() const { return rep.size(); } size_type max_size() const { return rep.max_size(); } bool empty() const { return rep.empty(); } size_type bucket_count() const { return rep.bucket_count(); } float load_factor() const { return size() * 1.0f / bucket_count(); } float max_load_factor() const { float shrink, grow; rep.get_resizing_parameters(&shrink, &grow); return grow; } void max_load_factor(float new_grow) { float shrink, grow; rep.get_resizing_parameters(&shrink, &grow); rep.set_resizing_parameters(shrink, new_grow); } // These aren't tr1 methods but perhaps ought to be. ABSL_DEPRECATED( "This method is slated for removal. Please migrate to " "absl::flat_hash_set.") float min_load_factor() const { float shrink, grow; rep.get_resizing_parameters(&shrink, &grow); return shrink; } void min_load_factor(float new_shrink) { float shrink, grow; rep.get_resizing_parameters(&shrink, &grow); rep.set_resizing_parameters(new_shrink, grow); } // Deprecated; use min_load_factor() or max_load_factor() instead. void set_resizing_parameters(float shrink, float grow) { rep.set_resizing_parameters(shrink, grow); } void resize(size_type hint) { rep.resize(hint); } void rehash(size_type hint) { resize(hint); } // the tr1 name // Lookup routines iterator find(const key_type& key) const { return rep.find(key); } size_type count(const key_type& key) const { return rep.count(key); } std::pair equal_range(const key_type& key) const { return rep.equal_range(key); } // Insertion routines std::pair insert(const value_type& obj) { std::pair p = rep.insert(obj); return std::pair(p.first, p.second); // const to non-const } std::pair insert(value_type&& obj) { // NOLINT std::pair p = rep.insert(std::move(obj)); return std::pair(p.first, p.second); // const to non-const } template void insert(InputIterator f, InputIterator l) { rep.insert(f, l); } void insert(const_iterator f, const_iterator l) { rep.insert(f, l); } // Required for std::insert_iterator; the passed-in iterator is ignored. iterator insert(iterator, const value_type& obj) { return insert(obj).first; } iterator insert(iterator, value_type&& obj) { // NOLINT return insert(std::move(obj)).first; } // Unlike std::set, we cannot construct an element in place, as we do not have // a layer of indirection like std::set nodes. Therefore, emplace* methods do // not provide a performance advantage over insert + move. template std::pair emplace(Args&&... args) { return rep.insert(value_type(std::forward(args)...)); } // The passed-in const_iterator is ignored. template iterator emplace_hint(const_iterator, Args&&... args) { return rep.insert(value_type(std::forward(args)...)).first; } // Deletion and empty routines // THESE ARE NON-STANDARD! I make you specify an "impossible" key // value to identify deleted and empty buckets. You can change the // deleted key as time goes on, or get rid of it entirely to be insert-only. void set_empty_key(const key_type& key) { rep.set_empty_key(key); } void set_deleted_key(const key_type& key) { rep.set_deleted_key(key); } // These are standard size_type erase(const key_type& key) { return rep.erase(key); } void erase(iterator it) { rep.erase(it); } void erase(iterator f, iterator l) { rep.erase(f, l); } // Comparison bool operator==(const dense_hash_set& hs) const { return rep == hs.rep; } bool operator!=(const dense_hash_set& hs) const { return rep != hs.rep; } }; template inline void swap(dense_hash_set& hs1, dense_hash_set& hs2) noexcept { hs1.swap(hs2); } } #endif // S2_UTIL_GTL_DENSE_HASH_SET_H_ src/s2/util/gtl/densehashtable.h000066400000000000000000001606421524103652300170710ustar00rootroot00000000000000// Copyright 2005 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // 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 Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. // --- // // A dense hashtable is a particular implementation of // a hashtable: one that is meant to minimize memory allocation. // It does this by using an array to store all the data. We // steal a value from the key space to indicate "empty" array // elements (ie indices where no item lives) and another to indicate // "deleted" elements. // // (Note it is possible to change the value of the delete key // on the fly; you can even remove it, though after that point // the hashtable is insert_only until you set it again. The empty // value however can't be changed.) // // To minimize allocation and pointer overhead, we use internal // probing, in which the hashtable is a single table, and collisions // are resolved by trying to insert again in another bucket. The // most cache-efficient internal probing schemes are linear probing // (which suffers, alas, from clumping) and quadratic probing, which // is what we implement by default. // // Type requirements: value_type is required to be Move Constructible // and Default Constructible. It is not required to be (and commonly // isn't) Assignable. // // You probably shouldn't use this code directly. Use dense_hash_map<> // or dense_hash_set<> instead. // You can change the following below: // HT_OCCUPANCY_PCT -- how full before we double size // HT_EMPTY_PCT -- how empty before we halve size // HT_MIN_BUCKETS -- default smallest bucket size // // You can also change enlarge_factor (which defaults to // HT_OCCUPANCY_PCT), and shrink_factor (which defaults to // HT_EMPTY_PCT) with set_resizing_parameters(). // // How to decide what values to use? // shrink_factor's default of .4 * OCCUPANCY_PCT, is probably good. // HT_MIN_BUCKETS is probably unnecessary since you can specify // (indirectly) the starting number of buckets at construct-time. // For enlarge_factor, you can use this chart to try to trade-off // expected lookup time to the space taken up. By default, this // code uses quadratic probing, though you can change it to linear // via JUMP_ below if you really want to. // // From // L = N / M, // where N is the number of data items in the table and M is the table size. // NUMBER OF PROBES / LOOKUP Successful Unsuccessful // Quadratic collision resolution 1 - ln(1-L) - L/2 1/(1-L) - L - ln(1-L) // Linear collision resolution [1+1/(1-L)]/2 [1+1/(1-L)^2]/2 // // -- enlarge_factor -- 0.10 0.50 0.60 0.75 0.80 0.90 0.99 // QUADRATIC COLLISION RES. // probes/successful lookup 1.05 1.44 1.62 2.01 2.21 2.85 5.11 // probes/unsuccessful lookup 1.11 2.19 2.82 4.64 5.81 11.4 103.6 // LINEAR COLLISION RES. // probes/successful lookup 1.06 1.5 1.75 2.5 3.0 5.5 50.5 // probes/unsuccessful lookup 1.12 2.5 3.6 8.5 13.0 50.0 5000.0 #ifndef S2_UTIL_GTL_DENSEHASHTABLE_H_ #define S2_UTIL_GTL_DENSEHASHTABLE_H_ #include // For swap(), eg #include #include #include #include // for FILE, fwrite, fread #include #include // For iterator tags #include // for numeric_limits #include // For uninitialized_fill #include #include #include #include #include #include "s2/util/gtl/hashtable_common.h" #include // For length_error namespace gtl { // Some files test for this symbol. #define S2__DENSEHASHTABLE_H_ // The probing method // Linear probing // #define JUMP_(key, num_probes) ( 1 ) // Quadratic probing #define JUMP_(key, num_probes) (num_probes) // The weird mod in the offset is entirely to quiet compiler warnings // as is the cast to int after doing the "x mod 256" #define PUT_(take_from, offset) \ do { \ if (putc(static_cast(offset >= sizeof(take_from) * 8) \ ? 0 \ : ((take_from) >> (offset)) % 256, \ fp) == EOF) \ return false; \ } while (0) #define GET_(add_to, offset) \ do { \ if ((x = getc(fp)) == EOF) \ return false; \ else if (offset >= sizeof(add_to) * 8) \ assert(x == 0); /* otherwise it's too big for us to represent */ \ else \ add_to |= \ (static_cast(x) << ((offset) % (sizeof(add_to) * 8))); \ } while (0) // Hashtable class, used to implement the hashed associative containers // hash_set and hash_map. // Value: what is stored in the table (each bucket is a Value). // Key: something in a 1-to-1 correspondence to a Value, that can be used // to search for a Value in the table (find() takes a Key). // HashFcn: Takes a Key and returns an integer, the more unique the better. // ExtractKey: given a Value, returns the unique Key associated with it. // Must have a result_type enum indicating the return type of // operator(). // SetKey: given a Value* and a Key, modifies the value such that // ExtractKey(value) == key. We guarantee this is only called // with key == deleted_key or key == empty_key. // EqualKey: Given two Keys, says whether they are the same (that is, // if they are both associated with the same Value). // Alloc: STL allocator to use to allocate memory. template class dense_hashtable; template struct dense_hashtable_const_iterator; // We're just an array, but we need to skip over empty and deleted elements template struct dense_hashtable_iterator { private: using value_alloc_type = typename std::allocator_traits::template rebind_alloc; using value_alloc_traits = typename std::allocator_traits::template rebind_traits; public: typedef dense_hashtable_iterator iterator; typedef dense_hashtable_const_iterator const_iterator; typedef std::forward_iterator_tag iterator_category; // very little defined! typedef V value_type; typedef typename value_alloc_traits::difference_type difference_type; typedef typename value_alloc_traits::size_type size_type; typedef typename value_alloc_traits::value_type& reference; typedef typename value_alloc_traits::pointer pointer; // "Real" constructor and default constructor dense_hashtable_iterator( const dense_hashtable* h, pointer it, pointer it_end, bool advance) : ht(h), pos(it), end(it_end) { if (advance) advance_past_empty_and_deleted(); } dense_hashtable_iterator() = default; // The default destructor is fine; we don't define one // The default operator= is fine; we don't define one // Happy dereferencer reference operator*() const { return *pos; } pointer operator->() const { return &(operator*()); } // Arithmetic. The only hard part is making sure that // we're not on an empty or marked-deleted array element void advance_past_empty_and_deleted() { while (pos != end && (ht->test_empty(*this) || ht->test_deleted(*this))) ++pos; } iterator& operator++() { assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; } iterator operator++(int /*unused*/) { auto tmp(*this); ++*this; return tmp; } // Comparison. bool operator==(const iterator& it) const { return pos == it.pos; } bool operator!=(const iterator& it) const { return pos != it.pos; } // The actual data const dense_hashtable* ht; pointer pos, end; }; // Now do it all again, but with const-ness! template struct dense_hashtable_const_iterator { private: using value_alloc_type = typename std::allocator_traits::template rebind_alloc; using value_alloc_traits = typename std::allocator_traits::template rebind_traits; public: typedef dense_hashtable_iterator iterator; typedef dense_hashtable_const_iterator const_iterator; typedef std::forward_iterator_tag iterator_category; // very little defined! typedef V value_type; typedef typename value_alloc_traits::difference_type difference_type; typedef typename value_alloc_traits::size_type size_type; typedef const typename value_alloc_traits::value_type& reference; typedef typename value_alloc_traits::const_pointer pointer; // "Real" constructor and default constructor dense_hashtable_const_iterator( const dense_hashtable* h, pointer it, pointer it_end, bool advance) : ht(h), pos(it), end(it_end) { if (advance) advance_past_empty_and_deleted(); } dense_hashtable_const_iterator() : ht(nullptr), pos(pointer()), end(pointer()) {} // This lets us convert regular iterators to const iterators dense_hashtable_const_iterator(const iterator& it) : ht(it.ht), pos(it.pos), end(it.end) {} // The default destructor is fine; we don't define one // The default operator= is fine; we don't define one // Happy dereferencer reference operator*() const { return *pos; } pointer operator->() const { return &(operator*()); } // Arithmetic. The only hard part is making sure that // we're not on an empty or marked-deleted array element void advance_past_empty_and_deleted() { while (pos != end && (ht->test_empty(*this) || ht->test_deleted(*this))) ++pos; } const_iterator& operator++() { assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; } const_iterator operator++(int /*unused*/) { auto tmp(*this); ++*this; return tmp; } // Comparison. bool operator==(const const_iterator& it) const { return pos == it.pos; } bool operator!=(const const_iterator& it) const { return pos != it.pos; } // The actual data const dense_hashtable* ht; pointer pos, end; }; template class dense_hashtable { private: using value_alloc_type = typename std::allocator_traits::template rebind_alloc; using value_alloc_traits = typename std::allocator_traits::template rebind_traits; public: typedef Key key_type; typedef Value value_type; typedef HashFcn hasher; typedef EqualKey key_equal; typedef Alloc allocator_type; typedef typename value_alloc_traits::size_type size_type; typedef typename value_alloc_traits::difference_type difference_type; typedef typename value_alloc_traits::value_type& reference; typedef const typename value_alloc_traits::value_type& const_reference; typedef typename value_alloc_traits::pointer pointer; typedef typename value_alloc_traits::const_pointer const_pointer; typedef dense_hashtable_iterator iterator; typedef dense_hashtable_const_iterator const_iterator; // These come from tr1. For us they're the same as regular iterators. typedef iterator local_iterator; typedef const_iterator const_local_iterator; // How full we let the table get before we resize, by default. // Knuth says .8 is good -- higher causes us to probe too much, // though it saves memory. static const int HT_OCCUPANCY_PCT; // defined at the bottom of this file // How empty we let the table get before we resize lower, by default. // (0.0 means never resize lower.) // It should be less than OCCUPANCY_PCT / 2 or we thrash resizing static const int HT_EMPTY_PCT; // defined at the bottom of this file // Minimum size we're willing to let hashtables be. // Must be a power of two, and at least 4. // Note, however, that for a given hashtable, the initial size is a // function of the first constructor arg, and may be >HT_MIN_BUCKETS. static const size_type HT_MIN_BUCKETS = 4; // By default, if you don't specify a hashtable size at // construction-time, we use this size. Must be a power of two, and // at least HT_MIN_BUCKETS. static const size_type HT_DEFAULT_STARTING_BUCKETS = 32; // ITERATOR FUNCTIONS iterator begin() { return iterator(this, table, table + num_buckets, true); } iterator end() { return iterator(this, table + num_buckets, table + num_buckets, true); } const_iterator begin() const { return const_iterator(this, table, table + num_buckets, true); } const_iterator end() const { return const_iterator(this, table + num_buckets, table + num_buckets, true); } // These come from tr1 unordered_map. They iterate over 'bucket' n. // We'll just consider bucket n to be the n-th element of the table. local_iterator begin(size_type i) { return local_iterator(this, table + i, table + i + 1, false); } local_iterator end(size_type i) { local_iterator it = begin(i); if (!test_empty(i) && !test_deleted(i)) ++it; return it; } const_local_iterator begin(size_type i) const { return const_local_iterator(this, table + i, table + i + 1, false); } const_local_iterator end(size_type i) const { const_local_iterator it = begin(i); if (!test_empty(i) && !test_deleted(i)) ++it; return it; } // ACCESSOR FUNCTIONS for the things we templatize on, basically hasher hash_funct() const { return settings; } key_equal key_eq() const { return key_info; } value_alloc_type get_allocator() const { return key_info; } // Accessor function for statistics gathering. int num_table_copies() const { return settings.num_ht_copies(); } private: // Annoyingly, we can't copy values around, because they might have // const components (they're probably std::pair). We use // explicit destructor invocation and placement new to get around // this. Arg. static void set_value(pointer dst, const_reference src) { dst->~value_type(); // delete the old value, if any new (dst) value_type(src); } static void set_value(pointer dst, value_type&& src) { // NOLINT dst->~value_type(); new (dst) value_type(std::move(src)); } void destroy_buckets(size_type first, size_type last) { for (; first != last; ++first) table[first].~value_type(); } // DELETE HELPER FUNCTIONS // This lets the user describe a key that will indicate deleted // table entries. This key should be an "impossible" entry -- // if you try to insert it for real, you won't be able to retrieve it! // (NB: while you pass in an entire value, only the key part is looked // at. This is just because I don't know how to assign just a key.) private: // Gets rid of any deleted entries we have. void squash_deleted() { if (num_deleted > 0) { rebucket(settings.min_buckets(size(), num_buckets)); } assert(num_deleted == 0); } // Test if the given key is the deleted indicator. Requires // num_deleted > 0, for correctness of read(), and because that // guarantees that key_info.delkey is valid. bool test_deleted_key(const key_type& key) const { assert(num_deleted > 0); return equals(key_info.delkey, key); } public: void set_deleted_key(const key_type& key) { // the empty indicator (if specified) and the deleted indicator // must be different assert((!settings.use_empty() || !equals(key, key_info.empty)) && "Passed the empty-key to set_deleted_key"); // It's only safe to change what "deleted" means if we purge deleted guys squash_deleted(); settings.set_use_deleted(true); key_info.delkey = key; } key_type deleted_key() const { assert(settings.use_deleted() && "Must set deleted key before calling deleted_key"); return key_info.delkey; } // These are public so the iterators can use them // True if the item at position bucknum is "deleted" marker bool test_deleted(size_type bucknum) const { // Invariant: !use_deleted() implies num_deleted is 0. assert(settings.use_deleted() || num_deleted == 0); return num_deleted > 0 && test_deleted_key(get_key(table[bucknum])); } bool test_deleted(const iterator& it) const { // Invariant: !use_deleted() implies num_deleted is 0. assert(settings.use_deleted() || num_deleted == 0); return num_deleted > 0 && test_deleted_key(get_key(*it)); } bool test_deleted(const const_iterator& it) const { // Invariant: !use_deleted() implies num_deleted is 0. assert(settings.use_deleted() || num_deleted == 0); return num_deleted > 0 && test_deleted_key(get_key(*it)); } private: void check_use_deleted(const char* caller) { (void)caller; // could log it if the assert failed assert(settings.use_deleted()); } // Write the deleted key to the position specified. // Requires: !test_deleted(it) void set_deleted(iterator& it) { check_use_deleted("set_deleted()"); assert(!test_deleted(it)); // &* converts from iterator to value-type. set_key(&(*it), key_info.delkey); } // We also allow to set/clear the deleted bit on a const iterator. // We allow a const_iterator for the same reason you can delete a // const pointer: it's convenient, and semantically you can't use // 'it' after it's been deleted anyway, so its const-ness doesn't // really matter. // Requires: !test_deleted(it) void set_deleted(const_iterator& it) { check_use_deleted("set_deleted()"); assert(!test_deleted(it)); set_key(const_cast(&(*it)), key_info.delkey); } // EMPTY HELPER FUNCTIONS // This lets the user describe a key that will indicate empty (unused) // table entries. This key should be an "impossible" entry -- // if you try to insert it for real, you won't be able to retrieve it! // (NB: while you pass in an entire value, only the key part is looked // at. This is just because I don't know how to assign just a key.) public: // These are public so the iterators can use them // True if the item at position bucknum is "empty" marker bool test_empty(size_type bucknum) const { assert(settings.use_empty()); // we always need to know what's empty! return equals(key_info.empty, get_key(table[bucknum])); } bool test_empty(const iterator& it) const { assert(settings.use_empty()); // we always need to know what's empty! return equals(key_info.empty, get_key(*it)); } bool test_empty(const const_iterator& it) const { assert(settings.use_empty()); // we always need to know what's empty! return equals(key_info.empty, get_key(*it)); } private: bool test_empty(size_type bucknum, const_pointer ptable) const { assert(settings.use_empty()); return equals(key_info.empty, get_key(ptable[bucknum])); } void fill_range_with_empty(pointer table_start, pointer table_end) { for (; table_start != table_end; ++table_start) { new (table_start) value_type(); set_key(table_start, key_info.empty); } } public: // TODO(user): change all callers of this to pass in a key instead, // and take a const key_type instead of const value_type. void set_empty_key(const_reference val) { // Once you set the empty key, you can't change it assert(!settings.use_empty() && "Calling set_empty_key multiple times"); // The deleted indicator (if specified) and the empty indicator // must be different. const key_type& key = get_key(val); assert((!settings.use_deleted() || !equals(key, key_info.delkey)) && "Setting the empty key the same as the deleted key"); settings.set_use_empty(true); key_info.empty.~key_type(); new (&key_info.empty) key_type(key); assert(!table); // must set before first use // num_buckets was set in constructor even though table was nullptr table = get_internal_allocator().allocate(num_buckets); fill_range_with_empty(table, table + num_buckets); } // TODO(user): this should return the key by const reference. value_type empty_key() const { assert(settings.use_empty()); value_type ret = value_type(); set_key(&ret, key_info.empty); return ret; } // FUNCTIONS CONCERNING SIZE public: size_type size() const { return num_elements - num_deleted; } size_type max_size() const { return std::allocator_traits::max_size(get_allocator()); } bool empty() const { return size() == 0; } size_type bucket_count() const { return num_buckets; } private: // Because of the above, size_type(-1) is never legal; use it for errors static const size_type ILLEGAL_BUCKET = size_type(-1); // Used after a string of deletes. Returns true if we actually shrunk. // TODO(user): take a delta so we can take into account inserts // done after shrinking. Maybe make part of the Settings class? bool maybe_shrink() { assert(num_elements >= num_deleted); assert((bucket_count() & (bucket_count() - 1)) == 0); // is a power of two assert(bucket_count() >= HT_MIN_BUCKETS); bool retval = false; // If you construct a hashtable with < HT_DEFAULT_STARTING_BUCKETS, // we'll never shrink until you get relatively big, and we'll never // shrink below HT_DEFAULT_STARTING_BUCKETS. Otherwise, something // like "dense_hash_set x; x.insert(4); x.erase(4);" will // shrink us down to HT_MIN_BUCKETS buckets, which is too small. const size_type num_remain = num_elements - num_deleted; const size_type shrink_threshold = settings.shrink_threshold(); if (shrink_threshold > 0 && num_remain < shrink_threshold && bucket_count() > HT_DEFAULT_STARTING_BUCKETS) { const float shrink_factor = settings.shrink_factor(); size_type sz = bucket_count() / 2; // find how much we should shrink while (sz > HT_DEFAULT_STARTING_BUCKETS && num_remain < sz * shrink_factor) { sz /= 2; // stay a power of 2 } rebucket(sz); retval = true; } settings.set_consider_shrink(false); // because we just considered it return retval; } // We'll let you resize a hashtable -- though this makes us copy all! // When you resize, you say, "make it big enough for this many more elements" // Returns true if we actually resized, false if size was already ok. bool resize_delta(size_type delta) { bool did_resize = false; if (settings.consider_shrink()) { // see if lots of deletes happened if (maybe_shrink()) did_resize = true; } if (num_elements >= std::numeric_limits::max() - delta) { throw std::length_error("resize overflow"); } assert(settings.enlarge_threshold() < bucket_count()); // Check if our work is done. if (bucket_count() >= HT_MIN_BUCKETS && num_elements + delta <= settings.enlarge_threshold()) { return did_resize; } // Sometimes, we need to resize just to get rid of all the // "deleted" buckets that are clogging up the hashtable. So when // deciding whether to resize, count the deleted buckets (which // are currently taking up room). But later, when we decide what // size to resize to, *don't* count deleted buckets, since they // get discarded during the resize. const size_type needed_size = settings.min_buckets(num_elements + delta, 0); if (needed_size <= bucket_count()) // we have enough buckets return did_resize; // We will rebucket. size_type resize_to = settings.min_buckets( num_elements - num_deleted + delta, bucket_count()); if (resize_to < needed_size) { // This situation means that we have enough deleted elements, // that once we purge them, we won't actually have needed to // grow. But we may want to grow anyway: if we just purge one // element, say, we'll have to grow anyway next time we // insert. Might as well grow now, since we're already going // through the trouble of rebucketing in order to purge the // deleted elements. (Safety note: Can resize_to * 2 overflow? No. // The output of min_buckets() is always a power of two, so resize_to // and needed_size are powers of two. That plus resize_to < needed_size // proves that overflow isn't a concern.) const size_type target = static_cast(settings.shrink_size(resize_to * 2)); if (num_elements - num_deleted + delta >= target) { // Good, we won't be below the shrink threshold even if we double. resize_to *= 2; } } rebucket(resize_to); return true; } // We require table be non-null and empty before calling this. void resize_table(size_type old_size, size_type new_size) { get_internal_allocator().deallocate(table, old_size); table = get_internal_allocator().allocate(new_size); } // Copy (or, if Iter is a move_iterator, move) the elements from // [src_first, src_last) into dest_table, which we assume has size // dest_bucket_count and has been initialized to the empty key. template void copy_elements(Iter src_first, Iter src_last, pointer dest_table, size_type dest_bucket_count) { assert((dest_bucket_count & (dest_bucket_count - 1)) == 0); // a power of 2 // We use a normal iterator to get non-deleted bcks from ht // We could use insert() here, but since we know there are // no duplicates and no deleted items, we can be more efficient for (; src_first != src_last; ++src_first) { size_type num_probes = 0; // how many times we've probed size_type bucknum; const size_type bucket_count_minus_one = dest_bucket_count - 1; for (bucknum = hash(get_key(*src_first)) & bucket_count_minus_one; !test_empty(bucknum, dest_table); // not empty bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) { ++num_probes; assert(num_probes < dest_bucket_count && "Hashtable is full: an error in key_equal<> or hash<>"); } // Copies or moves the value into dest_table. set_value(&dest_table[bucknum], *src_first); } } // Used to actually do the rehashing when we grow/shrink a hashtable void copy_from(const dense_hashtable& ht, size_type min_buckets_wanted) { size_type size = ht.size(); // clear_to_size() sets ht.size() to 0. clear_to_size(settings.min_buckets(ht.size(), min_buckets_wanted)); copy_elements(ht.begin(), ht.end(), table, bucket_count()); num_elements = size; settings.inc_num_ht_copies(); } // Rebuckets and resizes the hashtable. Gets rid of any deleted entries. void rebucket(size_type new_num_buckets) { if (table == nullptr) { // When we eventually allocate the table, it will have this many buckets. num_buckets = new_num_buckets; return; } assert(settings.use_empty()); assert((new_num_buckets & (new_num_buckets - 1)) == 0); // a power of two // If settings.shrink_factor() is zero then we must not shrink. assert(settings.shrink_factor() > 0 || new_num_buckets >= num_buckets); pointer new_table = get_internal_allocator().allocate(new_num_buckets); fill_range_with_empty(new_table, new_table + new_num_buckets); copy_elements(std::make_move_iterator(begin()), std::make_move_iterator(end()), new_table, new_num_buckets); destroy_buckets(0, num_buckets); // Destroy table's elements. get_internal_allocator().deallocate(table, num_buckets); table = new_table; num_buckets = new_num_buckets; assert(num_elements >= num_deleted); num_elements -= num_deleted; num_deleted = 0; settings.reset_thresholds(bucket_count()); settings.inc_num_ht_copies(); } // Required by the spec for hashed associative container public: // Though the docs say this should be num_buckets, I think it's much // more useful as num_elements. As a special feature, calling with // req_elements==0 will cause us to shrink if we can, saving space. void resize(size_type req_elements) { // resize to this or larger if (settings.consider_shrink() || req_elements == 0) maybe_shrink(); if (req_elements > num_elements) resize_delta(req_elements - num_elements); } // Get and change the value of shrink_factor and enlarge_factor. The // description at the beginning of this file explains how to choose // the values. Setting the shrink parameter to 0.0 ensures that the // table never shrinks. void get_resizing_parameters(float* shrink, float* grow) const { *shrink = settings.shrink_factor(); *grow = settings.enlarge_factor(); } void set_resizing_parameters(float shrink, float grow) { settings.set_resizing_parameters(shrink, grow); settings.reset_thresholds(bucket_count()); } // CONSTRUCTORS -- as required by the specs, we take a size, // but also let you specify a hashfunction, key comparator, // and key extractor. We also define a copy constructor and =. // DESTRUCTOR -- needs to free the table explicit dense_hashtable(size_type expected_max_items_in_table = 0, const HashFcn& hf = HashFcn(), const EqualKey& eql = EqualKey(), const ExtractKey& ext = ExtractKey(), const SetKey& set = SetKey(), const Alloc& alloc = Alloc()) : settings(hf), key_info(ext, set, eql, value_alloc_type(alloc)), num_deleted(0), num_elements(0), num_buckets(expected_max_items_in_table == 0 ? HT_DEFAULT_STARTING_BUCKETS : settings.min_buckets(expected_max_items_in_table, 0)), table(nullptr) { // table is nullptr until the empty key is set. However, we set num_buckets // here so we know how much space to allocate once the empty key is set. settings.reset_thresholds(bucket_count()); } // As a convenience for resize(), we allow an optional second argument // which lets you make this new hashtable a different size than ht dense_hashtable(const dense_hashtable& ht, size_type min_buckets_wanted = HT_DEFAULT_STARTING_BUCKETS) : settings(ht.settings), key_info(ht.key_info.as_extract_key(), ht.key_info.as_set_key(), ht.key_info.as_equal_key(), value_alloc_type(std::allocator_traits:: select_on_container_copy_construction( ht.key_info.as_value_alloc()))), num_deleted(0), num_elements(0), num_buckets(0), table(nullptr) { key_info.delkey = ht.key_info.delkey; key_info.empty = ht.key_info.empty; if (!ht.settings.use_empty()) { // If use_empty isn't set, copy_from will crash, so we do our own copying. assert(ht.empty()); num_buckets = settings.min_buckets(ht.size(), min_buckets_wanted); settings.reset_thresholds(bucket_count()); return; } settings.reset_thresholds(bucket_count()); copy_from(ht, min_buckets_wanted); // copy_from() ignores deleted entries } dense_hashtable& operator=(const dense_hashtable& ht) { if (&ht == this) return *this; // don't copy onto ourselves settings = ht.settings; key_info.as_extract_key() = ht.key_info.as_extract_key(); key_info.as_set_key() = ht.key_info.as_set_key(); key_info.as_equal_key() = ht.key_info.as_equal_key(); if (std::allocator_traits< value_alloc_type>::propagate_on_container_copy_assignment::value) { // If we're about to overwrite our allocator, we need to free all // memory using our old allocator. if (key_info.as_value_alloc() != ht.key_info.as_value_alloc()) { destroy_table(); } static_cast(key_info) = static_cast(ht.key_info); } key_info.empty = ht.key_info.empty; key_info.delkey = ht.key_info.delkey; if (ht.settings.use_empty()) { // copy_from() calls clear and sets num_deleted to 0 too copy_from(ht, HT_MIN_BUCKETS); } else { assert(ht.empty()); destroy_table(); } // we purposefully don't copy the allocator, which may not be copyable return *this; } dense_hashtable(dense_hashtable&& ht) noexcept : settings(std::move(ht.settings)), key_info(std::move(ht.key_info)), num_deleted(ht.num_deleted), num_elements(ht.num_elements), num_buckets(ht.num_buckets), table(ht.table) { ht.num_deleted = 0; ht.num_elements = 0; ht.table = nullptr; ht.num_buckets = HT_DEFAULT_STARTING_BUCKETS; ht.settings.set_use_empty(false); ht.settings.set_use_deleted(false); } dense_hashtable& operator=(dense_hashtable&& ht) noexcept { if (&ht == this) return *this; // don't move onto ourselves const bool can_move_table = std::allocator_traits< Alloc>::propagate_on_container_move_assignment::value || key_info.as_value_alloc() == ht.key_info.as_value_alloc(); // First, deallocate with this's allocator. destroy_table(); if (std::allocator_traits< value_alloc_type>::propagate_on_container_move_assignment::value) { // This moves the allocator. key_info = std::move(ht.key_info); } else { // Move all other base classes of key_info from ht, but don't move the // allocator. key_info.as_extract_key() = std::move(ht.key_info.as_extract_key()); key_info.as_set_key() = std::move(ht.key_info.as_set_key()); key_info.as_equal_key() = std::move(ht.key_info.as_equal_key()); key_info.delkey = std::move(ht.key_info.delkey); key_info.empty = std::move(ht.key_info.empty); } settings = std::move(ht.settings); num_deleted = ht.num_deleted; ht.num_deleted = 0; num_elements = ht.num_elements; ht.num_elements = 0; num_buckets = ht.num_buckets; ht.num_buckets = HT_DEFAULT_STARTING_BUCKETS; ht.settings.set_use_empty(false); ht.settings.set_use_deleted(false); if (can_move_table) { // We can transfer ownership of the table from ht to this because either // we're propagating the allocator or ht's allocator is equal to this's. table = ht.table; ht.table = nullptr; } else if (ht.table) { // We can't transfer ownership of any memory from ht to this, so the // best we can do is move element-by-element. table = get_internal_allocator().allocate(num_buckets); for (size_type i = 0; i < num_buckets; ++i) { new (table + i) Value(std::move(ht.table[i])); } ht.destroy_table(); } return *this; } ~dense_hashtable() { destroy_table(); } // Many STL algorithms use swap instead of copy constructors void swap(dense_hashtable& ht) noexcept { if (this == &ht) return; // swap with self. using std::swap; swap(settings, ht.settings); // Swap everything in key_info but the allocator. swap(key_info.as_extract_key(), ht.key_info.as_extract_key()); swap(key_info.as_set_key(), ht.key_info.as_set_key()); swap(key_info.as_equal_key(), ht.key_info.as_equal_key()); if (std::allocator_traits< value_alloc_type>::propagate_on_container_swap::value) { swap(static_cast(key_info), static_cast(ht.key_info)); } else { // Swapping when allocators are unequal and // propagate_on_container_swap is false is undefined behavior. ABSL_CHECK(key_info.as_value_alloc() == ht.key_info.as_value_alloc()); } swap(key_info.empty, ht.key_info.empty); swap(key_info.delkey, ht.key_info.delkey); swap(num_deleted, ht.num_deleted); swap(num_elements, ht.num_elements); swap(num_buckets, ht.num_buckets); swap(table, ht.table); } private: void destroy_table() { if (table) { destroy_buckets(0, num_buckets); get_internal_allocator().deallocate(table, num_buckets); table = nullptr; } } void clear_to_size(size_type new_num_buckets) { if (!table) { table = get_internal_allocator().allocate(new_num_buckets); } else { destroy_buckets(0, num_buckets); if (new_num_buckets != num_buckets) { // resize, if necessary resize_table(num_buckets, new_num_buckets); } } assert(table); fill_range_with_empty(table, table + new_num_buckets); num_elements = 0; num_deleted = 0; num_buckets = new_num_buckets; // our new size settings.reset_thresholds(bucket_count()); } public: // It's always nice to be able to clear a table without deallocating it void clear() { // If the table is already empty, and the number of buckets is // already as we desire, there's nothing to do. const size_type new_num_buckets = settings.min_buckets(0, 0); if (num_elements == 0 && new_num_buckets == num_buckets) { return; } clear_to_size(new_num_buckets); } // Clear the table without resizing it. // Mimics the stl_hashtable's behaviour when clear()-ing in that it // does not modify the bucket count void clear_no_resize() { if (num_elements > 0) { assert(table); destroy_buckets(0, num_buckets); fill_range_with_empty(table, table + num_buckets); } // don't consider to shrink before another erase() settings.reset_thresholds(bucket_count()); num_elements = 0; num_deleted = 0; } // LOOKUP ROUTINES private: template void assert_key_is_not_empty_or_deleted(const K& key) const { assert(settings.use_empty() && "set_empty_key() was not called"); assert(!equals(key, key_info.empty) && "Using the empty key as a regular key"); assert((!settings.use_deleted() || !equals(key, key_info.delkey)) && "Using the deleted key as a regular key"); } // Returns a pair of positions: 1st where the object is, 2nd where // it would go if you wanted to insert it. 1st is ILLEGAL_BUCKET // if object is not found; 2nd is ILLEGAL_BUCKET if it is. // Note: because of deletions where-to-insert is not trivial: it's the // first deleted bucket we see, as long as we don't find the key later template std::pair find_position_using_hash( const size_type key_hash, const K& key) const { assert_key_is_not_empty_or_deleted(key); size_type num_probes = 0; // how many times we've probed const size_type bucket_count_minus_one = bucket_count() - 1; size_type bucknum = key_hash & bucket_count_minus_one; size_type insert_pos = ILLEGAL_BUCKET; // where we would insert while (true) { // probe until something happens if (test_empty(bucknum)) { // bucket is empty if (insert_pos == ILLEGAL_BUCKET) // found no prior place to insert return std::pair(ILLEGAL_BUCKET, bucknum); else return std::pair(ILLEGAL_BUCKET, insert_pos); } else if (test_deleted(bucknum)) { // keep searching, but mark to insert if (insert_pos == ILLEGAL_BUCKET) insert_pos = bucknum; } else if (equals(key, get_key(table[bucknum]))) { return std::pair(bucknum, ILLEGAL_BUCKET); } ++num_probes; // we're doing another probe bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one; assert(num_probes < bucket_count() && "Hashtable is full: an error in key_equal<> or hash<>"); } } template std::pair find_if_present(const K& key) const { return find_if_present_using_hash(hash(key), key); } // Return where the key is (if at all), and if it is present. If // the key isn't present then the first part of the return value is // undefined. The same information can be extracted from the result // of find_position(), but that tends to be slower in practice. template std::pair find_if_present_using_hash( const size_type key_hash, const K& key) const { assert_key_is_not_empty_or_deleted(key); size_type num_probes = 0; // how many times we've probed const size_type bucket_count_minus_one = bucket_count() - 1; size_type bucknum = key_hash & bucket_count_minus_one; while (true) { // probe until something happens if (equals(key, get_key(table[bucknum]))) { return std::pair(bucknum, true); } else if (test_empty(bucknum)) { return std::pair(0, false); } ++num_probes; // we're doing another probe bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one; assert(num_probes < bucket_count() && "Hashtable is full: an error in key_equal<> or hash<>"); } } private: template iterator find_impl(const K& key) { std::pair pos = find_if_present(key); return pos.second ? iterator(this, table + pos.first, table + num_buckets, false) : end(); } template const_iterator find_impl(const K& key) const { std::pair pos = find_if_present(key); return pos.second ? const_iterator(this, table + pos.first, table + num_buckets, false) : end(); } template size_type count_impl(const K& key) const { return find_if_present(key).second ? 1 : 0; } template std::pair equal_range_impl(const K& key) { iterator pos = find(key); if (pos == end()) { return std::pair(pos, pos); } else { const iterator startpos = pos++; return std::pair(startpos, pos); } } template std::pair equal_range_impl( const K& key) const { const_iterator pos = find(key); if (pos == end()) { return std::pair(pos, pos); } else { const const_iterator startpos = pos++; return std::pair(startpos, pos); } } public: iterator find(const key_type& key) { return find_impl(key); } const_iterator find(const key_type& key) const { return find_impl(key); } // Counts how many elements have key key. For maps, it's either 0 or 1. size_type count(const key_type& key) const { return count_impl(key); } // Likewise, equal_range doesn't really make sense for us. Oh well. std::pair equal_range(const key_type& key) { return equal_range_impl(key); } std::pair equal_range( const key_type& key) const { return equal_range_impl(key); } // INSERTION ROUTINES private: // Private method used by insert_noresize and find_or_insert. // 'obj' is either value_type&& or const value_type&. template iterator insert_at(U&& obj, size_type pos) { if (size() >= max_size()) { throw std::length_error("insert overflow"); } if (test_deleted(pos)) { // just replace if it's been del. assert(num_deleted > 0); --num_deleted; // used to be, now it isn't } else { ++num_elements; // replacing an empty bucket } set_value(&table[pos], std::forward(obj)); return iterator(this, table + pos, table + num_buckets, false); } // If you know *this is big enough to hold obj, use this routine // 'obj' is value_type&& or const value_type&. template std::pair insert_noresize(U&& obj) { // NOLINT return insert_noresize_using_hash(hash(get_key(obj)), std::forward(obj)); } // If you know *this is big enough to hold obj, use this routine // 'obj' is value_type&& or const value_type&. template std::pair insert_noresize_using_hash(const size_type key_hash, U&& obj) { const std::pair pos = find_position_using_hash(key_hash, get_key(obj)); if (pos.first != ILLEGAL_BUCKET) { // object was already there return std::pair( iterator(this, table + pos.first, table + num_buckets, false), false); // false: we didn't insert } else { // pos.second says where to put it iterator i = insert_at(std::forward(obj), pos.second); return std::pair(i, true); } } // Specializations of insert(it, it) depending on the power of the iterator: // (1) Iterator supports operator-, resize before inserting template void insert(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) { size_t dist = std::distance(f, l); if (dist >= std::numeric_limits::max()) { throw std::length_error("insert-range overflow"); } resize_delta(static_cast(dist)); for (; dist > 0; --dist, ++f) { insert_noresize(*f); } } // (2) Arbitrary iterator, can't tell how much to resize template void insert(InputIterator f, InputIterator l, std::input_iterator_tag) { for (; f != l; ++f) insert(*f); } public: // This is the normal insert routine, used by the outside world std::pair insert(const value_type& obj) { resize_delta(1); // adding an object, grow if need be return insert_noresize(obj); } std::pair insert(value_type&& obj) { // NOLINT resize_delta(1); // adding an object, grow if need be return insert_noresize(std::move(obj)); } // When inserting a lot at a time, we specialize on the type of iterator template void insert(InputIterator f, InputIterator l) { // specializes on iterator type insert(f, l, typename std::iterator_traits::iterator_category()); } template value_type& find_or_insert(const key_type& key) { return find_or_insert_using_hash(hash(key), key); } // DefaultValue is a functor that takes a key and returns a value_type // representing the default value to be inserted if none is found. template value_type& find_or_insert_using_hash(const size_type key_hash, const key_type& key) { const std::pair pos = find_position_using_hash(key_hash, key); DefaultValue default_value; if (pos.first != ILLEGAL_BUCKET) { // object was already there return table[pos.first]; } else if (resize_delta(1)) { // needed to rehash to make room // Since we resized, we can't use pos, so recalculate where to insert. return *insert_noresize(default_value(key)).first; } else { // no need to rehash, insert right here return *insert_at(default_value(key), pos.second); } } // DELETION ROUTINES private: template size_type erase_impl(const K& key) { iterator pos = find(key); if (pos != end()) { assert(!test_deleted(pos)); // or find() shouldn't have returned it set_deleted(pos); ++num_deleted; // will think about shrink after next insert settings.set_consider_shrink(true); return 1; // because we deleted one thing } else { return 0; // because we deleted nothing } } public: size_type erase(const key_type& key) { return erase_impl(key); } void erase(iterator pos) { if (pos == end()) return; set_deleted(pos); ++num_deleted; // will think about shrink after next insert settings.set_consider_shrink(true); } void erase(iterator f, iterator l) { for (; f != l; ++f) { set_deleted(f); ++num_deleted; } // will think about shrink after next insert settings.set_consider_shrink(true); } // We allow you to erase a const_iterator just like we allow you to // erase an iterator. This is in parallel to 'delete': you can delete // a const pointer just like a non-const pointer. The logic is that // you can't use the object after it's erased anyway, so it doesn't matter // if it's const or not. void erase(const_iterator pos) { if (pos == end()) return; set_deleted(pos); ++num_deleted; // will think about shrink after next insert settings.set_consider_shrink(true); } void erase(const_iterator f, const_iterator l) { for (; f != l; ++f) { set_deleted(f); ++num_deleted; } // will think about shrink after next insert settings.set_consider_shrink(true); } // COMPARISON bool operator==(const dense_hashtable& ht) const { if (size() != ht.size()) { return false; } else if (this == &ht) { return true; } else { // Iterate through the elements in "this" and see if the // corresponding element is in ht for (const_iterator it = begin(); it != end(); ++it) { const_iterator it2 = ht.find(get_key(*it)); if ((it2 == ht.end()) || (*it != *it2)) { return false; } } return true; } } bool operator!=(const dense_hashtable& ht) const { return !(*this == ht); } // I/O // We support reading and writing hashtables to disk. Alas, since // I don't know how to write a hasher or key_equal, you have to make // sure everything but the table is the same. We compact before writing. private: // Every time the disk format changes, this should probably change too typedef unsigned long MagicNumberType; static const MagicNumberType MAGIC_NUMBER = 0x13578642; // Package functors with another class to eliminate memory needed for // zero-size functors. Since ExtractKey and hasher's operator() might // have the same function signature, they must be packaged in // different classes. struct Settings : sh_hashtable_settings { explicit Settings(const hasher& hf) : sh_hashtable_settings( hf, HT_OCCUPANCY_PCT / 100.0f, HT_EMPTY_PCT / 100.0f) {} }; // Packages ExtractKey, SetKey, EqualKey functors, allocator and deleted and // empty key values. struct KeyInfo : public ExtractKey, public SetKey, public EqualKey, public value_alloc_type { KeyInfo(const ExtractKey& ek, const SetKey& sk, const EqualKey& eq, const value_alloc_type& a) : ExtractKey(ek), SetKey(sk), EqualKey(eq), value_alloc_type(a), delkey(), empty() {} // Accessors for convenient access to base classes. ExtractKey& as_extract_key() { return *this; } const ExtractKey& as_extract_key() const { return *this; } SetKey& as_set_key() { return *this; } const SetKey& as_set_key() const { return *this; } EqualKey& as_equal_key() { return *this; } const EqualKey& as_equal_key() const { return *this; } value_alloc_type& as_value_alloc() { return *this; } const value_alloc_type& as_value_alloc() const { return *this; } // We want to return the exact same type as ExtractKey: Key or const Key& typename ExtractKey::result_type get_key(const_reference v) const { return ExtractKey::operator()(v); } void set_key(pointer v, const key_type& k) const { SetKey::operator()(v, k); } // We only ever call EqualKey::operator()(key_type, K) -- we never use the // other order of args. This allows consumers to get away with implementing // only half of operator==. template bool equals(const key_type& a, const K& b) const { return EqualKey::operator()(a, b); } // Which key marks deleted entries. // TODO(user): make a pointer, and get rid of use_deleted (benchmark!) typename std::remove_const::type delkey; // Key value used to mark unused entries. typename std::remove_const::type empty; }; // Returns the value_alloc_type used to allocate and deallocate // the table. This can be different from the one returned by get_allocator(). value_alloc_type& get_internal_allocator() { return key_info; } // Utility functions to access the templated operators size_type hash(const key_type& v) const { return settings.hash(v); } bool equals(const key_type& a, const key_type& b) const { return key_info.equals(a, b); } typename ExtractKey::result_type get_key(const_reference v) const { return key_info.get_key(v); } void set_key(pointer v, const key_type& k) const { key_info.set_key(v, k); } private: // Actual data Settings settings; KeyInfo key_info; size_type num_deleted; // how many occupied buckets are marked deleted size_type num_elements; size_type num_buckets; pointer table; }; // We need a global swap as well template inline void swap(dense_hashtable& x, dense_hashtable& y) noexcept { x.swap(y); } #undef JUMP_ #undef PUT_ #undef GET_ template const typename dense_hashtable::size_type dense_hashtable::ILLEGAL_BUCKET; // How full we let the table get before we resize. Knuth says .8 is // good -- higher causes us to probe too much, though saves memory. // However, we go with .5, getting better performance at the cost of // more space (a trade-off densehashtable explicitly chooses to make). // Feel free to play around with different values, though, via // max_load_factor() and/or set_resizing_parameters(). template const int dense_hashtable::HT_OCCUPANCY_PCT = 50; // How empty we let the table get before we resize lower. // It should be less than OCCUPANCY_PCT / 2 or we thrash resizing. template const int dense_hashtable::HT_EMPTY_PCT = static_cast( 0.4 * dense_hashtable::HT_OCCUPANCY_PCT); } #endif // S2_UTIL_GTL_DENSEHASHTABLE_H_ src/s2/util/gtl/hashtable_common.h000066400000000000000000000211271524103652300174140ustar00rootroot00000000000000// Copyright 2010 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // 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 Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 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. // --- #ifndef S2_UTIL_GTL_HASHTABLE_COMMON_H_ #define S2_UTIL_GTL_HASHTABLE_COMMON_H_ #include #include #include #include // For length_error // Settings contains parameters for growing and shrinking the table. // It also packages zero-size functor (ie. hasher). One invariant // enforced in enlarge_size() is that we never allow all slots // occupied. (This is unlikely to matter to users, because using // a load near 1 is slow and not recommended. It allows other code // to assume there is at least one empty bucket.) // // It does some munging of the hash value in cases where we think // (fear) the original hash function might not be very good. In // particular, the default hash of pointers is the identity hash, // so probably all the low bits are 0. We identify when we think // we're hashing a pointer, and chop off the low bits. Note this // isn't perfect: even when the key is a pointer, we can't tell // for sure that the hash is the identity hash. If it's not, this // is needless work (and possibly, though not likely, harmful). template class sh_hashtable_settings : public HashFunc { public: typedef Key key_type; typedef HashFunc hasher; typedef SizeType size_type; public: sh_hashtable_settings(const hasher& hf, const float ht_occupancy_flt, const float ht_empty_flt) : hasher(hf), enlarge_threshold_(0), shrink_threshold_(0), consider_shrink_(false), use_empty_(false), use_deleted_(false), num_ht_copies_(0) { set_enlarge_factor(ht_occupancy_flt); set_shrink_factor(ht_empty_flt); } template size_type hash(const K& v) const { // We munge the hash value when we don't trust hasher::operator(). It is // very important that we use hash_munger instead of hash_munger. // Within a given hashtable, all hash values must be munged in the same way. return hash_munger::MungedHash(hasher::operator()(v)); } float enlarge_factor() const { return enlarge_factor_; } void set_enlarge_factor(float f) { enlarge_factor_ = f; } float shrink_factor() const { return shrink_factor_; } void set_shrink_factor(float f) { shrink_factor_ = f; } size_type enlarge_threshold() const { return enlarge_threshold_; } void set_enlarge_threshold(size_type t) { enlarge_threshold_ = t; } size_type shrink_threshold() const { return shrink_threshold_; } void set_shrink_threshold(size_type t) { shrink_threshold_ = t; } size_type enlarge_size(size_type x) const { return std::min(x - 1, x * enlarge_factor_); } size_type shrink_size(size_type x) const { return static_cast(x * shrink_factor_); } bool consider_shrink() const { return consider_shrink_; } void set_consider_shrink(bool t) { consider_shrink_ = t; } bool use_empty() const { return use_empty_; } void set_use_empty(bool t) { use_empty_ = t; } bool use_deleted() const { return use_deleted_; } void set_use_deleted(bool t) { use_deleted_ = t; } size_type num_ht_copies() const { return static_cast(num_ht_copies_); } void inc_num_ht_copies() { ++num_ht_copies_; } // Reset the enlarge and shrink thresholds void reset_thresholds(size_type num_buckets) { set_enlarge_threshold(enlarge_size(num_buckets)); set_shrink_threshold(shrink_size(num_buckets)); // whatever caused us to reset already considered set_consider_shrink(false); } // Caller is responsible for calling reset_threshold right after // set_resizing_parameters. void set_resizing_parameters(float shrink, float grow) { assert(shrink >= 0.0); assert(grow <= 1.0); if (shrink > grow / 2.0f) shrink = grow / 2.0f; // otherwise we thrash hashtable size set_shrink_factor(shrink); set_enlarge_factor(grow); } // This is the smallest size a hashtable can be without being too crowded. // If you like, you can give a min #buckets as well as a min #elts. // This is guaranteed to return a power of two. size_type min_buckets(size_type num_elts, size_type min_buckets_wanted) { float enlarge = enlarge_factor(); size_type sz = HT_MIN_BUCKETS; // min buckets allowed while (sz < min_buckets_wanted || num_elts >= static_cast(sz * enlarge)) { // This just prevents overflowing size_type, since sz can exceed // max_size() here. if (static_cast(sz * 2) < sz) { throw std::length_error("resize overflow"); // protect against overflow } sz *= 2; } return sz; } private: template class hash_munger { public: static size_t MungedHash(size_t hash) { return hash; } }; // This matches when the hashtable key is a pointer. template class hash_munger { public: static size_t MungedHash(size_t hash) { // TODO(user): consider rotating instead: // static const int shift = (sizeof(void *) == 4) ? 2 : 3; // return (hash << (sizeof(hash) * 8) - shift)) | (hash >> shift); // This matters if we ever change sparse/dense_hash_* to compare // hashes before comparing actual values. It's speedy on x86. return hash / sizeof(void*); // get rid of known-0 bits } }; size_type enlarge_threshold_; // table.size() * enlarge_factor size_type shrink_threshold_; // table.size() * shrink_factor float enlarge_factor_; // how full before resize float shrink_factor_; // how empty before resize // consider_shrink=true if we should try to shrink before next insert bool consider_shrink_; bool use_empty_; // used only by densehashtable, not sparsehashtable bool use_deleted_; // false until delkey has been set // num_ht_copies is a counter incremented every Copy/Move unsigned int num_ht_copies_; }; // This traits class checks whether T::is_transparent exists and names a type. // // struct Foo { using is_transparent = void; }; // struct Bar {}; // static_assert(sh_is_transparent::value, "Foo is transparent."); // staitc_assert(!sh_is_transparent::value, "Bar is not transparent."); template struct sh_is_transparent { private: struct No {}; struct Yes { No x[2]; }; template static Yes Test(typename U::is_transparent*); template static No Test(...); public: enum { value = sizeof(Test(nullptr)) == sizeof(Yes) }; }; #endif // S2_UTIL_GTL_HASHTABLE_COMMON_H_ src/s2/util/gtl/requires.h000066400000000000000000000017561524103652300157560ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_UTIL_GTL_REQUIRES_H_ #define S2_UTIL_GTL_REQUIRES_H_ #include namespace gtl { // C++17 port of C++20's `requires` expressions. // https://en.cppreference.com/w/cpp/language/constraints#Requires_expressions template constexpr bool Requires(F) { return std::is_invocable_v; } } // namespace gtl #endif // S2_UTIL_GTL_REQUIRES_H_ src/s2/util/gtl/unaligned.h000066400000000000000000000020531524103652300160540ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_UTIL_GTL_UNALIGNED_H_ #define S2_UTIL_GTL_UNALIGNED_H_ #include namespace gtl { template T UnalignedLoad(const char *p) { static_assert(std::is_trivially_copyable_v); T v; memcpy(&v, p, sizeof(v)); return v; } template void UnalignedStore(T v, char *p) { static_assert(std::is_trivially_copyable_v); memcpy(p, &v, sizeof(v)); } } // namespace gtl #endif // S2_UTIL_GTL_UNALIGNED_H_ src/s2/util/gtl/value_or_die.h000066400000000000000000000017441524103652300165510ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef S2_UTIL_GTL_VALUE_OR_DIE_H_ #define S2_UTIL_GTL_VALUE_OR_DIE_H_ #include namespace gtl { // Equivalent to `std::move(v).value()`, but makes explicit that the behavior // is to die if `v` does not contain a value. template T ValueOrDie(absl::StatusOr&& v) { return std::move(v).value(); } } // namespace gtl #endif // S2_UTIL_GTL_VALUE_OR_DIE_H_ src/s2/util/hash/000077500000000000000000000000001524103652300140725ustar00rootroot00000000000000src/s2/util/hash/BUILD.bazel000066400000000000000000000002321524103652300157450ustar00rootroot00000000000000load("@rules_cc//cc:defs.bzl", "cc_library") package(default_visibility = ["//:__subpackages__"]) cc_library( name = "mix", hdrs = ["mix.h"], ) src/s2/util/hash/mix.h000066400000000000000000000046571524103652300150540ustar00rootroot00000000000000// Copyright 2013 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: jyrki@google.com (Jyrki Alakuijala) // // This file contains routines for mixing hashes. #ifndef S2_UTIL_HASH_MIX_H_ #define S2_UTIL_HASH_MIX_H_ #include #include // Fast mixing of hash values -- not strong enough for fingerprinting. // May change from time to time. // // Values given are expected to be hashes from good hash functions. // What constitutes a good hash may depend on your application. As a rule of // thumb, if std::hash is strong enough for your hashing need if // your data were just ints, it will most likely be the correct choice // for a mixed hash of data members. HashMix does one round of multiply and // rotate mixing, so you get some additional collision avoidance guarantees // compared to just using std::hash directly. // // Possible use: // // struct Xyzzy { // int x; // int y; // string id; // }; // // #ifndef SWIG // template<> struct XyzzyHash { // size_t operator()(const Xyzzy& c) const { // HashMix mix(hash()(c.x)); // mix.Mix(hash()(c.y)); // mix.Mix(GoodFastHash()(c.id)); // return mix.get(); // } // } // #endif // // HashMix is a lower level interface than std::hash>. // Use std::hash> instead of HashMix where appropriate. class HashMix { public: HashMix() : hash_(1) {} explicit HashMix(size_t val) : hash_(val + 83) {} void Mix(size_t val) { static const size_t kMul = static_cast(0xdc3eb94af8ab4c93ULL); // Multiplicative hashing will mix bits better in the msb end ... hash_ *= kMul; // ... and rotating will move the better mixed msb-bits to lsb-bits. hash_ = ((hash_ << 19) | (hash_ >> (std::numeric_limits::digits - 19))) + val; } size_t get() const { return hash_; } private: size_t hash_; }; #endif // S2_UTIL_HASH_MIX_H_ src/s2/util/math/000077500000000000000000000000001524103652300141005ustar00rootroot00000000000000src/s2/util/math/BUILD.bazel000066400000000000000000000010151524103652300157530ustar00rootroot00000000000000load("@rules_cc//cc:defs.bzl", "cc_library") package(default_visibility = ["//:__subpackages__"]) cc_library( name = "mathutil", srcs = ["mathutil.cc"], hdrs = ["mathutil.h"], ) cc_library( name = "matrix3x3", hdrs = ["matrix3x3.h"], deps = [ ":mathutil", ":vector", "@abseil-cpp//absl/log:absl_check", ], ) cc_library( name = "vector", hdrs = ["vector.h"], deps = [ "@abseil-cpp//absl/log:absl_check", "@abseil-cpp//absl/utility", ], ) src/s2/util/math/exactfloat/000077500000000000000000000000001524103652300162325ustar00rootroot00000000000000src/s2/util/math/exactfloat/BUILD.bazel000066400000000000000000000037151524103652300201160ustar00rootroot00000000000000load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") package(default_visibility = ["//:__subpackages__"]) cc_library( name = "bignum", srcs = ["bignum.cc"], hdrs = ["bignum.h"], visibility = ["//visibility:private"], deps = [ "@abseil-cpp//absl/algorithm:container", "@abseil-cpp//absl/container:inlined_vector", "@abseil-cpp//absl/log:absl_check", ], ) cc_library( name = "exactfloat", srcs = [ "exactfloat.cc", ], hdrs = [ "exactfloat.h", ], deps = [ ":bignum", "@abseil-cpp//absl/container:inlined_vector", "@abseil-cpp//absl/log:absl_check", "@abseil-cpp//absl/log:absl_log", "@abseil-cpp//absl/numeric:bits", "@abseil-cpp//absl/numeric:int128", "@abseil-cpp//absl/random:random", ], ) cc_test( name = "bignum_test", srcs = ["bignum_test.cc"], deps = [ ":bignum", "//:s2_testing_headers", "@abseil-cpp//absl/log:log_streamer", "@abseil-cpp//absl/random:bit_gen_ref", "@abseil-cpp//absl/strings:str_format", "@abseil-cpp//absl/strings:strings", "@googletest//:gtest_main", ] + select({ "//:use_openssl_setting": ["@openssl//:crypto"], "//conditions:default": ["@boringssl//:crypto"], }), ) cc_test( name = "exactfloat_test", srcs = ["exactfloat_test.cc"], deps = [ ":exactfloat", "//s2/testing:test_main", "//s2/util/math:vector", "@abseil-cpp//absl/base:core_headers", "@abseil-cpp//absl/base:no_destructor", "@abseil-cpp//absl/log:absl_check", "@abseil-cpp//absl/log:absl_log", "@abseil-cpp//absl/random", ], ) cc_test( name = "exactfloat_underflow_test", srcs = ["exactfloat_underflow_test.cc"], deps = [ ":exactfloat", "//s2/testing:test_main", "@abseil-cpp//absl/random:random", "@googletest//:gtest_main", ], ) src/s2/util/math/exactfloat/bignum.cc000066400000000000000000000641051524103652300200300ustar00rootroot00000000000000// Copyright 2025 Google LLC // Author: smcallis@google.com (Sean McAllister) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "s2/util/math/exactfloat/bignum.h" #ifdef __x86_64__ #include #endif #include #include #include #include #include #include #include #include #include "absl/algorithm/container.h" #include "absl/base/nullability.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" #include "absl/numeric/int128.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" namespace exactfloat_internal { // Number of bigits in smaller of the two operands before we fall back to simple // multiplication in the Karatsuba recursion. Determined empirically. static constexpr int kSimpleMulThreshold = 24; // Computes dst[i] = a[i]*b + c // // Returns the final carry, if any. inline Bigit MulWithCarry(absl::Span dst, absl::Span a, Bigit b, Bigit carry); // Compares magnitude magnitude of two bigit vectors, returning -1, 0, or +1. // // Magnitudes are compared lexicographically from the most significant bigit // to the least significant. int CmpAbs(absl::Span a, absl::Span b) { if (a.size() != b.size()) { return a.size() < b.size() ? -1 : +1; } for (int i = a.size() - 1; i >= 0; --i) { if (a[i] != b[i]) { return a[i] < b[i] ? -1 : +1; } } return 0; } int Bignum::Compare(const Bignum& b) const { if (is_negative() != b.is_negative()) { return is_negative() ? -1 : +1; } // Signs are equal, are they both zero? if (is_zero() && b.is_zero()) { return 0; } // Signs are equal and non-zero, compare magnitude. const int compare = CmpAbs(bigits_, b.bigits_); return is_negative() ? -compare : compare; } std::optional Bignum::FromString(absl::string_view s) { // A chunk is up to 19 decimal digits, which can always fit into a Bigit. static constexpr size_t kMaxChunkDigits = std::numeric_limits::digits10; // NOTE: We use a simple multiply-and-add (aka Horner's) method here for the // sake of simplicity. This isn't the fastest algorithm, being quadratic in // the number of chunks the input has. If we use divide and conquer approach // or an FFT based multiply we could probably make this ~O(n^1.5) or // semi-linear. // Precomputed powers of 10. static constexpr auto kPow10 = []() { std::array out = {1}; for (size_t i = 1; i < out.size(); ++i) { out[i] = 10 * out[i - 1]; } return out; }(); Bignum out; if (s.empty()) { return out; } out.bigits_.reserve((s.size() + kMaxChunkDigits - 1) / kMaxChunkDigits); bool negative = false; // Consume optional +/- at the front. const char* begin = s.data(); // std::from_chars needs pointers, not iterators if ((*begin == '+' || *begin == '-')) { negative = (s[0] == '-'); ++begin; } const char* end = s.data() + s.size(); while (begin < end) { size_t chunk_len = std::min(static_cast(end - begin), kMaxChunkDigits); Bigit chunk = 0; auto result = std::from_chars(begin, begin + chunk_len, chunk); if (result.ec != std::errc() || static_cast(result.ptr - begin) != chunk_len) { return std::nullopt; } begin += chunk_len; // Shift left by chunk_len digits and add the chunk to it. auto outspan = absl::MakeSpan(out.bigits_); Bigit carry = MulWithCarry(outspan, outspan, kPow10[chunk_len], chunk); if (carry) { out.bigits_.emplace_back(carry); } } out.negative_ = negative; out.Normalize(); return out; } int bit_width(const Bignum& a) { ABSL_DCHECK(a.bigits_.empty() || a.bigits_.back() != 0); if (a.is_zero()) { return 0; } // Bit width is the bits in the least significant bigits + bit width of // the most significant word. const int msw_width = absl::bit_width(a.bigits_.back()); const int lsw_width = (a.bigits_.size() - 1) * Bignum::kBigitBits; return msw_width + lsw_width; } int countr_zero(const Bignum& a) { int nzero = 0; for (Bigit bigit : a.bigits_) { if (bigit == 0) { nzero += Bignum::kBigitBits; } else { nzero += absl::countr_zero(bigit); break; } } return nzero; } bool Bignum::is_bit_set(int nbit) const { ABSL_DCHECK_GE(nbit, 0); const size_t digit = nbit / kBigitBits; const size_t shift = nbit % kBigitBits; if (digit >= bigits_.size()) { return false; } return ((bigits_[digit] >> shift) & 0x1) != 0; } Bignum Bignum::operator-() const { Bignum result = *this; result.negate(); return result; } Bignum& Bignum::operator<<=(int nbit) { ABSL_DCHECK_GE(nbit, 0); if (is_zero() || nbit == 0) { return *this; } const int nbigit = nbit / kBigitBits; const int nrem = nbit % kBigitBits; // First, handle the whole-bigit shift by inserting zeros. bigits_.insert(bigits_.begin(), nbigit, 0); // Then, handle the within-bigit shift, if any. if (nrem != 0) { Bigit carry = 0; for (size_t i = 0; i < bigits_.size(); ++i) { const Bigit old_val = bigits_[i]; bigits_[i] = (old_val << nrem) | carry; carry = old_val >> (kBigitBits - nrem); } if (carry) { bigits_.push_back(carry); } } return *this; } Bignum& Bignum::operator>>=(int nbit) { ABSL_DCHECK_GE(nbit, 0); if (is_zero() || nbit == 0) { return *this; } // Shifting by more than the bit width results in zero. if (nbit >= bit_width(*this)) { return set_zero(); } const int nbigit = nbit / kBigitBits; const int nrem = nbit % kBigitBits; // First, handle the whole-bigit shift by removing bigits. bigits_.erase(bigits_.begin(), bigits_.begin() + nbigit); // Then, handle the within-bigit shift, if any. if (nrem != 0) { Bigit carry = 0; for (int64_t i = static_cast(bigits_.size()) - 1; i >= 0; --i) { const Bigit old_val = bigits_[i]; bigits_[i] = (old_val >> nrem) | carry; carry = old_val << (kBigitBits - nrem); } } // Result might be smaller or zero, so normalize. Normalize(); return *this; } // Raise this value to the given power, which must be non-negative. Bignum Bignum::Pow(int32_t pow) const { ABSL_DCHECK_GE(pow, 0); // Anything to the zero-th power is 1 (including zero). if (pow == 0) { return Bignum(1); } if (is_zero()) { return Bignum(0); } // Core algorithm: Exponentiation by squaring. Bignum result(1); Bignum base = *this; // A mutable copy of the base. uint32_t upow = static_cast(pow); while (upow > 0) { if (upow & 1) { // If current exponent bit is 1, multiply into result. result *= base; } base *= base; upow >>= 1; } return result; } // Computes a + b + carry and updates the carry. inline Bigit AddBigit(Bigit a, Bigit b, Bigit* absl_nonnull carry) { // Compilers such as GCC and Clang are known to be terrible at generating good // code for long carry chains on Intel. Using the _addcarry_u64 intrinsic (which // maps to the add/adc instructions produces a tight series of add/adc/adc/adc // instructions, whereas writing the loop manually often generates many add/adc // pairs with spurious bit twiddling. // // Using the intrinsic here improves benchmarks by ~30% when summing larger // Bignums together. // // See this SO discussion for more information: // https://stackoverflow.com/questions/33690791 // // Godbolt link for comparison: // https://godbolt.org/z/cGnnfMbMn (no intrinsics) // https://godbolt.org/z/jnM1Y3Tjs (intrinsics) #ifdef __x86_64__ static_assert(sizeof(Bigit) == sizeof(unsigned long long)); Bigit out; *carry = _addcarry_u64(*carry, a, b, reinterpret_cast(&out)); return out; #else absl::uint128 sum = absl::uint128(a) + b + *carry; *carry = absl::Uint128High64(sum); return static_cast(sum); #endif } // Computes a - b - borrow and updates the borrow. // // NOTE: Borrow must be one or zero. inline Bigit SubBigit(Bigit a, Bigit b, Bigit* absl_nonnull borrow) { ABSL_DCHECK_LE(*borrow, Bigit(1)); // See notes in AddBigit on why using an intrinsic is the right choice here. #ifdef __x86_64__ Bigit out; *borrow = _subborrow_u64(static_cast(*borrow), a, b, reinterpret_cast(&out)); return out; #else Bigit diff = a - b - *borrow; *borrow = (a < b) || (*borrow && (a == b)); return diff; #endif } // Computes a * b + carry and updates the carry. inline Bigit MulBigit(Bigit a, Bigit b, Bigit* absl_nonnull carry) { absl::uint128 sum = absl::uint128(a) * b + *carry; *carry = absl::Uint128High64(sum); return static_cast(sum); } // Computes sum += a * b + carry and updates the carry. // // NOTE: Will not overflow even if a, b, and c are their maximum values. inline void MulAddBigit(Bigit* absl_nonnull sum, Bigit a, Bigit b, Bigit* absl_nonnull carry) { // Similar to the comment in AddBigit, and just for completeness, it's worth // noting that the "best" way to implement this is with the Intel MULX, ADCQ, // and ADOQ instructions (i.e. the _mulx_u64, _addcarry_u64, and // _addcarryx_u64 intrinsics), but GCC and Clang do not support _addcarryx_u64 // properly (and have no plans to do so). The issue is that gcc doesn't // support reasoning about separate dependency chains for the carry and // overflow flags, because all the flags are considered to be one // register. (The ADOX instructions were added specifically for this use case, // i.e. high-precision integer multiplies. They propagate carries using the // overflow flag rather than the carry flag, which lets you do two // extended-precision add operations in parallel without having them stomp on // each other's carry flags. ) absl::uint128 term = absl::uint128(a) * b + *carry + *sum; *carry = absl::Uint128High64(term); *sum = static_cast(term); } // Computes a += b in place. Returns the final carry (if any). // // A operand must be at least as large as B. When adding two same-sized values, // the result may overflow and be larger than either of them, in which case we // will return the final carry value. // // This allows a work flow like this: // Bigit carry = AddInPlace(a, b); // if (carry) { // a.bigits_.emplace_back(carry); // } // // Rather than having to expand A to B.bigits_.size() + 1, and popping off the // top bigit if it's unused (which is the most common case). ABSL_ATTRIBUTE_NOINLINE inline Bigit AddInPlace(absl::Span a, absl::Span b) { ABSL_DCHECK_GE(a.size(), b.size()); Bigit carry = 0; // Dispatch four at a time to help loop unrolling. size_t i = 0; while (i + 4 <= b.size()) { for (int j = 0; j < 4; ++j, ++i) { a[i] = AddBigit(a[i], b[i], &carry); } } // Finish remainder. for (; i < b.size(); ++i) { a[i] = AddBigit(a[i], b[i], &carry); } // Propagate carry through the rest of a. for (; carry && i < a.size(); ++i) { a[i] = AddBigit(a[i], 0, &carry); } return carry; } // Computes dst = a + b out of place. Returns the number of bigits actually // written into dst. // // NOTE: dst must be sized to be larger than max(a.size(), b.size()) + 1 (i.e. // it must be able to hold the carry bigit, if any. // // This allows for using a pre-allocated buffer to store the result of an // addition followed by trimming down to size: // // absl::Span out = arena.Alloc(std::max(a.size(), b.size()) + 1); // out = out.first(AddInto(out, a, b)); // // Which is used in the Karatsuba multiplication, where we don't have the option // to expand the allocate space on demand. inline size_t Add(absl::Span dst, absl::Span a, absl::Span b) { const size_t max_size = std::max(a.size(), b.size()); const size_t min_size = std::min(a.size(), b.size()); ABSL_DCHECK_GE(dst.size(), max_size + 1); // Add common parts. Bigit carry = 0; // Dispatch four at a time to help loop unrolling. size_t i = 0; while (i + 4 < min_size) { for (int j = 0; j < 4; ++j, ++i) { dst[i] = AddBigit(a[i], b[i], &carry); } } // Finish remainder of the parts common to A and B. for (; i < min_size; ++i) { dst[i] = AddBigit(a[i], b[i], &carry); } // Copy remaining digits from the longer operand and propagate carry. absl::Span longer = (a.size() > b.size()) ? a : b; // Dispatch four at a time for the remaining part. const size_t size = longer.size(); while (i + 4 < size) { for (int j = 0; j < 4; ++j, ++i) { dst[i] = AddBigit(longer[i], 0, &carry); } } // Propagate carry through the longer operand. for (; i < size; ++i) { dst[i] = AddBigit(longer[i], 0, &carry); } if (carry) { dst[i++] = carry; return max_size + 1; } return max_size; } // Computes a -= b. // // REQUIRES: |a| >= |b|. inline void SubInPlace(absl::Span a, absl::Span b) { ABSL_DCHECK_GE(a.size(), b.size()); ABSL_DCHECK_GE(CmpAbs(a, b), 0); Bigit borrow = 0; // Dispatch four at a time to help loop unrolling. size_t size = b.size(); size_t i = 0; while (i + 4 <= size) { for (int j = 0; j < 4; ++j, ++i) { a[i] = SubBigit(a[i], b[i], &borrow); } } // Finish remainder of subtraction. for (; i < size; ++i) { a[i] = SubBigit(a[i], b[i], &borrow); } // Propagate the borrow through a. for (; borrow && i < a.size(); ++i) { borrow = (a[i] == 0); a[i]--; } } // Computes a = b - a. // // NOTE: Requires |b| >= |a|. // // Since we write the result to a, but b is larger, a must be expanded with // enough leading zeros to fit the result. inline void SubReverseInPlace(absl::Span a, absl::Span b) { ABSL_DCHECK_GE(a.size(), b.size()); ABSL_DCHECK_GE(CmpAbs(b, a), 0); Bigit borrow = 0; // Dispatch four at a time to help loop unrolling. size_t size = a.size(); size_t i = 0; while (i + 4 <= size) { for (int j = 0; j < 4; ++j, ++i) { a[i] = SubBigit(b[i], a[i], &borrow); } } // Finish remainder. for (; i < size; ++i) { a[i] = SubBigit(b[i], a[i], &borrow); } } inline Bigit MulWithCarry(absl::Span dst, absl::Span a, Bigit b, Bigit carry) { ABSL_DCHECK_GE(dst.size(), a.size()); // Dispatch four at a time to help loop unrolling. size_t i = 0; while (i + 4 <= a.size()) { for (int j = 0; j < 4; ++j, ++i) { dst[i] = MulBigit(a[i], b, &carry); } } for (; i < a.size(); ++i) { dst[i] = MulBigit(a[i], b, &carry); } return carry; } // Computes sum[i] += a[i]*b in place. // // Returns the final carry, if any. inline Bigit MulAddInPlace(absl::Span sum, absl::Span a, Bigit b) { // Dispatch four at a time to help loop unrolling. Bigit carry = 0; size_t i = 0; while (i + 4 <= a.size()) { for (int j = 0; j < 4; ++j, ++i) { MulAddBigit(&sum[i], a[i], b, &carry); } } // Finish remainder. for (; i < a.size(); ++i) { MulAddBigit(&sum[i], a[i], b, &carry); } return carry; } // Implements the standard grade school long multiplication algorithm. The // output is computed by multiplying A by each digit of B and summing the // results as we go. This is a quadratic algorithm and only serves as the base // case for the recursive Karatsuba algorithm below. // // NOTE: out must be at least as large as the sums of the sizes of A and B. inline void MulQuadratic(absl::Span dst, absl::Span a, absl::Span b) { ABSL_DCHECK_GE(dst.size(), a.size() + b.size()); // Make sure A is the longer of the two arguments. if (a.size() < b.size()) { using std::swap; swap(a, b); } if (b.empty()) { absl::c_fill(dst, 0); return; } // Each call to MulAdd and MulAddInPlace only updates a.size() elements of out // so we manually set the carries as we go. We grab a span to the upper half // of out starting at a.size() to facilitate this. absl::Span upper = dst.subspan(a.size()); upper[0] = MulWithCarry(dst, a, b[0], 0); const size_t size = b.size(); size_t i = 1; for (; i < size; ++i) { upper[i] = MulAddInPlace(dst.subspan(i), a, b[i]); } // Finish zeroing out the upper half. for (; i < upper.size(); ++i) { upper[i] = 0; } } // Split a span into two contiguous spans of length at most a and b. // // If span.size() <= a, the second span is empty, otherwise the second span // has length at most b. If span.size() > a + b, then the two spans only cover // part of the input span. template inline std::pair, absl::Span> Split(absl::Span span, size_t a, size_t b) { if (a < span.size()) { return {span.subspan(0, a), span.subspan(a, b)}; } return {span.subspan(0, a), {}}; }; // A simple bump allocator to allow us to very efficiently allocate temporary // space when recursing in the Karatsuba multiply. The arena is pre-sized and // returns spans of memory via Alloc() which are then returned to the arena via // Release. // // NOTE: We use std::unique_ptr here instead of std::vector because we don't // want to initialize the memory unnecessarily and using std::vector without // resizing (and thus initializing) the container leads to false positives with // ASAN. class Arena { public: // TODO: Use make_unique_for_overwrite when on C++20. explicit Arena(size_t size) : size_(size), data_(new Bigit[size]) {} // Allocates a span of length n from the arena. absl::Span Alloc(size_t n) { ABSL_DCHECK_LE(used_ + n, size_); size_t start = used_; used_ += n; return absl::Span(data_.get() + start, n); } size_t Available() const { return size_ - used_; } size_t Used() const { return used_; } // Resets the arena to the given position which must be < Used(). void Reset(size_t to) { ABSL_DCHECK_LE(to, used_); used_ = to; } private: size_t size_ = 0; size_t used_ = 0; std::unique_ptr data_; }; // Returns the total arena size needed to multiply two number of a_size and // b_size bigits using the recursive Karatsuba implementation. This is enough // space for all the required recursive calls of KaratsubaMulRecursive. inline size_t ArenaSize(size_t a_size, size_t b_size) { // Each step of Karatsuba splits at: // N = (std::max(a.size() + b.size() + 1) / 2 // // We have to hold a total of 4*(N + 1) bigits as temporaries at each step. // // Simulate the recursion (log(n) steps) and compute the arena size. int peak = 0; while (std::min(a_size, b_size) > kSimpleMulThreshold) { int half = (std::max(a_size, b_size) + 1) / 2; int next = half + 1; peak += 4 * next; a_size = next; b_size = next; }; return peak; } // Recursive step in the Karatsuba multiplication. dst must be large enough to // hold the product of a and b (i.e. it must be at least as large as a.size() + // b.size()). The product is computed and stored in-place in dst. // // Additionally an arena must be provided for temporary storage for intermediate // products. The arena must have at least ArenaSize(a.size(), b.size()) space // available. inline void KaratsubaMulRecursive(absl::Span dst, absl::Span a, absl::Span b, Arena* absl_nonnull arena) { ABSL_DCHECK_GE(dst.size(), a.size() + b.size()); ABSL_DCHECK_GE(arena->Available(), ArenaSize(a.size(), b.size())); if (a.empty() || b.empty()) { absl::c_fill(dst, 0); return; } int arena_start = arena->Used(); // Karatsuba lets us represent two numbers of M bigits each, A and B, as: // // A = a1*10^(M/2) + a0 // B = b1*10^(M/2) + b0 // // Which we can multiply out: // AB = (a1*10^(M/2) + a0)*(b1*10^(M/2) + b0); // = a1*b1*10^M + (a1*b0 + a0*b1)*10^(M/2) + a0*b0 // = z2 * 10^M + z1*10^(M/2) + z0 // // Where: // z0 = a0*b0 // z1 = a1*b0 + a0*b1 // z2 = a1*b1 // // We can replace the multiplications in z1 by computing: // // z3 = (a0 + a1)*(b0 + b1) // // And noting z1 = z3 - z2 - z0 // // This lets us compute a 2M digit multiply with three M digit multiplies, // with those individual multiplies able to be recursively divided. // Fall back to long multiplication when we're small enough. if (std::min(a.size(), b.size()) <= kSimpleMulThreshold) { MulQuadratic(dst, a, b); return; } const size_t half = (std::max(a.size(), b.size()) + 1) / 2; // Split the inputs into contiguous subspans. auto [a0, a1] = Split(a, half, half); auto [b0, b1] = Split(b, half, half); // Make space to hold results in the output and multiply sub-terms. // z0 = a0 * b0 // z2 = a1 * b1 auto [z0, z2] = Split(dst, a0.size() + b0.size(), a1.size() + b1.size()); KaratsubaMulRecursive(z0, a0, b0, arena); KaratsubaMulRecursive(z2, a1, b1, arena); // Compute (a0 + a1) and (b0 + b1) // // If the upper terms are zero we can just re-use the terms we have, otherwise // we compute the sum and pop off the MSB bigit if no carry occurred. absl::Span asum = a0; if (!a1.empty()) { absl::Span tmp = arena->Alloc(half + 1); asum = tmp.first(Add(tmp, a0, a1)); } absl::Span bsum = b0; if (!b1.empty()) { absl::Span tmp = arena->Alloc(half + 1); bsum = tmp.first(Add(tmp, b0, b1)); } // Compute z1 = asum*bsum - z0 - z2 = (a0 + a1)*(b0 + b1) - z0 - z2 absl::Span z1 = arena->Alloc(asum.size() + bsum.size()); // Compute asum * bsum into the beginning of z1 KaratsubaMulRecursive(z1, asum, bsum, arena); // NOTE: (a0 + a1) * (b0 + b1) >= a0*b0 + a1*b1 so this never underflows. SubInPlace(z1, z0); if (!a1.empty() && !b1.empty()) { SubInPlace(z1, z2); } // We need to add z1*10^half, which we can do by simply adding z1 at a shifted // position in the output. absl::Span dst_z1 = dst.subspan(half); // Although the value of z1 is guaranteed to fit in the available space of // dst, it may have one or more high-order zero bigits because it was sized // conservatively to hold the intermediate result (asum * bsum). We trim these // leading zeros if necessary to ensure that the Add() operation below does // not attempt to write zero bigits past the end of dst. AddInPlace(dst_z1, z1.first(std::min(z1.size(), dst_z1.size()))); // Release temporary memory we used. arena->Reset(arena_start); } // Multiplies two unsigned bigit vectors together using Karatsuba's algorithm. // // This algorithm recursively subdivides the inputs until one or both is below // some threshold, and then falls back to standard long multiplication. void KaratsubaMul(absl::Span dst, absl::Span a, absl::Span b) { ABSL_DCHECK_GE(dst.size(), a.size() + b.size()); if (a.empty() || b.empty()) { absl::c_fill(dst, 0); return; } Arena arena(ArenaSize(a.size(), b.size())); KaratsubaMulRecursive(dst, a, b, &arena); } Bignum& Bignum::operator+=(const Bignum& b) { if (b.is_zero()) { return *this; } if (is_zero()) { *this = b; return *this; } if (is_negative() == b.is_negative()) { // Same sign: // +|a| + +|b| == +(|a| + |b|) // -|a| + -|b| == -(|a| + |b|) // // So we can just sum magnitudes, final sign is the same as A. bigits_.resize(std::max(bigits_.size(), b.bigits_.size()), 0); Bigit carry = AddInPlace(absl::MakeSpan(bigits_), b.bigits_); if (carry) { bigits_.emplace_back(carry); } } else { // We know the signs are different, so there's two options: // -|a| + +|b| = ?(|b| - |a|) // +|a| + -|b| = ?(|a| - |b|) // // With the final sign being dependent on how |a| and |b| relate. if (CmpAbs(bigits_, b.bigits_) >= 0) { // |a| >= |b| // -|a| + +|b| --> -(|a| - |b|) // +|a| + -|b| --> +(|a| - |b|) // // So we can subtract magnitudes, final sign is the same as A. SubInPlace(absl::MakeSpan(bigits_), b.bigits_); } else { // |a| < |b| // -|a| + +|b| --> +(|b| - |a|) // +|a| + -|b| --> -(|b| - |a|) // // So we can compute |b| - |a| and the final sign is the same as B. bigits_.resize(b.bigits_.size()); SubReverseInPlace(absl::MakeSpan(bigits_), b.bigits_); negative_ = b.is_negative(); } } Normalize(); return *this; } Bignum& Bignum::operator-=(const Bignum& b) { if (this == &b) { set_zero(); return *this; } // Compute -(-a + b) == a - b negate(); *this += b; negate(); return *this; } Bignum& Bignum::operator*=(const Bignum& b) { if (is_zero() || b.is_zero()) { return set_zero(); } // Result is only negative if signs are different. const bool negative = (is_negative() != b.is_negative()); // Fast path for single-bigit multiplication. if (bigits_.size() == 1 && b.bigits_.size() == 1) { absl::uint128 prod = absl::uint128(bigits_[0]) * b.bigits_[0]; const uint64_t lo = absl::Uint128Low64(prod); const uint64_t hi = absl::Uint128High64(prod); if (hi == 0) { bigits_ = {lo}; } else { bigits_ = {lo, hi}; } set_negative(negative); return *this; } // Use Karatsuba multiplication. // If the inputs are small enough this will just do long multiplication. BigitVector result; result.resize(bigits_.size() + b.bigits_.size()); KaratsubaMul(absl::MakeSpan(result), bigits_, b.bigits_); bigits_ = std::move(result); negative_ = negative; Normalize(); return *this; } } // namespace exactfloat_internal src/s2/util/math/exactfloat/bignum.h000066400000000000000000000272571524103652300177010ustar00rootroot00000000000000// Copyright 2025 Google LLC // Author: smcallis@google.com (Sean McAllister) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef S2_UTIL_MATH_EXACTFLOAT_BIGNUM_H_ #define S2_UTIL_MATH_EXACTFLOAT_BIGNUM_H_ #include #include #include #include #include #include "absl/algorithm/container.h" #include "absl/base/attributes.h" #include "absl/container/inlined_vector.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" #include "absl/numeric/int128.h" #include "absl/strings/ascii.h" #include "absl/strings/str_format.h" namespace exactfloat_internal { // A digit of a bignum. A contraction of "big digit" (rhymes with the latter). using Bigit = uint64_t; // A class to support arithmetic on large, arbitrary precision integers. // // Large integers are represented as an array of uint64_t values. class Bignum { public: // The most common use of ExactFloat involves evaluating a 3x3 determinant to // determine whether 3 points are oriented clockwise or counter-clockwise. // // The typical number of mantissa bits in the result is probably about 170, so // we allocate 4 bigits (256 bits) inline. using BigitVector = absl::InlinedVector; static constexpr int kBigitBits = std::numeric_limits::digits; Bignum() = default; // Constructs a bignum from an integral value (signed or unsigned). template ::is_integer>> explicit Bignum(T value); //-------------------------------------- // String formatting and parsing. //-------------------------------------- // Constructs a bignum from an ASCII string containing decimal digits. // // The input string must only have an optional leading +/- and decimal digits. // Any other characters will yield std::nullopt. static std::optional FromString(absl::string_view s); // Formats the bignum as a decimal integer into an abseil sink. template friend void AbslStringify(Sink& sink, const Bignum& b); friend std::ostream& operator<<(std::ostream& os, const Bignum& b) { return os << absl::StrFormat("%v", b); } friend std::ostream& operator<<(std::ostream& os, const std::optional& b) { if (!b) { return os << "[nullopt]"; } return os << *b; } //-------------------------------------- // Casting and coercion. //-------------------------------------- // Returns true if bignum can be stored in T without truncation or overflow. template >> bool FitsIn() const; // Cast to an integral type T unconditionally. Use FitsIn() or // ConvertTo to perform conversion with bounds checking. template >> T Cast() const; // Casts the value to the given type if it fits, otherwise std::nullopt. template >> std::optional ConvertTo() const { if (!FitsIn()) { return std::nullopt; } return Cast(); } //-------------------------------------- // General accessors. //-------------------------------------- // Returns the number of bits required for the magnitude of the value. // // Named to match std::bit_width. friend int bit_width(const Bignum& a); // Returns the number of consecutive 0 bits in the value, starting from the // least significant bit. // // Named to match std::countr_zero. friend int countr_zero(const Bignum& a); // Returns true if the n-th bit of the number's magnitude is 1. bool is_bit_set(int nbit) const; // Clears this bignum and sets it to zero. Bignum& set_zero() { negative_ = false; bigits_.clear(); return *this; } // Sets the negative flag on the value. If the value is zero, has no effect. Bignum& set_negative(bool negative = true) { negative_ = !bigits_.empty() && negative; return *this; } // Returns true if the number is zero. bool is_zero() const { return bigits_.empty(); } // Returns true if the number is less than zero. bool is_negative() const { return negative_; } // Returns true if the number is odd (least significant bit is 1). bool is_odd() const { return is_bit_set(0); } // Returns true if the number is even (least significant bit is 0). bool is_even() const { return !is_odd(); } //-------------------------------------- // Comparisons. //-------------------------------------- bool operator==(const Bignum& b) const { return negative_ == b.negative_ && bigits_ == b.bigits_; } bool operator!=(const Bignum& b) const { return !(*this == b); } bool operator<(const Bignum& b) const { return Compare(b) < 0; } bool operator<=(const Bignum& b) const { return Compare(b) <= 0; } bool operator>(const Bignum& b) const { return Compare(b) > 0; } bool operator>=(const Bignum& b) const { return Compare(b) >= 0; } //-------------------------------------- // Arithmetic operators. //-------------------------------------- Bignum operator+() const { return *this; } Bignum operator-() const; // Raise this value to the given power, which must be non-negative. Bignum Pow(int32_t pow) const; Bignum& operator+=(const Bignum& b); Bignum& operator-=(const Bignum& b); Bignum& operator*=(const Bignum& b); Bignum& operator<<=(int nbit); Bignum& operator>>=(int nbit); friend Bignum operator+(Bignum a, const Bignum& b) { return a += b; } friend Bignum operator-(Bignum a, const Bignum& b) { return a -= b; } friend Bignum operator*(Bignum a, const Bignum& b) { return a *= b; } friend Bignum operator<<(Bignum a, int nbit) { return a <<= nbit; } friend Bignum operator>>(Bignum a, int nbit) { return a >>= nbit; } // Negates this bignum in place. void negate() { negative_ = !negative_; if (bigits_.empty()) { negative_ = false; } } // Compares to another bignum, returning -1, 0, +1. int Compare(const Bignum& b) const; private: // Constructs a Bignum from bigits and an optional sign bit. explicit Bignum(BigitVector bigits, bool negative = false) : bigits_(std::move(bigits)), negative_(negative) { Normalize(); } // Drop leading zero bigits, and ensure sign is positive if result is zero. void Normalize() { while (!bigits_.empty() && bigits_.back() == 0) { bigits_.pop_back(); } if (bigits_.empty()) { negative_ = false; } } // We store bignums in sign-magnitude form. bigits_ contains the individual // 64-bit digits of the bignum, stored in little-endian order. If bigits_ is // non-empty, then the last element must be non-zero and when it is empty // (representing a zero value), negative_ must be false. BigitVector bigits_; bool negative_ = false; }; //////////////////////////////////////////////////////////////////////////////// // Implementation Details //////////////////////////////////////////////////////////////////////////////// // Constructs a bignum from an integral value (signed or unsigned). template Bignum::Bignum(T value) { using UT = std::make_unsigned_t; if (value == 0) { return; } negative_ = false; if constexpr (std::is_signed_v) { // Put into constexpr if to avoid warnings when T is unsigned. negative_ = (value < 0); } // Get magnitude of value, handle minimum value of T cleanly. UT mag = static_cast(value); if constexpr (std::is_signed_v) { if (value < 0) { mag = UT(0) - mag; } } // Pack the magnitude into bigits. if constexpr (std::numeric_limits::digits <= kBigitBits) { bigits_.push_back(static_cast(mag)); } else { while (mag) { bigits_.push_back(static_cast(mag)); mag >>= kBigitBits; } } } // Formats the bignum as a decimal integer into an abseil sink. template void AbslStringify(Sink& sink, const Bignum& b) { if (b.is_zero()) { sink.Append("0"); return; } // Sign if (b.is_negative()) { sink.Append("-"); } // Work on a copy of the magnitude. Bignum copy = b; copy.negative_ = false; // 10**19 is the largest power of 10 that fits in 64-bits. So we can // repeatedly divide and modulo the bignum to get uint64_t values we can // format as 19 decimal digits. static_assert(sizeof(Bigit) * 8 == 64); static constexpr uint64_t kChunkDivisor = 10'000'000'000'000'000'000u; Bignum::BigitVector chunks; while (!copy.is_zero()) { absl::uint128 rem = 0; for (int i = static_cast(copy.bigits_.size()) - 1; i >= 0; --i) { absl::uint128 acc = (rem << 64) + copy.bigits_[i]; Bigit quot = static_cast(acc / kChunkDivisor); rem = acc - absl::uint128(quot) * kChunkDivisor; copy.bigits_[i] = quot; } copy.Normalize(); chunks.push_back(static_cast(rem)); } ABSL_DCHECK(!chunks.empty()); // Emit most significant chunk without zero padding. absl::Format(&sink, "%d", chunks.back()); // Emit remaining chunks as fixed-width 19-digit zero-padded blocks. for (int i = static_cast(chunks.size()) - 2; i >= 0; --i) { absl::Format(&sink, "%019d", chunks[i]); } } template inline bool Bignum::FitsIn() const { using UT = std::make_unsigned_t; if (is_zero()) { return true; } // Maximum number of bits that could fit in the output type. constexpr int kTBitWidth = std::numeric_limits::digits; constexpr int kMaxBigits = (kTBitWidth + (kBigitBits - 1)) / kBigitBits; // Fast reject if the bignum couldn't conceivably fit. if (bigits_.size() > kMaxBigits) { return false; } // Unsigned type T can hold the value iff the value is non-negative and // the bitwidth is <= the maximum bit width of the type. if constexpr (!std::is_signed_v) { if (is_negative()) { return false; } return bit_width(*this) <= kTBitWidth; } // T is signed and our bignum isn't zero. ABSL_DCHECK(std::is_signed_v && !is_zero()); if (is_negative()) { // Magnitude must fit in negative value. If the value is negative and // the same bit width as the output type, the only valid value is // -2^(k-1). if (bit_width(*this) == kTBitWidth) { return countr_zero(*this) == kTBitWidth - 1; } return bit_width(*this) < kTBitWidth; } else /* positive */ { return bit_width(*this) <= (kTBitWidth - 1); } } template T Bignum::Cast() const { using UT = std::make_unsigned_t; constexpr int kTBitWidth = std::numeric_limits::digits; if (bigits_.empty()) { return 0; } // T fits in a Bigit, so just cast to truncate. UT residue = 0; if (kTBitWidth <= kBigitBits) { residue = static_cast(bigits_[0]); } else { ABSL_DCHECK_EQ(kTBitWidth % kBigitBits, 0); for (int i = 0; i < kTBitWidth / kBigitBits; ++i) { UT chunk = static_cast(bigits_[i]); residue |= chunk << (i * kBigitBits); } } // Compute two's complement of the residue if value is negative. if (is_negative()) { residue = UT(0) - residue; } return static_cast(residue); } } // namespace exactfloat_internal #endif // S2_UTIL_MATH_EXACTFLOAT_BIGNUM_H_ src/s2/util/math/exactfloat/bignum_test.cc000066400000000000000000001150241524103652300210640ustar00rootroot00000000000000// Copyright 2025 Google LLC // Author: smcallis@google.com (Sean McAllister) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "s2/util/math/exactfloat/bignum.h" #include #include #include #include #include #include #include // TODO: remove once benchmarks are available #if 0 #include "benchmark/benchmark.h" #endif #include #include #include #include "absl/log/log_streamer.h" #include "absl/random/bit_gen_ref.h" #include "absl/random/random.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "s2/s2testing.h" namespace exactfloat_internal { using ::testing::TestWithParam; constexpr uint64_t kU8max = std::numeric_limits::max(); constexpr uint64_t kU16max = std::numeric_limits::max(); constexpr uint64_t kU32max = std::numeric_limits::max(); constexpr uint64_t kU64max = std::numeric_limits::max(); constexpr int64_t kI8max = std::numeric_limits::max(); constexpr int64_t kI16max = std::numeric_limits::max(); constexpr int64_t kI32max = std::numeric_limits::max(); constexpr int64_t kI64max = std::numeric_limits::max(); constexpr int64_t kI8min = std::numeric_limits::min(); constexpr int64_t kI16min = std::numeric_limits::min(); constexpr int64_t kI32min = std::numeric_limits::min(); constexpr int64_t kI64min = std::numeric_limits::min(); // To reduce duplication. inline auto Bn(absl::string_view str) { return Bignum::FromString(str); }; TEST(BignumTest, ZeroInputsNormalizeToZero) { EXPECT_EQ(Bn(""), Bignum(0)); EXPECT_EQ(Bn("+"), Bignum(0)); EXPECT_EQ(Bn("-"), Bignum(0)); EXPECT_EQ(Bn("0"), Bignum(0)); EXPECT_EQ(Bn("-0"), Bignum(0)); EXPECT_EQ(Bn("000000"), Bignum(0)); EXPECT_EQ(Bn("-000000"), Bignum(0)); EXPECT_EQ(Bn("-00000000000000000000"), Bignum(0)); EXPECT_EQ(Bn("+00000000000000000000"), Bignum(0)); } TEST(BignumTest, BasicSmallNumbers) { EXPECT_EQ(Bn("42"), Bignum(42)); EXPECT_EQ(Bn("-17"), Bignum(-17)); EXPECT_EQ(Bn("+123"), Bignum(123)); } TEST(BignumTest, LeadingZeros) { EXPECT_EQ(Bn("0000042"), Bignum(42)); EXPECT_EQ(Bn("-00017"), Bignum(-17)); EXPECT_EQ(Bn("+00007"), Bignum(7)); // Larger bignums. // 10^19 and 10^19 - 1, near chunk boundaries. EXPECT_EQ(Bn("100000000000000000"), Bn("000100000000000000000")); EXPECT_EQ(Bn("99999999999999999"), Bn("000099999999999999999")); // 2^64 - 1 cross-check against integral constructor. EXPECT_EQ(Bn("18446744073709551615"), Bignum(18446744073709551615ull)); // 2^64 cross-check with leading zeros variant via string constructor. EXPECT_EQ(Bn("18446744073709551616"), Bn("00018446744073709551616")); EXPECT_EQ(Bn("-18446744073709551616"), Bn("-00018446744073709551616")); // Multi-digit bignums. // 2^80 EXPECT_EQ(Bn("1208925819614629174706176"), Bn("0001208925819614629174706176")); EXPECT_EQ(Bn("-1208925819614629174706176"), Bn("-0001208925819614629174706176")); // 2^128 EXPECT_EQ(Bn("340282366920938463463374607431768211456"), Bn("000340282366920938463463374607431768211456")); EXPECT_EQ(Bn("-340282366920938463463374607431768211456"), Bn("-000340282366920938463463374607431768211456")); } TEST(BignumTest, MultipleSignsBeforeDigitsCausesFailure) { EXPECT_EQ(Bn("++123"), std::nullopt); EXPECT_EQ(Bn("--42"), std::nullopt); EXPECT_EQ(Bn("+-9"), std::nullopt); EXPECT_EQ(Bn("-+9"), std::nullopt); } TEST(BignumTest, SignInWrongPlaceCausesFailure) { EXPECT_EQ(Bn("123-"), std::nullopt); EXPECT_EQ(Bn("456+"), std::nullopt); EXPECT_EQ(Bn("-789+"), std::nullopt); EXPECT_EQ(Bn("+314-"), std::nullopt); } TEST(BignumTest, ZeroAlwaysFitsIn) { const Bignum zero(0); EXPECT_TRUE(zero.FitsIn()); EXPECT_TRUE(zero.FitsIn()); EXPECT_TRUE(zero.FitsIn()); EXPECT_TRUE(zero.FitsIn()); EXPECT_TRUE(zero.FitsIn()); EXPECT_TRUE(zero.FitsIn()); EXPECT_TRUE(zero.FitsIn()); EXPECT_TRUE(zero.FitsIn()); } TEST(BignumTest, ZeroAlwaysCastsToZero) { Bignum zero; EXPECT_EQ(zero.Cast(), 0); EXPECT_EQ(zero.Cast(), 0); EXPECT_EQ(zero.Cast(), 0); EXPECT_EQ(zero.Cast(), 0); EXPECT_EQ(zero.Cast(), 0); EXPECT_EQ(zero.Cast(), 0); EXPECT_EQ(zero.Cast(), 0); EXPECT_EQ(zero.Cast(), 0); } TEST(BignumTest, NegativeOnlyFitsInSigned) { const Bignum small_neg(-1); EXPECT_FALSE(small_neg.FitsIn()); EXPECT_FALSE(small_neg.FitsIn()); EXPECT_FALSE(small_neg.FitsIn()); EXPECT_FALSE(small_neg.FitsIn()); EXPECT_TRUE(small_neg.FitsIn()); EXPECT_TRUE(small_neg.FitsIn()); EXPECT_TRUE(small_neg.FitsIn()); EXPECT_TRUE(small_neg.FitsIn()); } TEST(BignumTest, FitsInUnsignedBoundsChecks) { const Bignum bn_u8max(kU8max); const Bignum bn_u8over(kU8max + 1); EXPECT_TRUE(bn_u8max.FitsIn()); EXPECT_TRUE(bn_u8max.FitsIn()); EXPECT_TRUE(bn_u8max.FitsIn()); EXPECT_FALSE(bn_u8over.FitsIn()); EXPECT_TRUE(bn_u8over.FitsIn()); EXPECT_TRUE(bn_u8over.FitsIn()); const Bignum bn_u16max(kU16max); const Bignum bn_u16over(kU16max + 1); EXPECT_FALSE(bn_u16max.FitsIn()); EXPECT_TRUE(bn_u16max.FitsIn()); EXPECT_TRUE(bn_u16max.FitsIn()); EXPECT_FALSE(bn_u16over.FitsIn()); EXPECT_FALSE(bn_u16over.FitsIn()); EXPECT_TRUE(bn_u16over.FitsIn()); const Bignum bn_u32max(kU32max); const Bignum bn_u32over(kU32max + 1); EXPECT_FALSE(bn_u32max.FitsIn()); EXPECT_FALSE(bn_u32max.FitsIn()); EXPECT_TRUE(bn_u32max.FitsIn()); EXPECT_FALSE(bn_u32over.FitsIn()); EXPECT_FALSE(bn_u32over.FitsIn()); EXPECT_FALSE(bn_u32over.FitsIn()); const Bignum bn_u64max(kU64max); EXPECT_TRUE(bn_u64max.FitsIn()); // 2^64, need to use string constructor. Bignum bn0 = *Bn("18446744073709551616"); EXPECT_FALSE(bn0.FitsIn()); } TEST(BignumTest, FitsInSignedBoundsChecks) { const Bignum bn_i8max(kI8max); const Bignum bn_i8over(kI8max + 1); EXPECT_TRUE(bn_i8max.FitsIn()); EXPECT_TRUE(bn_i8max.FitsIn()); EXPECT_TRUE(bn_i8max.FitsIn()); EXPECT_FALSE(bn_i8over.FitsIn()); EXPECT_TRUE(bn_i8over.FitsIn()); EXPECT_TRUE(bn_i8over.FitsIn()); const Bignum bn_i16max(kI16max); const Bignum bn_i16over(kI16max + 1); EXPECT_FALSE(bn_i16max.FitsIn()); EXPECT_TRUE(bn_i16max.FitsIn()); EXPECT_TRUE(bn_i16max.FitsIn()); EXPECT_FALSE(bn_i16over.FitsIn()); EXPECT_FALSE(bn_i16over.FitsIn()); EXPECT_TRUE(bn_i16over.FitsIn()); const Bignum bn_i32max(kI32max); const Bignum bn_i32over(kI32max + 1); EXPECT_FALSE(bn_i32max.FitsIn()); EXPECT_FALSE(bn_i32max.FitsIn()); EXPECT_TRUE(bn_i32max.FitsIn()); EXPECT_FALSE(bn_i32over.FitsIn()); EXPECT_FALSE(bn_i32over.FitsIn()); EXPECT_FALSE(bn_i32over.FitsIn()); Bignum bn_i64max(kI64max); EXPECT_TRUE(bn_i64max.FitsIn()); // 2^63, need to use string constructor. Bignum bn0 = *Bn("9223372036854775808"); EXPECT_FALSE(bn0.FitsIn()); const Bignum bn_i8min(kI8min); const Bignum bn_i8under(kI8min - 1); EXPECT_TRUE(bn_i8min.FitsIn()); EXPECT_TRUE(bn_i8min.FitsIn()); EXPECT_TRUE(bn_i8min.FitsIn()); EXPECT_FALSE(bn_i8under.FitsIn()); EXPECT_TRUE(bn_i8under.FitsIn()); EXPECT_TRUE(bn_i8under.FitsIn()); const Bignum bn_i16min(kI16min); const Bignum bn_i16under(kI16min - 1); EXPECT_FALSE(bn_i16min.FitsIn()); EXPECT_TRUE(bn_i16min.FitsIn()); EXPECT_TRUE(bn_i16min.FitsIn()); EXPECT_FALSE(bn_i16under.FitsIn()); EXPECT_FALSE(bn_i16under.FitsIn()); EXPECT_TRUE(bn_i16under.FitsIn()); const Bignum bn_i32min(kI32min); const Bignum bn_i32under(kI32min - 1); EXPECT_FALSE(bn_i32min.FitsIn()); EXPECT_FALSE(bn_i32min.FitsIn()); EXPECT_TRUE(bn_i32min.FitsIn()); EXPECT_FALSE(bn_i32under.FitsIn()); EXPECT_FALSE(bn_i32under.FitsIn()); EXPECT_FALSE(bn_i32under.FitsIn()); Bignum bn_i64min(kI64min); EXPECT_TRUE(bn_i64min.FitsIn()); } TEST(BignumTest, FitsInBasicSanityChecks) { Bignum pos42(42); EXPECT_TRUE(pos42.FitsIn()); EXPECT_TRUE(pos42.FitsIn()); EXPECT_TRUE(pos42.FitsIn()); EXPECT_TRUE(pos42.FitsIn()); EXPECT_TRUE(pos42.FitsIn()); EXPECT_TRUE(pos42.FitsIn()); EXPECT_TRUE(pos42.FitsIn()); EXPECT_TRUE(pos42.FitsIn()); Bignum neg42(-42); EXPECT_TRUE(neg42.FitsIn()); EXPECT_FALSE(neg42.FitsIn()); EXPECT_TRUE(neg42.FitsIn()); EXPECT_FALSE(neg42.FitsIn()); EXPECT_TRUE(neg42.FitsIn()); EXPECT_FALSE(neg42.FitsIn()); EXPECT_TRUE(neg42.FitsIn()); EXPECT_FALSE(neg42.FitsIn()); } TEST(BignumTest, UnsignedCasting) { EXPECT_EQ(Bignum(300).Cast(), static_cast(300)); // Negative to unsigned -> maximum value. Bignum bn1(-1); EXPECT_EQ(bn1.Cast(), std::numeric_limits::max()); EXPECT_EQ(bn1.Cast(), std::numeric_limits::max()); EXPECT_EQ(bn1.Cast(), std::numeric_limits::max()); EXPECT_EQ(bn1.Cast(), std::numeric_limits::max()); // Big values via decimal: 2^64, 2^128-1, 2^128 Bignum bn2 = *Bn("18446744073709551616"); EXPECT_EQ(bn2.Cast(), 0); // 2^128 - 1 -> lower 64 bits = 2^64 - 1 Bignum bn3 = *Bn("340282366920938463463374607431768211455"); EXPECT_EQ(bn3.Cast(), std::numeric_limits::max()); // 2^128 -> lower 64 bits = 0 Bignum bn4 = *Bn("340282366920938463463374607431768211456"); EXPECT_EQ(bn4.Cast(), 0); } TEST(BignumTest, SignedCasting) { // In-range positives stay the same. Bignum bn0(127); EXPECT_EQ(bn0.Cast(), 127); // Positive overflow wraps into negative range. Bignum bn1(128); EXPECT_EQ(bn1.Cast(), -128); // In-range negatives stay the same. Bignum bn2(-128); EXPECT_EQ(bn2.Cast(), -128); // Negative overflow wraps into positive range. Bignum bn3(-129); EXPECT_EQ(bn3.Cast(), 127); // +2^63 over to -2^63 in signed int64. Bignum bn4 = *Bn("9223372036854775808"); EXPECT_EQ(bn4.Cast(), std::numeric_limits::min()); // +2^64 - 1 casts to -1. Bignum bn5 = *Bn("18446744073709551615"); EXPECT_EQ(bn5.Cast(), -1); // -(2^63) - 1 casts to 2^63 - 3 Bignum bn6 = *Bn("-9223372036854775809"); EXPECT_EQ(bn6.Cast(), std::numeric_limits::max()); } TEST(BignumTest, CastingLargeResidues) { // 2^80 + 0x1234 -> low 64 bits should be 0x1234. Bignum bn0 = *Bn("1208925819614629174710836"); EXPECT_EQ(bn0.Cast(), 0x1234); EXPECT_EQ(bn0.Cast(), 0x1234); // -(2^80 + 1) -> low 64 bits = 0xFFFFFFFFFFFFFFFF; signed = -1 Bignum bn1 = *Bn("-1208925819614629174706177"); EXPECT_EQ(bn1.Cast(), std::numeric_limits::max()); EXPECT_EQ(bn1.Cast(), -1); } TEST(BignumTest, UnaryOperators) { EXPECT_EQ(+Bignum(0), Bignum(0)); EXPECT_EQ(-Bignum(0), Bignum(0)); EXPECT_EQ(+Bignum(+42), Bignum(+42)); EXPECT_EQ(+Bignum(-42), Bignum(-42)); EXPECT_EQ(-Bignum(+42), Bignum(-42)); EXPECT_EQ(-Bignum(-17), Bignum(+17)); } TEST(BignumTest, Addition) { // Basic combinations of signs EXPECT_EQ(Bignum(+5) + Bignum(+3), Bignum(+8)); EXPECT_EQ(Bignum(-5) + Bignum(-3), Bignum(-8)); EXPECT_EQ(Bignum(+5) + Bignum(-3), Bignum(+2)); EXPECT_EQ(Bignum(-5) + Bignum(+3), Bignum(-2)); // Identity and additive inverse EXPECT_EQ(Bignum(42) + Bignum(0), Bignum(42)); EXPECT_EQ(Bignum(0) + Bignum(42), Bignum(42)); EXPECT_EQ(Bignum(5) + Bignum(-5), Bignum(0)); // Carry propagation const auto bn_u64max = Bignum(kU64max); EXPECT_EQ(bn_u64max + Bignum(1), *Bn("18446744073709551616")); EXPECT_EQ(bn_u64max + bn_u64max, *Bn("36893488147419103230")); // Aliasing (x += x) Bignum a = bn_u64max; a += a; EXPECT_EQ(a, *Bn("36893488147419103230")); } TEST(BignumTest, Subtraction) { // Basic combinations of signs EXPECT_EQ(Bignum(+5) - Bignum(+3), Bignum(+2)); EXPECT_EQ(Bignum(+3) - Bignum(+5), Bignum(-2)); EXPECT_EQ(Bignum(-5) - Bignum(-3), Bignum(-2)); EXPECT_EQ(Bignum(+5) - Bignum(-3), Bignum(+8)); EXPECT_EQ(Bignum(-5) - Bignum(+3), Bignum(-8)); // Identity and subtracting to zero EXPECT_EQ(Bignum(42) - Bignum(0), Bignum(42)); EXPECT_EQ(Bignum(0) - Bignum(42), Bignum(-42)); EXPECT_EQ(Bignum(42) - Bignum(42), Bignum(0)); // Borrow propagation const auto bn_u64max = Bignum(kU64max); const auto two_pow_64 = *Bn("18446744073709551616"); EXPECT_EQ(two_pow_64 - Bignum(1), bn_u64max); // Aliasing (x -= x) Bignum a(100); a -= a; EXPECT_EQ(a, Bignum(0)); } TEST(BignumTest, MixedOperations) { Bignum a(10), b(20), c(-5); EXPECT_EQ((a + b) - a, b); EXPECT_EQ((b - a) + a, b); EXPECT_EQ(a + c, Bignum(5)); EXPECT_EQ(c - a, Bignum(-15)); } TEST(BignumTest, LargeNumberArithmetic) { const auto two_pow_128_minus_1 = *Bn("340282366920938463463374607431768211455"); const auto two_pow_128 = *Bn("340282366920938463463374607431768211456"); const auto two_pow_64 = *Bn("18446744073709551616"); // Test multi-bigit carry propagation: (2^128 - 1) + 1 = 2^128 EXPECT_EQ(two_pow_128_minus_1 + Bignum(1), two_pow_128); // Test multi-bigit borrow propagation: 2^128 - 1 = (2^128 - 1) EXPECT_EQ(two_pow_128 - Bignum(1), two_pow_128_minus_1); // Subtraction resulting in a sign change with large numbers. const auto neg_two_pow_128_minus_1 = *Bn("-340282366920938463463374607431768211455"); EXPECT_EQ(Bignum(1) - two_pow_128, neg_two_pow_128_minus_1); // Addition of large numbers with different signs (triggers subtraction). EXPECT_EQ(two_pow_128 + Bignum(-1), two_pow_128_minus_1); // Subtraction of large numbers with different signs (triggers addition). EXPECT_EQ(two_pow_128_minus_1 - Bignum(-1), two_pow_128); // Add two different large positive numbers: 2^128 + 2^64 const auto sum_128_64 = *Bn("340282366920938463481821351505477763072"); EXPECT_EQ(two_pow_128 + two_pow_64, sum_128_64); // Subtract two different large positive numbers: 2^128 - 2^64 const auto diff_128_64 = *Bn("340282366920938463444927863358058659840"); EXPECT_EQ(two_pow_128 - two_pow_64, diff_128_64); } TEST(BignumTest, LeftShift) { EXPECT_EQ((Bignum(1) << 0), Bignum(1)); EXPECT_EQ((Bignum(1) << 1), Bignum(2)); EXPECT_EQ((Bignum(1) << 63), *Bn("9223372036854775808")); EXPECT_EQ((Bignum(1) << 64), *Bn("18446744073709551616")); EXPECT_EQ((Bignum(-1) << 64), *Bn("-18446744073709551616")); const auto bn_u64max = Bignum(kU64max); const auto two_pow_128_minus_two_pow_64 = *Bn("340282366920938463444927863358058659840"); EXPECT_EQ((bn_u64max << 64), two_pow_128_minus_two_pow_64); Bignum a(5); a <<= 2; EXPECT_EQ(a, Bignum(20)); // Shifting zero or by zero amount. EXPECT_EQ((Bignum(0) << 100), Bignum(0)); EXPECT_EQ((Bignum(123) << 0), Bignum(123)); } TEST(BignumTest, RightShift) { EXPECT_EQ((Bignum(8) >> 0), Bignum(8)); EXPECT_EQ((Bignum(8) >> 3), Bignum(1)); EXPECT_EQ((Bignum(8) >> 4), Bignum(0)); EXPECT_EQ((Bignum(7) >> 2), Bignum(1)); EXPECT_EQ((Bignum(-7) >> 2), Bignum(-1)); const auto two_pow_64 = *Bn("18446744073709551616"); EXPECT_EQ((two_pow_64 >> 1), *Bn("9223372036854775808")); EXPECT_EQ((two_pow_64 >> 64), Bignum(1)); EXPECT_EQ((two_pow_64 >> 65), Bignum(0)); const auto u64max = Bignum(std::numeric_limits::max()); const auto two_pow_128_minus_1 = *Bn("340282366920938463463374607431768211455"); EXPECT_EQ((two_pow_128_minus_1 >> 64), u64max); const auto two_pow_65_minus_1 = *Bn("36893488147419103231"); EXPECT_EQ((two_pow_65_minus_1 >> 63), Bignum(3)); Bignum b(20); b >>= 2; EXPECT_EQ(b, Bignum(5)); // Shifting zero or by zero amount. EXPECT_EQ((Bignum(0) >> 100), Bignum(0)); EXPECT_EQ((Bignum(123) >> 0), Bignum(123)); // Shifting to zero. EXPECT_EQ((Bignum(100) >> 100), Bignum(0)); } TEST(BignumTest, Multiplication) { // Zero EXPECT_EQ(Bignum(123) * Bignum(0), Bignum(0)); EXPECT_EQ(Bignum(0) * Bignum(456), Bignum(0)); // Identity EXPECT_EQ(Bignum(123) * Bignum(1), Bignum(123)); EXPECT_EQ(Bignum(1) * Bignum(456), Bignum(456)); EXPECT_EQ(Bignum(-123) * Bignum(1), Bignum(-123)); // Signs EXPECT_EQ(Bignum(10) * Bignum(20), Bignum(200)); EXPECT_EQ(Bignum(-10) * Bignum(20), Bignum(-200)); EXPECT_EQ(Bignum(10) * Bignum(-20), Bignum(-200)); EXPECT_EQ(Bignum(-10) * Bignum(-20), Bignum(200)); // Simple carry const auto bn_u32max = Bignum(kU32max); EXPECT_EQ(bn_u32max * Bignum(2), *Bn("8589934590")); // 1x1 bigit fast path const auto bn_u64max = Bignum(kU64max); EXPECT_EQ(Bignum(2) * bn_u64max, *Bn("36893488147419103230")); // 1xN bigit multiplication const auto two_pow_128_minus_1 = *Bn("340282366920938463463374607431768211455"); const auto res_1xN = *Bn("680564733841876926926749214863536422910"); EXPECT_EQ(two_pow_128_minus_1 * Bignum(2), res_1xN); // Check that aliasing doesn't cause problems. Bignum a(100); a *= a; EXPECT_EQ(a, Bignum(10000)); Bignum b = *Bn("10000000000000000000"); // > 64 bits b *= b; EXPECT_EQ(b, *Bn("100000000000000000000000000000000000000")); // Karatsuba threshold test // (2^128 - 1) * (2^128 - 1) = 2^256 - 2*2^128 + 1 // This should trigger karatsuba if the threshold is low enough. EXPECT_EQ(two_pow_128_minus_1 * two_pow_128_minus_1, *Bn("115792089237316195423570985008687907852589419931798687112530" "834793049593217025")); // Karatsuba with uneven operands EXPECT_EQ(two_pow_128_minus_1 * bn_u64max, *Bn("6277101735386680763495507056286727952620534092958556749825")); } TEST(BignumTest, CountrZero) { EXPECT_EQ(countr_zero(Bignum(0)), 0); EXPECT_EQ(countr_zero(Bignum(1)), 0); EXPECT_EQ(countr_zero(Bignum(7)), 0); EXPECT_EQ(countr_zero(Bignum(-7)), 0); EXPECT_EQ(countr_zero(Bignum(2)), 1); EXPECT_EQ(countr_zero(Bignum(8)), 3); EXPECT_EQ(countr_zero(Bignum(10)), 1); // 0b1010 EXPECT_EQ(countr_zero(Bignum(12)), 2); // 0b1100 auto two_pow_64 = Bignum(1) << 64; EXPECT_EQ(countr_zero(two_pow_64), 64); auto large_shifted = Bignum(6) << 100; // 0b110 << 100 EXPECT_EQ(countr_zero(large_shifted), 101); auto neg_large_shifted = Bignum(-5) << 200; EXPECT_EQ(countr_zero(neg_large_shifted), 200); } TEST(BignumTest, is_bit_set) { EXPECT_FALSE(Bignum(0).is_bit_set(0)); EXPECT_FALSE(Bignum(0).is_bit_set(100)); // 5 = 0b101 Bignum five(5); EXPECT_TRUE(five.is_bit_set(0)); EXPECT_FALSE(five.is_bit_set(1)); EXPECT_TRUE(five.is_bit_set(2)); EXPECT_FALSE(five.is_bit_set(3)); // Negative numbers should test the magnitude. Bignum neg_five(-5); EXPECT_TRUE(neg_five.is_bit_set(0)); EXPECT_FALSE(neg_five.is_bit_set(1)); EXPECT_TRUE(neg_five.is_bit_set(2)); // Test edges of and across bigits. Bignum high_is_bit_set_63 = Bignum(1) << 63; EXPECT_FALSE(high_is_bit_set_63.is_bit_set(62)); EXPECT_TRUE(high_is_bit_set_63.is_bit_set(63)); EXPECT_FALSE(high_is_bit_set_63.is_bit_set(64)); Bignum cross_bigit = (Bignum(1) << 100) + Bignum(1); EXPECT_TRUE(cross_bigit.is_bit_set(0)); EXPECT_TRUE(cross_bigit.is_bit_set(100)); EXPECT_FALSE(cross_bigit.is_bit_set(50)); EXPECT_FALSE(cross_bigit.is_bit_set(1000)); } TEST(BignumTest, Pow) { // Edge cases EXPECT_EQ(Bignum(0).Pow(0), Bignum(1)); EXPECT_EQ(Bignum(123).Pow(0), Bignum(1)); EXPECT_EQ(Bignum(0).Pow(123), Bignum(0)); EXPECT_EQ(Bignum(1).Pow(12345), Bignum(1)); // Negative base EXPECT_EQ(Bignum(-1).Pow(2), Bignum(1)); EXPECT_EQ(Bignum(-1).Pow(3), Bignum(-1)); EXPECT_EQ(Bignum(-2).Pow(2), Bignum(4)); EXPECT_EQ(Bignum(-2).Pow(3), Bignum(-8)); // Basic powers EXPECT_EQ(Bignum(2).Pow(10), Bignum(1024)); EXPECT_EQ(Bignum(3).Pow(5), Bignum(243)); EXPECT_EQ(Bignum(10).Pow(18), *Bn("1000000000000000000")); // Large exponent Bignum two_pow_100 = Bignum(1) << 100; EXPECT_EQ(Bignum(2).Pow(100), two_pow_100); // Large base Bignum ten_pow_19 = *Bn("10000000000000000000"); Bignum ten_pow_38 = *Bn("100000000000000000000000000000000000000"); EXPECT_EQ(ten_pow_19.Pow(2), ten_pow_38); } TEST(BignumTest, SetZero) { Bignum a(123); a.set_zero(); EXPECT_TRUE(a.is_zero()); Bignum b(-456); b.set_zero(); EXPECT_EQ(b, Bignum(0)); } TEST(BignumTest, SetNegativeSetPositive) { Bignum a(42); a.set_negative(); EXPECT_TRUE(a.is_negative()); EXPECT_EQ(a, Bignum(-42)); a.set_negative(false); EXPECT_FALSE(a.is_negative()); EXPECT_EQ(a, Bignum(42)); // set_negative() has no effect on zero. Bignum b(0); b.set_negative(); EXPECT_FALSE(b.is_negative()); EXPECT_EQ(b, Bignum(0)); } TEST(BignumTest, Comparisons) { EXPECT_EQ(*Bn("123"), Bignum(123)); EXPECT_EQ(*Bn("-123"), Bignum(-123)); EXPECT_NE(*Bn("123"), Bignum(-123)); EXPECT_EQ(Bignum(0), Bignum(0)); EXPECT_NE(Bignum(0), Bignum(1)); // Positive vs Positive EXPECT_LT(Bignum(100), Bignum(200)); EXPECT_GT(Bignum(200), Bignum(100)); EXPECT_LE(Bignum(100), Bignum(200)); EXPECT_GE(Bignum(200), Bignum(100)); // Negative vs Negative EXPECT_LT(Bignum(-200), Bignum(-100)); EXPECT_GT(Bignum(-100), Bignum(-200)); EXPECT_GE(Bignum(-100), Bignum(-200)); EXPECT_LE(Bignum(-200), Bignum(-100)); // Positive vs Negative EXPECT_LT(Bignum(-10), Bignum(10)); EXPECT_GT(Bignum(10), Bignum(-10)); // Zero EXPECT_LT(Bignum(-1), Bignum(0)); EXPECT_LT(Bignum(0), Bignum(1)); EXPECT_GT(Bignum(0), Bignum(-1)); EXPECT_GT(Bignum(1), Bignum(0)); // Multi-bigit const auto two_pow_64 = *Bn("18446744073709551616"); EXPECT_LT(Bignum(0), two_pow_64); EXPECT_GT(two_pow_64, Bignum(0)); EXPECT_LT(Bignum(-1), two_pow_64); EXPECT_GT(two_pow_64, Bignum(-1)); EXPECT_LE(Bignum(100), Bignum(200)); EXPECT_LE(Bignum(100), Bignum(100)); EXPECT_LE(Bignum(-200), Bignum(-100)); EXPECT_LE(Bignum(-100), Bignum(-100)); EXPECT_GT(Bignum(200), Bignum(100)); EXPECT_GE(Bignum(200), Bignum(100)); EXPECT_GE(Bignum(100), Bignum(100)); EXPECT_GE(Bignum(-100), Bignum(-200)); EXPECT_GE(Bignum(-100), Bignum(-100)); EXPECT_LT(Bignum(100), Bignum(200)); EXPECT_LE(Bignum(0), Bignum(0)); EXPECT_GE(Bignum(0), Bignum(0)); } // RAII wrapper for OpenSSL BIGNUM class OpenSSLBignum { public: OpenSSLBignum() : bn_(BN_new()) {} // Construct from a decimal number in a string. // // We take decimal as a string so that it's explicitly zero-terminated. explicit OpenSSLBignum(const std::string& decimal) : bn_(BN_new()) { BN_dec2bn(&bn_, decimal.data()); } explicit OpenSSLBignum(uint64_t value) : bn_(BN_new()) { BN_set_word(bn_, value); } ~OpenSSLBignum() { BN_free(bn_); } OpenSSLBignum(OpenSSLBignum&& other) noexcept : bn_(other.bn_) { other.bn_ = nullptr; } OpenSSLBignum& operator=(OpenSSLBignum&& other) noexcept { if (this != &other) { BN_free(bn_); bn_ = other.bn_; other.bn_ = nullptr; } return *this; } OpenSSLBignum(const OpenSSLBignum& other) : bn_(BN_dup(other.bn_)) {} OpenSSLBignum& operator=(const OpenSSLBignum& other) { if (this != &other) { BN_copy(bn_, other.bn_); } return *this; } BIGNUM* get() const { return bn_; } private: BIGNUM* bn_; }; // Power of two for fast modulo. const int kRandomBignumCount = 128; static std::vector GenerateRandomNumberStrings( absl::BitGenRef bitgen, int bits) { std::vector numbers; numbers.reserve(kRandomBignumCount); for (int i = 0; i < kRandomBignumCount; ++i) { std::string num; // Generate approximately `bits` worth of decimal digits int decimal_digits = (bits * 3) / 10; // log10(2^bits) ≈ bits * 0.301 // First digit can't be zero absl::StrAppend(&num, absl::StrFormat("%d", absl::Uniform(bitgen, 1, 9))); for (int j = 1; j < decimal_digits; ++j) { num += absl::Uniform(bitgen, '0', '9'); } numbers.push_back(num); } return numbers; } // Basic correctness test to ensure OpenSSL integration is working TEST(BignumTest, OpenSSLIntegration) { OpenSSLBignum a(123); OpenSSLBignum b(456); OpenSSLBignum result; BN_add(result.get(), a.get(), b.get()); char* str = BN_bn2dec(result.get()); EXPECT_STREQ(str, "579"); OPENSSL_free(str); } TEST(BignumTest, ResultsMatch) { // Test that and OpenSSL produce the same results const Bignum w_a(12345); const Bignum w_b(67890); Bignum w_result = w_a + w_b; const OpenSSLBignum ssl_a(12345); const OpenSSLBignum ssl_b(67890); OpenSSLBignum ssl_result; BN_add(ssl_result.get(), ssl_a.get(), ssl_b.get()); char* ssl_str = BN_bn2dec(ssl_result.get()); std::string w_str = absl::StrFormat("%v", w_result); EXPECT_EQ(w_str, std::string(ssl_str)); OPENSSL_free(ssl_str); } // Different number sizes for benchmarking. enum class NumberSizeClass : uint32_t { kSmall = 64, kMedium = 256, kLarge = 1024, kHuge = 4096, kMega = 18000 }; std::vector RandomNumberStrings(absl::BitGenRef bitgen, NumberSizeClass size_class) { return GenerateRandomNumberStrings(bitgen, static_cast(size_class)); } class VsOpenSSLTest : public TestWithParam> { protected: // Returns a vector of pairs of numbers (as decimal strings) based on the // parameters that the test suite was created with. // // E.g. If the test suite was instantiate with (kSmall, kHuge) as the number // classes, then this will return a small value on the left and a huge value // on the right. (kHuge, kSmall) would return the opposite. std::vector> Numbers( absl::BitGenRef bitgen) { auto numbers0 = RandomNumberStrings(bitgen, GetParam().first); auto numbers1 = RandomNumberStrings(bitgen, GetParam().second); ABSL_CHECK_EQ(numbers0.size(), numbers1.size()); std::vector> numbers; numbers.reserve(numbers0.size()); for (size_t i = 0; i < numbers0.size(); ++i) { numbers.emplace_back(numbers0[i], numbers1[i]); } return numbers; } }; TEST_P(VsOpenSSLTest, MultiplyCorrect) { absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "MULTIPLY_CORRECT", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); // Test that multiplication produces the same results as OpenSSL. BN_CTX* ctx = BN_CTX_new(); for (const auto& [a, b] : Numbers(bitgen)) { const Bignum bn_a = *Bignum::FromString(a); const Bignum bn_b = *Bignum::FromString(b); const Bignum bn_result = bn_a * bn_b; const OpenSSLBignum ssl_a(a); const OpenSSLBignum ssl_b(b); OpenSSLBignum ssl_result; BN_mul(ssl_result.get(), ssl_a.get(), ssl_b.get(), ctx); // Compare string representations char* ssl_str = BN_bn2dec(ssl_result.get()); std::string bn_str = absl::StrFormat("%v", bn_result); EXPECT_EQ(bn_str, std::string(ssl_str)) << "Mismatch for multiplication" << "\nBignum result: " << bn_str.substr(0, 100) << "..." << "\nOpenSSL result: " << std::string(ssl_str).substr(0, 100) << "..."; OPENSSL_free(ssl_str); } BN_CTX_free(ctx); } TEST_P(VsOpenSSLTest, AdditionCorrect) { absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "ADDITION_CORRECT", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); // Test that addition produces correct results by comparing to OpenSSL. for (const auto& [a, b] : Numbers(bitgen)) { const Bignum bn_a = *Bignum::FromString(a); const Bignum bn_b = *Bignum::FromString(b); const Bignum bn_result = bn_a + bn_b; const OpenSSLBignum ssl_a(a); const OpenSSLBignum ssl_b(b); OpenSSLBignum ssl_result; BN_add(ssl_result.get(), ssl_a.get(), ssl_b.get()); // Compare string representations char* ssl_str = BN_bn2dec(ssl_result.get()); std::string bn_str = absl::StrFormat("%v", bn_result); EXPECT_EQ(bn_str, std::string(ssl_str)) << "Mismatch for addition" << "\nBignum result: " << bn_str.substr(0, 100) << "..." << "\nOpenSSL result: " << std::string(ssl_str).substr(0, 100) << "..."; OPENSSL_free(ssl_str); } } TEST_P(VsOpenSSLTest, SubtractionCorrect) { absl::BitGen bitgen(S2Testing::MakeTaggedSeedSeq( "SUBTRACTION_CORRECT", absl::LogInfoStreamer(__FILE__, __LINE__).stream())); // Test that subtraction produces correct results by comparing to // OpenSSL. for (const auto& [a, b] : Numbers(bitgen)) { const Bignum bn_a = *Bignum::FromString(a); const Bignum bn_b = *Bignum::FromString(b); const Bignum bn_result = bn_a - bn_b; const OpenSSLBignum ssl_a(a); const OpenSSLBignum ssl_b(b); OpenSSLBignum ssl_result; BN_sub(ssl_result.get(), ssl_a.get(), ssl_b.get()); // Compare string representations char* ssl_str = BN_bn2dec(ssl_result.get()); std::string bn_str = absl::StrFormat("%v", bn_result); EXPECT_EQ(bn_str, std::string(ssl_str)) << "Mismatch for addition" << "\nBignum result: " << bn_str.substr(0, 100) << "..." << "\nOpenSSL result: " << std::string(ssl_str).substr(0, 100) << "..."; OPENSSL_free(ssl_str); } } // clang-format off INSTANTIATE_TEST_SUITE_P( VsOpenSSL, VsOpenSSLTest, ::testing::Values( std::make_pair(NumberSizeClass::kSmall, NumberSizeClass::kSmall), std::make_pair(NumberSizeClass::kSmall, NumberSizeClass::kHuge), std::make_pair(NumberSizeClass::kHuge, NumberSizeClass::kSmall), std::make_pair(NumberSizeClass::kMedium, NumberSizeClass::kMedium), std::make_pair(NumberSizeClass::kLarge, NumberSizeClass::kLarge), std::make_pair(NumberSizeClass::kHuge, NumberSizeClass::kHuge), std::make_pair(NumberSizeClass::kMega, NumberSizeClass::kMega))); // clang-format on // TODO: Enable once benchmark is integrated. #if 0 template void BignumBinaryOpBenchmark(benchmark::State& state, const std::vector& number_strings, BinaryOp op) { std::vector numbers; for (const auto& str : number_strings) { numbers.push_back(*Bignum::FromString(str)); } Bignum result; size_t idx = 0; for (auto _ : state) { const Bignum& a = numbers[(idx + 0) % kRandomBignumCount]; const Bignum& b = numbers[(idx + 1) % kRandomBignumCount]; result = op(a, b); benchmark::DoNotOptimize(result); ++idx; } } void BignumPowBenchmark(benchmark::State& state, const std::vector& number_strings, int exponent) { std::vector numbers; for (const auto& str : number_strings) { numbers.push_back(*Bignum::FromString(str)); } Bignum result; size_t idx = 0; for (auto _ : state) { const Bignum& base = numbers[(idx + 0) % kRandomBignumCount]; result = base.Pow(exponent); benchmark::DoNotOptimize(result); ++idx; } } template void OpenSSLBinaryOpBenchmark(benchmark::State& state, const std::vector& number_strings, BinaryOp op) { std::vector numbers; for (const auto& str : number_strings) { numbers.emplace_back(str); } size_t idx = 0; for (auto _ : state) { OpenSSLBignum result; const OpenSSLBignum& a = numbers[(idx + 0) % kRandomBignumCount]; const OpenSSLBignum& b = numbers[(idx + 1) % kRandomBignumCount]; op(result.get(), a.get(), b.get()); benchmark::DoNotOptimize(result.get()); ++idx; } } template void OpenSSLMulOpBenchmark(benchmark::State& state, const std::vector& number_strings, MulOp op) { std::vector numbers; for (const auto& str : number_strings) { numbers.emplace_back(str); } BN_CTX* ctx = BN_CTX_new(); size_t idx = 0; for (auto _ : state) { OpenSSLBignum result; const OpenSSLBignum& a = numbers[(idx + 0) % kRandomBignumCount]; const OpenSSLBignum& b = numbers[(idx + 1) % kRandomBignumCount]; op(result.get(), a.get(), b.get(), ctx); benchmark::DoNotOptimize(result.get()); ++idx; } BN_CTX_free(ctx); } void OpenSSLPowBenchmark(benchmark::State& state, const std::vector& number_strings, int exponent) { std::vector numbers; for (const auto& str : number_strings) { numbers.emplace_back(str); } const OpenSSLBignum exp(exponent); BN_CTX* ctx = BN_CTX_new(); size_t idx = 0; for (auto _ : state) { OpenSSLBignum result; const OpenSSLBignum& base = numbers[(idx + 0) % kRandomBignumCount]; BN_exp(result.get(), base.get(), exp.get(), ctx); benchmark::DoNotOptimize(result.get()); ++idx; } BN_CTX_free(ctx); } std::vector SmallNumbers(absl::BitGenRef bitgen) { return RandomNumberStrings(bitgen, NumberSizeClass::kSmall); } std::vector MediumNumbers(absl::BitGenRef bitgen) { return RandomNumberStrings(bitgen, NumberSizeClass::kMedium); } std::vector LargeNumbers(absl::BitGenRef bitgen) { return RandomNumberStrings(bitgen, NumberSizeClass::kLarge); } std::vector HugeNumbers(absl::BitGenRef bitgen) { return RandomNumberStrings(bitgen, NumberSizeClass::kHuge); } std::vector MegaNumbers(absl::BitGenRef bitgen) { return RandomNumberStrings(bitgen, NumberSizeClass::kMega); } void BM_Bignum_AddSmall(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, SmallNumbers(bitgen), std::plus{}); } BENCHMARK(BM_Bignum_AddSmall); void BM_Bignum_AddMedium(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, MediumNumbers(bitgen), std::plus{}); } BENCHMARK(BM_Bignum_AddMedium); void BM_Bignum_AddLarge(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, LargeNumbers(bitgen), std::plus{}); } BENCHMARK(BM_Bignum_AddLarge); void BM_Bignum_AddHuge(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, HugeNumbers(bitgen), std::plus{}); } BENCHMARK(BM_Bignum_AddHuge); void BM_Bignum_AddMega(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, MegaNumbers(bitgen), std::plus{}); } BENCHMARK(BM_Bignum_AddMega); void BM_OpenSSL_AddSmall(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLBinaryOpBenchmark(state, SmallNumbers(bitgen), BN_add); } BENCHMARK(BM_OpenSSL_AddSmall); void BM_OpenSSL_AddMedium(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLBinaryOpBenchmark(state, MediumNumbers(bitgen), BN_add); } BENCHMARK(BM_OpenSSL_AddMedium); void BM_OpenSSL_AddLarge(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLBinaryOpBenchmark(state, LargeNumbers(bitgen), BN_add); } BENCHMARK(BM_OpenSSL_AddLarge); void BM_OpenSSL_AddHuge(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLBinaryOpBenchmark(state, HugeNumbers(bitgen), BN_add); } BENCHMARK(BM_OpenSSL_AddHuge); void BM_OpenSSL_AddMega(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLBinaryOpBenchmark(state, MegaNumbers(bitgen), BN_add); } BENCHMARK(BM_OpenSSL_AddMega); void BM_Bignum_MulSmall(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, SmallNumbers(bitgen), std::multiplies{}); } BENCHMARK(BM_Bignum_MulSmall); void BM_Bignum_MulMedium(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, MediumNumbers(bitgen), std::multiplies{}); } BENCHMARK(BM_Bignum_MulMedium); void BM_Bignum_MulLarge(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, LargeNumbers(bitgen), std::multiplies{}); } BENCHMARK(BM_Bignum_MulLarge); void BM_Bignum_MulHuge(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, HugeNumbers(bitgen), std::multiplies{}); } BENCHMARK(BM_Bignum_MulHuge); void BM_Bignum_MulMega(benchmark::State& state) { std::mt19937_64 bitgen; BignumBinaryOpBenchmark(state, MegaNumbers(bitgen), std::multiplies{}); } BENCHMARK(BM_Bignum_MulMega); void BM_OpenSSL_MulSmall(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLMulOpBenchmark(state, SmallNumbers(bitgen), BN_mul); } BENCHMARK(BM_OpenSSL_MulSmall); void BM_OpenSSL_MulMedium(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLMulOpBenchmark(state, MediumNumbers(bitgen), BN_mul); } BENCHMARK(BM_OpenSSL_MulMedium); void BM_OpenSSL_MulLarge(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLMulOpBenchmark(state, LargeNumbers(bitgen), BN_mul); } BENCHMARK(BM_OpenSSL_MulLarge); void BM_OpenSSL_MulHuge(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLMulOpBenchmark(state, HugeNumbers(bitgen), BN_mul); } BENCHMARK(BM_OpenSSL_MulHuge); void BM_OpenSSL_MulMega(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLMulOpBenchmark(state, MegaNumbers(bitgen), BN_mul); } BENCHMARK(BM_OpenSSL_MulMega); void BM_Bignum_PowSmall(benchmark::State& state) { std::mt19937_64 bitgen; BignumPowBenchmark(state, SmallNumbers(bitgen), 20); } BENCHMARK(BM_Bignum_PowSmall); void BM_Bignum_PowMedium(benchmark::State& state) { std::mt19937_64 bitgen; BignumPowBenchmark(state, MediumNumbers(bitgen), 10); } BENCHMARK(BM_Bignum_PowMedium); void BM_OpenSSL_PowSmall(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLPowBenchmark(state, SmallNumbers(bitgen), 20); } BENCHMARK(BM_OpenSSL_PowSmall); void BM_OpenSSL_PowMedium(benchmark::State& state) { std::mt19937_64 bitgen; OpenSSLPowBenchmark(state, MediumNumbers(bitgen), 10); } BENCHMARK(BM_OpenSSL_PowMedium); #endif } // namespace exactfloat_internal src/s2/util/math/exactfloat/exactfloat.cc000066400000000000000000000546341524103652300207070ustar00rootroot00000000000000// Copyright 2009 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/util/math/exactfloat/exactfloat.h" #include #include #include #include #include #include #include #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" namespace exactfloat { using std::max; // To simplify the overflow/underflow logic, we limit the exponent and // precision range so that (2 * bn_exp_) does not overflow an "int". We take // advantage of this, for example, by only checking for overflow/underflow // *after* multiplying two numbers. static_assert(ExactFloat::kMaxExp <= INT_MAX / 2 && ExactFloat::kMinExp - ExactFloat::kMaxPrec >= INT_MIN / 2, "exactfloat exponent might overflow"); ExactFloat::ExactFloat(double v) { sign_ = std::signbit(v) ? -1 : 1; if (std::isnan(v)) { set_nan(); } else if (std::isinf(v)) { set_inf(sign_); } else { // The following code is much simpler than messing about with bit masks, // has the advantage of handling denormalized numbers and zero correctly, // and is actually quite efficient (at least compared to the rest of this // code). "f" is a fraction in the range [0.5, 1), so if we shift it left // by the number of mantissa bits in a double (53, including the leading // "1") then the result is always an integer. int exp; double f = std::frexp(std::fabs(v), &exp); uint64_t m = static_cast(std::ldexp(f, kDoubleMantissaBits)); bn_ = Bignum(m); bn_exp_ = exp - kDoubleMantissaBits; Canonicalize(); } } // Calculates abs(v) without UB. SafeAbs(INT_MIN) == INT_MIN. // Generates the same code as std::abs(). // https://godbolt.org/z/eT6KW1zGb unsigned SafeAbs(int v) { return v < 0 ? -static_cast(v) : v; } ExactFloat::ExactFloat(int v) { sign_ = (v >= 0) ? 1 : -1; bn_exp_ = 0; bn_ = Bignum(SafeAbs(v)); Canonicalize(); } ExactFloat ExactFloat::SignedZero(int sign) { ExactFloat r; r.set_zero(sign); return r; } ExactFloat ExactFloat::Infinity(int sign) { ExactFloat r; r.set_inf(sign); return r; } ExactFloat ExactFloat::NaN() { ExactFloat r; r.set_nan(); return r; } int ExactFloat::prec() const { return bit_width(bn_); } int ExactFloat::exp() const { ABSL_DCHECK(isnormal(*this)); return bn_exp_ + bit_width(bn_); } void ExactFloat::set_zero(int sign) { sign_ = sign; bn_exp_ = kExpZero; bn_.set_zero(); } void ExactFloat::set_inf(int sign) { sign_ = sign; bn_exp_ = kExpInfinity; bn_.set_zero(); } void ExactFloat::set_nan() { sign_ = 1; bn_exp_ = kExpNaN; bn_.set_zero(); } int fpclassify(ExactFloat const& x) { switch (x.bn_exp_) { case ExactFloat::kExpNaN: return FP_NAN; case ExactFloat::kExpInfinity: return FP_INFINITE; case ExactFloat::kExpZero: return FP_ZERO; // There are no subnormal `ExactFloat`s. default: return FP_NORMAL; } } ExactFloat::operator double() const { // If the mantissa has too many bits, we need to round it. if (prec() <= kDoubleMantissaBits) { return ToDoubleHelper(); } else { ExactFloat r = RoundToMaxPrec(kDoubleMantissaBits, kRoundTiesToEven); return r.ToDoubleHelper(); } } double ExactFloat::ToDoubleHelper() const { ABSL_DCHECK_LE(bit_width(bn_), kDoubleMantissaBits); if (!isnormal(*this)) { if (is_zero()) return std::copysign(0, sign_); if (isinf(*this)) { return std::copysign(std::numeric_limits::infinity(), sign_); } return std::copysign(std::numeric_limits::quiet_NaN(), sign_); } const double d_mantissa = static_cast(bn_.Cast()); // We rely on ldexp() to handle overflow and underflow. (It will return a // signed zero or infinity if the result is too small or too large.) return sign_ * std::ldexp(d_mantissa, bn_exp_); } ExactFloat ExactFloat::RoundToMaxPrec(int max_prec, RoundingMode mode) const { // The "kRoundTiesToEven" mode requires at least 2 bits of precision // (otherwise both adjacent representable values may be odd). ABSL_DCHECK_GE(max_prec, 2); ABSL_DCHECK_LE(max_prec, kMaxPrec); // The following test also catches zero, infinity, and NaN. int shift = prec() - max_prec; if (shift <= 0) return *this; // Round by removing the appropriate number of bits from the mantissa. Note // that if the value is rounded up to a power of 2, the high-order bit // position may increase, but in that case Canonicalize() will remove at // least one zero bit and so the output will still have prec() <= max_prec. return RoundToPowerOf2(bn_exp_ + shift, mode); } ExactFloat ExactFloat::RoundToPowerOf2(int bit_exp, RoundingMode mode) const { ABSL_DCHECK_GE(bit_exp, kMinExp - kMaxPrec); ABSL_DCHECK_LE(bit_exp, kMaxExp); // If the exponent is already large enough, or the value is zero, infinity, // or NaN, then there is nothing to do. int shift = bit_exp - bn_exp_; if (shift <= 0) return *this; ABSL_DCHECK(isnormal(*this)); // Convert rounding up/down to toward/away from zero, so that we don't need // to consider the sign of the number from this point onward. if (mode == kRoundTowardPositive) { mode = (sign_ > 0) ? kRoundAwayFromZero : kRoundTowardZero; } else if (mode == kRoundTowardNegative) { mode = (sign_ > 0) ? kRoundTowardZero : kRoundAwayFromZero; } // Rounding consists of right-shifting the mantissa by "shift", and then // possibly incrementing the result (depending on the rounding mode, the // bits that were discarded, and sometimes the lowest kept bit). The // following code figures out whether we need to increment. ExactFloat r; bool increment = false; if (mode == kRoundTowardZero) { // Never increment. } else if (mode == kRoundTiesAwayFromZero) { // Increment if the highest discarded bit is 1. if (bn_.is_bit_set(shift - 1)) increment = true; } else if (mode == kRoundAwayFromZero) { // Increment unless all discarded bits are zero. if (countr_zero(bn_) < shift) increment = true; } else { ABSL_DCHECK_EQ(mode, kRoundTiesToEven); // Let "w/xyz" denote a mantissa where "w" is the lowest kept bit and // "xyz" are the discarded bits. Then using regexp notation: // ./0.* -> Don't increment (fraction < 1/2) // 0/10* -> Don't increment (fraction = 1/2, kept part even) // 1/10* -> Increment (fraction = 1/2, kept part odd) // ./1.*1.* -> Increment (fraction > 1/2) if (bn_.is_bit_set(shift - 1) && ((bn_.is_bit_set(shift) || countr_zero(bn_) < shift - 1))) { increment = true; } } r.bn_exp_ = bn_exp_ + shift; r.bn_ = bn_ >> shift; if (increment) { r.bn_ += Bignum(1); } r.sign_ = sign_; r.Canonicalize(); return r; } int ExactFloat::NumSignificantDigitsForPrec(int prec) { // The simplest bound is // // d <= 1 + ceil(prec * log10(2)) // // The following bound is tighter by 0.5 digits on average, but requires // the exponent to be known as well: // // d <= ceil(exp * log10(2)) - floor((exp - prec) * log10(2)) // // Since either of these bounds can be too large by 0, 1, or 2 digits, we // stick with the simpler first bound. return static_cast(1 + std::ceil(prec * (M_LN2 / M_LN10))); } // Numbers are always formatted with at least this many significant digits. // This prevents small integers from being formatted in exponential notation // (e.g. 1024 formatted as 1e+03), and also avoids the confusion of having // supposedly "high precision" numbers formatted with just 1 or 2 digits // (e.g. 1/512 == 0.001953125 formatted as 0.002). static const int kMinSignificantDigits = 10; std::string ExactFloat::ToString() const { int max_digits = max(kMinSignificantDigits, NumSignificantDigitsForPrec(prec())); return ToStringWithMaxDigits(max_digits); } std::string ExactFloat::ToStringWithMaxDigits(int max_digits) const { ABSL_DCHECK_GT(max_digits, 0); if (!isnormal(*this)) { if (isnan(*this)) return "nan"; if (is_zero()) return (sign_ < 0) ? "-0" : "0"; return (sign_ < 0) ? "-inf" : "inf"; } std::string digits; int exp10 = GetDecimalDigits(max_digits, &digits); std::string str; if (sign_ < 0) str.push_back('-'); // We use the standard '%g' formatting rules. If the exponent is less than // -4 or greater than or equal to the requested precision (i.e., max_digits) // then we use exponential notation. // // But since "exp10" is the base-10 exponent corresponding to a mantissa in // the range [0.1, 1), whereas the '%g' rules assume a mantissa in the range // [1.0, 10), we need to adjust these parameters by 1. if (exp10 <= -4 || exp10 > max_digits) { // Use exponential format. str.push_back(digits[0]); if (digits.size() > 1) { str.push_back('.'); str.append(digits.begin() + 1, digits.end()); } absl::StrAppendFormat(&str, "e%+02d", exp10 - 1); } else { // Use fixed format. We split this into two cases depending on whether // the integer portion is non-zero or not. if (exp10 > 0) { if (static_cast(exp10) >= digits.size()) { absl::StrAppend(&str, digits); for (int i = exp10 - digits.size(); i > 0; --i) { str.push_back('0'); } } else { str.append(digits.begin(), digits.begin() + exp10); str.push_back('.'); str.append(digits.begin() + exp10, digits.end()); } } else { absl::StrAppend(&str, "0."); for (int i = exp10; i < 0; ++i) { str.push_back('0'); } absl::StrAppend(&str, digits); } } return str; } // Increment an unsigned integer represented as a string of ASCII digits. static void IncrementDecimalDigits(std::string* digits) { std::string::iterator pos = digits->end(); while (--pos >= digits->begin()) { if (*pos < '9') { ++*pos; return; } *pos = '0'; } digits->insert(0, "1"); } int ExactFloat::GetDecimalDigits(int max_digits, std::string* digits) const { ABSL_DCHECK(isnormal(*this)); // Convert the value to the form (bn * (10 ** bn_exp10)) where "bn" is a // positive integer. Bignum bn; int bn_exp10; if (bn_exp_ >= 0) { // The easy case: bn = bn_ * (2 ** bn_exp_)), bn_exp10 = 0. bn = bn_ << bn_exp_; bn_exp10 = 0; } else { // Set bn = bn_ * (5 ** -bn_exp_) and bn_exp10 = bn_exp_. This is // equivalent to the original value of (bn_ * (2 ** bn_exp_)). bn = bn_ * Bignum(5).Pow(-bn_exp_); bn_exp10 = bn_exp_; } // Now convert "bn" to a decimal string using our Bignum's string conversion. std::string all_digits = absl::StrFormat("%v", bn); ABSL_DCHECK(!all_digits.empty()); // Check whether we have too many digits and round if necessary. int num_digits = all_digits.length(); if (num_digits <= max_digits) { *digits = all_digits; } else { digits->assign(all_digits, 0, max_digits); // Standard "printf" formatting rounds ties to an even number. This means // that we round up (away from zero) if highest discarded digit is '5' or // more, unless all other discarded digits are zero in which case we round // up only if the lowest kept digit is odd. if (all_digits[max_digits] >= '5' && ((all_digits[max_digits - 1] & 1) == 1 || all_digits.find_first_not_of('0', max_digits + 1) != std::string::npos)) { // This can increase the number of digits by 1, but in that case at // least one trailing zero will be stripped off below. IncrementDecimalDigits(digits); } // Adjust the base-10 exponent to reflect the digits we have removed. bn_exp10 += num_digits - max_digits; } // Now strip any trailing zeros. ABSL_DCHECK_NE((*digits)[0], '0'); std::string::size_type pos = digits->find_last_not_of('0') + 1; bn_exp10 += digits->size() - pos; digits->erase(pos); ABSL_DCHECK_LE(static_cast(digits->size()), max_digits); // Finally, we adjust the base-10 exponent so that the mantissa is a // fraction in the range [0.1, 1) rather than an integer. return bn_exp10 + digits->size(); } std::string ExactFloat::ToUniqueString() const { return absl::StrFormat("%s<%d>", ToString(), prec()); } ExactFloat ExactFloat::operator-() const { return CopyWithSign(-sign_); } ExactFloat operator+(const ExactFloat& a, const ExactFloat& b) { return ExactFloat::SignedSum(a.sign_, &a, b.sign_, &b); } ExactFloat operator-(const ExactFloat& a, const ExactFloat& b) { return ExactFloat::SignedSum(a.sign_, &a, -b.sign_, &b); } ExactFloat ExactFloat::SignedSum(int a_sign, const ExactFloat* a, int b_sign, const ExactFloat* b) { if (!isnormal(*a) || !isnormal(*b)) { // Handle zero, infinity, and NaN according to IEEE 754-2008. if (isnan(*a)) return *a; if (isnan(*b)) return *b; if (isinf(*a)) { // Adding two infinities with opposite sign yields NaN. if (isinf(*b) && a_sign != b_sign) return NaN(); return Infinity(a_sign); } if (isinf(*b)) return Infinity(b_sign); if (a->is_zero()) { if (!b->is_zero()) return b->CopyWithSign(b_sign); // Adding two zeros with the same sign preserves the sign. if (a_sign == b_sign) return SignedZero(a_sign); // Adding two zeros of opposite sign produces +0. return SignedZero(+1); } ABSL_DCHECK(b->is_zero()); return a->CopyWithSign(a_sign); } // Swap the numbers if necessary so that "a" has the larger bn_exp_. if (a->bn_exp_ < b->bn_exp_) { using std::swap; swap(a_sign, b_sign); swap(a, b); } // Shift "a" if necessary so that both values have the same bn_exp_. ExactFloat r; r.bn_ = a->bn_; r.bn_ <<= (a->bn_exp_ - b->bn_exp_); r.bn_exp_ = b->bn_exp_; if (a_sign == b_sign) { r.bn_ += b->bn_; r.sign_ = a_sign; } else { r.bn_ -= b->bn_; if (r.bn_.is_zero()) { r.sign_ = +1; } else if (r.bn_.is_negative()) { // |b| was greater than |a|. r.sign_ = b_sign; r.bn_.set_negative(false); } else { // |a| was greater than |b| r.sign_ = a_sign; } } r.Canonicalize(); return r; } void ExactFloat::Canonicalize() { if (!isnormal(*this)) return; // Underflow/overflow occurs if exp() is not in [kMinExp, kMaxExp]. // We also convert a zero mantissa to signed zero. int my_exp = exp(); if (my_exp < kMinExp || bn_.is_zero()) { set_zero(sign_); } else if (my_exp > kMaxExp) { set_inf(sign_); } else if (bn_.is_even()) { // Remove any low-order zero bits from the mantissa. ABSL_DCHECK(!bn_.is_zero()); int shift = countr_zero(bn_); if (shift > 0) { bn_ >>= shift; bn_exp_ += shift; } } // If the mantissa has too many bits, we replace it by NaN to indicate // that an inexact calculation has occurred. if (prec() > kMaxPrec) { set_nan(); } } ExactFloat operator*(const ExactFloat& a, const ExactFloat& b) { int result_sign = a.sign_ * b.sign_; if (!isnormal(a) || !isnormal(b)) { // Handle zero, infinity, and NaN according to IEEE 754-2008. if (isnan(a)) return a; if (isnan(b)) return b; if (isinf(a)) { // Infinity times zero yields NaN. if (b.is_zero()) return ExactFloat::NaN(); return ExactFloat::Infinity(result_sign); } if (isinf(b)) { if (a.is_zero()) return ExactFloat::NaN(); return ExactFloat::Infinity(result_sign); } ABSL_DCHECK(a.is_zero() || b.is_zero()); return ExactFloat::SignedZero(result_sign); } ExactFloat r; r.sign_ = result_sign; r.bn_exp_ = a.bn_exp_ + b.bn_exp_; r.bn_ = a.bn_ * b.bn_; r.Canonicalize(); return r; } bool operator==(const ExactFloat& a, const ExactFloat& b) { // NaN is not equal to anything, not even itself. if (isnan(a) || isnan(b)) return false; // Since Canonicalize() strips low-order zero bits, all other cases // (including non-normal values) require bn_exp_ to be equal. if (a.bn_exp_ != b.bn_exp_) return false; // Positive and negative zero are equal. if (a.is_zero() && b.is_zero()) return true; // Otherwise, the signs and mantissas must match. Note that non-normal // values such as infinity have a mantissa of zero. return a.sign_ == b.sign_ && a.bn_ == b.bn_; } int ExactFloat::ScaleAndCompare(const ExactFloat& b) const { ABSL_DCHECK(isnormal(*this) && isnormal(b) && bn_exp_ >= b.bn_exp_); ExactFloat tmp = *this; tmp.bn_ <<= (bn_exp_ - b.bn_exp_); return tmp.bn_.Compare(b.bn_); } bool ExactFloat::UnsignedLess(const ExactFloat& b) const { // Handle the zero/infinity cases (NaN has already been done). if (isinf(*this) || b.is_zero()) return false; if (is_zero() || isinf(b)) return true; // If the high-order bit positions differ, we are done. int cmp = exp() - b.exp(); if (cmp != 0) return cmp < 0; // Otherwise shift one of the two values so that they both have the same // bn_exp_ and then compare the mantissas. return (bn_exp_ >= b.bn_exp_ ? ScaleAndCompare(b) < 0 : b.ScaleAndCompare(*this) > 0); } bool operator<(const ExactFloat& a, const ExactFloat& b) { // NaN is unordered compared to everything, including itself. if (isnan(a) || isnan(b)) return false; // Positive and negative zero are equal. if (a.is_zero() && b.is_zero()) return false; // Otherwise, anything negative is less than anything positive. if (a.sign_ != b.sign_) return a.sign_ < b.sign_; // Now we just compare absolute values. return (a.sign_ > 0) ? a.UnsignedLess(b) : b.UnsignedLess(a); } ExactFloat fabs(const ExactFloat& a) { return abs(a); } ExactFloat abs(const ExactFloat& a) { return a.CopyWithSign(+1); } ExactFloat fmax(const ExactFloat& a, const ExactFloat& b) { // If one argument is NaN, return the other argument. if (isnan(a)) return b; if (isnan(b)) return a; // Not required by IEEE 754, but we prefer +0 over -0. if (a.sign_ != b.sign_) { return (a.sign_ < b.sign_) ? b : a; } return (a < b) ? b : a; } ExactFloat fmin(const ExactFloat& a, const ExactFloat& b) { // If one argument is NaN, return the other argument. if (isnan(a)) return b; if (isnan(b)) return a; // Not required by IEEE 754, but we prefer -0 over +0. if (a.sign_ != b.sign_) { return (a.sign_ < b.sign_) ? a : b; } return (a < b) ? a : b; } ExactFloat fdim(const ExactFloat& a, const ExactFloat& b) { // This formulation has the correct behavior for NaNs. return (a <= b) ? 0 : (a - b); } ExactFloat ceil(const ExactFloat& a) { return a.RoundToPowerOf2(0, ExactFloat::kRoundTowardPositive); } ExactFloat floor(const ExactFloat& a) { return a.RoundToPowerOf2(0, ExactFloat::kRoundTowardNegative); } ExactFloat trunc(const ExactFloat& a) { return a.RoundToPowerOf2(0, ExactFloat::kRoundTowardZero); } ExactFloat round(const ExactFloat& a) { return a.RoundToPowerOf2(0, ExactFloat::kRoundTiesAwayFromZero); } ExactFloat rint(const ExactFloat& a) { return a.RoundToPowerOf2(0, ExactFloat::kRoundTiesToEven); } template T ExactFloat::ToInteger(RoundingMode mode) const { using std::numeric_limits; static_assert(sizeof(T) <= sizeof(uint64_t), "max 64 bits supported"); static_assert(numeric_limits::is_signed, "only signed types supported"); const int64_t kMinValue = numeric_limits::min(); const int64_t kMaxValue = numeric_limits::max(); ExactFloat r = RoundToPowerOf2(0, mode); if (isnan(r)) return kMaxValue; if (r.is_zero()) return 0; if (!isinf(r)) { // If the unsigned value has more than 63 bits it is always clamped. if (r.exp() < 64) { int64_t value = r.bn_.Cast() << r.bn_exp_; if (r.sign_ < 0) value = -value; return std::clamp(value, kMinValue, kMaxValue); } } return (r.sign_ < 0) ? kMinValue : kMaxValue; } // NOLINTBEGIN(runtime/int, google-runtime-int) long lrint(const ExactFloat& a) { return a.ToInteger(ExactFloat::kRoundTiesToEven); } long long llrint(const ExactFloat& a) { return a.ToInteger(ExactFloat::kRoundTiesToEven); } long lround(const ExactFloat& a) { return a.ToInteger(ExactFloat::kRoundTiesAwayFromZero); } long long llround(const ExactFloat& a) { return a.ToInteger(ExactFloat::kRoundTiesAwayFromZero); } // NOLINTEND(runtime/int, google-runtime-int) ExactFloat copysign(const ExactFloat& a, const ExactFloat& b) { return a.CopyWithSign(b.sign_); } ExactFloat frexp(const ExactFloat& a, int* exp) { if (!isnormal(a)) { // If a == 0, exp should be zero. If a.is_inf() or a.is_nan(), exp is not // defined but the glibc implementation returns zero. *exp = 0; return a; } *exp = a.exp(); return ldexp(a, -a.exp()); } ExactFloat ldexp(const ExactFloat& a, int exp) { if (!isnormal(a)) return a; // To prevent integer overflow, we first clamp "exp" so that // (kMinExp - 1) <= (a_exp + exp) <= (kMaxExp + 1). int a_exp = a.exp(); exp = std::clamp(exp, // ExactFloat::kMinExp - 1 + a_exp, ExactFloat::kMaxExp + 1 - a_exp); // Now modify the exponent and check for overflow/underflow. ExactFloat r = a; r.bn_exp_ += exp; r.Canonicalize(); return r; } ExactFloat scalbln(const ExactFloat& a, long exp) { // Clamp the exponent to the range of "int" in order to avoid truncation. // NOLINTNEXTLINE(runtime/int, google-runtime-int) exp = std::clamp(exp, INT_MIN, INT_MAX); return ldexp(a, static_cast(exp)); } int ilogb(const ExactFloat& a) { if (a.is_zero()) return FP_ILOGB0; if (isinf(a)) return INT_MAX; if (isnan(a)) return FP_ILOGBNAN; // a.exp() assumes the significand is in the range [0.5, 1). return a.exp() - 1; } ExactFloat logb(const ExactFloat& a) { if (a.is_zero()) return ExactFloat::Infinity(-1); if (isinf(a)) return ExactFloat::Infinity(+1); // Even if a < 0. if (isnan(a)) return a; // exp() assumes the significand is in the range [0.5,1). return ExactFloat(a.exp() - 1); } ExactFloat ExactFloat::Unimplemented() { ABSL_LOG(FATAL) << "Unimplemented ExactFloat method called"; return NaN(); } } // namespace exactfloat src/s2/util/math/exactfloat/exactfloat.h000066400000000000000000000623071524103652300205450ustar00rootroot00000000000000// Copyright 2009 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) // // ExactFloat is a multiple-precision floating point type that uses a custom // Bignum library for numerical calculations. It has the same interface as the // built-in "float" and "double" types, but only supports the subset of // operators and intrinsics where it is possible to compute the result exactly. // So for example, ExactFloat supports addition and multiplication but not // division (since in general, the quotient of two floating-point numbers cannot // be represented exactly). Exact arithmetic is useful for geometric // algorithms, especially for disambiguating cases where ordinary // double-precision arithmetic yields an uncertain result. // // ExactFloat was originally based on OpenSSL's Bignum library, but has been // updated to use a custom implementation to remove external dependencies. // // ExactFloat has the following features: // // - It uses the same syntax as the built-in "float" and "double" // types, for example: x += 4 + fabs(2*y*y - z*z). There are a few // differences (see below), but the syntax is compatible enough so that // ExactFloat can be used as a template argument to templatized classes // such as Vector2, VectorN, Matrix3x3, etc. // // - Results are not rounded; instead, precision is increased so that the // result can be represented exactly. An inexact result is returned only // in the case of underflow or overflow (yielding signed zero or infinity // respectively), or if the maximum allowed precision is exceeded (yielding // NaN). ExactFloat uses IEEE 754-2008 rules for handling infinities, NaN, // rounding to integers, etc. // // - ExactFloat only supports calculations where the result can be // represented exactly. Therefore it supports intrinsics such as fabs() // but not transcendentals such as sin(), sqrt(), etc. // // Syntax Compatibility with "float" and "double" // ---------------------------------------------- // // ExactFloat supports a subset of the operators and intrinsics for the // built-in "double" type. (Thus it supports fabs() but not fabsf(), for // example.) The syntax is different only in the following cases: // // - Explicit conversion to double is supported, but casts and implicit // conversions to other built-in types (including "bool") are not. // So for example, the following will not compile: // // ExactFloat x = 7.5; // double y = x; // ERROR: use static_cast(x) instead // long z = x; // ERROR: use static_cast(x) or // // lround(trunc(x)) // q = static_cast(x); // ERROR: use static_cast(x) or // // lround(trunc(x)) // if (x) { ... } // ERROR: use (x != 0) instead // // - The floating-point classification functions (isfinite, isnormal, isnan, // isinf, fpclassify) are supported. // // ExactFloat x; // if (isnan(x)) { ... } // if (isinf(x)) { ... } // // Using ExactFloat with Vector3, etc. // ----------------------------------- // // ExactFloat can be used with templatized classes such as Vector2 and Vector3 // (see "util/math/vector.h"). // // Precision Semantics // ------------------- // // Unlike MPFloat, ExactFloat does not allow a maximum precision to be // specified (it is always unbounded). Therefore it does not have any of the // corresponding constructors. // // The current precision of an ExactFloat (i.e., the number of bits in its // mantissa) is returned by prec(). The precision is increased as necessary // so that the result of every operation can be represented exactly. #ifndef S2_UTIL_MATH_EXACTFLOAT_EXACTFLOAT_H_ #define S2_UTIL_MATH_EXACTFLOAT_EXACTFLOAT_H_ #include #include #include #include #include #include #include "s2/util/math/exactfloat/bignum.h" namespace exactfloat { class ExactFloat { public: // The following limits are imposed by OpenSSL. // The maximum exponent supported. If a value has an exponent larger than // this, it is replaced by infinity (with the appropriate sign). static constexpr int kMaxExp = 200 * 1000 * 1000; // About 10**(60 million) // The minimum exponent supported. If a value has an exponent less than // this, it is replaced by zero (with the appropriate sign). static constexpr int kMinExp = -kMaxExp; // About 10**(-60 million) // The maximum number of mantissa bits supported. If a value has more // mantissa bits than this, it is replaced with NaN. (It is expected that // users of this class will never want this much precision.) static constexpr int kMaxPrec = 64 << 20; // About 20 million digits // Rounding modes. kRoundTiesToEven and kRoundTiesAwayFromZero both round // to the nearest representable value unless two values are equally close. // In that case kRoundTiesToEven rounds to the nearest even value, while // kRoundTiesAwayFromZero always rounds away from zero. enum RoundingMode { kRoundTiesToEven, kRoundTiesAwayFromZero, kRoundTowardZero, kRoundAwayFromZero, kRoundTowardPositive, kRoundTowardNegative }; ///////////////////////////////////////////////////////////////////////////// // Constructors // The default constructor initializes the value to zero. (The initial // value must be zero rather than NaN for compatibility with the built-in // float types.) inline ExactFloat() = default; // Construct an ExactFloat from a "double". The constructor is implicit so // that this class can be used as a replacement for "float" or "double" in // templatized libraries. (With an explicit constructor, code such as // "ExactFloat f = 2.5;" would not compile.) All double-precision values are // supported, including denormalized numbers, infinities, and NaNs. ExactFloat(double v); // NOLINT(google-explicit-constructor) // Construct an ExactFloat from an "int". Note that in general, ints are // automatically converted to doubles and so would be handled by the // constructor above. However, the particular argument (0) would be // ambiguous; the compiler wouldn't know whether to treat it as a "double" or // "const char*" (since 0 is a valid null pointer constant). Adding an "int" // constructor solves this problem. // // We do not provide constructors for "unsigned", "long", "unsigned long", // "long long", or "unsigned long long", since these types are not typically // used in floating-point calculations and it is safer to require them to be // explicitly cast. ExactFloat(int v); // NOLINT(google-explicit-constructor) // Construct an ExactFloat from a string (such as "1.2e50"). Requires that // the value is exactly representable as a floating-point number (so for // example, "0.125" is allowed but "0.1" is not). explicit ExactFloat(const char* s) { Unimplemented(); } ///////////////////////////////////////////////////////////////////// // Constants // // As an alternative to the constants below, you can also just use the // constants defined in , for example: // // ExactFloat x = NAN, y = -INFINITY; // Return an ExactFloat equal to positive zero (if sign >= 0) or // negative zero (if sign < 0). static ExactFloat SignedZero(int sign); // Return an ExactFloat equal to positive infinity (if sign >= 0) or // negative infinity (if sign < 0). static ExactFloat Infinity(int sign); // Return an ExactFloat that is NaN (Not-a-Number). static ExactFloat NaN(); ///////////////////////////////////////////////////////////////////////////// // Accessor Methods // Return the maximum precision of the ExactFloat. This method exists only // for compatibility with MPFloat. int max_prec() const { return kMaxPrec; } // Return the actual precision of this ExactFloat (the current number of // bits in its mantissa). Returns 0 for non-normal numbers such as NaN. int prec() const; // Return the exponent of this ExactFloat given that the mantissa is in the // range [0.5, 1). It is an error to call this method if the value is zero, // infinity, or NaN. int exp() const; // Set the value of the ExactFloat to +0 (if sign >= 0) or -0 (if sign < 0). void set_zero(int sign); // Set the value of the ExactFloat to positive infinity (if sign >= 0) or // negative infinity (if sign < 0). void set_inf(int sign); // Set the value of the ExactFloat to NaN (Not-a-Number). void set_nan(); // Classification functions. These are similar to the std::is* functions. friend int fpclassify(ExactFloat const& x); // Return true if this value is infinity (positive or negative). friend inline bool isinf(ExactFloat const& x); // Return true if this value is NaN (Not-a-Number). friend inline bool isnan(ExactFloat const& x); // Return true if this value is a normal floating-point number. Non-normal // values (zero, infinity, and NaN) often need to be handled separately // because they are represented using special exponent values and their // mantissa is not defined. friend inline bool isnormal(ExactFloat const& x); // Return true if this value is a normal floating-point number or zero, // i.e. it is not infinity or NaN. friend inline bool isfinite(ExactFloat const& x); // Return true if the sign bit is set (this includes negative zero). friend inline bool signbit(ExactFloat const& x); // Additional classification functions with no std:: equivalents. // Return true if this value is zero (including negative zero). inline bool is_zero() const; // Return +1 if this ExactFloat is positive, -1 if it is negative, and 0 // if it is zero or NaN. Note that unlike sign_bit(), sgn() returns 0 for // both positive and negative zero. inline int sgn() const; ///////////////////////////////////////////////////////////////////////////// // Conversion Methods // // Note that some conversions are defined as functions further below, // e.g. to convert to an integer you can use lround(), llrint(), etc. // Round to double precision. Note that since doubles have a much smaller // exponent range than ExactFloats, very small values may be rounded to // (positive or negative) zero, and very large values may be rounded to // infinity. // // It is very important to make an explicit conversion rather than an // implicit one, because otherwise there would be a silent loss of precision // whenever some desired operator or function happens not to be implemented. // For example, if fabs() were not implemented and "x" and "y" were // ExactFloats, then x = fabs(y) would silently convert "y" to a "double", // take its absolute value, and convert it back to an ExactFloat. explicit operator double() const; // Return a human-readable string such that if two values with the same // precision are different, then their string representations are different. // The format is similar to printf("%g"), except that the number of // significant digits depends on the precision (with a minimum of 10). // Trailing zeros are stripped (just like "%g"). // // Note that if two values have different precisions, they may have the same // ToString() value even though their values are slightly different. If you // need to distinguish such values, use ToUniqueString() instead. std::string ToString() const; // Return a string formatted according to printf("%Ng") where N is the given // maximum number of significant digits. std::string ToStringWithMaxDigits(int max_digits) const; // Return a human-readable string such that if two ExactFloats have different // values, then their string representations are always different. This // method is useful for debugging. The string has the form "value", // where "prec" is the actual precision of the ExactFloat (e.g., "0.215<50>"). std::string ToUniqueString() const; // Return an upper bound on the number of significant digits required to // distinguish any two floating-point numbers with the given precision when // they are formatted as decimal strings in exponential format. static int NumSignificantDigitsForPrec(int prec); // Output the ExactFloat in human-readable format, e.g. for logging. friend std::ostream& operator<<(std::ostream& o, ExactFloat const& f) { return o << f.ToString(); } ///////////////////////////////////////////////////////////////////////////// // Other Methods // Round the ExactFloat so that its mantissa has at most "max_prec" bits // using the given rounding mode. Requires "max_prec" to be at least 2 // (since kRoundTiesToEven doesn't make sense with fewer bits than this). ExactFloat RoundToMaxPrec(int max_prec, RoundingMode mode) const; ///////////////////////////////////////////////////////////////////////////// // Operators // Unary plus. ExactFloat operator+() const { return *this; } // Unary minus. ExactFloat operator-() const; // Addition. friend ExactFloat operator+(const ExactFloat& a, const ExactFloat& b); // Subtraction. friend ExactFloat operator-(const ExactFloat& a, const ExactFloat& b); // Multiplication. friend ExactFloat operator*(const ExactFloat& a, const ExactFloat& b); // Division is not implemented because the result cannot be represented // exactly in general. Doing this properly would require extending all the // operations to support rounding to a specified precision. // Arithmetic assignment operators (+=, -=, *=). ExactFloat& operator+=(const ExactFloat& b) { return (*this = *this + b); } ExactFloat& operator-=(const ExactFloat& b) { return (*this = *this - b); } ExactFloat& operator*=(const ExactFloat& b) { return (*this = *this * b); } // Comparison operators (==, !=, <, <=, >, >=). friend bool operator==(const ExactFloat& a, const ExactFloat& b); friend bool operator<(const ExactFloat& a, const ExactFloat& b); // These don't need to be friends but are declared here for completeness. inline friend bool operator!=(const ExactFloat& a, const ExactFloat& b); inline friend bool operator<=(const ExactFloat& a, const ExactFloat& b); inline friend bool operator>(const ExactFloat& a, const ExactFloat& b); inline friend bool operator>=(const ExactFloat& a, const ExactFloat& b); ///////////////////////////////////////////////////////////////////// // Math Intrinsics // // The math intrinsics currently supported by ExactFloat are listed below. // Except as noted, they behave identically to the usual std:: functions // except that they have greater precision. See the man pages for more // information. //////// Miscellaneous simple arithmetic functions. // Absolute value. friend ExactFloat fabs(const ExactFloat& a); friend ExactFloat abs(const ExactFloat& a); // Maximum of two values. friend ExactFloat fmax(const ExactFloat& a, const ExactFloat& b); // Minimum of two values. friend ExactFloat fmin(const ExactFloat& a, const ExactFloat& b); // Positive difference: max(a - b, 0). friend ExactFloat fdim(const ExactFloat& a, const ExactFloat& b); //////// Integer rounding functions that return ExactFloat values. // Round up to the nearest integer. friend ExactFloat ceil(const ExactFloat& a); // Round down to the nearest integer. friend ExactFloat floor(const ExactFloat& a); // Round to the nearest integer not larger in absolute value. // For example: f(-1.9) = -1, f(2.9) = 2. friend ExactFloat trunc(const ExactFloat& a); // Round to the nearest integer, rounding halfway cases away from zero. // For example: f(-0.5) = -1, f(0.5) = 1, f(1.5) = 2, f(2.5) = 3. friend ExactFloat round(const ExactFloat& a); // Round to the nearest integer, rounding halfway cases to an even integer. // For example: f(-0.5) = 0, f(0.5) = 0, f(1.5) = 2, f(2.5) = 2. friend ExactFloat rint(const ExactFloat& a); // A synonym for rint(). friend ExactFloat nearbyint(const ExactFloat& a) { return rint(a); } //////// Integer rounding functions that return C++ integer types. // Like rint(), but rounds to the nearest "long" value. Returns the // minimum/maximum possible integer if the value is out of range. // NOLINTNEXTLINE(runtime/int, google-runtime-int) friend long lrint(const ExactFloat& a); // Like rint(), but rounds to the nearest "long long" value. Returns the // minimum/maximum possible integer if the value is out of range. // NOLINTNEXTLINE(runtime/int, google-runtime-int) friend long long llrint(const ExactFloat& a); // Like round(), but rounds to the nearest "long" value. Returns the // minimum/maximum possible integer if the value is out of range. // NOLINTNEXTLINE(runtime/int, google-runtime-int) friend long lround(const ExactFloat& a); // Like round(), but rounds to the nearest "long long" value. Returns the // minimum/maximum possible integer if the value is out of range. // NOLINTNEXTLINE(runtime/int, google-runtime-int) friend long long llround(const ExactFloat& a); //////// Remainder functions. // The remainder of dividing "a" by "b", where the quotient is rounded toward // zero to the nearest integer. Similar to (a - trunc(a / b) * b). friend ExactFloat fmod(const ExactFloat& a, const ExactFloat& b) { // Note that it is possible to implement this operation exactly, it just // hasn't been done. return Unimplemented(); } // The remainder of dividing "a" by "b", where the quotient is rounded to the // nearest integer, rounding halfway cases to an even integer. Similar to // (a - rint(a / b) * b). friend ExactFloat remainder(const ExactFloat& a, const ExactFloat& b) { // Note that it is possible to implement this operation exactly, it just // hasn't been done. return Unimplemented(); } // A synonym for remainder(). friend ExactFloat drem(const ExactFloat& a, const ExactFloat& b) { return remainder(a, b); } // Break the argument "a" into integer and fractional parts, each of which // has the same sign as "a". The fractional part is returned, and the // integer part is stored in the output parameter "i_ptr". Both output // values are set to have the same maximum precision as "a". friend ExactFloat modf(const ExactFloat& a, ExactFloat* i_ptr) { // Note that it is possible to implement this operation exactly, it just // hasn't been done. return Unimplemented(); } //////// Floating-point manipulation functions. // Return an ExactFloat with the magnitude of "a" and the sign bit of "b". // (Note that an IEEE zero can be either positive or negative.) friend ExactFloat copysign(const ExactFloat& a, const ExactFloat& b); // Convert "a" to a normalized fraction in the range [0.5, 1) times a power // of two. Return the fraction and set "exp" to the exponent. If "a" is // zero, infinity, or NaN then return "a" and set "exp" to zero. friend ExactFloat frexp(const ExactFloat& a, int* exp); // Return "a" multiplied by 2 raised to the power "exp". friend ExactFloat ldexp(const ExactFloat& a, int exp); // A synonym for ldexp(). friend ExactFloat scalbn(const ExactFloat& a, int exp) { return ldexp(a, exp); } // A version of ldexp() where "exp" is a long integer. // NOLINTNEXTLINE(runtime/int, google-runtime-int) friend ExactFloat scalbln(const ExactFloat& a, long exp); // Convert "a" to a normalized fraction in the range [1,2) times a power of // two, and return the exponent value as an integer. This is equivalent to // lrint(floor(log2(fabs(a)))) but it is computed more efficiently. Returns // the constants documented in the man page for zero, infinity, or NaN. friend int ilogb(const ExactFloat& a); // Convert "a" to a normalized fraction in the range [1,2) times a power of // two, and return the exponent value as an ExactFloat. This is equivalent to // floor(log2(fabs(a))) but it is computed more efficiently. friend ExactFloat logb(const ExactFloat& a); protected: using Bignum = exactfloat_internal::Bignum; // Non-normal numbers are represented using special exponent values and a // mantissa of zero. Do not change these values; methods such as // is_normal() make assumptions about their ordering. Non-normal numbers // can have either a positive or negative sign (including zero and NaN). static constexpr int32_t kExpNaN = INT_MAX; static constexpr int32_t kExpInfinity = INT_MAX - 1; static constexpr int32_t kExpZero = INT_MAX - 2; // Normal numbers are represented as (sign_ * bn_ * (2 ** bn_exp_)), where: // - sign_ is either +1 or -1 // - bn_ is a Bignum with a positive value // - bn_exp_ is the base-2 exponent applied to bn_. // // bn_ stores the magnitude for the mantissa of the floating point value. We // store a sign bit here separately from bn_ so that functions like exp() are // easier to reason about (as the sign would flip depending on whether the // exponent were odd or even). int32_t sign_ = 1; int32_t bn_exp_ = kExpZero; Bignum bn_; // A standard IEEE "double" has a 53-bit mantissa consisting of a 52-bit // fraction plus an implicit leading "1" bit. static constexpr int kDoubleMantissaBits = 53; // Convert an ExactFloat with no more than 53 bits in its mantissa to a // "double". This method handles non-normal values (NaN, etc). double ToDoubleHelper() const; // Round an ExactFloat so that it is a multiple of (2 ** bit_exp), using the // given rounding mode. ExactFloat RoundToPowerOf2(int bit_exp, RoundingMode mode) const; // Convert the ExactFloat to a decimal value of the form 0.ddd * (10 ** x), // with at most "max_digits" significant digits (trailing zeros are removed). // Set (*digits) to the ASCII digits (just the "ddd" portion, without leading // "0.") and return the decimal exponent "x". int GetDecimalDigits(int max_digits, std::string* digits) const; // Return a_sign * fabs(a) + b_sign * fabs(b). Used to implement addition // and subtraction. static ExactFloat SignedSum(int a_sign, const ExactFloat* a, int b_sign, const ExactFloat* b); // Convert an ExactFloat to its canonical form. Underflow results in signed // zero, overflow results in signed infinity, and precision overflow results // in NaN. A zero mantissa is converted to the canonical zero value with // the given sign; otherwise the mantissa is normalized so that its low bit // is 1. Non-normal numbers are left unchanged. void Canonicalize(); // Scale the mantissa of this ExactFloat so that it has the same bn_exp_ as // "b", then return -1, 0, or 1 according to whether the scaled mantissa is // less, equal, or greater than the mantissa of "b". Requires that both // values are normal. int ScaleAndCompare(const ExactFloat& b) const; // Return true if the magnitude of this ExactFloat is less than the // magnitude of "b". Requires that neither value is NaN. bool UnsignedLess(const ExactFloat& b) const; // Return an ExactFloat with the magnitude of this ExactFloat and the given // sign. (Similar to copysign, except that the sign is given explicitly // rather than being copied from another ExactFloat.) inline ExactFloat CopyWithSign(int sign) const; // Convert an ExactFloat to an integer of type "T" using the given rounding // mode. The type "T" must be signed. Returns the largest possible integer // for NaN, and clamps out of range values to the largest or smallest // possible values. template T ToInteger(RoundingMode mode) const; // Log a fatal error message (used for unimplemented methods). static ExactFloat Unimplemented(); }; ///////////////////////////////////////////////////////////////////////// // Implementation details follow: inline bool isinf(ExactFloat const& x) { return x.bn_exp_ == ExactFloat::kExpInfinity; } inline bool isnan(ExactFloat const& x) { return x.bn_exp_ == ExactFloat::kExpNaN; } inline bool isnormal(ExactFloat const& x) { return x.bn_exp_ < ExactFloat::kExpZero; } inline bool isfinite(ExactFloat const& x) { return x.bn_exp_ <= ExactFloat::kExpZero; } inline bool signbit(ExactFloat const& x) { return x.sign_ < 0; } inline bool ExactFloat::is_zero() const { return bn_exp_ == kExpZero; } inline int ExactFloat::sgn() const { return (isnan(*this) || is_zero()) ? 0 : sign_; } inline bool operator!=(const ExactFloat& a, const ExactFloat& b) { return !(a == b); } inline bool operator<=(const ExactFloat& a, const ExactFloat& b) { // NaN is unordered compared to everything, including itself. if (isnan(a) || isnan(b)) return false; return !(b < a); } inline bool operator>(const ExactFloat& a, const ExactFloat& b) { return b < a; } inline bool operator>=(const ExactFloat& a, const ExactFloat& b) { return b <= a; } inline ExactFloat ExactFloat::CopyWithSign(int sign) const { ExactFloat r = *this; r.sign_ = sign; return r; } } // namespace exactfloat #endif // S2_UTIL_MATH_EXACTFLOAT_EXACTFLOAT_H_ src/s2/util/math/exactfloat/exactfloat_test.cc000066400000000000000000001101161524103652300217320ustar00rootroot00000000000000// Copyright 2009 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: ericv@google.com (Eric Veach) #include "s2/util/math/exactfloat/exactfloat.h" #include #include #include #include #include #include #include #include #include #include #include "absl/base/casts.h" #include "absl/base/macros.h" #include "absl/base/no_destructor.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/random/random.h" #include "s2/util/math/vector.h" namespace { using ::exactfloat::ExactFloat; // Usually, these would be found by ADL, but we use them as function pointers. using ::exactfloat::isfinite; using ::exactfloat::isinf; using ::exactfloat::isnan; using ::exactfloat::isnormal; using ::exactfloat::signbit; // To check the handling of boundary cases (NaN, infinities, out of range, // overflow, etc), we check the ExactFloat versions of all the operators and // functions against the glibc and/or hardware versions. // // The results are not always identical for several reasons. The main reasons // are that ExactFloat has a much higher precision, a much larger exponent // range, and does not round. But some differences are due to bugs in glibc. // The worst of these are fixed below. #ifndef DONT_FIX_GLIBC_MATH_FUNCTIONS // There are a few cases where the glibc math functions return an incorrect // result. We handle this by defining our own corrected versions here. // // Note that these corrections are only known to be sufficient on exactly one // platform, namely "--march=k8 --mfpmath=sse" with glibc 2.3.6. Glibc // undoubtedly has other bugs in other platforms and versions which would need // to be corrected separately. double fdim(double a, double b) { // ::fdim(-inf, -inf) incorrectly returns NaN. The result should be zero // because fdim is defined to return 0 when a <= b, and IEEE 754 defines // -inf to be equal to itself (even though (-inf) - (-inf) is NaN). // // Note that ::fdim(inf, inf) does return 0 (the correct result). if (a == b) return 0; return ::fdim(a, b); } double fmax(double a, double b) { // fmax(0, -0) returns -0 rather than +0. This is technically not a bug, // but it is different from (and inferior to) the MPFloat behavior. if (a == 0 && b == 0) return a + b; return ::fmax(a, b); } double fmin(double a, double b) { // fmin(-0, 0) returns +0 rather than -0. This is technically not a bug, // but it is different from (and inferior to) the MPFloat behavior. if (a == 0 && b == 0 && (std::signbit(a) || std::signbit(b))) { return copysign(0, -1); } return ::fmin(a, b); } double logb(double a) { // If "a" is denormalized, logb() is supposed to return the exponent that // "a" would have if it were normalized. (But it doesn't.) if (a != 0 && fabs(a) < std::numeric_limits::min()) { return ::logb(scalbn(a, 100)) - 100; } return ::logb(a); } double ldexp(double a, int exp) { // ldexp() incorrectly returns infinity rather than zero when the // "a" is finite and "exp" is a very large negative value. double r = ::ldexp(a, exp); if (std::isinf(r) && !std::isinf(a) && exp < 0) { return copysign(0, r); } return r; } double scalbn(double a, int exp) { return ldexp(a, exp); // See ldexp(). } double scalbln(double a, long exp) { // Clamp the exponent to the range of "int" in order to avoid truncation. exp = std::max(static_cast(INT_MIN), std::min(static_cast(INT_MAX), exp)); return ldexp(a, exp); // See ldexp(). } // The C standard does not specify the result of converting a floating-point // number to an integer if the argument is NaN or out of range. This applies // to both static_cast and functions such as lrint, lround, etc. // // With the glibc/Intel platform tested here, these conversions return the // minimum possible value of the result type. (Except if the argument is a // constant, in which case gcc converts NaN to zero and clamps out of range // arguments to the minimum or maximum possible value.) // // Here we fix the rounding functions to match MPFloat, which clamps out of // range values and returns the maximum possible value for NaN. #define FIX_INT_ROUNDING(T, fname) \ T fname(double a) { \ if (std::isnan(a)) return std::numeric_limits::max(); \ if (a <= std::numeric_limits::min()) \ return std::numeric_limits::min(); \ if (a >= std::numeric_limits::max()) \ return std::numeric_limits::max(); \ return ::fname(a); \ } FIX_INT_ROUNDING(long, lrint) FIX_INT_ROUNDING(long, lround) FIX_INT_ROUNDING(long long, llrint) FIX_INT_ROUNDING(long long, llround) #endif // DONT_FIX_GLIBC_MATH_FUNCTIONS // A list of double-precision constants to use as arguments when evaluating // math intrinsics. The negated values of these constants are used as well, // so only one constant with a given absolute value needs to be listed. constexpr double kSpecialUnsignedDoubleValues[] = { std::numeric_limits::quiet_NaN(), // Minimum and maximum values of various relevant C++ types. std::numeric_limits::infinity(), std::numeric_limits::max(), std::numeric_limits::min(), std::numeric_limits::denorm_min(), static_cast(std::numeric_limits::max()), static_cast(std::numeric_limits::min()), static_cast(std::numeric_limits::max()), static_cast(std::numeric_limits::min()), static_cast(std::numeric_limits::max()), 0, // Small and large values that are not quite minimums or maximums. 1.23e-300, 1e-20, 1e20, 1.23e300, // Interesting values for trigonometric, exponential, and logarithm // functions. 2 * M_PI, M_PI, M_PI_2, M_PI_4, M_E, M_LN2, // Positive and negative powers of two. 1 << 30, 256, 16, 2, 1, 0.5, 1.0 / 256, 1.0 / (1 << 30), // Interesting values for integer rounding functions. 1.5, 2.5, 3.5, // Miscellaneous integer and non-integer "ordinary" values. 42, 7, 5, 0.3, 0.17, }; class ExactFloatTest : public ::testing::Test { public: // Initialize the list of constants to be used for testing intrinsics. static void SetUpTestSuite() { ABSL_CHECK(special_double_values_->empty()); for (double d : kSpecialUnsignedDoubleValues) { special_double_values_->push_back(d); // Glibc and MPFloat handle negative NaN values differently. To avoid // discrepancies, we only test positively-signed NaN values. if (!std::isnan(d)) { special_double_values_->push_back(-d); } } } static void TearDownTestSuite() { special_double_values_->clear(); } // Return the difference measured in ulps (units in the last place) between // two floating-point values. Return 0 if the values are equal or both are // NaN, and return the largest possible uint64_t if exactly one value is NaN. // Note that +0 and -0 are equal (i.e., they differ by 0 ulps), and that the // smallest positive and negative values differ by 2 ulps. Infinity is one // ulp larger than the largest finite number. static uint64_t GetErrorUlps(double a, double b) { if (std::isnan(a) && std::isnan(b)) return 0; if (std::isnan(a) || std::isnan(b)) { return std::numeric_limits::max(); } // Floating-point numbers are arranged so that for numbers of the same // sign, the difference in ulps is just the difference between the two // numbers viewed as 64-bit unsigned integers. uint64_t a_bits = absl::bit_cast(a); uint64_t b_bits = absl::bit_cast(b); if (std::signbit(a) == std::signbit(b)) { return (a_bits > b_bits) ? (a_bits - b_bits) : (b_bits - a_bits); } // For numbers of opposite sign, we take the difference in ulps between // each number and the zero of the same sign, and add them together. a_bits ^= static_cast(1) << 63; return a_bits + b_bits; } // Return true if the difference between "expected" and "actual" is at most // the given number of ulps (units in the last place). The two values are // also required to have the same sign bit unless they are both NaN. (So for // example, +0 and -0 are not equivalent.) static bool IsExpected(double expected, double actual, uint64_t ulps) { // We require the sign bit to match unless the values are NaN. if (!std::isnan(expected) && std::signbit(expected) != std::signbit(actual)) { return false; } return GetErrorUlps(expected, actual) <= ulps; } // Expect "actual" to have the given value when converted to a "double". // Two values are considered equivalent if they have the same bit pattern or // they are both NaN. (So for example, +0 and -0 are not equivalent.) void ExpectSame(double expected, const ExactFloat& xf_actual) { double actual = static_cast(xf_actual); if (std::isnan(expected)) { EXPECT_TRUE(std::isnan(actual)); } else { // Keep the ugly std::signbit() macro out of the error messages. bool expected_sign = std::signbit(expected); bool actual_sign = std::signbit(actual); EXPECT_EQ(expected_sign, actual_sign); EXPECT_EQ(expected, actual); } } // Like ExpectSame() but also check that "actual" has the expected precision. void ExpectSameWithPrec(double expected_value, int expected_prec, const ExactFloat& xf_actual) { ExpectSame(expected_value, xf_actual); EXPECT_EQ(expected_prec, xf_actual.prec()); } // Log an error when a math intrinsic does not return the expected result. static void AddMathcallFailure(const testing::Message& call_msg, double expected, double actual) { ADD_FAILURE() << call_msg << "\nExpected (glibc): " << ExactFloat(expected) << "\nActual (ExactFloat): " << ExactFloat(actual) << "\nError: " << GetErrorUlps(expected, actual) << " ulps"; } protected: // Given two versions "f" and "mp_f" of the unary function called "fname", // check that their results agree to within the given number of ulps for a // range of test arguments. void TestMathcall1(const char* fname, double f(double), ExactFloat mp_f(const ExactFloat&), uint64_t ulps) { for (double a : *special_double_values_) { double expected = f(a); double actual = static_cast(mp_f(ExactFloat(a))); if (!IsExpected(expected, actual, ulps)) { AddMathcallFailure(testing::Message() << fname << "(" << ExactFloat(a) << ")", expected, actual); } } } // Given two versions "f" and "mp_f" of the binary function called "fname", // check that their results agree to within the given number of ulps for a // range of test arguments. void TestMathcall2(const char* fname, double f(double, double), ExactFloat mp_f(const ExactFloat&, const ExactFloat&), uint64_t ulps) { for (double a : *special_double_values_) { for (double b : *special_double_values_) { double expected = f(a, b); double actual = static_cast(mp_f(ExactFloat(a), ExactFloat(b))); if (!IsExpected(expected, actual, ulps)) { AddMathcallFailure(testing::Message() << fname << "(" << ExactFloat(a) << ", " << ExactFloat(b) << ")", expected, actual); } } } } // Given a one-argument function "f" and a zero-argument ExactFloat member // function "mp_f", check that they return the same result on a range of // test arguments. template void TestFn(const char* fname, ResultType f_dbl(double), ResultType f_xf(const ExactFloat&)) { for (double a : *special_double_values_) { ResultType expected = f_dbl(a); ResultType actual = f_xf(ExactFloat(a)); if (expected != actual) { AddMathcallFailure(testing::Message() << ExactFloat(a) << "." << fname << "()", expected, actual); } } } // Given two versions "f" and "mp_f" of a unary function called "fname" that // returns the integer type ResultType, check that they return the same // value for a range of test arguments. template void TestIntMathcall1(const char* fname, ResultType f(double), ResultType mp_f(const ExactFloat&)) { for (double a : *special_double_values_) { ResultType expected = f(a); ResultType actual = mp_f(ExactFloat(a)); if (actual != expected) { AddMathcallFailure( testing::Message() << fname << "(" << ExactFloat(a) << ")", static_cast(expected), static_cast(actual)); } } } // Given two versions "f" and "mp_f" of a function called "fname" that has // an interface similar to ldexp() (i.e., with one "double" argument and one // integer argument), check that they return the same result for a range of // test arguments. "ExpType" is the type of the integer argument. template void TestLdexpCall(const char* fname, double f(double, ExpType), ExactFloat mp_f(const ExactFloat&, ExpType)) { static constexpr ExpType kUnsignedExpValues[] = { // Doesn't test with numeric_limits::min() because it's // undefined // to negate the min value of a signed number. std::numeric_limits::max(), 0, 1, 2, 3, 10, 20, 50, 100, 200, 500, 999, 1022, 1023, 1024, 1073, 1074, 2046, 2047, 2048, 4096, 1000000, }; for (double a : *special_double_values_) { for (ExpType unsigned_exp : kUnsignedExpValues) { for (int sign : {-1, +1}) { ExpType exp = sign * unsigned_exp; double expected = f(a, exp); double actual = static_cast(mp_f(ExactFloat(a), exp)); if (!IsExpected(expected, actual, 0)) { AddMathcallFailure(testing::Message() << fname << "(" << ExactFloat(a) << ", " << exp << ")", expected, actual); } } } } } private: // Uses `isnan` in initialization; this can be `constexpr` when we support // C++23; `isnan` is not `constexpr` until then. static absl::NoDestructor> special_double_values_; }; absl::NoDestructor> ExactFloatTest::special_double_values_; TEST_F(ExactFloatTest, GetErrorUlps) { // Verify some of the assertions made by GetErrorUlps(). EXPECT_EQ(0, GetErrorUlps(NAN, -NAN)); EXPECT_EQ(0, GetErrorUlps(0, copysign(0, -1))); EXPECT_EQ(2, GetErrorUlps(std::numeric_limits::denorm_min(), -std::numeric_limits::denorm_min())); EXPECT_EQ(1, GetErrorUlps(std::numeric_limits::max(), INFINITY)); EXPECT_EQ(std::numeric_limits::max(), GetErrorUlps(0, NAN)); } TEST_F(ExactFloatTest, Constructors) { // Default constructor. ExactFloat a; ExpectSameWithPrec(0.0, 0, a); // Construct an ExactFloat from the literal constant "0". It is necessary to // have an implicit constructor that takes an "int" argument for this to // work; otherwise the compiler thinks that "0" is ambiguous (it could be a // "double" or a "const char*"). ExactFloat a0 = 0; ExpectSameWithPrec(0.0, 0, a); // Implicit constructor from "double". ExactFloat b = 2.5; ExpectSameWithPrec(2.5, 3, b); // Implicit constructor from "int". ExactFloat c = -125; ExpectSameWithPrec(-125, 7, c); // Copy constructor. ExactFloat e = c; ExpectSameWithPrec(-125, 7, e); } TEST_F(ExactFloatTest, IntMinConstruction) { // Ensure that construction with INT_MIN works properly. ExactFloat f = INT_MIN; ExpectSame(INT_MIN, f); } TEST_F(ExactFloatTest, Constants) { EXPECT_TRUE(ExactFloat::SignedZero(+1).is_zero()); EXPECT_EQ(false, signbit(ExactFloat::SignedZero(+1))); EXPECT_TRUE(ExactFloat::SignedZero(-1).is_zero()); EXPECT_EQ(true, signbit(ExactFloat::SignedZero(-1))); EXPECT_TRUE(isinf(ExactFloat::Infinity(+1))); EXPECT_EQ(false, signbit(ExactFloat::Infinity(+1))); EXPECT_TRUE(isinf(ExactFloat::Infinity(-1))); EXPECT_EQ(true, signbit(ExactFloat::Infinity(-1))); EXPECT_TRUE(isnan(ExactFloat::NaN())); } TEST_F(ExactFloatTest, Accessors) { // A few quick checks of prec(), max_prec(), and exp(). ExactFloat x = 7.25; ExpectSameWithPrec(7.25, 5, x); EXPECT_EQ(3, x.exp()); EXPECT_EQ(ExactFloat::kMaxPrec, x.max_prec()); x = 255; ExpectSameWithPrec(255, 8, x); EXPECT_EQ(8, x.exp()); x = 256; ExpectSameWithPrec(256, 1, x); EXPECT_EQ(9, x.exp()); } TEST_F(ExactFloatTest, set_zero) { ExactFloat x = 5.0; EXPECT_FALSE(x.is_zero()); x.set_zero(+1); EXPECT_TRUE(x.is_zero()); ExpectSameWithPrec(0.0, 0, x); x.set_zero(-1); EXPECT_TRUE(x.is_zero()); ExpectSameWithPrec(copysign(0.0, -1), 0, x); } TEST_F(ExactFloatTest, set_inf) { ExactFloat x; EXPECT_FALSE(isinf(x)); x.set_inf(+1); EXPECT_TRUE(isinf(x)); ExpectSameWithPrec(INFINITY, 0, x); x.set_inf(-1); EXPECT_TRUE(isinf(x)); ExpectSameWithPrec(-INFINITY, 0, x); x = NAN; EXPECT_FALSE(isinf(x)); x = INFINITY; EXPECT_TRUE(isinf(x)); ExpectSameWithPrec(INFINITY, 0, x); x = -INFINITY; EXPECT_TRUE(isinf(x)); ExpectSameWithPrec(-INFINITY, 0, x); } TEST_F(ExactFloatTest, set_nan) { ExactFloat x; EXPECT_FALSE(isnan(x)); ExpectSameWithPrec(0.0, 0, x); x.set_nan(); EXPECT_TRUE(isnan(x)); ExpectSameWithPrec(NAN, 0, x); x = 2; EXPECT_FALSE(isnan(x)); x = NAN; EXPECT_TRUE(isnan(x)); ExpectSameWithPrec(NAN, 0, x); } TEST_F(ExactFloatTest, OperatorDouble) { EXPECT_EQ(0, static_cast(ExactFloat(0))); ExpectSame(copysign(0.0, -1), -ExactFloat(0)); EXPECT_EQ( std::numeric_limits::max(), static_cast(ExactFloat(std::numeric_limits::max()))); EXPECT_EQ( -std::numeric_limits::min(), static_cast(ExactFloat(-std::numeric_limits::min()))); EXPECT_EQ(std::numeric_limits::denorm_min(), static_cast( ExactFloat(std::numeric_limits::denorm_min()))); EXPECT_EQ(-12.7, static_cast(ExactFloat(-12.7))); EXPECT_EQ(M_PI, static_cast(ExactFloat(M_PI))); EXPECT_EQ(INFINITY, static_cast(ExactFloat(INFINITY))); EXPECT_EQ(-INFINITY, static_cast(ExactFloat(-INFINITY))); EXPECT_TRUE(std::isnan(static_cast(ExactFloat(NAN)))); } TEST_F(ExactFloatTest, ToString) { EXPECT_EQ("0.001", ExactFloat(0.001).ToString()); EXPECT_EQ("0.10000000000000001", ExactFloat(0.1).ToString()); EXPECT_EQ("0.001953125", ExactFloat(1. / 512).ToString()); EXPECT_EQ("1e-50", ExactFloat(1e-50).ToString()); EXPECT_EQ("1e-50", ExactFloat(1e-50).ToString()); EXPECT_EQ("0", ExactFloat(0).ToString()); EXPECT_EQ("nan", ExactFloat(NAN).ToString()); EXPECT_EQ("-inf", ExactFloat(-INFINITY).ToString()); EXPECT_EQ("65536", ExactFloat(65536).ToString()); EXPECT_EQ("1048576", ExactFloat(1 << 20).ToString()); EXPECT_EQ("1048575", ExactFloat((1 << 20) - 1).ToString()); EXPECT_EQ("1073741824", ExactFloat(1 << 30).ToString()); EXPECT_EQ("1073741823", ExactFloat((1 << 30) - 1).ToString()); EXPECT_EQ("1.099511628e+12", ExactFloat(pow(2, 40)).ToString()); EXPECT_EQ("1099511627775", ExactFloat(pow(2, 40) - 1).ToString()); EXPECT_EQ("1.606938044e+60", ExactFloat(pow(2, 200)).ToString()); EXPECT_EQ("1606938044258990275541962092341162602522202993782792835301375", (ExactFloat(pow(2, 200)) - 1).ToString()); EXPECT_EQ("3.1415926535897931", ExactFloat(M_PI).ToString()); // Verify that ToString implements kRoundTiesToEven (the same as glibc). EXPECT_EQ("0.62", ExactFloat(0.625).ToStringWithMaxDigits(2)); EXPECT_EQ("0.62", ExactFloat(0.625).ToStringWithMaxDigits(2)); EXPECT_EQ("1.88", ExactFloat(1.875).ToStringWithMaxDigits(3)); // Three digits are sufficient to distinguish any two numbers with 6-bit // mantissas, but up to four digits are required to distinguish two numbers // with 7-bit mantissas (e.g. 1016 and 1024). EXPECT_EQ(3, ExactFloat::NumSignificantDigitsForPrec(6)); EXPECT_EQ(4, ExactFloat::NumSignificantDigitsForPrec(7)); ABSL_LOG(INFO) << "Test of ExactFloat stream output: " << ExactFloat(1.23456); } TEST_F(ExactFloatTest, ToUniqueString) { // The following test demonstrates that ExactFloats with different values and // different precisions can generate the same ToString() value. ExactFloat value = 0.01; ExactFloat v1 = value.RoundToMaxPrec(33, ExactFloat::kRoundTiesToEven); ExactFloat v2 = value.RoundToMaxPrec(46, ExactFloat::kRoundTiesToEven); EXPECT_NE(v1, v2); EXPECT_EQ("0.01", v1.ToString()); EXPECT_EQ("0.01", v2.ToString()); EXPECT_EQ("0.01<33>", v1.ToUniqueString()); EXPECT_EQ("0.01<46>", v2.ToUniqueString()); } TEST_F(ExactFloatTest, RoundToMaxPrec) { // This method is used by the `operator double()` implementation and also the // rounding function such as trunc(), floor(), etc, so it is already pretty // well tested. We do a few other tests here. EXPECT_EQ(ExactFloat(pow(2, 500)), (ExactFloat(pow(2, 500)) - 1) .RoundToMaxPrec(2, ExactFloat::kRoundTiesToEven)); EXPECT_EQ(ExactFloat(pow(2, 500)), (ExactFloat(pow(2, 500)) - 1) .RoundToMaxPrec(499, ExactFloat::kRoundTiesToEven)); EXPECT_EQ(ExactFloat(pow(2, 500)) - 4, (ExactFloat(pow(2, 500)) - 3) .RoundToMaxPrec(499, ExactFloat::kRoundTiesToEven)); EXPECT_EQ(ExactFloat(pow(2, 500)) + 16, (ExactFloat(pow(2, 500)) + 1) .RoundToMaxPrec(497, ExactFloat::kRoundTowardPositive)); EXPECT_EQ(2.7, ExactFloat(2.7).RoundToMaxPrec(1000000, ExactFloat::kRoundTiesToEven)); } // Test the ExactFloat version of the unary operator "op" against the // corresponding C++ operator. #define TEST_MATHOP1(op_name, op) \ double op_name(double a) { return op(a); } \ ExactFloat mp_##op_name(const ExactFloat& a) { return op(a); } \ TEST_F(ExactFloatTest, op_name) { \ TestMathcall1(#op_name, op_name, mp_##op_name, 0); \ } TEST_MATHOP1(plus, +) TEST_MATHOP1(minus, -) // Test the ExactFloat version of the binary operator "op" against the // corresponding C++ operator. #define TEST_MATHOP2(op_name, op) \ double op_name(double a, double b) { return (a)op(b); } \ ExactFloat mp_##op_name(const ExactFloat& a, const ExactFloat& b) { \ return (a)op(b); \ } \ TEST_F(ExactFloatTest, op_name) { \ TestMathcall2(#op_name, op_name, mp_##op_name, 0); \ } TEST_MATHOP2(add, +); TEST_MATHOP2(subtract, -); TEST_MATHOP2(multiply, *); // Division is not defined. TEST_MATHOP2(equal, ==); TEST_MATHOP2(less, <); TEST_MATHOP2(greater, >); TEST_MATHOP2(not_equal, !=); TEST_MATHOP2(not_less, >=); TEST_MATHOP2(not_greater, <=); // Test the various assignment operators. #define TEST_ASSIGNOP(op_name, op) \ double op_name(double a, double b) { \ (a) op(b); \ return a; \ } \ ExactFloat mp_##op_name(const ExactFloat& a, const ExactFloat& b) { \ ExactFloat x = a; \ x op(b); \ return x; \ } \ TEST_F(ExactFloatTest, op_name) { \ TestMathcall2(#op_name, op_name, mp_##op_name, 0); \ } TEST_ASSIGNOP(assignment, =); TEST_ASSIGNOP(plus_equals, +=); TEST_ASSIGNOP(minus_equals, -=); TEST_ASSIGNOP(times_equals, *=); // Division is not defined. // Check that the ExactFloat and glibc versions of "func" always return the same // value to within the given number of ulps. #define TEST_MATHCALL1(func, ulps) \ /* We define a wrapper function around ExactFloat version of "func" */ \ /* so that we can take its address (gcc can't find it otherwise). */ \ ExactFloat mp_##func(const ExactFloat& a) { return func(a); } \ TEST_F(ExactFloatTest, func) { TestMathcall1(#func, func, mp_##func, ulps); } // Test all the unary math instrinsics (in the same order as the .h file). TEST_MATHCALL1(fabs, 0) TEST_MATHCALL1(ceil, 0) TEST_MATHCALL1(floor, 0) TEST_MATHCALL1(trunc, 0) TEST_MATHCALL1(rint, 0) TEST_MATHCALL1(nearbyint, 0) TEST_MATHCALL1(logb, 0) TEST_MATHCALL1(round, 0) // Check that the ExactFloat and glibc versions of "func" always return the // same value to within the given number of ulps. #define TEST_MATHCALL2(func, ulps) \ ExactFloat mp_##func(const ExactFloat& a, const ExactFloat& b) { \ return func(a, b); \ } \ TEST_F(ExactFloatTest, func) { TestMathcall2(#func, func, mp_##func, ulps); } // Test all the binary math instrinsics (in the same order as the .h file). TEST_MATHCALL2(fmax, 0) TEST_MATHCALL2(fmin, 0) TEST_MATHCALL2(fdim, 0) TEST_MATHCALL2(copysign, 0) // Check that the ExactFloat and glibc versions of "func" return the same // integer value. #define TEST_INTEGER_MATHCALL1(ResultType, func) \ ResultType mp_##func(const ExactFloat& a) { return func(a); } \ TEST_F(ExactFloatTest, func) { TestIntMathcall1(#func, func, mp_##func); } TEST_INTEGER_MATHCALL1(long, lrint); TEST_INTEGER_MATHCALL1(long long, llrint); TEST_INTEGER_MATHCALL1(long, lround); TEST_INTEGER_MATHCALL1(long long, llround); TEST_INTEGER_MATHCALL1(int, ilogb); //////////////////////////////////////////////////////////////////////////// // frexp(): Test using wrapper functions to check each result separately. double frexp_frac(double a) { int exp_part; return frexp(a, &exp_part); } int frexp_exp(double a) { int exp_part; (void)frexp(a, &exp_part); return exp_part; } ExactFloat mp_frexp_frac(const ExactFloat& a) { int exp_part; return frexp(a, &exp_part); } int mp_frexp_exp(const ExactFloat& a) { int exp_part; (void)frexp(a, &exp_part); return exp_part; } #if !defined(__wasm__) TEST_F(ExactFloatTest, frexp) { TestMathcall1("frexp_frac", frexp_frac, mp_frexp_frac, 0); TestIntMathcall1("frexp_exp", frexp_exp, mp_frexp_exp); } #endif //////////////////////////////////////////////////////////////////////////// // ldexp(), scalbn(), scalbln() #define TEST_LDEXP_CALL(ExpType, func) \ ExactFloat mp_##func(const ExactFloat& a, ExpType exp) { \ return func(a, exp); \ } \ TEST_F(ExactFloatTest, func) { TestLdexpCall(#func, func, mp_##func); } // Results are different on Apple platforms; it's not clear if it's an Apple // or glibc problem. #if !defined(__APPLE__) TEST_LDEXP_CALL(int, ldexp); TEST_LDEXP_CALL(int, scalbn); TEST_LDEXP_CALL(long, scalbln); #endif // Test a zero-argument ExactFloat member function against a corresponding // one-argument reference function. #define TEST_FN_VS_REF(ResultType, fn_xf, fn_dbl) \ TEST_F(ExactFloatTest, fn_xf) { TestFn(#fn_xf, fn_dbl, fn_xf); } // "Reference versions" of various zero-argument methods. bool ref_iszero(double a) { return a == 0; } bool ref_isnormal(double a) { return (a != 0) && !std::isinf(a) && !std::isnan(a); } int ref_sgn(double a) { return (a > 0) ? 1 : (a < 0) ? -1 : 0; } bool xf_iszero(const ExactFloat& xf) { return xf.is_zero(); } int xf_sgn(const ExactFloat& xf) { return xf.sgn(); } TEST_FN_VS_REF(bool, isnormal, ref_isnormal) TEST_FN_VS_REF(bool, xf_iszero, ref_iszero) TEST_FN_VS_REF(int, xf_sgn, ref_sgn) // Test a zero-argument ExactFloat member function against a corresponding // one-argument std:: function. #define TEST_FN_VS_STD_FN(ResultType, fn) \ ResultType ref_##fn(double a) { return std::fn(a); } \ TEST_FN_VS_REF(ResultType, fn, ref_##fn) TEST_FN_VS_STD_FN(bool, isinf) TEST_FN_VS_STD_FN(bool, isnan) TEST_FN_VS_STD_FN(bool, isfinite) TEST_FN_VS_STD_FN(bool, signbit) TEST(FpClassify, Nan) { EXPECT_EQ(fpclassify(ExactFloat(NAN)), FP_NAN); } TEST(FpClassify, Infinity) { EXPECT_EQ(fpclassify(ExactFloat(INFINITY)), FP_INFINITE); EXPECT_EQ(fpclassify(ExactFloat(-INFINITY)), FP_INFINITE); } TEST(FpClassify, Zero) { EXPECT_EQ(fpclassify(ExactFloat(0.0)), FP_ZERO); EXPECT_EQ(fpclassify(ExactFloat(std::copysign(0.0, -1.0))), FP_ZERO); } TEST(FpClassify, Normal) { EXPECT_EQ(fpclassify(ExactFloat(1.0)), FP_NORMAL); // Would be FP_INFINITE with double arg. EXPECT_EQ(fpclassify(2.0 * ExactFloat(std::numeric_limits::max())), FP_NORMAL); // Would be FP_SUBNORMAL with double arg. EXPECT_EQ(fpclassify(ExactFloat(std::numeric_limits::denorm_min())), FP_NORMAL); } typedef Vector2 MyVec2; typedef Vector3 MyVec3; TEST_F(ExactFloatTest, Vector3_Part1) { // Check that ExactFloat can be used with templatized classes such as Vector2 // and Vector3. We exercise all the methods of Vector3 to check that they // compile and do something reasonable. // // IsNaN() is not tested because it cannot be used with vectors of ExactFloats // (see the header file). // // This test is split into parts because of the stack frame size limit. MyVec3 zero; MyVec3 zero2(0, 0, 0); EXPECT_EQ(zero, zero2); MyVec3 zero3(MyVec2(0, 0), 0); EXPECT_EQ(zero, zero3); MyVec3 almost_zero(1e-200, 1e-100, 1e-50); EXPECT_NE(zero, almost_zero); EXPECT_TRUE(almost_zero.aequal(zero, 1e-15)); EXPECT_LT(zero, almost_zero); // Total order, for STL purposes. MyVec3 almost_zero2(ExactFloat(1e-320), 0, 0); EXPECT_NE(zero, almost_zero2); EXPECT_TRUE(almost_zero2.aequal(zero, 1e-300)); EXPECT_LT(almost_zero2, almost_zero); EXPECT_LT(zero, almost_zero2); EXPECT_EQ(MyVec3(1, -2, 3), MyVec3::Cast(Vector3_d(1, -2, 3))); EXPECT_EQ(MyVec3(1, -2, 3), MyVec3::Cast(Vector3(1, -2, 3))); // Two ways to convert, these are the same. MyVec3 x(1.5, 2.5, 3.5); Vector3_d y1 = Vector3_d::Cast(x); EXPECT_EQ(y1, Vector3_d(1.5, 2.5, 3.5)); Vector3_d y2 = Vector3_d(static_cast(x[0]), static_cast(x[1]), static_cast(x[2])); EXPECT_EQ(y2, Vector3_d(1.5, 2.5, 3.5)); } TEST_F(ExactFloatTest, Vector3_Part2) { MyVec3 x; x.Set(1, 2, 3.5); EXPECT_EQ(MyVec3(1, 2, 3.5), x); x = MyVec3(4, 5, 6); EXPECT_EQ(MyVec3(4, 5, 6), x); x += MyVec3(1, 2, 3); EXPECT_EQ(MyVec3(5, 7, 9), x); x -= MyVec3(3, 2, 1); EXPECT_EQ(MyVec3(2, 5, 8), x); x *= 3; EXPECT_EQ(MyVec3(6, 15, 24), x); x = MyVec3(2, 5, 8); MyVec3 y(1, 2, 3); MyVec3 z = x.MulComponents(y); EXPECT_EQ(MyVec3(2, 10, 24), z); z = MyVec3(1, 2, 3); EXPECT_EQ(MyVec3(5, 7, 9), z + MyVec3(4, 5, 6)); EXPECT_EQ(MyVec3(-5, -3, -1), z - MyVec3(6, 5, 4)); EXPECT_EQ(MyVec3(-1, -2, -3), -z); EXPECT_EQ(z.DotProd(z), 14); EXPECT_EQ(MyVec3(2, 4, 6), 2 * z); } TEST_F(ExactFloatTest, Vector3_Part3) { MyVec3 y(3, 4, 1); MyVec3 z(2, -3, 1); EXPECT_EQ(MyVec3(7, -1, -17), y.CrossProd(z)); EXPECT_EQ(3, y[0]); y[0] = 5; EXPECT_EQ(5, y.x()); EXPECT_EQ(4, y.y()); EXPECT_EQ(1, y.z()); y.x(3); EXPECT_EQ(MyVec3(3, 4, 1), y); ExactFloat* y_data = y.Data(); y_data[2] = 12; EXPECT_EQ(MyVec3(3, 4, 12), y); EXPECT_EQ(y.Data()[1], ExactFloat(4)); EXPECT_EQ(y.Norm2(), 169); EXPECT_EQ(6, z.DotProd(y)); EXPECT_EQ(2, y.LargestAbsComponent()); EXPECT_EQ(Vector3(1, 2, 0), z.ComponentOrder()); EXPECT_EQ(MyVec3(4, -6, 2), 2 * z); EXPECT_EQ(MyVec3(4, 9, 1), z.MulComponents(z)); EXPECT_EQ(MyVec3(2, 3, 1), z.Abs()); EXPECT_EQ(MyVec3(2, 3, 1), z.Fabs()); z.Set(-0.5, 1.5, 2.5); EXPECT_EQ(MyVec3(-1, 1, 2), z.Floor()); EXPECT_EQ(MyVec3(0, 2, 3), z.Ceil()); EXPECT_EQ(MyVec3(0, 2, 2), z.FRound()); EXPECT_EQ(Vector3_i(0, 2, 2), z.IRound()); y.Set(2.0, -2.0, 0.0); EXPECT_EQ(MyVec3(2.0, 1.5, 2.5), Max(z, y)); EXPECT_EQ(MyVec3(-0.5, -2.0, 0.0), Min(z, y)); y.Clear(); EXPECT_EQ(MyVec3(0, 0, 0), y); ABSL_LOG(INFO) << "Test of Vector3 stream output: " << y; } TEST_F(ExactFloatTest, Vector3_IsNaN_NoNaNsReturnsFalse) { EXPECT_FALSE(MyVec3(1, 2, 3).IsNaN()); } TEST_F(ExactFloatTest, Vector3_IsNaN_AnyNanReturnsTrue) { constexpr double kNaN = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(MyVec3(kNaN, 2, 3).IsNaN()); EXPECT_TRUE(MyVec3(1, 2, kNaN).IsNaN()); } TEST_F(ExactFloatTest, ImplicitConversions) { // Check that constants are implicitly converted to ExactFloats when they are // used in arithmetic expressions. // Check that ints/doubles are converted to ExactFloats in comparisons. EXPECT_EQ(1, ExactFloat(1.0)); EXPECT_LE(1.5, ExactFloat(2.5)); // Check that ints/doubles can be used as the first argument in arithmetic // operations. ExactFloat x = 11; EXPECT_EQ(24, 13 + x); EXPECT_EQ(10.5, 21.5 - x); EXPECT_EQ(-22, 2.0 * -x); // Intrinsic where one argument is an ExactFloat and the other is an int. EXPECT_EQ(3.0, fmax(ExactFloat(1), 3)); } TEST_F(ExactFloatTest, ExactCalculations) { // Try a calculation that requires high precision. ExactFloat v1 = pow(2, 1000); ExactFloat v2 = v1 - pow(2, -1000); ExactFloat v3 = v1 + pow(2, -1000); EXPECT_EQ(v3 * v3 - v2 * v2, 4 * v1 * pow(2, -1000)); EXPECT_EQ((v3 + v2) * (v3 - v2), 4 * v1 * pow(2, -1000)); // Check that precision is increased as necessary to avoid rounding. typedef Vector3 Vector3_xf; Vector3_xf x(1.1e300, 1.1e-300, 1.1); Vector3_xf y(1.1, 1.1e300, 1.1e-300); Vector3_xf z(1.1e-300, 1.1, 1.1e300); ExactFloat det = x.CrossProd(y).DotProd(z); EXPECT_GE(det.prec(), 6000); EXPECT_LT(det.prec(), 6300); } void BM_Det3x3(benchmark::State &state) { // Compute the determinant of a 3x3 matrix of numbers in the range [0,1). // (It would be better to use a different matrix for each iteration, but // then generating the matrix takes up a significant fraction of the time.) typedef Vector3 Vector3_xf; std::mt19937_64 rnd; Vector3_d a(absl::Uniform(rnd, 0, 1), absl::Uniform(rnd, 0, 1), absl::Uniform(rnd, 0, 1)); Vector3_d b(absl::Uniform(rnd, 0, 1), absl::Uniform(rnd, 0, 1), absl::Uniform(rnd, 0, 1)); Vector3_d c(absl::Uniform(rnd, 0, 1), absl::Uniform(rnd, 0, 1), absl::Uniform(rnd, 0, 1)); for (auto _ : state) { Vector3_xf xa = Vector3_xf::Cast(a); Vector3_xf xb = Vector3_xf::Cast(b); Vector3_xf xc = Vector3_xf::Cast(c); ExactFloat det = xa.CrossProd(xb).DotProd(xc); ABSL_CHECK_NE(det.sgn(), 0); } } BENCHMARK(BM_Det3x3); } // namespace src/s2/util/math/exactfloat/exactfloat_underflow_test.cc000066400000000000000000000104641524103652300240240ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include #include "s2/util/math/exactfloat/exactfloat.h" namespace { using ::exactfloat::ExactFloat; TEST(ExactFloatTest, Overflow) { // Construct an ExactFloat whose exponent is kMaxExp. const int kMaxExp = ExactFloat::kMaxExp; ExactFloat v = ldexp(ExactFloat(0.5), kMaxExp); EXPECT_FALSE(isinf(v)); EXPECT_EQ(kMaxExp, v.exp()); // Now check that if the exponent is made larger, it overflows. EXPECT_TRUE(isinf(2 * v)); EXPECT_GT(2 * v, 0); EXPECT_TRUE(isinf(-2 * v)); EXPECT_LT(-2 * v, 0); // Check that overflowing the exponent a lot does not cause problems. EXPECT_TRUE(isinf(v * v)); } TEST(ExactFloatTest, OverflowMaxExpAndPrecision) { const int kMaxExp = ExactFloat::kMaxExp; const int kMaxPrec = ExactFloat::kMaxPrec; const int kMinExp = ExactFloat::kMinExp; // Now build an ExactFloat whose exponent and precision are both maximal (!) const ExactFloat v = ldexp(1.0 - ldexp(ExactFloat(1.0), -kMaxPrec), kMaxExp); EXPECT_FALSE(isinf(v)); EXPECT_EQ(ExactFloat::kMaxExp, v.exp()); EXPECT_EQ(ExactFloat::kMaxPrec, v.prec()); // Try overflowing it in various ways. EXPECT_TRUE( isinf(v + ldexp(ExactFloat(1.0), kMaxExp - kMaxPrec))); EXPECT_TRUE(isinf(2 * v)); // Check that if kMaxPrec is exceeded, the result is NaN. The first line // attempts to add one more bit to the mantissa, while the second line // attempts to add as many bits as possible (by adding together the largest // and smallest possible maximum-precision numbers). EXPECT_TRUE( isnan(v + ldexp(ExactFloat(1.0), kMaxExp - kMaxPrec - 1))); EXPECT_TRUE(isnan( v + ldexp(1.0 - ldexp(ExactFloat(1.0), -kMaxPrec), kMinExp))); // Check that if kMaxExp and kMaxPrec are exceeded simultaneously, the // result is infinity rather than NaN. ExactFloat a = ldexp(1.0 - ldexp(ExactFloat(1.0), -kMaxPrec), kMaxExp); ExactFloat b = ldexp(1.0 - ldexp(ExactFloat(1.0), -kMaxPrec), kMaxExp - 1); EXPECT_TRUE(isinf(a + b)); } TEST(ExactFloatTest, Underflow) { // Construct an ExactFloat whose exponent is kMinExp. const int kMinExp = ExactFloat::kMinExp; const ExactFloat v = ldexp(ExactFloat(0.5), kMinExp); EXPECT_FALSE(v.is_zero()); EXPECT_EQ(kMinExp, v.exp()); // Now check that if the exponent is made smaller, it underflows. EXPECT_TRUE((0.5 * v).is_zero()); EXPECT_FALSE(signbit(0.5 * v)); EXPECT_TRUE((-0.5 * v).is_zero()); EXPECT_TRUE(signbit(-0.5 * v)); // Check that underflowing the exponent a lot does not cause problems. EXPECT_TRUE((v * v).is_zero()); } // Skip this test for iOS* and Android because it times out constantly. #if !defined(__ANDROID__) && !defined(__APPLE__) TEST(ExactFloatTest, UnderflowMaxExpAndMinPrecision) { const int kMinExp = ExactFloat::kMinExp; const int kMaxPrec = ExactFloat::kMaxPrec; // Now build an ExactFloat whose exponent is minimal and whose precision is // maximal. const ExactFloat v = ldexp(1.0 - ldexp(ExactFloat(1.0), -kMaxPrec), kMinExp); EXPECT_FALSE(v.is_zero()); EXPECT_EQ(ExactFloat::kMinExp, v.exp()); EXPECT_EQ(ExactFloat::kMaxPrec, v.prec()); // Try underflowing it in various ways. ExactFloat underflow = 0.5 * v; EXPECT_TRUE(underflow.is_zero() && !signbit(underflow)); underflow = -0.5 * v; EXPECT_TRUE(underflow.is_zero() && signbit(underflow)); // Check that if kMaxPrec is exceeded, the result is NaN. EXPECT_TRUE(isnan(v + ldexp(ExactFloat(1.0), kMinExp + 1))); // Check that if kMinExp and kMaxPrec are exceeded simultaneously, the // result is zero rather than NaN. underflow = ldexp(v, -1); EXPECT_TRUE(underflow.is_zero() && !signbit(underflow)); underflow = ldexp(-v, -1); EXPECT_TRUE(underflow.is_zero() && signbit(underflow)); } #endif } // namespace src/s2/util/math/mathutil.cc000066400000000000000000000043261524103652300162430ustar00rootroot00000000000000// Copyright 2008 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "s2/util/math/mathutil.h" #include #include bool MathUtil::RealRootsForCubic(long double const a, long double const b, long double const c, long double *const r1, long double *const r2, long double *const r3) { // According to Numerical Recipes (pp. 184-5), what // follows is an arrangement of computations to // compute the roots of a cubic that minimizes // roundoff error (as pointed out by A.J. Glassman). long double const a_squared = a * a, a_third = a / 3.0, b_tripled = 3.0 * b; long double const Q = (a_squared - b_tripled) / 9.0; long double const R = (2.0 * a_squared * a - 3.0 * a * b_tripled + 27.0 * c) / 54.0; long double const R_squared = R * R; long double const Q_cubed = Q * Q * Q; if (R_squared < Q_cubed) { long double const root_Q = sqrt(Q); long double const two_pi_third = 2.0 * M_PI / 3.0; long double const theta_third = acos(R / sqrt(Q_cubed)) / 3.0; long double const minus_two_root_Q = -2.0 * root_Q; *r1 = minus_two_root_Q * cos(theta_third) - a_third; *r2 = minus_two_root_Q * cos(theta_third + two_pi_third) - a_third; *r3 = minus_two_root_Q * cos(theta_third - two_pi_third) - a_third; return true; } long double const A = -sgn(R) * pow(std::abs(R) + sqrt(R_squared - Q_cubed), 1.0 / 3.0L); if (A != 0.0) { // in which case, B from NR is zero *r1 = A + Q / A - a_third; return false; } *r1 = *r2 = *r3 = -a_third; return true; } src/s2/util/math/mathutil.h000066400000000000000000000170061524103652300161040ustar00rootroot00000000000000// Copyright 2001 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // // This class is intended to contain a collection of useful (static) // mathematical functions, properly coded (by consulting numerical // recipes or another authoritative source first). #ifndef S2_UTIL_MATH_MATHUTIL_H_ #define S2_UTIL_MATH_MATHUTIL_H_ #include #include // Returns the sign of x: // -1 if x < 0, // +1 if x > 0, // 0 if x = 0, // unspecified if x is NaN. template inline T sgn(const T x) { return (x == 0 ? 0 : (x < 0 ? -1 : 1)); } class MathUtil { public: // Solves for the real roots of x^3+ax^2+bx+c=0, returns true iff // all three are real, in which case the roots are stored (in any // order) in r1, r2, r3; otherwise, exactly one real root exists and // it is stored in r1. static bool RealRootsForCubic(long double a, long double b, long double c, long double *r1, long double *r2, long double *r3); // -------------------------------------------------------------------- // Round // This function rounds a floating-point number to an integer. It // works for positive or negative numbers. // // Values that are halfway between two integers may be rounded up or // down, for example Round(0.5) == 0 and Round(1.5) == 2. // This allows the function to be implemented efficiently on Intel // processors (see the template specializations at the bottom of this // file). You should not use this function if you care about which // way such half-integers are rounded. // // Example usage: // double y, z; // int x = Round(y + 3.7); // int64_t b = Round(0.3 * z); // // Note that the floating-point template parameter is typically inferred // from the argument type, i.e. there is no need to specify it explicitly. // -------------------------------------------------------------------- template static IntOut Round(FloatIn x) { static_assert(!std::is_integral::value, "FloatIn is integer"); static_assert(std::is_integral::value, "IntOut is not integer"); // We don't use sgn(x) below because there is no need to distinguish the // (x == 0) case. Also note that there are specialized faster versions // of this function for Intel processors at the bottom of this file. return static_cast(x < 0 ? (x - 0.5) : (x + 0.5)); } // -------------------------------------------------------------------- // FastIntRound, FastInt64Round // Fast routines for converting floating-point numbers to integers. // // These routines are approximately 6 times faster than the default // implementation of Round on Intel processors (12 times faster on // the Pentium 3). They are also more than 5 times faster than simply // casting a "double" to an "int" using static_cast. This is // because casts are defined to truncate towards zero, which on Intel // processors requires changing the rounding mode and flushing the // floating-point pipeline (unless programs are compiled specifically // for the Pentium 4, which has a new instruction to avoid this). // // Numbers that are halfway between two integers may be rounded up or // down. This is because the conversion is done using the default // rounding mode, which rounds towards the closest even number in case // of ties. So for example, FastIntRound(0.5) == 0, but // FastIntRound(1.5) == 2. These functions should only be used with // applications that don't care about which way such half-integers are // rounded. // // There are template specializations of Round() which call these // functions (for "int" and "int64_t" only), but it's safer to call them // directly. // // This functions are equivalent to lrint() and llrint() as defined in // the ISO C99 standard. Unfortunately this standard does not seem to // widely adopted yet and these functions are not available by default. // -------------------------------------------------------------------- static int32_t FastIntRound(double x) { // This function is not templatized because gcc doesn't seem to be able // to deal with inline assembly code in templatized functions, and there // is no advantage to passing an argument type of "float" on Intel // architectures anyway. #if defined __GNUC__ && (defined __i386__ || defined __SSE2__) #if defined __SSE2__ // SSE2. int32_t result; __asm__ __volatile__ ("cvtsd2si %1, %0" : "=r" (result) // Output operand is a register : "x" (x)); // Input operand is an xmm register return result; #elif defined __i386__ // FPU stack. Adapted from /usr/include/bits/mathinline.h. int32_t result; __asm__ __volatile__ ("fistpl %0" : "=m" (result) // Output operand is a memory location : "t" (x) // Input operand is top of FP stack : "st"); // Clobbers (pops) top of FP stack return result; #endif // if defined __x86_64__ || ... #else return Round(x); #endif // if defined __GNUC__ && ... } static int64_t FastInt64Round(double x) { #if defined __GNUC__ && (defined __i386__ || defined __x86_64__) #if defined __x86_64__ // SSE2. int64_t result; __asm__ __volatile__ ("cvtsd2si %1, %0" : "=r" (result) // Output operand is a register : "x" (x)); // Input operand is an xmm register return result; #elif defined __i386__ // There is no CVTSD2SI in i386 to produce a 64 bit int, even with SSE2. // FPU stack. Adapted from /usr/include/bits/mathinline.h. int64_t result; __asm__ __volatile__ ("fistpll %0" : "=m" (result) // Output operand is a memory location : "t" (x) // Input operand is top of FP stack : "st"); // Clobbers (pops) top of FP stack return result; #endif // if defined __i386__ #else return Round(x); #endif // if defined __GNUC__ && ... } }; // ========================================================================= // #if (defined __i386__ || defined __x86_64__) && defined __GNUC__ // We define template specializations of Round() to get the more efficient // Intel versions when possible. Note that gcc does not currently support // partial specialization of templatized functions. template <> inline int32_t MathUtil::Round(double x) { return FastIntRound(x); } template <> inline int32_t MathUtil::Round(float x) { return FastIntRound(x); } template <> inline int64_t MathUtil::Round(double x) { return FastInt64Round(x); } template <> inline int64_t MathUtil::Round(float x) { return FastInt64Round(x); } #endif #endif // S2_UTIL_MATH_MATHUTIL_H_ src/s2/util/math/matrix3x3.h000066400000000000000000000446631524103652300161300ustar00rootroot00000000000000// Copyright 2003 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // // A simple class to handle 3x3 matrices // The aim of this class is to be able to manipulate 3x3 matrices // and 3D vectors as naturally as possible and make calculations // readable. // For that reason, the operators +, -, * are overloaded. // (Reading a = a + b*2 - c is much easier to read than // a = Sub(Add(a, Mul(b,2)),c) ) // // Please be careful about overflows when using those matrices with integer types // The calculations are carried with VType. eg : if you are using uint8 as the // base type, all values will be modulo 256. // This feature is necessary to use the class in a more general framework with // VType != plain old data type. #ifndef S2_UTIL_MATH_MATRIX3X3_H_ #define S2_UTIL_MATH_MATRIX3X3_H_ #include #include #include #include "absl/log/absl_check.h" #include "s2/util/math/mathutil.h" #include "s2/util/math/vector.h" template class Matrix3x3 { private: VType m_[3][3]; public: typedef Matrix3x3 Self; typedef VType BaseType; typedef Vector3 MVector; // Initialize the matrix to 0 Matrix3x3() { m_[0][2] = m_[0][1] = m_[0][0] = VType(); m_[1][2] = m_[1][1] = m_[1][0] = VType(); m_[2][2] = m_[2][1] = m_[2][0] = VType(); } // Constructor explicitly setting the values of all the coefficient of // the matrix Matrix3x3(const VType &m00, const VType &m01, const VType &m02, const VType &m10, const VType &m11, const VType &m12, const VType &m20, const VType &m21, const VType &m22) { m_[0][0] = m00; m_[0][1] = m01; m_[0][2] = m02; m_[1][0] = m10; m_[1][1] = m11; m_[1][2] = m12; m_[2][0] = m20; m_[2][1] = m21; m_[2][2] = m22; } // Casting constructor template static Matrix3x3 Cast(const Matrix3x3 &mb) { return Matrix3x3(static_cast(mb(0, 0)), // static_cast(mb(0, 1)), // static_cast(mb(0, 2)), // static_cast(mb(1, 0)), // static_cast(mb(1, 1)), // static_cast(mb(1, 2)), // static_cast(mb(2, 0)), // static_cast(mb(2, 1)), // static_cast(mb(2, 2))); } // Change the value of all the coefficients of the matrix inline Matrix3x3 &Set(const VType &m00, const VType &m01, const VType &m02, const VType &m10, const VType &m11, const VType &m12, const VType &m20, const VType &m21, const VType &m22) { m_[0][0] = m00; m_[0][1] = m01; m_[0][2] = m02; m_[1][0] = m10; m_[1][1] = m11; m_[1][2] = m12; m_[2][0] = m20; m_[2][1] = m21; m_[2][2] = m22; return (*this); } // Matrix addition inline Matrix3x3 &operator+=(const Matrix3x3 &mb) { m_[0][0] += mb.m_[0][0]; m_[0][1] += mb.m_[0][1]; m_[0][2] += mb.m_[0][2]; m_[1][0] += mb.m_[1][0]; m_[1][1] += mb.m_[1][1]; m_[1][2] += mb.m_[1][2]; m_[2][0] += mb.m_[2][0]; m_[2][1] += mb.m_[2][1]; m_[2][2] += mb.m_[2][2]; return (*this); } // Matrix subtraction inline Matrix3x3 &operator-=(const Matrix3x3 &mb) { m_[0][0] -= mb.m_[0][0]; m_[0][1] -= mb.m_[0][1]; m_[0][2] -= mb.m_[0][2]; m_[1][0] -= mb.m_[1][0]; m_[1][1] -= mb.m_[1][1]; m_[1][2] -= mb.m_[1][2]; m_[2][0] -= mb.m_[2][0]; m_[2][1] -= mb.m_[2][1]; m_[2][2] -= mb.m_[2][2]; return (*this); } // Matrix multiplication by a scalar inline Matrix3x3 &operator*=(const VType &k) { m_[0][0] *= k; m_[0][1] *= k; m_[0][2] *= k; m_[1][0] *= k; m_[1][1] *= k; m_[1][2] *= k; m_[2][0] *= k; m_[2][1] *= k; m_[2][2] *= k; return (*this); } // Matrix addition inline Matrix3x3 operator+(const Matrix3x3 &mb) const { return Matrix3x3(*this) += mb; } // Matrix subtraction inline Matrix3x3 operator-(const Matrix3x3 &mb) const { return Matrix3x3(*this) -= mb; } // Change the sign of all the coefficients in the matrix friend inline Matrix3x3 operator-(const Matrix3x3 &vb) { return Matrix3x3(-vb.m_[0][0], -vb.m_[0][1], -vb.m_[0][2], // -vb.m_[1][0], -vb.m_[1][1], -vb.m_[1][2], // -vb.m_[2][0], -vb.m_[2][1], -vb.m_[2][2]); } // Matrix multiplication by a scalar inline Matrix3x3 operator*(const VType &k) const { return Matrix3x3(*this) *= k; } friend inline Matrix3x3 operator*(const VType &k, const Matrix3x3 &mb) { return Matrix3x3(mb) * k; } // Matrix multiplication inline Matrix3x3 operator*(const Matrix3x3 &mb) const { // clang-format off return Matrix3x3( m_[0][0] * mb.m_[0][0] + m_[0][1] * mb.m_[1][0] + m_[0][2] * mb.m_[2][0], m_[0][0] * mb.m_[0][1] + m_[0][1] * mb.m_[1][1] + m_[0][2] * mb.m_[2][1], m_[0][0] * mb.m_[0][2] + m_[0][1] * mb.m_[1][2] + m_[0][2] * mb.m_[2][2], m_[1][0] * mb.m_[0][0] + m_[1][1] * mb.m_[1][0] + m_[1][2] * mb.m_[2][0], m_[1][0] * mb.m_[0][1] + m_[1][1] * mb.m_[1][1] + m_[1][2] * mb.m_[2][1], m_[1][0] * mb.m_[0][2] + m_[1][1] * mb.m_[1][2] + m_[1][2] * mb.m_[2][2], m_[2][0] * mb.m_[0][0] + m_[2][1] * mb.m_[1][0] + m_[2][2] * mb.m_[2][0], m_[2][0] * mb.m_[0][1] + m_[2][1] * mb.m_[1][1] + m_[2][2] * mb.m_[2][1], m_[2][0] * mb.m_[0][2] + m_[2][1] * mb.m_[1][2] + m_[2][2] * mb.m_[2][2]); // clang-format on } // Multiplication of a matrix by a vector inline MVector operator*(const MVector &v) const { return MVector(m_[0][0] * v[0] + m_[0][1] * v[1] + m_[0][2] * v[2], m_[1][0] * v[0] + m_[1][1] * v[1] + m_[1][2] * v[2], m_[2][0] * v[0] + m_[2][1] * v[1] + m_[2][2] * v[2]); } // Return the determinant of the matrix inline VType Det() const { return m_[0][0] * m_[1][1] * m_[2][2] + m_[0][1] * m_[1][2] * m_[2][0] + m_[0][2] * m_[1][0] * m_[2][1] - m_[2][0] * m_[1][1] * m_[0][2] - m_[2][1] * m_[1][2] * m_[0][0] - m_[2][2] * m_[1][0] * m_[0][1]; } // Return the trace of the matrix inline VType Trace() const { return m_[0][0] + m_[1][1] + m_[2][2]; } // Return a pointer to the data array for interface with other libraries // like opencv VType *Data() { return reinterpret_cast(m_); } const VType *Data() const { return reinterpret_cast(m_); } // Return matrix element (i,j) with 0<=i<=2 0<=j<=2 inline VType &operator()(const int i, const int j) { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 3); ABSL_DCHECK_GE(j, 0); ABSL_DCHECK_LT(j, 3); return m_[i][j]; } inline VType operator()(const int i, const int j) const { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 3); ABSL_DCHECK_GE(j, 0); ABSL_DCHECK_LT(j, 3); return m_[i][j]; } // Return matrix element (i/3,i%3) with 0<=i<=8 (access concatenated rows). inline VType &operator[](const int i) { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 9); return reinterpret_cast(m_)[i]; } inline VType operator[](const int i) const { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 9); return reinterpret_cast(m_)[i]; } // Return the transposed matrix inline Matrix3x3 Transpose() const { return Matrix3x3(m_[0][0], m_[1][0], m_[2][0], // m_[0][1], m_[1][1], m_[2][1], // m_[0][2], m_[1][2], m_[2][2]); } // Return the transposed of the matrix of the cofactors // (Useful for inversion for example) inline Matrix3x3 ComatrixTransposed() const { return Matrix3x3(m_[1][1] * m_[2][2] - m_[2][1] * m_[1][2], m_[2][1] * m_[0][2] - m_[0][1] * m_[2][2], m_[0][1] * m_[1][2] - m_[1][1] * m_[0][2], m_[1][2] * m_[2][0] - m_[2][2] * m_[1][0], m_[2][2] * m_[0][0] - m_[0][2] * m_[2][0], m_[0][2] * m_[1][0] - m_[1][2] * m_[0][0], m_[1][0] * m_[2][1] - m_[2][0] * m_[1][1], m_[2][0] * m_[0][1] - m_[0][0] * m_[2][1], m_[0][0] * m_[1][1] - m_[1][0] * m_[0][1]); } // Matrix inversion inline Matrix3x3 Inverse() const { VType det = Det(); ABSL_CHECK_NE(det, VType(0)) << " Can't inverse. Determinant = 0."; return (VType(1) / det) * ComatrixTransposed(); } // Return the vector 3D at row i inline MVector Row(const int i) const { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 3); return MVector(m_[i][0], m_[i][1], m_[i][2]); } // Return the vector 3D at col i inline MVector Col(const int i) const { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 3); return MVector(m_[0][i], m_[1][i], m_[2][i]); } // Create a matrix from 3 row vectors static inline Matrix3x3 FromRows(const MVector &v1, const MVector &v2, const MVector &v3) { Matrix3x3 temp; temp.Set(v1[0], v1[1], v1[2], // v2[0], v2[1], v2[2], // v3[0], v3[1], v3[2]); return temp; } // Create a matrix from 3 column vectors static inline Matrix3x3 FromCols(const MVector &v1, const MVector &v2, const MVector &v3) { Matrix3x3 temp; temp.Set(v1[0], v2[0], v3[0], // v1[1], v2[1], v3[1], // v1[2], v2[2], v3[2]); return temp; } // Create a matrix from outer product of two vectors. static inline Matrix3x3 FromOuter(const MVector &ma, const MVector &mb) { Matrix3x3 m; for (int row = 0; row < 3; ++row) { m.SetRow(row, ma[row] * mb); } return m; } // Set the vector in row i to be v1 void SetRow(int i, const MVector &v1) { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 3); m_[i][0] = v1[0]; m_[i][1] = v1[1]; m_[i][2] = v1[2]; } // Set the vector in column i to be v1 void SetCol(int i, const MVector &v1) { ABSL_DCHECK_GE(i, 0); ABSL_DCHECK_LT(i, 3); m_[0][i] = v1[0]; m_[1][i] = v1[1]; m_[2][i] = v1[2]; } // Return a matrix M close to the original but verifying MtM = I // (useful to compensate for errors in a rotation matrix) Matrix3x3 Orthogonalize() const { MVector r1, r2, r3; r1 = Row(0).Normalize(); r2 = (Row(2).CrossProd(r1)).Normalize(); r3 = (r1.CrossProd(r2)).Normalize(); return FromRows(r1, r2, r3); } // Return the identity matrix static inline Matrix3x3 Identity() { Matrix3x3 temp; temp.Set(VType(1), VType(0), VType(0), // VType(0), VType(1), VType(0), // VType(0), VType(0), VType(1)); return temp; } // Return a matrix full of zeros static inline Matrix3x3 Zero() { return Matrix3x3(); } // Return a diagonal matrix with the coefficients in v static inline Matrix3x3 Diagonal(const MVector &v) { return Matrix3x3(v[0], VType(), VType(), // VType(), v[1], VType(), // VType(), VType(), v[2]); } // Return the matrix vvT static Matrix3x3 Sym3(const MVector &v) { return Matrix3x3(v[0] * v[0], v[0] * v[1], v[0] * v[2], // v[1] * v[0], v[1] * v[1], v[1] * v[2], // v[2] * v[0], v[2] * v[1], v[2] * v[2]); } // Return a matrix M such that: // for each u, M * u = v.CrossProd(u) static Matrix3x3 AntiSym3(const MVector &v) { return Matrix3x3(VType(), -v[2], v[1], // v[2], VType(), -v[0], // -v[1], v[0], VType()); } // Returns matrix that rotates |rot| radians around axis rot. static Matrix3x3 Rodrigues(const MVector &rot) { Matrix3x3 R; VType theta = rot.Norm(); MVector w = rot.Normalize(); Matrix3x3 Wv = Matrix3x3::AntiSym3(w); Matrix3x3 I = Matrix3x3::Identity(); Matrix3x3 A = Matrix3x3::Sym3(w); using std::cos; using std::sin; R = (1 - cos(theta)) * A + sin(theta) * Wv + cos(theta) * I; return R; } // Return a matrix that reflects a point across the plane defined by normal. static Matrix3x3 Householder(const MVector &normal) { MVector unit = normal.Normalize(); return Matrix3x3::Identity() - 2 * Matrix3x3::FromOuter(unit, unit); } // Returns v.Transpose() * (*this) * u VType MulBothSides(const MVector &v, const MVector &u) const { return ((*this) * u).DotProd(v); } // Use the 3x3 matrix as a projective transform for 2d points Vector2 Project(const Vector2 &v) const { MVector temp = (*this) * MVector(v[0], v[1], 1); return Vector2(temp[0] / temp[2], temp[1] / temp[2]); } // Return the Frobenius norm of the matrix: sqrt(sum(aij^2)) VType FrobeniusNorm() const { VType sum = VType(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { sum += m_[i][j] * m_[i][j]; } } using std::sqrt; return sqrt(sum); } // Finds the eigen values of the matrix. Return the number of real eigenvalues // found. // If the matrix is known to be symmetric due to your problem formulation, // then please use SymmetricEigenSolver, since this method does not guarantee // finding all 3 real eigenvalues in pathological cases. See CL 49170250. int EigenValues(MVector *eig_val) const { long double r1, r2, r3; // NOLINT // characteristic polynomial // x^3 + a*x^2 + b*x + c VType a = -Trace(); VType b = m_[0][0] * m_[1][1] + m_[1][1] * m_[2][2] + m_[2][2] * m_[0][0] - m_[1][0] * m_[0][1] - m_[2][1] * m_[1][2] - m_[0][2] * m_[2][0]; VType c = -Det(); bool res = MathUtil::RealRootsForCubic(a, b, c, &r1, &r2, &r3); (*eig_val)[0] = r1; if (res) { (*eig_val)[1] = r2; (*eig_val)[2] = r3; return 3; } return 1; } // Finds the eigen values and optional associated eigen vectors of a // symmetric 3x3 matrix (not necessarily positive definite). // eigen values are sorted in decreasing order; // eig_val corresponds to the columns of the eig_vec matrix. // Note: The routine will only use the lower diagonal part // of the matrix, i.e. // | a00, | // | a10, a11, | // | a20, a21, a22 | void SymmetricEigenSolver(MVector *eig_val, Matrix3x3 *eig_vec /*nullable*/) const { // Compute characteristic polynomial coefficients. double c2 = -Trace(); double c1 = -(m_[1][0] * m_[1][0] - m_[0][0] * m_[1][1] - m_[0][0] * m_[2][2] - m_[1][1] * m_[2][2] + m_[2][0] * m_[2][0] + m_[2][1] * m_[2][1]); double c0 = -(m_[0][0] * m_[1][1] * m_[2][2] // - m_[2][0] * m_[2][0] * m_[1][1] // - m_[1][0] * m_[1][0] * m_[2][2] // - m_[0][0] * m_[2][1] * m_[2][1] // + 2 * m_[1][0] * m_[2][0] * m_[2][1]); // Root finding x^3 + c2*x^2 + c1*x + c0 = 0. // NOTE: Cannot reuse general cubic solver MathUtil::RealRootsForCubic() // because it doesn't guarantee finding 3 real roots, e.g. it won't always // return roots {2, 2, 0} for the cubic x^3 - 4*x^2 + 4*x + epsilon = 0. double q = (c2 * c2 - 3 * c1) / 9.0; double r = (2 * c2 * c2 * c2 - 9 * c2 * c1 + 27 * c0) / 54.0; // Assume R^2 <= Q^3 so there are three real roots. // Avoid sqrt of negative q, which can only happen due to numerical error. if (q < 0) q = 0; double sqrt_q = -2.0 * sqrt(q); double q3_r2 = q * q * q - r * r; // Avoid sqrt of negative q3_r2, which can only happen due to numerical // error. double theta = atan2(q3_r2 <= 0 ? 0 : sqrt(q3_r2), r); double c2_3 = c2 / 3; (*eig_val)[0] = sqrt_q * cos(theta / 3.0) - c2_3; (*eig_val)[1] = sqrt_q * cos((theta + 2.0 * M_PI) / 3.0) - c2_3; (*eig_val)[2] = sqrt_q * cos((theta - 2.0 * M_PI) / 3.0) - c2_3; // Sort eigen value in decreasing order Vector3 d_order = eig_val->ComponentOrder(); (*eig_val) = MVector((*eig_val)[d_order[2]], (*eig_val)[d_order[1]], (*eig_val)[d_order[0]]); // Compute eigenvectors if (!eig_vec) return; for (int i = 0; i < 3; ++i) { MVector r1, r2, r3, e1, e2, e3; r1[0] = m_[0][0] - (*eig_val)[i]; r2[0] = m_[1][0]; r3[0] = m_[2][0]; r1[1] = m_[1][0]; r2[1] = m_[1][1] - (*eig_val)[i]; r3[1] = m_[2][1]; r1[2] = m_[2][0]; r2[2] = m_[2][1]; r3[2] = m_[2][2] - (*eig_val)[i]; e1 = r1.CrossProd(r2); e2 = r2.CrossProd(r3); e3 = r3.CrossProd(r1); // Make e2 and e3 point in the same direction as e1 if (e2.DotProd(e1) < 0) e2 = -e2; if (e3.DotProd(e1) < 0) e3 = -e3; MVector e = (e1 + e2 + e3).Normalize(); eig_vec->SetCol(i, e); } } // Return true is one of the elements of the matrix is NaN bool IsNaN() const { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (isnan(m_[i][j])) { return true; } } } return false; } friend bool operator==(const Matrix3x3 &a, const Matrix3x3 &b) { return a.m_[0][0] == b.m_[0][0] && a.m_[0][1] == b.m_[0][1] && a.m_[0][2] == b.m_[0][2] && a.m_[1][0] == b.m_[1][0] && a.m_[1][1] == b.m_[1][1] && a.m_[1][2] == b.m_[1][2] && a.m_[2][0] == b.m_[2][0] && a.m_[2][1] == b.m_[2][1] && a.m_[2][2] == b.m_[2][2]; } friend bool operator!=(const Matrix3x3 &a, const Matrix3x3 &b) { return !(a == b); } friend std::ostream &operator<<(std::ostream &out, const Matrix3x3 &mb) { int i, j; for (i = 0; i < 3; i++) { if (i == 0) { out << "["; } else { out << " "; } for (j = 0; j < 3; j++) { out << mb(i, j) << " "; } if (i == 2) { out << "]"; } else { out << std::endl; } } return out; } template friend H AbslHashValue(H h, const Matrix3x3 &m) { return H::combine_contiguous(std::move(h), m.Data(), 3 * 3); } }; typedef Matrix3x3 Matrix3x3_i; typedef Matrix3x3 Matrix3x3_f; typedef Matrix3x3 Matrix3x3_d; #endif // S2_UTIL_MATH_MATRIX3X3_H_ src/s2/util/math/vector.h000066400000000000000000000460051524103652300155600ustar00rootroot00000000000000// Copyright Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Simple classes to handle vectors in 2D, 3D, and 4D. // // Maintainers: Please be mindful of extreme degradations in unoptimized // performance here. #ifndef S2_UTIL_MATH_VECTOR_H_ #define S2_UTIL_MATH_VECTOR_H_ #include #include #include #include #include #include #include // NOLINT(readability/streams) #include #include #include #include "absl/log/absl_check.h" #include "absl/utility/utility.h" template class Vector2; template class Vector3; template class Vector4; namespace util { namespace math { namespace internal_vector { // CRTP base class for all Vector templates. template